Merge branch 'dev' into blazor-ui

pull/5399/head
Halil İbrahim Kalkan 5 years ago
commit 6151e282eb

@ -19,7 +19,7 @@
"RoleDeletionConfirmationMessage": "角色 '{0}' 將被刪除. 你確定嗎?",
"DisplayName:RoleName": "角色名稱",
"DisplayName:UserName": "使用者名稱",
"DisplayName:Name": "名",
"DisplayName:Name": "名",
"DisplayName:Surname": "姓",
"DisplayName:Password": "密碼",
"DisplayName:Email": "電子信箱地址",
@ -61,11 +61,13 @@
"Volo.Abp.Identity:UserNameNotFound": "使用者 {0} 不存在.",
"Volo.Abp.Identity:UserNotInRole": "使用者不具有 '{0}' 角色.",
"Volo.Abp.Identity:PasswordConfirmationFailed": "密碼或確認密碼不一致.",
"Volo.Abp.Identity:010001": "您無法刪除自己的帳號!",
"Volo.Abp.Identity:010002": "一個使用者不能設定超過 {MaxUserMembershipCount} 個組織單位",
"Volo.Abp.Identity:010003": "外部登入的使用者不能改變密碼!",
"Volo.Abp.Identity:010004": "組織內單位內已包含名稱 {0}.同一層級組織,兩個單位不能有相同名稱",
"Volo.Abp.Identity:010005": "無法重命名靜態角色.",
"Volo.Abp.Identity:010006": "無法刪除靜態角色.",
"Volo.Abp.Identity:010004": "組織內單位內已包含名稱 {0}.同一層級組織,兩個單位不能有相同名稱",
"Identity.OrganizationUnit.MaxUserMembershipCount": "允許一個使用者至多可隸屬在幾個組織單位",
"Volo.Abp.Identity:010001": "您無法刪除自己的帳號!",
"Permission:IdentityManagement": "身份識別管理",
"Permission:RoleManagement": "角色管理",
"Permission:Create": "建立",
@ -73,6 +75,34 @@
"Permission:Delete": "刪除",
"Permission:ChangePermissions": "更改權限",
"Permission:UserManagement": "使用者管理",
"Permission:UserLookup": "使用者查詢"
"Permission:UserLookup": "使用者查詢",
"DisplayName:Abp.Identity.Password.RequiredLength": "長度需符合",
"DisplayName:Abp.Identity.Password.RequiredUniqueChars": "需最小特殊字元數",
"DisplayName:Abp.Identity.Password.RequireNonAlphanumeric": "需包含非數字字母",
"DisplayName:Abp.Identity.Password.RequireLowercase": "需小寫字元",
"DisplayName:Abp.Identity.Password.RequireUppercase": "需大寫字元",
"DisplayName:Abp.Identity.Password.RequireDigit": "需要數字",
"DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "允許新的使用者",
"DisplayName:Abp.Identity.Lockout.LockoutDuration": "被鎖定期間(秒)",
"DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "最大登入次數嘗試",
"DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "信箱需被確認",
"DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "允許使用者確認電話號碼",
"DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "電話號碼需認證",
"DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "允許使用者更新帳號名稱",
"DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "允許使用者更新信箱",
"Description:Abp.Identity.Password.RequiredLength": "密碼須符合最小長度.",
"Description:Abp.Identity.Password.RequiredUniqueChars": "密碼至少要包含特殊字元個數.",
"Description:Abp.Identity.Password.RequireNonAlphanumeric": "密碼須包含特殊字元.",
"Description:Abp.Identity.Password.RequireLowercase": "須包含小寫字母.",
"Description:Abp.Identity.Password.RequireUppercase": "須包含大寫字母.",
"Description:Abp.Identity.Password.RequireDigit": "密碼必須包含數字.",
"Description:Abp.Identity.Lockout.AllowedForNewUsers": "使用者是否會被鎖定.",
"Description:Abp.Identity.Lockout.LockoutDuration": "使用者被鎖定後的時間.",
"Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "當啟用鎖定功能,設定最大嘗試輸入次數,超過後就被鎖定.",
"Description:Abp.Identity.SignIn.RequireConfirmedEmail": "決定使用者是否需信箱驗證後才能登入.",
"Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "是否啟用電話認證.",
"Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "決定使用者是否需電話認證後才能登入.",
"Description:Abp.Identity.User.IsUserNameUpdateEnabled": "決定使用者是否能更新帳號.",
"Description:Abp.Identity.User.IsEmailUpdateEnabled": "決定使用者是否能更新信箱."
}
}

