Merge pull request #662 from aspnetboilerplate/issue-#6993
Upgrade to Angular 18
This commit is contained in:
Коммит
1e732c4853
|
@ -183,5 +183,8 @@
|
|||
"@schematics/angular:directive": {
|
||||
"prefix": "app"
|
||||
}
|
||||
},
|
||||
"cli": {
|
||||
"analytics": false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,14 +13,14 @@
|
|||
"test": "ng test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/animations": "^18.1.1",
|
||||
"@angular/common": "^18.1.1",
|
||||
"@angular/compiler": "^18.1.1",
|
||||
"@angular/core": "^18.1.1",
|
||||
"@angular/forms": "^18.1.1",
|
||||
"@angular/platform-browser": "^18.1.1",
|
||||
"@angular/platform-browser-dynamic": "^18.1.1",
|
||||
"@angular/router": "^18.1.1",
|
||||
"@angular/animations": "^18.1.2",
|
||||
"@angular/common": "^18.1.2",
|
||||
"@angular/compiler": "^18.1.2",
|
||||
"@angular/core": "^18.1.2",
|
||||
"@angular/forms": "^18.1.2",
|
||||
"@angular/platform-browser": "^18.1.2",
|
||||
"@angular/platform-browser-dynamic": "^18.1.2",
|
||||
"@angular/router": "^18.1.2",
|
||||
"@microsoft/signalr": "^8.0.7",
|
||||
"@fortawesome/fontawesome-free": "^6.6.0",
|
||||
"abp-ng2-module": "10.0.0",
|
||||
|
@ -37,19 +37,17 @@
|
|||
"rxjs": "^7.8.1",
|
||||
"sweetalert2": "^11.12.2",
|
||||
"ts-helpers": "^1.1.2",
|
||||
"tslib": "^2.6.3",
|
||||
"zone.js": "~0.14.8"
|
||||
"tslib": "^2.6.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^18.1.1",
|
||||
"@angular/cli": "^18.1.1",
|
||||
"@angular/compiler-cli": "^18.1.1",
|
||||
"@angular-devkit/build-angular": "^18.1.2",
|
||||
"@angular/cli": "^18.1.2",
|
||||
"@angular/compiler-cli": "^18.1.2",
|
||||
"@angularclass/hmr": "^3.0.0",
|
||||
"@types/jasmine": "~5.1.4",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/moment-timezone": "^0.5.30",
|
||||
"@types/node": "^20.11.1",
|
||||
"codelyzer": "^6.0.2",
|
||||
"jasmine-core": "~5.1.2",
|
||||
"jasmine-spec-reporter": "~7.0.0",
|
||||
"karma": "~6.4.3",
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
<div class="login-box">
|
||||
<account-header></account-header>
|
||||
<div class="card">
|
||||
<div *ngIf="showTenantChange()" class="card-header">
|
||||
<tenant-change></tenant-change>
|
||||
</div>
|
||||
@if (showTenantChange()) {
|
||||
<div class="card-header">
|
||||
<tenant-change></tenant-change>
|
||||
</div>
|
||||
}
|
||||
<div class="card-body login-card-body">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
<div class="text-center">
|
||||
<ng-container *ngFor="let language of languages">
|
||||
<a
|
||||
*ngIf="language.name != currentLanguage.name"
|
||||
href="javascript:void(0);"
|
||||
(click)="changeLanguage(language.name)"
|
||||
>
|
||||
<span
|
||||
title="{{ language.displayName }}"
|
||||
<div class="text-center">
|
||||
@for (language of languages; track language) {
|
||||
@if (language.name != currentLanguage.name) {
|
||||
<a
|
||||
href="javascript:void(0);"
|
||||
(click)="changeLanguage(language.name)"
|
||||
>
|
||||
<span
|
||||
title="{{ language.displayName }}"
|
||||
[attr.class.current-language-icon]="
|
||||
language.name != currentLanguage.name
|
||||
"
|
||||
>
|
||||
<i class="d-inline-block mx-1 {{ language.icon }}"></i>
|
||||
</span>
|
||||
</a>
|
||||
</ng-container>
|
||||
>
|
||||
<i class="d-inline-block mx-1 {{ language.icon }}"></i>
|
||||
</span>
|
||||
</a>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
|
|
@ -13,71 +13,73 @@
|
|||
maxlength="256"
|
||||
#userNameOrEmailAddressModel="ngModel"
|
||||
#userNameOrEmailAddressEl
|
||||
/>
|
||||
<div class="input-group-append">
|
||||
<div class="input-group-text">
|
||||
<span class="fas fa-user"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<abp-validation-summary
|
||||
[control]="userNameOrEmailAddressModel"
|
||||
[controlEl]="userNameOrEmailAddressEl"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<input
|
||||
type="password"
|
||||
class="form-control"
|
||||
name="password"
|
||||
[(ngModel)]="authService.authenticateModel.password"
|
||||
[placeholder]="'Password' | localize"
|
||||
required
|
||||
maxlength="32"
|
||||
#passwordModel="ngModel"
|
||||
#passwordEl
|
||||
/>
|
||||
<div class="input-group-append">
|
||||
<div class="input-group-text">
|
||||
<span class="fas fa-lock"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<abp-validation-summary
|
||||
[control]="passwordModel"
|
||||
[controlEl]="passwordEl"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-8">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="custom-control-input"
|
||||
id="rememberMe"
|
||||
name="rememberMe"
|
||||
[(ngModel)]="authService.rememberMe"
|
||||
/>
|
||||
<label for="rememberMe" class="custom-control-label">
|
||||
{{ "RememberMe" | localize }}
|
||||
</label>
|
||||
<div class="input-group-append">
|
||||
<div class="input-group-text">
|
||||
<span class="fas fa-user"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<abp-validation-summary
|
||||
[control]="userNameOrEmailAddressModel"
|
||||
[controlEl]="userNameOrEmailAddressEl"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary btn-block"
|
||||
[disabled]="!loginForm.form.valid || submitting"
|
||||
>
|
||||
{{ "LogIn" | localize }}
|
||||
</button>
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<input
|
||||
type="password"
|
||||
class="form-control"
|
||||
name="password"
|
||||
[(ngModel)]="authService.authenticateModel.password"
|
||||
[placeholder]="'Password' | localize"
|
||||
required
|
||||
maxlength="32"
|
||||
#passwordModel="ngModel"
|
||||
#passwordEl
|
||||
/>
|
||||
<div class="input-group-append">
|
||||
<div class="input-group-text">
|
||||
<span class="fas fa-lock"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<abp-validation-summary
|
||||
[control]="passwordModel"
|
||||
[controlEl]="passwordEl"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-8">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="custom-control-input"
|
||||
id="rememberMe"
|
||||
name="rememberMe"
|
||||
[(ngModel)]="authService.rememberMe"
|
||||
/>
|
||||
<label for="rememberMe" class="custom-control-label">
|
||||
{{ "RememberMe" | localize }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary btn-block"
|
||||
[disabled]="!loginForm.form.valid || submitting"
|
||||
>
|
||||
{{ "LogIn" | localize }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@if (isSelfRegistrationAllowed) {
|
||||
<p class="mb-1">
|
||||
<a [routerLink]="['../register']">
|
||||
<i class="fa fa-plus-circle"></i> {{ "Register" | localize }}
|
||||
</a>
|
||||
</p>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<p *ngIf="isSelfRegistrationAllowed" class="mb-1">
|
||||
<a [routerLink]="['../register']">
|
||||
<i class="fa fa-plus-circle"></i> {{ "Register" | localize }}
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Component, Injector } from '@angular/core';
|
||||
import { Component, Injector, Input } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { finalize } from 'rxjs/operators';
|
||||
import { AppComponentBase } from '@shared/app-component-base';
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
<div *ngIf="isMultiTenancyEnabled" class="text-center tenant-change-component">
|
||||
<span>
|
||||
{{ "CurrentTenant" | localize }}:
|
||||
<span *ngIf="tenancyName" title="{{ name }}">
|
||||
<strong>{{ tenancyName }}</strong>
|
||||
</span>
|
||||
<span *ngIf="!tenancyName">{{ "NotSelected" | localize }}</span>
|
||||
(<a href="javascript:;" (click)="showChangeModal()">
|
||||
@if (isMultiTenancyEnabled) {
|
||||
<div class="text-center tenant-change-component">
|
||||
<span>
|
||||
{{ "CurrentTenant" | localize }}:
|
||||
@if (tenancyName) {
|
||||
<span title="{{ name }}">
|
||||
<strong>{{ tenancyName }}</strong>
|
||||
</span>
|
||||
}
|
||||
@if (!tenancyName) {
|
||||
<span>{{ "NotSelected" | localize }}</span>
|
||||
}
|
||||
(<a href="javascript:;" (click)="showChangeModal()">
|
||||
{{ "Change" | localize }} </a
|
||||
>)
|
||||
</span>
|
||||
</div>
|
||||
>)
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
|
|
|
@ -6,16 +6,17 @@
|
|||
</span>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-right p-0" *dropdownMenu>
|
||||
<ng-container *ngFor="let language of languages">
|
||||
<a
|
||||
*ngIf="language.name != currentLanguage.name"
|
||||
class="dropdown-item"
|
||||
href="javascript:;"
|
||||
(click)="changeLanguage(language.name)"
|
||||
>
|
||||
<i class="d-inline-block {{ language.icon }} mr-1"></i>
|
||||
{{ language.displayName }}
|
||||
</a>
|
||||
</ng-container>
|
||||
@for (language of languages; track language) {
|
||||
@if (language.name != currentLanguage.name) {
|
||||
<a
|
||||
class="dropdown-item"
|
||||
href="javascript:;"
|
||||
(click)="changeLanguage(language.name)"
|
||||
>
|
||||
<i class="d-inline-block {{ language.icon }} mr-1"></i>
|
||||
{{ language.displayName }}
|
||||
</a>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</li>
|
||||
|
|
|
@ -4,68 +4,73 @@
|
|||
data-widget="treeview"
|
||||
role="menu"
|
||||
data-accordion="false"
|
||||
>
|
||||
<ng-container *ngFor="let item of menuItems">
|
||||
>
|
||||
@for (item of menuItems; track item) {
|
||||
<ng-container
|
||||
*ngTemplateOutlet="sidebarInner; context: { item: item }"
|
||||
></ng-container>
|
||||
</ng-container>
|
||||
}
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<ng-template #sidebarInner let-item="item">
|
||||
<li
|
||||
*ngIf="isMenuItemVisible(item)"
|
||||
class="nav-item"
|
||||
[class.menu-open]="!item.isCollapsed"
|
||||
[class.has-treeview]="item.children"
|
||||
>
|
||||
<a
|
||||
*ngIf="item.route && item.route.indexOf('http') != 0"
|
||||
class="nav-link"
|
||||
[routerLink]="item.route"
|
||||
[class.active]="item.isActive"
|
||||
>
|
||||
<i class="nav-icon {{ item.icon }}"></i>
|
||||
<p>
|
||||
{{ item.label }}
|
||||
</p>
|
||||
</a>
|
||||
<a
|
||||
*ngIf="item.route && item.route.indexOf('http') == 0 && !item.children"
|
||||
class="nav-link"
|
||||
target="_blank"
|
||||
[href]="item.route"
|
||||
>
|
||||
<i class="nav-icon {{ item.icon }}"></i>
|
||||
<p>
|
||||
{{ item.label }}
|
||||
</p>
|
||||
</a>
|
||||
<a
|
||||
*ngIf="!item.route && item.children"
|
||||
class="nav-link"
|
||||
href="javascript:;"
|
||||
[class.active]="item.isActive"
|
||||
(click)="item.isCollapsed = !item.isCollapsed"
|
||||
>
|
||||
<i class="nav-icon {{ item.icon }}"></i>
|
||||
<p>
|
||||
{{ item.label }}
|
||||
<i class="right fas fa-angle-left"></i>
|
||||
</p>
|
||||
</a>
|
||||
<ul
|
||||
*ngIf="item.children"
|
||||
class="nav nav-treeview"
|
||||
[collapse]="item.isCollapsed"
|
||||
[isAnimated]="true"
|
||||
>
|
||||
<ng-container *ngFor="let item of item.children">
|
||||
<ng-container
|
||||
*ngTemplateOutlet="sidebarInner; context: { item: item }"
|
||||
></ng-container>
|
||||
</ng-container>
|
||||
</ul>
|
||||
</li>
|
||||
@if (isMenuItemVisible(item)) {
|
||||
<li
|
||||
class="nav-item"
|
||||
[class.menu-open]="!item.isCollapsed"
|
||||
[class.has-treeview]="item.children"
|
||||
>
|
||||
@if (item.route && item.route.indexOf('http') != 0) {
|
||||
<a
|
||||
class="nav-link"
|
||||
[routerLink]="item.route"
|
||||
[class.active]="item.isActive"
|
||||
>
|
||||
<i class="nav-icon {{ item.icon }}"></i>
|
||||
<p>
|
||||
{{ item.label }}
|
||||
</p>
|
||||
</a>
|
||||
}
|
||||
@if (item.route && item.route.indexOf('http') == 0 && !item.children) {
|
||||
<a
|
||||
class="nav-link"
|
||||
target="_blank"
|
||||
[href]="item.route"
|
||||
>
|
||||
<i class="nav-icon {{ item.icon }}"></i>
|
||||
<p>
|
||||
{{ item.label }}
|
||||
</p>
|
||||
</a>
|
||||
}
|
||||
@if (!item.route && item.children) {
|
||||
<a
|
||||
class="nav-link"
|
||||
href="javascript:;"
|
||||
[class.active]="item.isActive"
|
||||
(click)="item.isCollapsed = !item.isCollapsed"
|
||||
>
|
||||
<i class="nav-icon {{ item.icon }}"></i>
|
||||
<p>
|
||||
{{ item.label }}
|
||||
<i class="right fas fa-angle-left"></i>
|
||||
</p>
|
||||
</a>
|
||||
}
|
||||
@if (item.children) {
|
||||
<ul
|
||||
class="nav nav-treeview"
|
||||
[collapse]="item.isCollapsed"
|
||||
[isAnimated]="true"
|
||||
>
|
||||
@for (item of item.children; track item) {
|
||||
<ng-container
|
||||
*ngTemplateOutlet="sidebarInner; context: { item: item }"
|
||||
></ng-container>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
</li>
|
||||
}
|
||||
</ng-template>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
autocomplete="off"
|
||||
#createRoleForm="ngForm"
|
||||
(ngSubmit)="save()"
|
||||
>
|
||||
>
|
||||
<abp-modal-header
|
||||
[title]="'CreateNewRole' | localize"
|
||||
(onCloseClick)="bsModalRef.hide()"
|
||||
|
@ -27,77 +27,77 @@
|
|||
[(ngModel)]="role.name"
|
||||
#nameModel="ngModel"
|
||||
#nameEl
|
||||
/>
|
||||
<abp-validation-summary
|
||||
[control]="nameModel"
|
||||
[controlEl]="nameEl"
|
||||
></abp-validation-summary>
|
||||
/>
|
||||
<abp-validation-summary
|
||||
[control]="nameModel"
|
||||
[controlEl]="nameEl"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row required">
|
||||
<label class="col-md-3 col-form-label" for="displayName">
|
||||
{{ "DisplayName" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="displayName"
|
||||
id="displayName"
|
||||
required
|
||||
minlength="2"
|
||||
maxlength="32"
|
||||
[(ngModel)]="role.displayName"
|
||||
#displayNameModel="ngModel"
|
||||
#displayNameEl
|
||||
/>
|
||||
<abp-validation-summary
|
||||
[control]="displayNameModel"
|
||||
[controlEl]="displayNameEl"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row mb-0">
|
||||
<label class="col-md-3 col-form-label" for="description">
|
||||
{{ "RoleDescription" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<textarea
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="description"
|
||||
id="description"
|
||||
[(ngModel)]="role.description"
|
||||
>
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</tab>
|
||||
<tab [heading]="'Permissions' | localize" class="pt-3 px-2">
|
||||
<div class="form-group row mb-0">
|
||||
<ng-container *ngFor="let permission of permissions; let i = index">
|
||||
<div class="col-md-6">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="custom-control-input"
|
||||
[id]="'permission_' + i"
|
||||
[checked]="isPermissionChecked(permission.name)"
|
||||
(change)="onPermissionChange(permission, $event)"
|
||||
<div class="form-group row required">
|
||||
<label class="col-md-3 col-form-label" for="displayName">
|
||||
{{ "DisplayName" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="displayName"
|
||||
id="displayName"
|
||||
required
|
||||
minlength="2"
|
||||
maxlength="32"
|
||||
[(ngModel)]="role.displayName"
|
||||
#displayNameModel="ngModel"
|
||||
#displayNameEl
|
||||
/>
|
||||
<label class="custom-control-label" [for]="'permission_' + i">
|
||||
{{ permission.displayName }}
|
||||
</label>
|
||||
<abp-validation-summary
|
||||
[control]="displayNameModel"
|
||||
[controlEl]="displayNameEl"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<div class="form-group row mb-0">
|
||||
<label class="col-md-3 col-form-label" for="description">
|
||||
{{ "RoleDescription" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<textarea
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="description"
|
||||
id="description"
|
||||
[(ngModel)]="role.description"
|
||||
>
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</tab>
|
||||
<tab [heading]="'Permissions' | localize" class="pt-3 px-2">
|
||||
<div class="form-group row mb-0">
|
||||
@for (permission of permissions; track permission; let i = $index) {
|
||||
<div class="col-md-6">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="custom-control-input"
|
||||
[id]="'permission_' + i"
|
||||
[checked]="isPermissionChecked(permission.name)"
|
||||
(change)="onPermissionChange(permission, $event)"
|
||||
/>
|
||||
<label class="custom-control-label" [for]="'permission_' + i">
|
||||
{{ permission.displayName }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</tab>
|
||||
</tabset>
|
||||
</div>
|
||||
</tab>
|
||||
</tabset>
|
||||
</div>
|
||||
<abp-modal-footer
|
||||
[cancelDisabled]="saving"
|
||||
[saveDisabled]="!createRoleForm.form.valid || saving"
|
||||
(onCancelClick)="bsModalRef.hide()"
|
||||
></abp-modal-footer>
|
||||
</form>
|
||||
<abp-modal-footer
|
||||
[cancelDisabled]="saving"
|
||||
[saveDisabled]="!createRoleForm.form.valid || saving"
|
||||
(onCancelClick)="bsModalRef.hide()"
|
||||
></abp-modal-footer>
|
||||
</form>
|
||||
|
|
|
@ -3,7 +3,8 @@ import {
|
|||
Injector,
|
||||
OnInit,
|
||||
EventEmitter,
|
||||
Output,
|
||||
output,
|
||||
ChangeDetectorRef,
|
||||
} from '@angular/core';
|
||||
import { BsModalRef } from 'ngx-bootstrap/modal';
|
||||
import { AppComponentBase } from '@shared/app-component-base';
|
||||
|
@ -27,12 +28,13 @@ export class CreateRoleDialogComponent extends AppComponentBase
|
|||
checkedPermissionsMap: { [key: string]: boolean } = {};
|
||||
defaultPermissionCheckedStatus = true;
|
||||
|
||||
@Output() onSave = new EventEmitter<any>();
|
||||
onSave = output<EventEmitter<any>>()
|
||||
|
||||
constructor(
|
||||
injector: Injector,
|
||||
private _roleService: RoleServiceProxy,
|
||||
public bsModalRef: BsModalRef
|
||||
public bsModalRef: BsModalRef,
|
||||
private cd: ChangeDetectorRef
|
||||
) {
|
||||
super(injector);
|
||||
}
|
||||
|
@ -43,6 +45,7 @@ export class CreateRoleDialogComponent extends AppComponentBase
|
|||
.subscribe((result: PermissionDtoListResultDto) => {
|
||||
this.permissions = result.items;
|
||||
this.setInitialPermissionsStatus();
|
||||
this.cd.detectChanges();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -87,10 +90,11 @@ export class CreateRoleDialogComponent extends AppComponentBase
|
|||
() => {
|
||||
this.notify.info(this.l('SavedSuccessfully'));
|
||||
this.bsModalRef.hide();
|
||||
this.onSave.emit();
|
||||
this.onSave.emit(null);
|
||||
},
|
||||
() => {
|
||||
this.saving = false;
|
||||
this.cd.detectChanges();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
autocomplete="off"
|
||||
#editRoleForm="ngForm"
|
||||
(ngSubmit)="save()"
|
||||
>
|
||||
>
|
||||
<abp-modal-header
|
||||
[title]="'EditRole' | localize"
|
||||
(onCloseClick)="bsModalRef.hide()"
|
||||
|
@ -27,78 +27,78 @@
|
|||
[(ngModel)]="role.name"
|
||||
#nameModel="ngModel"
|
||||
#nameEl
|
||||
/>
|
||||
<abp-validation-summary
|
||||
[control]="nameModel"
|
||||
[controlEl]="nameEl"
|
||||
></abp-validation-summary>
|
||||
/>
|
||||
<abp-validation-summary
|
||||
[control]="nameModel"
|
||||
[controlEl]="nameEl"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row required">
|
||||
<label class="col-md-3 col-form-label" for="displayName">
|
||||
{{ "DisplayName" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="displayName"
|
||||
id="displayName"
|
||||
required
|
||||
minlength="2"
|
||||
maxlength="32"
|
||||
[(ngModel)]="role.displayName"
|
||||
#displayNameModel="ngModel"
|
||||
#displayNameEl
|
||||
/>
|
||||
<abp-validation-summary
|
||||
[control]="displayNameModel"
|
||||
[controlEl]="displayNameEl"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row mb-0">
|
||||
<label class="col-md-3 col-form-label" for="description">
|
||||
{{ "RoleDescription" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<textarea
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="description"
|
||||
id="description"
|
||||
[(ngModel)]="role.description"
|
||||
>
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</tab>
|
||||
<tab [heading]="'Permissions' | localize" class="pt-3 px-2">
|
||||
<div class="form-group row mb-0">
|
||||
<ng-container *ngFor="let permission of permissions; let i = index">
|
||||
<div class="col-md-6">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="custom-control-input"
|
||||
[id]="'permission_' + i"
|
||||
[checked]="isPermissionChecked(permission.name)"
|
||||
[disabled]="role.isStatic"
|
||||
(change)="onPermissionChange(permission, $event)"
|
||||
<div class="form-group row required">
|
||||
<label class="col-md-3 col-form-label" for="displayName">
|
||||
{{ "DisplayName" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="displayName"
|
||||
id="displayName"
|
||||
required
|
||||
minlength="2"
|
||||
maxlength="32"
|
||||
[(ngModel)]="role.displayName"
|
||||
#displayNameModel="ngModel"
|
||||
#displayNameEl
|
||||
/>
|
||||
<label class="custom-control-label" [for]="'permission_' + i">
|
||||
{{ permission.displayName }}
|
||||
</label>
|
||||
<abp-validation-summary
|
||||
[control]="displayNameModel"
|
||||
[controlEl]="displayNameEl"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<div class="form-group row mb-0">
|
||||
<label class="col-md-3 col-form-label" for="description">
|
||||
{{ "RoleDescription" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<textarea
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="description"
|
||||
id="description"
|
||||
[(ngModel)]="role.description"
|
||||
>
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</tab>
|
||||
<tab [heading]="'Permissions' | localize" class="pt-3 px-2">
|
||||
<div class="form-group row mb-0">
|
||||
@for (permission of permissions; track permission; let i = $index) {
|
||||
<div class="col-md-6">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="custom-control-input"
|
||||
[id]="'permission_' + i"
|
||||
[checked]="isPermissionChecked(permission.name)"
|
||||
[disabled]="role.isStatic"
|
||||
(change)="onPermissionChange(permission, $event)"
|
||||
/>
|
||||
<label class="custom-control-label" [for]="'permission_' + i">
|
||||
{{ permission.displayName }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</tab>
|
||||
</tabset>
|
||||
</div>
|
||||
</tab>
|
||||
</tabset>
|
||||
</div>
|
||||
<abp-modal-footer
|
||||
[cancelDisabled]="saving"
|
||||
[saveDisabled]="!editRoleForm.form.valid || saving"
|
||||
(onCancelClick)="bsModalRef.hide()"
|
||||
></abp-modal-footer>
|
||||
</form>
|
||||
<abp-modal-footer
|
||||
[cancelDisabled]="saving"
|
||||
[saveDisabled]="!editRoleForm.form.valid || saving"
|
||||
(onCancelClick)="bsModalRef.hide()"
|
||||
></abp-modal-footer>
|
||||
</form>
|
||||
|
|
|
@ -4,6 +4,7 @@ import {
|
|||
OnInit,
|
||||
EventEmitter,
|
||||
Output,
|
||||
ChangeDetectorRef,
|
||||
} from '@angular/core';
|
||||
import { BsModalRef } from 'ngx-bootstrap/modal';
|
||||
import { forEach as _forEach, includes as _includes, map as _map } from 'lodash-es';
|
||||
|
@ -34,7 +35,8 @@ export class EditRoleDialogComponent extends AppComponentBase
|
|||
constructor(
|
||||
injector: Injector,
|
||||
private _roleService: RoleServiceProxy,
|
||||
public bsModalRef: BsModalRef
|
||||
public bsModalRef: BsModalRef,
|
||||
private cd: ChangeDetectorRef
|
||||
) {
|
||||
super(injector);
|
||||
}
|
||||
|
@ -47,6 +49,7 @@ export class EditRoleDialogComponent extends AppComponentBase
|
|||
this.permissions = result.permissions;
|
||||
this.grantedPermissionNames = result.grantedPermissionNames;
|
||||
this.setInitialPermissionsStatus();
|
||||
this.cd.detectChanges();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -62,7 +65,7 @@ export class EditRoleDialogComponent extends AppComponentBase
|
|||
return _includes(this.grantedPermissionNames, permissionName);
|
||||
}
|
||||
|
||||
onPermissionChange(permission: PermissionDto, $event) {
|
||||
onPermissionChange(permission: FlatPermissionDto, $event) {
|
||||
this.checkedPermissionsMap[permission.name] = $event.target.checked;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,49 +37,52 @@
|
|||
[placeholder]="'SearchWithThreeDot' | localize"
|
||||
[(ngModel)]="keyword"
|
||||
(keyup.enter)="getDataPage(1)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-bordered"
|
||||
[busy]="isTableLoading">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th>{{ "RoleName" | localize }}</th>
|
||||
<th>{{ "DisplayName" | localize }}</th>
|
||||
<th style="width: 200px;">{{ "Actions" | localize }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="
|
||||
let role of roles
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-bordered"
|
||||
[busy]="isTableLoading">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th>{{ "RoleName" | localize }}</th>
|
||||
<th>{{ "DisplayName" | localize }}</th>
|
||||
<th style="width: 200px;">{{ "Actions" | localize }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@for (
|
||||
role of roles
|
||||
| paginate
|
||||
: {
|
||||
id: 'server',
|
||||
itemsPerPage: pageSize,
|
||||
currentPage: pageNumber,
|
||||
totalItems: totalItems
|
||||
}
|
||||
">
|
||||
<td>{{ role.name }}</td>
|
||||
<td>{{ role.displayName }}</td>
|
||||
<td>
|
||||
<button type="button"
|
||||
class="btn btn-sm bg-secondary"
|
||||
(click)="editRole(role)">
|
||||
<i class="fas fa-pencil-alt"></i>
|
||||
{{ "Edit" | localize }}
|
||||
</button>
|
||||
<button type="button"
|
||||
class="btn btn-sm bg-danger mx-2"
|
||||
(click)="delete(role)">
|
||||
<i class="fas fa-trash"></i>
|
||||
{{ "Delete" | localize }}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
: {
|
||||
id: 'server',
|
||||
itemsPerPage: pageSize,
|
||||
currentPage: pageNumber,
|
||||
totalItems: totalItems
|
||||
}
|
||||
; track
|
||||
role.id) {
|
||||
<tr>
|
||||
<td>{{ role.name }}</td>
|
||||
<td>{{ role.displayName }}</td>
|
||||
<td>
|
||||
<button type="button"
|
||||
class="btn btn-sm bg-secondary"
|
||||
(click)="editRole(role)">
|
||||
<i class="fas fa-pencil-alt"></i>
|
||||
{{ "Edit" | localize }}
|
||||
</button>
|
||||
<button type="button"
|
||||
class="btn btn-sm bg-danger mx-2"
|
||||
(click)="delete(role)">
|
||||
<i class="fas fa-trash"></i>
|
||||
{{ "Delete" | localize }}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Component, Injector } from '@angular/core';
|
||||
import { Component, Injector, ChangeDetectorRef } from '@angular/core';
|
||||
import { finalize } from 'rxjs/operators';
|
||||
import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
|
||||
import { appModuleAnimation } from '@shared/animations/routerTransition';
|
||||
|
@ -29,9 +29,10 @@ export class RolesComponent extends PagedListingComponentBase<RoleDto> {
|
|||
constructor(
|
||||
injector: Injector,
|
||||
private _rolesService: RoleServiceProxy,
|
||||
private _modalService: BsModalService
|
||||
private _modalService: BsModalService,
|
||||
cd: ChangeDetectorRef
|
||||
) {
|
||||
super(injector);
|
||||
super(injector, cd);
|
||||
}
|
||||
|
||||
list(
|
||||
|
@ -51,6 +52,7 @@ export class RolesComponent extends PagedListingComponentBase<RoleDto> {
|
|||
.subscribe((result: RoleDtoPagedResultDto) => {
|
||||
this.roles = result.items;
|
||||
this.showPaging(result, pageNumber);
|
||||
this.cd.detectChanges();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,8 @@ import {
|
|||
Injector,
|
||||
OnInit,
|
||||
Output,
|
||||
EventEmitter
|
||||
EventEmitter,
|
||||
ChangeDetectorRef
|
||||
} from '@angular/core';
|
||||
import { BsModalRef } from 'ngx-bootstrap/modal';
|
||||
import { AppComponentBase } from '@shared/app-component-base';
|
||||
|
@ -25,13 +26,15 @@ export class CreateTenantDialogComponent extends AppComponentBase
|
|||
constructor(
|
||||
injector: Injector,
|
||||
public _tenantService: TenantServiceProxy,
|
||||
public bsModalRef: BsModalRef
|
||||
public bsModalRef: BsModalRef,
|
||||
private cd: ChangeDetectorRef
|
||||
) {
|
||||
super(injector);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.tenant.isActive = true;
|
||||
this.cd.detectChanges();
|
||||
}
|
||||
|
||||
save(): void {
|
||||
|
|
|
@ -3,7 +3,8 @@ import {
|
|||
Injector,
|
||||
OnInit,
|
||||
Output,
|
||||
EventEmitter
|
||||
EventEmitter,
|
||||
ChangeDetectorRef
|
||||
} from '@angular/core';
|
||||
import { BsModalRef } from 'ngx-bootstrap/modal';
|
||||
import { AppComponentBase } from '@shared/app-component-base';
|
||||
|
@ -26,7 +27,8 @@ export class EditTenantDialogComponent extends AppComponentBase
|
|||
constructor(
|
||||
injector: Injector,
|
||||
public _tenantService: TenantServiceProxy,
|
||||
public bsModalRef: BsModalRef
|
||||
public bsModalRef: BsModalRef,
|
||||
private cd: ChangeDetectorRef
|
||||
) {
|
||||
super(injector);
|
||||
}
|
||||
|
@ -34,6 +36,7 @@ export class EditTenantDialogComponent extends AppComponentBase
|
|||
ngOnInit(): void {
|
||||
this._tenantService.get(this.id).subscribe((result: TenantDto) => {
|
||||
this.tenant = result;
|
||||
this.cd.detectChanges();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,224 +1,228 @@
|
|||
<div [@routerTransition]>
|
||||
<section class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<h1>{{ "Tenants" | localize }}</h1>
|
||||
</div>
|
||||
<div class="col-6 text-right">
|
||||
<a href="javascript:;" class="btn bg-blue" (click)="createTenant()">
|
||||
<i class="fa fa-plus-square"></i>
|
||||
{{ "Create" | localize }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<section class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<h1>{{ "Tenants" | localize }}</h1>
|
||||
</div>
|
||||
</section>
|
||||
<section class="content px-2">
|
||||
<div class="container-fluid">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="col-6 text-right">
|
||||
<a href="javascript:;" class="btn bg-blue" (click)="createTenant()">
|
||||
<i class="fa fa-plus-square"></i>
|
||||
{{ "Create" | localize }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="content px-2">
|
||||
<div class="container-fluid">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="row">
|
||||
<div class="col-md-6"> </div>
|
||||
<div class="col-md-6">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<button
|
||||
type="button"
|
||||
class="btn bg-blue"
|
||||
(click)="getDataPage(1)"
|
||||
>
|
||||
<i class="fas fa-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="keyword"
|
||||
[placeholder]="'SearchWithThreeDot' | localize"
|
||||
[(ngModel)]="keyword"
|
||||
(keyup.enter)="getDataPage(1)"
|
||||
/>
|
||||
<div class="input-group-append">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-default"
|
||||
(click)="advancedFiltersVisible = !advancedFiltersVisible"
|
||||
>
|
||||
<i
|
||||
class="fas"
|
||||
[class.fa-angle-up]="advancedFiltersVisible"
|
||||
[class.fa-angle-down]="!advancedFiltersVisible"
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@if (advancedFiltersVisible) {
|
||||
<div class="card mb-0 mt-1">
|
||||
<div class="card-body">
|
||||
<form class="form-horizontal">
|
||||
<div class="row">
|
||||
<div class="col-md-6"> </div>
|
||||
<div class="col-md-6">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<button
|
||||
type="button"
|
||||
class="btn bg-blue"
|
||||
(click)="getDataPage(1)"
|
||||
>
|
||||
<i class="fas fa-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="keyword"
|
||||
[placeholder]="'SearchWithThreeDot' | localize"
|
||||
[(ngModel)]="keyword"
|
||||
(keyup.enter)="getDataPage(1)"
|
||||
<div class="col-md-6">
|
||||
<div class="form-group row mb-0">
|
||||
<label class="col-md-3 col-form-label">
|
||||
{{ "IsActive" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9 pt-2">
|
||||
<div class="custom-control custom-radio d-inline">
|
||||
<input
|
||||
type="radio"
|
||||
class="custom-control-input"
|
||||
id="isActiveAll"
|
||||
name="isActive"
|
||||
[(ngModel)]="isActive"
|
||||
[value]="undefined"
|
||||
checked
|
||||
/>
|
||||
<div class="input-group-append">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-default"
|
||||
(click)="advancedFiltersVisible = !advancedFiltersVisible"
|
||||
<label class="custom-control-label" for="isActiveAll">
|
||||
{{ "All" | localize }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="custom-control custom-radio d-inline mx-3">
|
||||
<input
|
||||
type="radio"
|
||||
class="custom-control-input"
|
||||
id="isActiveActive"
|
||||
name="isActive"
|
||||
[(ngModel)]="isActive"
|
||||
[value]="true"
|
||||
/>
|
||||
<label
|
||||
class="custom-control-label"
|
||||
for="isActiveActive"
|
||||
>
|
||||
<i
|
||||
class="fas"
|
||||
[class.fa-angle-up]="advancedFiltersVisible"
|
||||
[class.fa-angle-down]="!advancedFiltersVisible"
|
||||
></i>
|
||||
</button>
|
||||
{{ "Yes" | localize }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="custom-control custom-radio d-inline">
|
||||
<input
|
||||
type="radio"
|
||||
class="custom-control-input"
|
||||
id="isActivePassive"
|
||||
name="isActive"
|
||||
[(ngModel)]="isActive"
|
||||
[value]="false"
|
||||
/>
|
||||
<label
|
||||
class="custom-control-label"
|
||||
for="isActivePassive"
|
||||
>
|
||||
{{ "No" | localize }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="advancedFiltersVisible" class="card mb-0 mt-1">
|
||||
<div class="card-body">
|
||||
<form class="form-horizontal">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group row mb-0">
|
||||
<label class="col-md-3 col-form-label">
|
||||
{{ "IsActive" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9 pt-2">
|
||||
<div class="custom-control custom-radio d-inline">
|
||||
<input
|
||||
type="radio"
|
||||
class="custom-control-input"
|
||||
id="isActiveAll"
|
||||
name="isActive"
|
||||
[(ngModel)]="isActive"
|
||||
[value]="undefined"
|
||||
checked
|
||||
/>
|
||||
<label class="custom-control-label" for="isActiveAll">
|
||||
{{ "All" | localize }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="custom-control custom-radio d-inline mx-3">
|
||||
<input
|
||||
type="radio"
|
||||
class="custom-control-input"
|
||||
id="isActiveActive"
|
||||
name="isActive"
|
||||
[(ngModel)]="isActive"
|
||||
[value]="true"
|
||||
/>
|
||||
<label
|
||||
class="custom-control-label"
|
||||
for="isActiveActive"
|
||||
>
|
||||
{{ "Yes" | localize }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="custom-control custom-radio d-inline">
|
||||
<input
|
||||
type="radio"
|
||||
class="custom-control-input"
|
||||
id="isActivePassive"
|
||||
name="isActive"
|
||||
[(ngModel)]="isActive"
|
||||
[value]="false"
|
||||
/>
|
||||
<label
|
||||
class="custom-control-label"
|
||||
for="isActivePassive"
|
||||
>
|
||||
{{ "No" | localize }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="btn bg-blue"
|
||||
(click)="getDataPage(1)"
|
||||
>
|
||||
{{ "Search" | localize }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-default float-right"
|
||||
(click)="clearFilters()"
|
||||
>
|
||||
{{ "Clear" | localize }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="btn bg-blue"
|
||||
(click)="getDataPage(1)"
|
||||
>
|
||||
{{ "Search" | localize }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-default float-right"
|
||||
(click)="clearFilters()"
|
||||
>
|
||||
{{ "Clear" | localize }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-bordered" [busy]="isTableLoading">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th>{{ "TenancyName" | localize }}</th>
|
||||
<th>{{ "Name" | localize }}</th>
|
||||
<th>{{ "IsActive" | localize }}</th>
|
||||
<th style="width: 200px;">{{ "Actions" | localize }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
*ngFor="
|
||||
let tenant of tenants
|
||||
| paginate
|
||||
: {
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-bordered" [busy]="isTableLoading">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th>{{ "TenancyName" | localize }}</th>
|
||||
<th>{{ "Name" | localize }}</th>
|
||||
<th>{{ "IsActive" | localize }}</th>
|
||||
<th style="width: 200px;">{{ "Actions" | localize }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@for (
|
||||
tenant of tenants
|
||||
| paginate
|
||||
: {
|
||||
id: 'server',
|
||||
itemsPerPage: pageSize,
|
||||
currentPage: pageNumber,
|
||||
totalItems: totalItems
|
||||
}
|
||||
"
|
||||
>
|
||||
<td>{{ tenant.tenancyName }}</td>
|
||||
<td>{{ tenant.name }}</td>
|
||||
<td>
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="custom-control-input"
|
||||
disabled
|
||||
[checked]="tenant.isActive"
|
||||
/>
|
||||
<label class="custom-control-label"></label>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm bg-secondary"
|
||||
(click)="editTenant(tenant)"
|
||||
>
|
||||
<i class="fas fa-pencil-alt"></i>
|
||||
{{ "Edit" | localize }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm bg-danger mx-2"
|
||||
(click)="delete(tenant)"
|
||||
>
|
||||
<i class="fas fa-trash"></i>
|
||||
{{ "Delete" | localize }}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
; track
|
||||
tenant.id) {
|
||||
<tr
|
||||
>
|
||||
<td>{{ tenant.tenancyName }}</td>
|
||||
<td>{{ tenant.name }}</td>
|
||||
<td>
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="custom-control-input"
|
||||
disabled
|
||||
[checked]="tenant.isActive"
|
||||
/>
|
||||
<label class="custom-control-label"></label>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm bg-secondary"
|
||||
(click)="editTenant(tenant)"
|
||||
>
|
||||
<i class="fas fa-pencil-alt"></i>
|
||||
{{ "Edit" | localize }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm bg-danger mx-2"
|
||||
(click)="delete(tenant)"
|
||||
>
|
||||
<i class="fas fa-trash"></i>
|
||||
{{ "Delete" | localize }}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer table-card-footer bg-light border-top">
|
||||
<div class="row">
|
||||
<div class="col-sm-4 col-12 text-sm-left text-center">
|
||||
<button class="btn btn-secondary" (click)="refresh()">
|
||||
<i class="fas fa-redo-alt"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-sm-4 col-12 text-center">
|
||||
<p class="mb-0 my-2">
|
||||
{{ "TotalRecordsCount" | localize: totalItems }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-sm-4 col-12">
|
||||
<div class="float-sm-right m-auto">
|
||||
<abp-pagination-controls
|
||||
id="server"
|
||||
(pageChange)="getDataPage($event)"
|
||||
>
|
||||
</abp-pagination-controls>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-4 col-12 text-sm-left text-center">
|
||||
<button class="btn btn-secondary" (click)="refresh()">
|
||||
<i class="fas fa-redo-alt"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-sm-4 col-12 text-center">
|
||||
<p class="mb-0 my-2">
|
||||
{{ "TotalRecordsCount" | localize: totalItems }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-sm-4 col-12">
|
||||
<div class="float-sm-right m-auto">
|
||||
<abp-pagination-controls
|
||||
id="server"
|
||||
(pageChange)="getDataPage($event)"
|
||||
>
|
||||
</abp-pagination-controls>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Component, Injector } from '@angular/core';
|
||||
import { ChangeDetectorRef, Component, Injector } from '@angular/core';
|
||||
import { finalize } from 'rxjs/operators';
|
||||
import { BsModalService, BsModalRef } from 'ngx-bootstrap/modal';
|
||||
import { appModuleAnimation } from '@shared/animations/routerTransition';
|
||||
|
@ -32,9 +32,10 @@ export class TenantsComponent extends PagedListingComponentBase<TenantDto> {
|
|||
constructor(
|
||||
injector: Injector,
|
||||
private _tenantService: TenantServiceProxy,
|
||||
private _modalService: BsModalService
|
||||
private _modalService: BsModalService,
|
||||
cd: ChangeDetectorRef
|
||||
) {
|
||||
super(injector);
|
||||
super(injector, cd);
|
||||
}
|
||||
|
||||
list(
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
autocomplete="off"
|
||||
#createUserModal="ngForm"
|
||||
(ngSubmit)="save()"
|
||||
>
|
||||
>
|
||||
<abp-modal-header
|
||||
[title]="'CreateNewUser' | localize"
|
||||
(onCloseClick)="bsModalRef.hide()"
|
||||
|
@ -26,175 +26,175 @@
|
|||
[(ngModel)]="user.name"
|
||||
#nameModel="ngModel"
|
||||
#nameEl
|
||||
/>
|
||||
<abp-validation-summary
|
||||
[control]="nameModel"
|
||||
[controlEl]="nameEl"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row required">
|
||||
<label class="col-md-3 col-form-label" for="surname">
|
||||
{{ "Surname" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="surname"
|
||||
id="surname"
|
||||
required
|
||||
maxlength="32"
|
||||
[(ngModel)]="user.surname"
|
||||
#surnameModel="ngModel"
|
||||
#surnameEl
|
||||
/>
|
||||
<abp-validation-summary
|
||||
[control]="surnameModel"
|
||||
[controlEl]="surnameEl"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row required">
|
||||
<label class="col-md-3 col-form-label" for="userName">
|
||||
{{ "UserName" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="userName"
|
||||
id="userName"
|
||||
required
|
||||
minlength="2"
|
||||
maxlength="32"
|
||||
[(ngModel)]="user.userName"
|
||||
#userNameModel="ngModel"
|
||||
#userNameEl
|
||||
/>
|
||||
<abp-validation-summary
|
||||
[control]="userNameModel"
|
||||
[controlEl]="userNameEl"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row required">
|
||||
<label class="col-md-3 col-form-label" for="password">
|
||||
{{ "Password" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<input
|
||||
type="password"
|
||||
class="form-control"
|
||||
name="password"
|
||||
id="password"
|
||||
required
|
||||
maxlength="32"
|
||||
validateEqual="confirmPassword"
|
||||
reverse="true"
|
||||
pattern="(?=^.{8,}$)(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?!.*\s)[0-9a-zA-Z!@#$%^&*()]*$"
|
||||
[(ngModel)]="user.password"
|
||||
#passwordModel="ngModel"
|
||||
#passwordEl
|
||||
/>
|
||||
<abp-validation-summary
|
||||
[control]="passwordModel"
|
||||
[controlEl]="passwordEl"
|
||||
[customValidationErrors]="passwordValidationErrors"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row required">
|
||||
<label class="col-md-3 col-form-label" for="confirmPassword">
|
||||
{{ "ConfirmPassword" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<input
|
||||
type="password"
|
||||
class="form-control"
|
||||
name="confirmPassword"
|
||||
id="confirmPassword"
|
||||
required
|
||||
maxlength="32"
|
||||
validateEqual="password"
|
||||
reverse="false"
|
||||
ngModel
|
||||
#confirmPasswordModel="ngModel"
|
||||
#confirmPasswordEl
|
||||
/>
|
||||
<abp-validation-summary
|
||||
[control]="confirmPasswordModel"
|
||||
[controlEl]="confirmPasswordEl"
|
||||
[customValidationErrors]="confirmPasswordValidationErrors"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row required">
|
||||
<label class="col-md-3 col-form-label" for="emailAddress">
|
||||
{{ "EmailAddress" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<input
|
||||
type="email"
|
||||
class="form-control"
|
||||
name="emailAddress"
|
||||
id="emailAddress"
|
||||
required
|
||||
maxlength="256"
|
||||
pattern="^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{1,})+$"
|
||||
[(ngModel)]="user.emailAddress"
|
||||
#emailAddressModel="ngModel"
|
||||
#emailAddressEl
|
||||
/>
|
||||
<abp-validation-summary
|
||||
[control]="emailAddressModel"
|
||||
[controlEl]="emailAddressEl"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row mb-0">
|
||||
<label class="col-md-3 col-form-label">
|
||||
{{ "IsActive" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="custom-control-input"
|
||||
name="isActive"
|
||||
id="isActive"
|
||||
[(ngModel)]="user.isActive"
|
||||
/>
|
||||
<label class="custom-control-label mt-2" for="isActive"></label>
|
||||
<abp-validation-summary
|
||||
[control]="nameModel"
|
||||
[controlEl]="nameEl"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</tab>
|
||||
<tab [heading]="'UserRoles' | localize" class="pt-3 px-2">
|
||||
<div class="form-group row mb-0">
|
||||
<ng-container *ngFor="let role of roles; let i = index">
|
||||
<div class="col-md-6">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="custom-control-input"
|
||||
[id]="'role_' + i"
|
||||
[checked]="isRoleChecked(role.normalizedName)"
|
||||
(change)="onRoleChange(role, $event)"
|
||||
<div class="form-group row required">
|
||||
<label class="col-md-3 col-form-label" for="surname">
|
||||
{{ "Surname" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="surname"
|
||||
id="surname"
|
||||
required
|
||||
maxlength="32"
|
||||
[(ngModel)]="user.surname"
|
||||
#surnameModel="ngModel"
|
||||
#surnameEl
|
||||
/>
|
||||
<label class="custom-control-label" [for]="'role_' + i">
|
||||
{{ role.name }}
|
||||
</label>
|
||||
<abp-validation-summary
|
||||
[control]="surnameModel"
|
||||
[controlEl]="surnameEl"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</tab>
|
||||
</tabset>
|
||||
</div>
|
||||
<abp-modal-footer
|
||||
[cancelDisabled]="saving"
|
||||
[saveDisabled]="!createUserModal.form.valid || saving"
|
||||
(onCancelClick)="bsModalRef.hide()"
|
||||
></abp-modal-footer>
|
||||
</form>
|
||||
<div class="form-group row required">
|
||||
<label class="col-md-3 col-form-label" for="userName">
|
||||
{{ "UserName" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="userName"
|
||||
id="userName"
|
||||
required
|
||||
minlength="2"
|
||||
maxlength="32"
|
||||
[(ngModel)]="user.userName"
|
||||
#userNameModel="ngModel"
|
||||
#userNameEl
|
||||
/>
|
||||
<abp-validation-summary
|
||||
[control]="userNameModel"
|
||||
[controlEl]="userNameEl"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row required">
|
||||
<label class="col-md-3 col-form-label" for="password">
|
||||
{{ "Password" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<input
|
||||
type="password"
|
||||
class="form-control"
|
||||
name="password"
|
||||
id="password"
|
||||
required
|
||||
maxlength="32"
|
||||
validateEqual="confirmPassword"
|
||||
reverse="true"
|
||||
pattern="(?=^.{8,}$)(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?!.*\s)[0-9a-zA-Z!@#$%^&*()]*$"
|
||||
[(ngModel)]="user.password"
|
||||
#passwordModel="ngModel"
|
||||
#passwordEl
|
||||
/>
|
||||
<abp-validation-summary
|
||||
[control]="passwordModel"
|
||||
[controlEl]="passwordEl"
|
||||
[customValidationErrors]="passwordValidationErrors"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row required">
|
||||
<label class="col-md-3 col-form-label" for="confirmPassword">
|
||||
{{ "ConfirmPassword" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<input
|
||||
type="password"
|
||||
class="form-control"
|
||||
name="confirmPassword"
|
||||
id="confirmPassword"
|
||||
required
|
||||
maxlength="32"
|
||||
validateEqual="password"
|
||||
reverse="false"
|
||||
ngModel
|
||||
#confirmPasswordModel="ngModel"
|
||||
#confirmPasswordEl
|
||||
/>
|
||||
<abp-validation-summary
|
||||
[control]="confirmPasswordModel"
|
||||
[controlEl]="confirmPasswordEl"
|
||||
[customValidationErrors]="confirmPasswordValidationErrors"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row required">
|
||||
<label class="col-md-3 col-form-label" for="emailAddress">
|
||||
{{ "EmailAddress" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<input
|
||||
type="email"
|
||||
class="form-control"
|
||||
name="emailAddress"
|
||||
id="emailAddress"
|
||||
required
|
||||
maxlength="256"
|
||||
pattern="^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{1,})+$"
|
||||
[(ngModel)]="user.emailAddress"
|
||||
#emailAddressModel="ngModel"
|
||||
#emailAddressEl
|
||||
/>
|
||||
<abp-validation-summary
|
||||
[control]="emailAddressModel"
|
||||
[controlEl]="emailAddressEl"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row mb-0">
|
||||
<label class="col-md-3 col-form-label">
|
||||
{{ "IsActive" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="custom-control-input"
|
||||
name="isActive"
|
||||
id="isActive"
|
||||
[(ngModel)]="user.isActive"
|
||||
/>
|
||||
<label class="custom-control-label mt-2" for="isActive"></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</tab>
|
||||
<tab [heading]="'UserRoles' | localize" class="pt-3 px-2">
|
||||
<div class="form-group row mb-0">
|
||||
@for (role of roles; track role; let i = $index) {
|
||||
<div class="col-md-6">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="custom-control-input"
|
||||
[id]="'role_' + i"
|
||||
[checked]="isRoleChecked(role.normalizedName)"
|
||||
(change)="onRoleChange(role, $event)"
|
||||
/>
|
||||
<label class="custom-control-label" [for]="'role_' + i">
|
||||
{{ role.name }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</tab>
|
||||
</tabset>
|
||||
</div>
|
||||
<abp-modal-footer
|
||||
[cancelDisabled]="saving"
|
||||
[saveDisabled]="!createUserModal.form.valid || saving"
|
||||
(onCancelClick)="bsModalRef.hide()"
|
||||
></abp-modal-footer>
|
||||
</form>
|
||||
|
|
|
@ -3,7 +3,8 @@ import {
|
|||
Injector,
|
||||
OnInit,
|
||||
EventEmitter,
|
||||
Output
|
||||
Output,
|
||||
ChangeDetectorRef
|
||||
} from '@angular/core';
|
||||
import { BsModalRef } from 'ngx-bootstrap/modal';
|
||||
import { forEach as _forEach, map as _map } from 'lodash-es';
|
||||
|
@ -44,7 +45,8 @@ export class CreateUserDialogComponent extends AppComponentBase
|
|||
constructor(
|
||||
injector: Injector,
|
||||
public _userService: UserServiceProxy,
|
||||
public bsModalRef: BsModalRef
|
||||
public bsModalRef: BsModalRef,
|
||||
private cd: ChangeDetectorRef
|
||||
) {
|
||||
super(injector);
|
||||
}
|
||||
|
@ -55,6 +57,7 @@ export class CreateUserDialogComponent extends AppComponentBase
|
|||
this._userService.getRoles().subscribe((result) => {
|
||||
this.roles = result.items;
|
||||
this.setInitialRolesStatus();
|
||||
this.cd.detectChanges();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
autocomplete="off"
|
||||
#editUserModal="ngForm"
|
||||
(ngSubmit)="save()"
|
||||
>
|
||||
>
|
||||
<abp-modal-header
|
||||
[title]="'EditUser' | localize"
|
||||
(onCloseClick)="bsModalRef.hide()"
|
||||
|
@ -26,124 +26,124 @@
|
|||
[(ngModel)]="user.name"
|
||||
#nameModel="ngModel"
|
||||
#nameEl
|
||||
/>
|
||||
<abp-validation-summary
|
||||
[control]="nameModel"
|
||||
[controlEl]="nameEl"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row required">
|
||||
<label class="col-md-3 col-form-label" for="surname">
|
||||
{{ "Surname" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="surname"
|
||||
id="surname"
|
||||
required
|
||||
maxlength="32"
|
||||
[(ngModel)]="user.surname"
|
||||
#surnameModel="ngModel"
|
||||
#surnameEl
|
||||
/>
|
||||
<abp-validation-summary
|
||||
[control]="surnameModel"
|
||||
[controlEl]="surnameEl"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row required">
|
||||
<label class="col-md-3 col-form-label" for="userName">
|
||||
{{ "UserName" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="userName"
|
||||
id="userName"
|
||||
required
|
||||
minlength="2"
|
||||
maxlength="32"
|
||||
[(ngModel)]="user.userName"
|
||||
#userNameModel="ngModel"
|
||||
#userNameEl
|
||||
/>
|
||||
<abp-validation-summary
|
||||
[control]="userNameModel"
|
||||
[controlEl]="userNameEl"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row required">
|
||||
<label class="col-md-3 col-form-label" for="emailAddress">
|
||||
{{ "EmailAddress" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<input
|
||||
type="email"
|
||||
class="form-control"
|
||||
name="emailAddress"
|
||||
id="emailAddress"
|
||||
required
|
||||
maxlength="256"
|
||||
pattern="^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{1,})+$"
|
||||
[(ngModel)]="user.emailAddress"
|
||||
#emailAddressModel="ngModel"
|
||||
#emailAddressEl
|
||||
/>
|
||||
<abp-validation-summary
|
||||
[control]="emailAddressModel"
|
||||
[controlEl]="emailAddressEl"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row mb-0">
|
||||
<label class="col-md-3 col-form-label">
|
||||
{{ "IsActive" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="custom-control-input"
|
||||
name="isActive"
|
||||
id="isActive"
|
||||
[(ngModel)]="user.isActive"
|
||||
/>
|
||||
<label class="custom-control-label mt-2" for="isActive"></label>
|
||||
<abp-validation-summary
|
||||
[control]="nameModel"
|
||||
[controlEl]="nameEl"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</tab>
|
||||
<tab [heading]="'UserRoles' | localize" class="pt-3 px-2">
|
||||
<div class="form-group row mb-0">
|
||||
<ng-container *ngFor="let role of roles; let i = index">
|
||||
<div class="col-md-6">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="custom-control-input"
|
||||
[id]="'role_' + i"
|
||||
[checked]="isRoleChecked(role.normalizedName)"
|
||||
(change)="onRoleChange(role, $event)"
|
||||
<div class="form-group row required">
|
||||
<label class="col-md-3 col-form-label" for="surname">
|
||||
{{ "Surname" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="surname"
|
||||
id="surname"
|
||||
required
|
||||
maxlength="32"
|
||||
[(ngModel)]="user.surname"
|
||||
#surnameModel="ngModel"
|
||||
#surnameEl
|
||||
/>
|
||||
<label class="custom-control-label" [for]="'role_' + i">
|
||||
{{ role.name }}
|
||||
</label>
|
||||
<abp-validation-summary
|
||||
[control]="surnameModel"
|
||||
[controlEl]="surnameEl"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</tab>
|
||||
</tabset>
|
||||
</div>
|
||||
<abp-modal-footer
|
||||
[cancelDisabled]="saving"
|
||||
[saveDisabled]="!editUserModal.form.valid || saving"
|
||||
(onCancelClick)="bsModalRef.hide()"
|
||||
></abp-modal-footer>
|
||||
</form>
|
||||
<div class="form-group row required">
|
||||
<label class="col-md-3 col-form-label" for="userName">
|
||||
{{ "UserName" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="userName"
|
||||
id="userName"
|
||||
required
|
||||
minlength="2"
|
||||
maxlength="32"
|
||||
[(ngModel)]="user.userName"
|
||||
#userNameModel="ngModel"
|
||||
#userNameEl
|
||||
/>
|
||||
<abp-validation-summary
|
||||
[control]="userNameModel"
|
||||
[controlEl]="userNameEl"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row required">
|
||||
<label class="col-md-3 col-form-label" for="emailAddress">
|
||||
{{ "EmailAddress" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<input
|
||||
type="email"
|
||||
class="form-control"
|
||||
name="emailAddress"
|
||||
id="emailAddress"
|
||||
required
|
||||
maxlength="256"
|
||||
pattern="^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{1,})+$"
|
||||
[(ngModel)]="user.emailAddress"
|
||||
#emailAddressModel="ngModel"
|
||||
#emailAddressEl
|
||||
/>
|
||||
<abp-validation-summary
|
||||
[control]="emailAddressModel"
|
||||
[controlEl]="emailAddressEl"
|
||||
></abp-validation-summary>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row mb-0">
|
||||
<label class="col-md-3 col-form-label">
|
||||
{{ "IsActive" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="custom-control-input"
|
||||
name="isActive"
|
||||
id="isActive"
|
||||
[(ngModel)]="user.isActive"
|
||||
/>
|
||||
<label class="custom-control-label mt-2" for="isActive"></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</tab>
|
||||
<tab [heading]="'UserRoles' | localize" class="pt-3 px-2">
|
||||
<div class="form-group row mb-0">
|
||||
@for (role of roles; track role; let i = $index) {
|
||||
<div class="col-md-6">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="custom-control-input"
|
||||
[id]="'role_' + i"
|
||||
[checked]="isRoleChecked(role.normalizedName)"
|
||||
(change)="onRoleChange(role, $event)"
|
||||
/>
|
||||
<label class="custom-control-label" [for]="'role_' + i">
|
||||
{{ role.name }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</tab>
|
||||
</tabset>
|
||||
</div>
|
||||
<abp-modal-footer
|
||||
[cancelDisabled]="saving"
|
||||
[saveDisabled]="!editUserModal.form.valid || saving"
|
||||
(onCancelClick)="bsModalRef.hide()"
|
||||
></abp-modal-footer>
|
||||
</form>
|
||||
|
|
|
@ -3,7 +3,8 @@ import {
|
|||
Injector,
|
||||
OnInit,
|
||||
EventEmitter,
|
||||
Output
|
||||
Output,
|
||||
ChangeDetectorRef
|
||||
} from '@angular/core';
|
||||
import { BsModalRef } from 'ngx-bootstrap/modal';
|
||||
import { forEach as _forEach, includes as _includes, map as _map } from 'lodash-es';
|
||||
|
@ -30,7 +31,8 @@ export class EditUserDialogComponent extends AppComponentBase
|
|||
constructor(
|
||||
injector: Injector,
|
||||
public _userService: UserServiceProxy,
|
||||
public bsModalRef: BsModalRef
|
||||
public bsModalRef: BsModalRef,
|
||||
private cd: ChangeDetectorRef
|
||||
) {
|
||||
super(injector);
|
||||
}
|
||||
|
@ -42,6 +44,7 @@ export class EditUserDialogComponent extends AppComponentBase
|
|||
this._userService.getRoles().subscribe((result2) => {
|
||||
this.roles = result2.items;
|
||||
this.setInitialRolesStatus();
|
||||
this.cd.detectChanges();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,234 +1,238 @@
|
|||
<div [@routerTransition]>
|
||||
<section class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<h1>{{ "Users" | localize }}</h1>
|
||||
</div>
|
||||
<div class="col-6 text-right">
|
||||
<a href="javascript:;" class="btn bg-blue" (click)="createUser()">
|
||||
<i class="fa fa-plus-square"></i>
|
||||
{{ "Create" | localize }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<section class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<h1>{{ "Users" | localize }}</h1>
|
||||
</div>
|
||||
</section>
|
||||
<section class="content px-2">
|
||||
<div class="container-fluid">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="col-6 text-right">
|
||||
<a href="javascript:;" class="btn bg-blue" (click)="createUser()">
|
||||
<i class="fa fa-plus-square"></i>
|
||||
{{ "Create" | localize }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="content px-2">
|
||||
<div class="container-fluid">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="row">
|
||||
<div class="col-md-6"> </div>
|
||||
<div class="col-md-6">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<button
|
||||
type="button"
|
||||
class="btn bg-blue"
|
||||
(click)="getDataPage(1)"
|
||||
>
|
||||
<i class="fas fa-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="keyword"
|
||||
[placeholder]="'SearchWithThreeDot' | localize"
|
||||
[(ngModel)]="keyword"
|
||||
(keyup.enter)="getDataPage(1)"
|
||||
/>
|
||||
<div class="input-group-append">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-default"
|
||||
(click)="advancedFiltersVisible = !advancedFiltersVisible"
|
||||
>
|
||||
<i
|
||||
class="fas"
|
||||
[class.fa-angle-up]="advancedFiltersVisible"
|
||||
[class.fa-angle-down]="!advancedFiltersVisible"
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@if (advancedFiltersVisible) {
|
||||
<div class="card mb-0 mt-1">
|
||||
<div class="card-body">
|
||||
<form class="form-horizontal">
|
||||
<div class="row">
|
||||
<div class="col-md-6"> </div>
|
||||
<div class="col-md-6">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<button
|
||||
type="button"
|
||||
class="btn bg-blue"
|
||||
(click)="getDataPage(1)"
|
||||
>
|
||||
<i class="fas fa-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
name="keyword"
|
||||
[placeholder]="'SearchWithThreeDot' | localize"
|
||||
[(ngModel)]="keyword"
|
||||
(keyup.enter)="getDataPage(1)"
|
||||
<div class="col-md-6">
|
||||
<div class="form-group row mb-0">
|
||||
<label class="col-md-3 col-form-label">
|
||||
{{ "IsActive" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9 pt-2">
|
||||
<div class="custom-control custom-radio d-inline">
|
||||
<input
|
||||
type="radio"
|
||||
class="custom-control-input"
|
||||
id="isActiveAll"
|
||||
name="isActive"
|
||||
[(ngModel)]="isActive"
|
||||
[value]="undefined"
|
||||
checked
|
||||
/>
|
||||
<div class="input-group-append">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-default"
|
||||
(click)="advancedFiltersVisible = !advancedFiltersVisible"
|
||||
<label class="custom-control-label" for="isActiveAll">
|
||||
{{ "All" | localize }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="custom-control custom-radio d-inline mx-3">
|
||||
<input
|
||||
type="radio"
|
||||
class="custom-control-input"
|
||||
id="isActiveActive"
|
||||
name="isActive"
|
||||
[(ngModel)]="isActive"
|
||||
[value]="true"
|
||||
/>
|
||||
<label
|
||||
class="custom-control-label"
|
||||
for="isActiveActive"
|
||||
>
|
||||
<i
|
||||
class="fas"
|
||||
[class.fa-angle-up]="advancedFiltersVisible"
|
||||
[class.fa-angle-down]="!advancedFiltersVisible"
|
||||
></i>
|
||||
</button>
|
||||
{{ "Yes" | localize }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="custom-control custom-radio d-inline">
|
||||
<input
|
||||
type="radio"
|
||||
class="custom-control-input"
|
||||
id="isActivePassive"
|
||||
name="isActive"
|
||||
[(ngModel)]="isActive"
|
||||
[value]="false"
|
||||
/>
|
||||
<label
|
||||
class="custom-control-label"
|
||||
for="isActivePassive"
|
||||
>
|
||||
{{ "No" | localize }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="advancedFiltersVisible" class="card mb-0 mt-1">
|
||||
<div class="card-body">
|
||||
<form class="form-horizontal">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group row mb-0">
|
||||
<label class="col-md-3 col-form-label">
|
||||
{{ "IsActive" | localize }}
|
||||
</label>
|
||||
<div class="col-md-9 pt-2">
|
||||
<div class="custom-control custom-radio d-inline">
|
||||
<input
|
||||
type="radio"
|
||||
class="custom-control-input"
|
||||
id="isActiveAll"
|
||||
name="isActive"
|
||||
[(ngModel)]="isActive"
|
||||
[value]="undefined"
|
||||
checked
|
||||
/>
|
||||
<label class="custom-control-label" for="isActiveAll">
|
||||
{{ "All" | localize }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="custom-control custom-radio d-inline mx-3">
|
||||
<input
|
||||
type="radio"
|
||||
class="custom-control-input"
|
||||
id="isActiveActive"
|
||||
name="isActive"
|
||||
[(ngModel)]="isActive"
|
||||
[value]="true"
|
||||
/>
|
||||
<label
|
||||
class="custom-control-label"
|
||||
for="isActiveActive"
|
||||
>
|
||||
{{ "Yes" | localize }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="custom-control custom-radio d-inline">
|
||||
<input
|
||||
type="radio"
|
||||
class="custom-control-input"
|
||||
id="isActivePassive"
|
||||
name="isActive"
|
||||
[(ngModel)]="isActive"
|
||||
[value]="false"
|
||||
/>
|
||||
<label
|
||||
class="custom-control-label"
|
||||
for="isActivePassive"
|
||||
>
|
||||
{{ "No" | localize }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="btn bg-blue"
|
||||
(click)="getDataPage(1)"
|
||||
>
|
||||
{{ "Search" | localize }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-default float-right"
|
||||
(click)="clearFilters()"
|
||||
>
|
||||
{{ "Clear" | localize }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="btn bg-blue"
|
||||
(click)="getDataPage(1)"
|
||||
>
|
||||
{{ "Search" | localize }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-default float-right"
|
||||
(click)="clearFilters()"
|
||||
>
|
||||
{{ "Clear" | localize }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-bordered" [busy]="isTableLoading">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th>{{ "UserName" | localize }}</th>
|
||||
<th>{{ "FullName" | localize }}</th>
|
||||
<th>{{ "EmailAddress" | localize }}</th>
|
||||
<th>{{ "IsActive" | localize }}</th>
|
||||
<th style="width: 310px;">{{ "Actions" | localize }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
*ngFor="
|
||||
let user of users
|
||||
| paginate
|
||||
: {
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-bordered" [busy]="isTableLoading">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th>{{ "UserName" | localize }}</th>
|
||||
<th>{{ "FullName" | localize }}</th>
|
||||
<th>{{ "EmailAddress" | localize }}</th>
|
||||
<th>{{ "IsActive" | localize }}</th>
|
||||
<th style="width: 310px;">{{ "Actions" | localize }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@for (
|
||||
user of users
|
||||
| paginate
|
||||
: {
|
||||
id: 'server',
|
||||
itemsPerPage: pageSize,
|
||||
currentPage: pageNumber,
|
||||
totalItems: totalItems
|
||||
}
|
||||
"
|
||||
>
|
||||
<td>{{ user.userName }}</td>
|
||||
<td>{{ user.fullName }}</td>
|
||||
<td>{{ user.emailAddress }}</td>
|
||||
<td>
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="custom-control-input"
|
||||
disabled
|
||||
[checked]="user.isActive"
|
||||
/>
|
||||
<label class="custom-control-label"></label>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm bg-secondary"
|
||||
(click)="editUser(user)"
|
||||
>
|
||||
<i class="fas fa-pencil-alt"></i>
|
||||
{{ "Edit" | localize }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm bg-danger mx-2"
|
||||
(click)="delete(user)"
|
||||
>
|
||||
<i class="fas fa-trash"></i>
|
||||
{{ "Delete" | localize }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm bg-secondary"
|
||||
(click)="resetPassword(user)"
|
||||
>
|
||||
<i class="fas fa-lock"></i>
|
||||
{{ "ResetPassword" | localize }}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
; track
|
||||
user.id) {
|
||||
<tr
|
||||
>
|
||||
<td>{{ user.userName }}</td>
|
||||
<td>{{ user.fullName }}</td>
|
||||
<td>{{ user.emailAddress }}</td>
|
||||
<td>
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="custom-control-input"
|
||||
disabled
|
||||
[checked]="user.isActive"
|
||||
/>
|
||||
<label class="custom-control-label"></label>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm bg-secondary"
|
||||
(click)="editUser(user)"
|
||||
>
|
||||
<i class="fas fa-pencil-alt"></i>
|
||||
{{ "Edit" | localize }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm bg-danger mx-2"
|
||||
(click)="delete(user)"
|
||||
>
|
||||
<i class="fas fa-trash"></i>
|
||||
{{ "Delete" | localize }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm bg-secondary"
|
||||
(click)="resetPassword(user)"
|
||||
>
|
||||
<i class="fas fa-lock"></i>
|
||||
{{ "ResetPassword" | localize }}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer table-card-footer bg-light border-top">
|
||||
<div class="row">
|
||||
<div class="col-sm-4 col-12 text-sm-left text-center">
|
||||
<button class="btn btn-secondary" (click)="refresh()">
|
||||
<i class="fas fa-redo-alt"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-sm-4 col-12 text-center">
|
||||
<p class="mb-0 my-2">
|
||||
{{ "TotalRecordsCount" | localize: totalItems }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-sm-4 col-12">
|
||||
<div class="float-sm-right m-auto">
|
||||
<abp-pagination-controls
|
||||
id="server"
|
||||
(pageChange)="getDataPage($event)"
|
||||
>
|
||||
</abp-pagination-controls>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-4 col-12 text-sm-left text-center">
|
||||
<button class="btn btn-secondary" (click)="refresh()">
|
||||
<i class="fas fa-redo-alt"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-sm-4 col-12 text-center">
|
||||
<p class="mb-0 my-2">
|
||||
{{ "TotalRecordsCount" | localize: totalItems }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-sm-4 col-12">
|
||||
<div class="float-sm-right m-auto">
|
||||
<abp-pagination-controls
|
||||
id="server"
|
||||
(pageChange)="getDataPage($event)"
|
||||
>
|
||||
</abp-pagination-controls>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Component, Injector } from '@angular/core';
|
||||
import { ChangeDetectorRef, Component, Injector } from '@angular/core';
|
||||
import { finalize } from 'rxjs/operators';
|
||||
import { BsModalService, BsModalRef } from 'ngx-bootstrap/modal';
|
||||
import { appModuleAnimation } from '@shared/animations/routerTransition';
|
||||
|
@ -33,9 +33,10 @@ export class UsersComponent extends PagedListingComponentBase<UserDto> {
|
|||
constructor(
|
||||
injector: Injector,
|
||||
private _userService: UserServiceProxy,
|
||||
private _modalService: BsModalService
|
||||
private _modalService: BsModalService,
|
||||
cd: ChangeDetectorRef
|
||||
) {
|
||||
super(injector);
|
||||
super(injector, cd);
|
||||
}
|
||||
|
||||
createUser(): void {
|
||||
|
|
|
@ -12,7 +12,7 @@ if (environment.production) {
|
|||
}
|
||||
|
||||
const bootstrap = () => {
|
||||
return platformBrowserDynamic().bootstrapModule(RootModule);
|
||||
return platformBrowserDynamic().bootstrapModule(RootModule, {ngZone: 'noop'});
|
||||
};
|
||||
|
||||
/* "Hot Module Replacement" is enabled as described on
|
||||
|
|
|
@ -16,4 +16,3 @@ import 'core-js/es/string';
|
|||
import 'core-js/es/symbol';
|
||||
import 'core-js/es/reflect';
|
||||
import { finalize } from 'rxjs/operators';
|
||||
import 'zone.js';
|
|
@ -1,5 +1,5 @@
|
|||
import { NgModule, APP_INITIALIZER, LOCALE_ID } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule, APP_INITIALIZER, LOCALE_ID,provideExperimentalZonelessChangeDetection} from '@angular/core';
|
||||
import { BrowserModule, provideClientHydration } from '@angular/platform-browser';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||
|
||||
|
@ -43,6 +43,8 @@ export function getCurrentLanguage(): string {
|
|||
],
|
||||
declarations: [RootComponent],
|
||||
providers: [
|
||||
provideExperimentalZonelessChangeDetection(),
|
||||
provideClientHydration(),
|
||||
{ provide: HTTP_INTERCEPTORS, useClass: AbpHttpInterceptor, multi: true },
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
<button
|
||||
type="button"
|
||||
class="btn btn-default"
|
||||
[disabled]="cancelDisabled"
|
||||
(click)="onCancelClick.emit()"
|
||||
[disabled]="cancelDisabled()"
|
||||
(click)="onCancelClick.emit($event)"
|
||||
>
|
||||
{{ cancelLabel }}
|
||||
{{ cancelLabel() }}
|
||||
</button>
|
||||
<button type="submit" class="btn btn-primary" [disabled]="saveDisabled">
|
||||
{{ saveLabel }}
|
||||
<button type="submit" class="btn btn-primary" [disabled]="saveDisabled()">
|
||||
{{ saveLabel() }}
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {
|
||||
Component,
|
||||
Input,
|
||||
Output,
|
||||
input,
|
||||
output,
|
||||
EventEmitter,
|
||||
ChangeDetectionStrategy,
|
||||
Injector
|
||||
|
@ -14,12 +14,12 @@ import { AppComponentBase } from '@shared/app-component-base';
|
|||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class AbpModalFooterComponent extends AppComponentBase {
|
||||
@Input() cancelLabel = this.l('Cancel');
|
||||
@Input() cancelDisabled: boolean;
|
||||
@Input() saveLabel = this.l('Save');
|
||||
@Input() saveDisabled: boolean;
|
||||
cancelLabel = input(this.l('Cancel'));
|
||||
cancelDisabled= input<boolean>();
|
||||
saveLabel = input(this.l('Save'));
|
||||
saveDisabled = input<boolean>();
|
||||
|
||||
@Output() onCancelClick = new EventEmitter<number>();
|
||||
onCancelClick = output<EventEmitter<number>>();
|
||||
|
||||
constructor(injector: Injector) {
|
||||
super(injector);
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<div class="modal-header">
|
||||
<h4 class="modal-title">{{ title }}</h4>
|
||||
<h4 class="modal-title">{{ title() }}</h4>
|
||||
<button
|
||||
type="button"
|
||||
class="close"
|
||||
aria-label="Close"
|
||||
(click)="onCloseClick.emit()"
|
||||
(click)="onCloseClick.emit($event)"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {
|
||||
Component,
|
||||
Input,
|
||||
Output,
|
||||
input,
|
||||
output,
|
||||
EventEmitter,
|
||||
ChangeDetectionStrategy,
|
||||
Injector
|
||||
|
@ -14,9 +14,9 @@ import { AppComponentBase } from '@shared/app-component-base';
|
|||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class AbpModalHeaderComponent extends AppComponentBase {
|
||||
@Input() title: string;
|
||||
title = input<string>();
|
||||
|
||||
@Output() onCloseClick = new EventEmitter<number>();
|
||||
onCloseClick = output<EventEmitter<number>>();
|
||||
|
||||
constructor(injector: Injector) {
|
||||
super(injector);
|
||||
|
|
|
@ -3,57 +3,68 @@
|
|||
[id]="id"
|
||||
[maxSize]="maxSize"
|
||||
(pageChange)="pageChange.emit($event)"
|
||||
>
|
||||
>
|
||||
<nav>
|
||||
<ul *ngIf="!(autoHide && p.pages.length <= 1)" class="pagination m-0">
|
||||
<li
|
||||
*ngIf="directionLinks"
|
||||
class="page-item"
|
||||
[class.disabled]="p.isFirstPage()"
|
||||
>
|
||||
<a
|
||||
*ngIf="!p.isFirstPage()"
|
||||
class="page-link"
|
||||
href="javascript:;"
|
||||
(click)="p.previous()"
|
||||
>
|
||||
<i class="fas fa-chevron-left"></i>
|
||||
</a>
|
||||
<a *ngIf="p.isFirstPage()" class="page-link" href="javascript:;">
|
||||
<i class="fas fa-chevron-left"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
*ngFor="let page of p.pages"
|
||||
class="page-item"
|
||||
[class.active]="p.getCurrent() === page.value"
|
||||
[style.z-index]="p.getCurrent() === page.value ? '0' : ''"
|
||||
>
|
||||
<a
|
||||
class="page-link"
|
||||
href="javascript:;"
|
||||
(click)="p.setCurrent(page.value)"
|
||||
>
|
||||
{{ page.label }}
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
*ngIf="directionLinks"
|
||||
class="page-item"
|
||||
[class.disabled]="p.isLastPage()"
|
||||
>
|
||||
<a
|
||||
*ngIf="!p.isLastPage()"
|
||||
class="page-link"
|
||||
href="javascript:;"
|
||||
(click)="p.next()"
|
||||
>
|
||||
<i class="fas fa-chevron-right"></i>
|
||||
</a>
|
||||
<a *ngIf="p.isLastPage()" class="page-link" href="javascript:;">
|
||||
<i class="fas fa-chevron-right"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
@if (!(autoHide && p.pages.length <= 1)) {
|
||||
<ul class="pagination m-0">
|
||||
@if (directionLinks) {
|
||||
<li
|
||||
class="page-item"
|
||||
[class.disabled]="p.isFirstPage()"
|
||||
>
|
||||
@if (!p.isFirstPage()) {
|
||||
<a
|
||||
class="page-link"
|
||||
href="javascript:;"
|
||||
(click)="p.previous()"
|
||||
>
|
||||
<i class="fas fa-chevron-left"></i>
|
||||
</a>
|
||||
}
|
||||
@if (p.isFirstPage()) {
|
||||
<a class="page-link" href="javascript:;">
|
||||
<i class="fas fa-chevron-left"></i>
|
||||
</a>
|
||||
}
|
||||
</li>
|
||||
}
|
||||
@for (page of p.pages; track page.label) {
|
||||
<li
|
||||
class="page-item"
|
||||
[class.active]="p.getCurrent() === page.value"
|
||||
[style.z-index]="p.getCurrent() === page.value ? '0' : ''"
|
||||
>
|
||||
<a
|
||||
class="page-link"
|
||||
href="javascript:;"
|
||||
(click)="p.setCurrent(page.value)"
|
||||
>
|
||||
{{ page.label }}
|
||||
</a>
|
||||
</li>
|
||||
}
|
||||
@if (directionLinks) {
|
||||
<li
|
||||
class="page-item"
|
||||
[class.disabled]="p.isLastPage()"
|
||||
>
|
||||
@if (!p.isLastPage()) {
|
||||
<a
|
||||
class="page-link"
|
||||
href="javascript:;"
|
||||
(click)="p.next()"
|
||||
>
|
||||
<i class="fas fa-chevron-right"></i>
|
||||
</a>
|
||||
}
|
||||
@if (p.isLastPage()) {
|
||||
<a class="page-link" href="javascript:;">
|
||||
<i class="fas fa-chevron-right"></i>
|
||||
</a>
|
||||
}
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
</nav>
|
||||
</pagination-template>
|
||||
|
|
|
@ -5,7 +5,6 @@ import { Component, Input, Output, EventEmitter } from '@angular/core';
|
|||
templateUrl: './abp-pagination-controls.component.html'
|
||||
})
|
||||
export class AbpPaginationControlsComponent {
|
||||
|
||||
@Input() id: string;
|
||||
@Input() maxSize = 7;
|
||||
@Input() previousLabel = 'Previous';
|
||||
|
@ -13,7 +12,7 @@ export class AbpPaginationControlsComponent {
|
|||
@Input() screenReaderPaginationLabel = 'Pagination';
|
||||
@Input() screenReaderPageLabel = 'page';
|
||||
@Input() screenReaderCurrentLabel = `You're on page`;
|
||||
@Output() pageChange: EventEmitter<number> = new EventEmitter<number>();
|
||||
@Output() pageChange = new EventEmitter<number>();
|
||||
|
||||
private _directionLinks = true;
|
||||
private _autoHide = false;
|
||||
|
@ -25,6 +24,7 @@ export class AbpPaginationControlsComponent {
|
|||
set directionLinks(value: boolean) {
|
||||
this._directionLinks = !!value && <any>value !== 'false';
|
||||
}
|
||||
|
||||
@Input()
|
||||
get autoHide(): boolean {
|
||||
return this._autoHide;
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
<ng-container *ngIf="control.invalid && (control.dirty || control.touched)">
|
||||
<ng-container *ngFor="let validationError of validationErrors">
|
||||
<span
|
||||
*ngIf="!!this.control.errors[validationError.name]"
|
||||
class="error invalid-feedback"
|
||||
[class.d-block]="!!this.control.errors[validationError.name]"
|
||||
>
|
||||
{{ getValidationErrorMessage(validationError) }}
|
||||
</span>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
@if (control.invalid && (control.dirty || control.touched)) {
|
||||
@for (validationError of validationErrors; track validationError) {
|
||||
@if (!!this.control.errors[validationError.name]) {
|
||||
<span
|
||||
class="error invalid-feedback"
|
||||
[class.d-block]="!!this.control.errors[validationError.name]"
|
||||
>
|
||||
{{ getValidationErrorMessage(validationError) }}
|
||||
</span>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,6 @@ export class QueryStringTenantResolver {
|
|||
|
||||
resolve(appBaseUrl): string {
|
||||
let queryParams = UrlHelper.getQueryParameters();
|
||||
console.log('queryParams');
|
||||
console.log(queryParams);
|
||||
return queryParams['abp_tenancy_name'];
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { AppComponentBase } from 'shared/app-component-base';
|
||||
import { Component, Injector, OnInit } from '@angular/core';
|
||||
import { Component, Injector, OnInit, ChangeDetectorRef } from '@angular/core';
|
||||
|
||||
export class PagedResultDto {
|
||||
items: any[];
|
||||
|
@ -25,9 +25,14 @@ export abstract class PagedListingComponentBase<TEntityDto> extends AppComponent
|
|||
public totalPages = 1;
|
||||
public totalItems: number;
|
||||
public isTableLoading = false;
|
||||
protected cd: ChangeDetectorRef;
|
||||
|
||||
constructor(injector: Injector) {
|
||||
constructor(
|
||||
injector: Injector,
|
||||
cd: ChangeDetectorRef
|
||||
) {
|
||||
super(injector);
|
||||
this.cd = cd;
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
|
@ -53,6 +58,7 @@ export abstract class PagedListingComponentBase<TEntityDto> extends AppComponent
|
|||
this.isTableLoading = true;
|
||||
this.list(req, page, () => {
|
||||
this.isTableLoading = false;
|
||||
this.cd.detectChanges();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
||||
|
||||
import 'zone.js/dist/long-stack-trace-zone';
|
||||
import 'zone.js/dist/proxy.js';
|
||||
import 'zone.js/dist/sync-test';
|
||||
import 'zone.js/dist/jasmine-patch';
|
||||
import 'zone.js/dist/async-test';
|
||||
import 'zone.js/dist/fake-async-test';
|
||||
import { getTestBed } from '@angular/core/testing';
|
||||
import {
|
||||
BrowserDynamicTestingModule,
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Загрузка…
Ссылка в новой задаче