@ -22,5 +22,9 @@ export const environment = {
url: 'https://localhost:44305',
rootNamespace: 'MyCompanyName.MyProjectName',
},
AbpFeatureManagement: {
url: 'https://localhost:44305',
rootNamespace: 'Volo.Abp',
},
},
} as Config.Environment;

@ -1,10 +1,16 @@
import { FeatureManagement } from '../models';
/**
* @deprecated To be deleted in v4.0.
*/
export class GetFeatures {
static readonly type = '[FeatureManagement] Get Features';
constructor(public payload: FeatureManagement.Provider) {}
}
/**
* @deprecated To be deleted in v4.0.
*/
export class UpdateFeatures {
static readonly type = '[FeatureManagement] Update Features';
constructor(public payload: FeatureManagement.Provider & FeatureManagement.Features) {}

@ -1,35 +1,107 @@
<abp-modal size="md" [(visible)]="visible" [busy]="modalBusy">
<abp-modal size="lg" [(visible)]="visible" [busy]="modalBusy">
<ng-template #abpHeader>
<h3>{{ 'AbpFeatureManagement::Features' | abpLocalization }}</h3>
</ng-template>
<ng-template #abpBody>
<form *ngIf="form" (ngSubmit)="save()" [formGroup]="form" validateOnSubmit>
<div
class="row my-3"
*ngFor="let feature of features$ | async; let i = index"
[ngSwitch]="feature.valueType.name"
>
<div class="mr-2">{{ feature.displayName }}</div>
<div *ngSwitchCase="'ToggleStringValueType'">
<input type="checkbox" name="feature.name" [formControlName]="i" />
</div>
<div *ngSwitchCase="'FreeTextStringValueType'">
<input type="text" name="feature.name" [formControlName]="i" />
</div>
<div class="row">
<div class="col-md-4">
<ul
ngbNav
#nav="ngbNav"
[(activeId)]="selectedGroup"
class="nav-pills"
orientation="vertical"
>
<li *ngFor="let groupName of groups" [ngbNavItem]="groupName">
<a ngbNavLink>{{ groupName }}</a>
<ng-template ngbNavContent>
<h4>{{ selectedGroup }}</h4>
<hr class="mt-2 mb-3" />
<div
class="row my-3"
*ngFor="let feature of features[groupName]; let i = index; trackBy: track.by('id')"
[ngStyle]="feature.style"
[ngSwitch]="feature.valueType?.name"
(keyup.enter)="save()"
>
<div *ngSwitchCase="valueTypes.ToggleStringValueType">
<div class="custom-checkbox custom-control">
<input
class="custom-control-input"
type="checkbox"
[id]="feature.name"
[(ngModel)]="feature.value"
/>
<label class="custom-control-label" [htmlFor]="feature.name">{{
feature.displayName
}}</label>
<ng-container
*ngTemplateOutlet="descTmp; context: { $implicit: feature.description }"
></ng-container>
</div>
</div>
<div *ngSwitchCase="valueTypes.FreeTextStringValueType">
<div class="form-group mb-0">
<label [htmlFor]="feature.name">{{ feature.displayName }}</label>
<input
class="form-control"
type="text"
[id]="feature.name"
[(ngModel)]="feature.value"
/>
<ng-container
*ngTemplateOutlet="descTmp; context: { $implicit: feature.description }"
></ng-container>
</div>
</div>
<div *ngSwitchCase="valueTypes.SelectionStringValueType">
<div class="form-group mb-0">
<label [htmlFor]="feature.name">{{ feature.displayName }}</label>
<select class="form-control" [id]="feature.name" [(ngModel)]="feature.value">
<option [ngValue]=""></option>
<option
*ngFor="
let prop of feature.valueType.properties | keyvalue;
trackBy: track.by('key')
"
[ngValue]="prop.value"
>
{{ prop.key }}</option
>
</select>
<ng-container
*ngTemplateOutlet="descTmp; context: { $implicit: feature.description }"
></ng-container>
</div>
</div>
<div *ngSwitchDefault>{{ feature.displayName }}</div>
</div>
</ng-template>
</li>
</ul>
</div>
<div *ngIf="!(features$ | async)?.length">
<ng-template #descTmp let-description>
<small *ngIf="description" class="form-text text-muted">{{ description }}</small>
</ng-template>
<div class="col-md-8"><div [ngbNavOutlet]="nav"></div></div>
<div class="mx-3" *ngIf="!groups.length">
{{ 'AbpFeatureManagement::NoFeatureFoundMessage' | abpLocalization }}
</div>
</form>
</div>
</ng-template>
<ng-template #abpFooter>
<ng-container *ngIf="(features$ | async)?.length">
<ng-container *ngIf="groups.length">
<button #abpClose type="button" class="btn btn-secondary">
{{ 'AbpFeatureManagement::Cancel' | abpLocalization }}
</button>
<abp-button iconClass="fa fa-check" [disabled]="form?.invalid || modalBusy" (click)="save()">
<abp-button iconClass="fa fa-check" [disabled]="modalBusy" (click)="save()">
{{ 'AbpFeatureManagement::Save' | abpLocalization }}
</abp-button>
</ng-container>

@ -1,11 +1,15 @@
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
import { Select, Store } from '@ngxs/store';
import { Observable } from 'rxjs';
import { GetFeatures, UpdateFeatures } from '../../actions';
import { TrackByService } from '@abp/ng.core';
import { LocaleDirection } from '@abp/ng.theme.shared';
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { finalize } from 'rxjs/operators';
import { FeatureManagement } from '../../models/feature-management';
import { FeatureManagementState } from '../../states';
import { FormGroup, FormControl } from '@angular/forms';
import { pluck, finalize } from 'rxjs/operators';
import { FeatureDto, FeaturesService, UpdateFeatureDto } from '../../proxy/feature-management';
enum ValueTypes {
ToggleStringValueType = 'ToggleStringValueType',
FreeTextStringValueType = 'FreeTextStringValueType',
SelectionStringValueType = 'SelectionStringValueType',
}
@Component({
selector: 'abp-feature-management',
@ -22,6 +26,16 @@ export class FeatureManagementComponent
@Input()
providerName: string;
selectedGroup: string;
groups: string[] = [];
features: {
[group: string]: Array<FeatureDto & { style?: { [key: string]: number }; initialValue: any }>;
};
valueTypes = ValueTypes;
protected _visible;
@Input()
@ -30,78 +44,82 @@ export class FeatureManagementComponent
}
set visible(value: boolean) {
if (this._visible === value) return;
this._visible = value;
this.visibleChange.emit(value);
if (value) this.openModal();
}
@Output() readonly visibleChange = new EventEmitter<boolean>();
@Select(FeatureManagementState.getFeatures)
features$: Observable<FeatureManagement.Feature[]>;
modalBusy = false;
form: FormGroup;
constructor(private store: Store) {}
constructor(public readonly track: TrackByService, private service: FeaturesService) {}
openModal() {
if (!this.providerKey || !this.providerName) {
throw new Error('Provider Key and Provider Name are required.');
if (!this.providerName) {
throw new Error('providerName is required.');
}
this.getFeatures();
}
getFeatures() {
this.store
.dispatch(
new GetFeatures({
providerKey: this.providerKey,
providerName: this.providerName,
this.service.get(this.providerName, this.providerKey).subscribe(res => {
this.groups = res.groups.map(group => group.displayName);
this.selectedGroup = this.groups[0];
this.features = res.groups.reduce(
(acc, val) => ({
...acc,
[val.name]: mapFeatures(val.features, document.body.dir as LocaleDirection),
}),
)
.pipe(pluck('FeatureManagementState', 'features'))
.subscribe(features => {
this.buildForm(features);
});
}
buildForm(features) {
const formGroupObj = {};
for (let i = 0; i < features.length; i++) {
formGroupObj[i] = new FormControl(features[i].value === 'false' ? null : features[i].value);
}
this.form = new FormGroup(formGroupObj);
{},
);
});
}
save() {
if (this.modalBusy) return;
this.modalBusy = true;
const changedFeatures = [] as UpdateFeatureDto[];
let features = this.store.selectSnapshot(FeatureManagementState.getFeatures);
Object.keys(this.features).forEach(key => {
this.features[key].forEach(feature => {
if (feature.value !== feature.initialValue)
changedFeatures.push({ name: feature.name, value: feature.value });
});
});
features = features.map((feature, i) => ({
...feature,
value: this.form.value[i],
}));
this.store
.dispatch(
new UpdateFeatures({
providerKey: this.providerKey,
providerName: this.providerName,
features,
}),
)
if (!changedFeatures.length) {
this.visible = false;
return;
}
this.modalBusy = true;
this.service
.update(this.providerName, this.providerKey, { features: changedFeatures })
.pipe(finalize(() => (this.modalBusy = false)))
.subscribe(() => {
this.visible = false;
});
}
}
function mapFeatures(features: FeatureDto[], dir: LocaleDirection) {
const margin = `margin-${dir === 'rtl' ? 'right' : 'left'}.px`;
return features.map(feature => {
const value =
feature.valueType?.name === ValueTypes.ToggleStringValueType
? (feature.value || '').toLowerCase() === 'true'
: feature.value;
return {
...feature,
value,
initialValue: value,
style: { [margin]: feature.depth * 20 },
};
});
}

@ -4,10 +4,16 @@ import { NgModule } from '@angular/core';
import { FeatureManagementComponent } from './components/feature-management/feature-management.component';
import { NgxsModule } from '@ngxs/store';
import { FeatureManagementState } from './states/feature-management.state';
import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap';
@NgModule({
declarations: [FeatureManagementComponent],
imports: [CoreModule, ThemeSharedModule, NgxsModule.forFeature([FeatureManagementState])],
imports: [
CoreModule,
ThemeSharedModule,
NgbNavModule,
NgxsModule.forFeature([FeatureManagementState]),
],
exports: [FeatureManagementComponent],
})
export class FeatureManagementModule {}

@ -1,16 +1,25 @@
import { EventEmitter } from '@angular/core';
export namespace FeatureManagement {
/**
* @deprecated To be deleted in v4.0.
*/
export interface State {
features: Feature[];
}
/**
* @deprecated To be deleted in v4.0.
*/
export interface ValueType {
name: string;
properties: object;
validator: object;
}
/**
* @deprecated To be deleted in v4.0.
*/
export interface Feature {
name: string;
displayName: string;
@ -21,10 +30,16 @@ export namespace FeatureManagement {
parentName?: string;
}
/**
* @deprecated To be deleted in v4.0.
*/
export interface Features {
features: Feature[];
}
/**
* @deprecated To be deleted in v4.0.
*/
export interface Provider {
providerName: string;
providerKey: string;

@ -0,0 +1,13 @@
# Proxy Generation Output
This directory includes the output of the latest proxy generation.
The files and folders in it will be overwritten when proxy generation is run again.
Therefore, please do not place your own content in this folder.
In addition, `generate-proxy.json` works like a lock file.
It includes information used by the proxy generator, so please do not delete or modify it.
Finally, the name of the files and folders should not be changed for two reasons:
- Proxy generator will keep creating them at those paths and you will have multiple copies of the same content.
- ABP Suite generates files which include imports from this folder.

@ -0,0 +1,29 @@
import type { GetFeatureListResultDto, UpdateFeaturesDto } from './models';
import { RestService } from '@abp/ng.core';
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class FeaturesService {
apiName = 'AbpFeatureManagement';
get = (providerName: string, providerKey: string) =>
this.restService.request<any, GetFeatureListResultDto>({
method: 'GET',
url: '/api/feature-management/features',
params: { providerName, providerKey },
},
{ apiName: this.apiName });
update = (providerName: string, providerKey: string, input: UpdateFeaturesDto) =>
this.restService.request<any, void>({
method: 'PUT',
url: '/api/feature-management/features',
params: { providerName, providerKey },
body: input,
},
{ apiName: this.apiName });
constructor(private restService: RestService) {}
}

@ -0,0 +1,2 @@
export * from './features.service';
export * from './models';

@ -0,0 +1,36 @@
import type { IStringValueType } from '../validation/string-values/models';
export interface FeatureDto {
name: string;
displayName: string;
value: string;
provider: FeatureProviderDto;
description: string;
valueType: IStringValueType;
depth: number;
parentName: string;
}
export interface FeatureGroupDto {
name: string;
displayName: string;
features: FeatureDto[];
}
export interface FeatureProviderDto {
name: string;
key: string;
}
export interface GetFeatureListResultDto {
groups: FeatureGroupDto[];
}
export interface UpdateFeatureDto {
name: string;
value: string;
}
export interface UpdateFeaturesDto {
features: UpdateFeatureDto[];
}

@ -0,0 +1,2 @@
export * as FeatureManagement from './feature-management';
export * as Validation from './validation';

@ -0,0 +1 @@
export * as StringValues from './string-values';

@ -0,0 +1,13 @@
export interface IStringValueType {
name: string;
item: object;
properties: Record<string, object>;
validator: IValueValidator;
}
export interface IValueValidator {
name: string;
item: object;
properties: Record<string, object>;
}

@ -7,6 +7,9 @@ import { FeatureManagement } from '../models';
@Injectable({
providedIn: 'root',
})
/**
* @deprecated Use FeaturesService instead. To be deleted in v4.0.
*/
export class FeatureManagementService {
apiName = 'FeatureManagement';

@ -5,6 +5,9 @@ import { FeatureManagement } from '../models/feature-management';
import { FeatureManagementService } from '../services/feature-management.service';
import { Injectable } from '@angular/core';
/**
* @deprecated To be deleted in v4.0.
*/
@State<FeatureManagement.State>({
name: 'FeatureManagementState',
defaults: { features: {} } as FeatureManagement.State,
@ -21,7 +24,7 @@ export class FeatureManagementState {
@Action(GetFeatures)
getFeatures({ patchState }: StateContext<FeatureManagement.State>, { payload }: GetFeatures) {
return this.featureManagementService.getFeatures(payload).pipe(
tap(({ features }) =>
tap(({ features = [] }) =>
patchState({
features,
}),

@ -1,3 +1,5 @@
export * from './lib/feature-management.module';
export * from './lib/components';
export * from './lib/enums/components';
export * from './lib/proxy/feature-management';
export * from './lib/proxy/validation/string-values';

@ -1,17 +1,8 @@
{
"extends": "../../tslint.json",
"rules": {
"directive-selector": [
true,
"attribute",
"abp",
"camelCase"
],
"component-selector": [
true,
"element",
"abp",
"kebab-case"
]
"interface-name": false,
"directive-selector": [true, "attribute", "abp", "camelCase"],
"component-selector": [true, "element", "abp", "kebab-case"]
}
}

@ -5,6 +5,16 @@
<h5 class="card-title">{{ 'AbpTenantManagement::Tenants' | abpLocalization }}</h5>
</div>
<div class="text-right col col-md-6">
<button
*abpPermission="'FeatureManagement.ManageHostFeatures'"
id="manage-host-features"
class="btn btn-primary mr-1"
type="button"
(click)="openFeaturesModal(null)"
>
<i class="fa fa-plus mr-1"></i>
<span>{{ 'AbpTenantManagement::ManageHostFeatures' | abpLocalization }}</span>
</button>
<button
*abpPermission="'AbpTenantManagement.Tenants.Create'"
id="create-tenants"

File diff suppressed because it is too large Load Diff

@ -2,20 +2,20 @@
# yarn lockfile v1
"@abp/ng.account@~3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@abp/ng.account/-/ng.account-3.1.0.tgz#cd5fb46dffd7455188c10769220ed58806f455fa"
integrity sha512-/v+yyagHIUhjpJ1exzubf54XQBsgO2o3r3bFJFlWqzJoeCLufzyyppqK2UQ+6sQ7CjWP5jFCqo87R9myNn2xHA==
"@abp/ng.account@~3.1.2":
version "3.1.2"
resolved "https://registry.yarnpkg.com/@abp/ng.account/-/ng.account-3.1.2.tgz#42f95ad70f06586848737ad5e18461a193a51348"
integrity sha512-sFJPvak4pGbX0dDtVjBhY0slRRI0oTz8reJqcFfpUywPMJj2VsCz97W70xB33Yr/mQZDg6BjhXkrl15GdyWt2w==
dependencies:
"@abp/ng.theme.shared" "~3.1.0"
"@abp/ng.theme.shared" "~3.1.2"
tslib "^2.0.0"
"@abp/ng.core@~3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@abp/ng.core/-/ng.core-3.1.0.tgz#aba988fd915a633ea7af3a68278cc2557a37446f"
integrity sha512-SRRA7MYh12irJMRCj9emE5hyw+5aeiETlohP1CdgpdhhT3/RSPwrSeZNGJU0ilk6tKoO2rcZT6fgGjhqQfMyOw==
"@abp/ng.core@~3.1.2":
version "3.1.2"
resolved "https://registry.yarnpkg.com/@abp/ng.core/-/ng.core-3.1.2.tgz#edc2de8fa7332f4bd17ddeaee94c52aa8bb51fcc"
integrity sha512-ura5fD4ZIJhLD97WrSNILoFfwFqJJJOygeZuGpfslCbeNM1JEf4Jk4XQzfnk7u+xW7IgtBZXtisheIuY2taawA==
dependencies:
"@abp/utils" "^3.1.0-rc.4"
"@abp/utils" "^3.1.1"
"@angular/localize" "~10.0.10"
"@ngxs/router-plugin" "^3.6.2"
"@ngxs/storage-plugin" "^3.6.2"
@ -27,35 +27,35 @@
ts-toolbelt "6.15.4"
tslib "^2.0.0"
"@abp/ng.feature-management@~3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@abp/ng.feature-management/-/ng.feature-management-3.1.0.tgz#a93b0d63dc542e3880a1c79ac1e630b2db19b8bf"
integrity sha512-CayqVZ8XJQXsmz+IU+OchXK/vl01x6DHA/oTpvkW9HM2kYYJ8dmD940kjr5i3ZX6WF2Q4yTc+wLgZhGQt7eK9Q==
"@abp/ng.feature-management@~3.1.2":
version "3.1.2"
resolved "https://registry.yarnpkg.com/@abp/ng.feature-management/-/ng.feature-management-3.1.2.tgz#91269097f925bc0772c443d688f46070fce5def9"
integrity sha512-s59KNoOY2TWuume2iAzdKz9GBFVyj3q0BmhL7hW6IgyV96Zg9FP+UKYCXvPM8HtsLmXis3Zrv7TnJDAF+5VrHw==
dependencies:
"@abp/ng.theme.shared" "~3.1.0"
"@abp/ng.theme.shared" "~3.1.2"
tslib "^2.0.0"
"@abp/ng.identity@~3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@abp/ng.identity/-/ng.identity-3.1.0.tgz#d3086dd887c7ea2786e4c8620b3448333065053a"
integrity sha512-G4CToeEou4Zwr4NkpauwMKJme61lofd77PycWvFPVJ8Df6EctmxJc+u6NVgG7+ZjuFI+oTQrLwCEl3uPuznnpA==
"@abp/ng.identity@~3.1.2":
version "3.1.2"
resolved "https://registry.yarnpkg.com/@abp/ng.identity/-/ng.identity-3.1.2.tgz#6d039a6cbb431c61a8bf9d291c1e6bf2120e478e"
integrity sha512-p+NGSuSd6OPxDZQr7iOhUIWTkpzyGUcphy6iloDgXX9YoTdIoh03ZMMJMpR6UBmPYLjPpP4U/eUFVxi2DjdCzA==
dependencies:
"@abp/ng.permission-management" "~3.1.0"
"@abp/ng.theme.shared" "~3.1.0"
"@abp/ng.permission-management" "~3.1.2"
"@abp/ng.theme.shared" "~3.1.2"
tslib "^2.0.0"
"@abp/ng.permission-management@~3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@abp/ng.permission-management/-/ng.permission-management-3.1.0.tgz#c0a9a135699b7c8a329c0c9ac839cde06dce3db2"
integrity sha512-u3JwxK1vAlqC6YBVqnyP26FZqArrIQn94fZ/Vm6n9rjId7VaJbA0UrX9d2YAwKROKOpAnBNc5GA0A2gaWIO9rg==
"@abp/ng.permission-management@~3.1.2":
version "3.1.2"
resolved "https://registry.yarnpkg.com/@abp/ng.permission-management/-/ng.permission-management-3.1.2.tgz#bacc09d3e92262d111734e4ffc4344300b16f978"
integrity sha512-nqLo3VFNFeouU33qQHK0abbKCjSlT9VXJk0WYzsiS2Z7lENYqtImRCxqpHlB32ACIdMMUWbmo8OMvYzpt++kRg==
dependencies:
"@abp/ng.theme.shared" "~3.1.0"
"@abp/ng.theme.shared" "~3.1.2"
tslib "^2.0.0"
"@abp/ng.schematics@~3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@abp/ng.schematics/-/ng.schematics-3.1.0.tgz#ea7dd6d7dfd02425e7eff25c7e350614a4c0cad8"
integrity sha512-Vn0G6Wi+/JJ7vFgSkt5sRtdWBWdBQSncwH+kI2O1F0GvhJTrf1eDQ8XTk2yZiOD8oFLgt8mnJzTVzJbs3RqR+Q==
"@abp/ng.schematics@~3.1.2":
version "3.1.2"
resolved "https://registry.yarnpkg.com/@abp/ng.schematics/-/ng.schematics-3.1.2.tgz#37a634ada068967468e68def9110ead6960bf8a4"
integrity sha512-ULvkA/smLhErHLe6TdW0CzrortAf4Rjq/eshrMqS0A7EANzlw2TBpjZmn7kJSFawLTatDy9+GyQ8Cewc9H0VXA==
dependencies:
"@angular-devkit/core" "~10.0.3"
"@angular-devkit/schematics" "~10.0.3"
@ -63,37 +63,37 @@
jsonc-parser "^2.3.0"
typescript "~3.9.2"
"@abp/ng.setting-management@~3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@abp/ng.setting-management/-/ng.setting-management-3.1.0.tgz#eebb1c7bdfd75a04cba4c1f8d0f5cfc306a64f43"
integrity sha512-jPBn9vpDHqCDscyo445MWdCd/C0pR+WEnXPxCu7lCOs+ry1n16etoWuLAIfI2LtpI0+g8AgMyL3hacP0MPzpGg==
"@abp/ng.setting-management@~3.1.2":
version "3.1.2"
resolved "https://registry.yarnpkg.com/@abp/ng.setting-management/-/ng.setting-management-3.1.2.tgz#dda39e646e79e853b090c3f4af79181a65446af2"
integrity sha512-o01Z7abV0kL4wwsOcRJZp8btev+X0qHCHfLf4u0zAwTjtXc4LzTtlU2hHLT19U42UYZlFUJvENnmTAhLnCLAVw==
dependencies:
"@abp/ng.theme.shared" "~3.1.0"
"@abp/ng.theme.shared" "~3.1.2"
tslib "^2.0.0"
"@abp/ng.tenant-management@~3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@abp/ng.tenant-management/-/ng.tenant-management-3.1.0.tgz#d0b58b711269d91530f36f8ddcb3f6d8f80c0927"
integrity sha512-//g3O2b2NvV7NQtEydbrhZqkdyS3FccVs6wX204ylTLCaLDAwneqNnAnSCQHnUI9GNMjBpj3/VFRGBlvGeW+tw==
"@abp/ng.tenant-management@~3.1.2":
version "3.1.2"
resolved "https://registry.yarnpkg.com/@abp/ng.tenant-management/-/ng.tenant-management-3.1.2.tgz#94fd626515575f8c0e361b36eb173a772ea3fc54"
integrity sha512-vdPSBYYxWUSZxhDg2FMadndj+kZ3ddPkzgBaQldncIvhHsxLQCPwj4ZhqXJ7HHqvZ30JqGiJzk4Ejx0Rv5vu+Q==
dependencies:
"@abp/ng.feature-management" "~3.1.0"
"@abp/ng.theme.shared" "~3.1.0"
"@abp/ng.feature-management" "~3.1.2"
"@abp/ng.theme.shared" "~3.1.2"
tslib "^2.0.0"
"@abp/ng.theme.basic@~3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@abp/ng.theme.basic/-/ng.theme.basic-3.1.0.tgz#53db1e40ed4bf34d2efdc4a990ce9838f61b8d5e"
integrity sha512-C2yXYoSApLzUaOiLAAfFGEkAAP59KHJXaJTG2tsyGAsf+H2yFp2sQW+R0i59opmhW3LUXpAZV9aHKk++w+CGcQ==
"@abp/ng.theme.basic@~3.1.2":
version "3.1.2"
resolved "https://registry.yarnpkg.com/@abp/ng.theme.basic/-/ng.theme.basic-3.1.2.tgz#e60d15db641a13eebc76d7e793efdc5cf4a6a8f7"
integrity sha512-gYS82euwyVU0D9GLXIqt8h1qtwqXtmu7KqIRyjb0IFi2iIvBGal6jMNKHk6wEI0A0/iNy6pra98bYPUZo+FKxQ==
dependencies:
"@abp/ng.theme.shared" "~3.1.0"
"@abp/ng.theme.shared" "~3.1.2"
tslib "^2.0.0"
"@abp/ng.theme.shared@~3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@abp/ng.theme.shared/-/ng.theme.shared-3.1.0.tgz#12fc8fb84b27c74603945dc5384afcf62bb985b6"
integrity sha512-cknvClcDbaCrfTagNuojRbOG88NYCLDEPOOrXdTcSKfieJM2L7w/Ku2piqneV17CCM51Ce7Tl1BO7osYtxTS9Q==
"@abp/ng.theme.shared@~3.1.2":
version "3.1.2"
resolved "https://registry.yarnpkg.com/@abp/ng.theme.shared/-/ng.theme.shared-3.1.2.tgz#b86940d569a992e72e279c34f50f4e4353b6ecc8"
integrity sha512-/e0oB0azdms4QJTtw+7l95t/UmxU5CxQAB4RLIlbnuJFK4NXZObRjb2ujc6PqdaUCGh5djsWxNqVjkcsWcHX2Q==
dependencies:
"@abp/ng.core" "~3.1.0"
"@abp/ng.core" "~3.1.2"
"@fortawesome/fontawesome-free" "^5.14.0"
"@ng-bootstrap/ng-bootstrap" "^7.0.0"
"@ngx-validate/core" "^0.0.11"
@ -102,10 +102,10 @@
chart.js "^2.9.3"
tslib "^2.0.0"
"@abp/utils@^3.1.0-rc.4":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-3.1.0.tgz#ccbfed6591ab11466bf3fed740c8422acf6a84df"
integrity sha512-I5yjM1ovqcpBAT2LFOfwLibVE0Ql6XbP3tQj6YMEZ/foDXekn/4P6Spgq5DTZCMo+0jskS0D8NfL7Ce4p89buw==
"@abp/utils@^3.1.1":
version "3.1.2"
resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-3.1.2.tgz#e9bca8f6133dc2af587c45825e734d2accabcd96"
integrity sha512-wnbHGQDGkQYazez1YSXAZ0ZDbsIZZr2ZN8V4LtOSAfzmYhPhFZ5qftoM0xoxlbmsuLLX6QtiPvxU35kEmlZPyg==
dependencies:
just-compare "^1.3.0"
@ -9717,4 +9717,4 @@ yn@^3.0.0:
zone.js@~0.10.2:
version "0.10.3"
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.10.3.tgz#3e5e4da03c607c9dcd92e37dd35687a14a140c16"
integrity sha512-LXVLVEq0NNOqK/fLJo3d0kfzd4sxwn2/h67/02pjCjfKDxgx1i9QqpvtHD8CrBnSSwMw5+dy11O7FRX5mkO7Cg==
integrity sha512-LXVLVEq0NNOqK/fLJo3d0kfzd4sxwn2/h67/02pjCjfKDxgx1i9QqpvtHD8CrBnSSwMw5+dy11O7FRX5mkO7Cg==

Loading…
Cancel
Save