diff --git a/npm/ng-packs/packages/theme-shared/extensions/src/lib/components/extensible-form/extensible-form-prop.component.html b/npm/ng-packs/packages/theme-shared/extensions/src/lib/components/extensible-form/extensible-form-prop.component.html
index 60f35d636e..f3f60a56dc 100644
--- a/npm/ng-packs/packages/theme-shared/extensions/src/lib/components/extensible-form/extensible-form-prop.component.html
+++ b/npm/ng-packs/packages/theme-shared/extensions/src/lib/components/extensible-form/extensible-form-prop.component.html
@@ -1,6 +1,6 @@
+
+
+
+
diff --git a/npm/ng-packs/packages/theme-shared/extensions/src/lib/components/extensible-form/extensible-form-prop.component.ts b/npm/ng-packs/packages/theme-shared/extensions/src/lib/components/extensible-form/extensible-form-prop.component.ts
index 6b5b241924..658845c045 100644
--- a/npm/ng-packs/packages/theme-shared/extensions/src/lib/components/extensible-form/extensible-form-prop.component.ts
+++ b/npm/ng-packs/packages/theme-shared/extensions/src/lib/components/extensible-form/extensible-form-prop.component.ts
@@ -4,16 +4,25 @@ import {
ChangeDetectorRef,
Component,
Input,
+ OnChanges,
Optional,
SimpleChanges,
SkipSelf,
- OnChanges,
} from '@angular/core';
-import { ControlContainer, Validators, ValidatorFn } from '@angular/forms';
+import {
+ ControlContainer,
+ FormGroup,
+ FormGroupDirective,
+ ValidatorFn,
+ Validators,
+} from '@angular/forms';
import { NgbDateAdapter, NgbTimeAdapter } from '@ng-bootstrap/ng-bootstrap';
import { Observable, of } from 'rxjs';
+import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators';
+import snq from 'snq';
import { DateAdapter } from '../../adapters/date.adapter';
import { TimeAdapter } from '../../adapters/time.adapter';
+import { EXTRA_PROPERTIES_KEY } from '../../constants/extra-properties';
import { ePropType } from '../../enums/props.enum';
import { FormProp } from '../../models/form-props';
import { PropData } from '../../models/props';
@@ -38,6 +47,8 @@ export class ExtensibleFormPropComponent implements OnChanges {
@Input() prop: FormProp;
+ asterisk = '';
+
options$: Observable[]> = of([]);
validators: ValidatorFn[] = [];
@@ -46,15 +57,59 @@ export class ExtensibleFormPropComponent implements OnChanges {
disabled: boolean;
- constructor(public readonly cdRef: ChangeDetectorRef, public readonly track: TrackByService) {}
+ private readonly form: FormGroup;
+
+ typeaheadModel: any;
- get asterisk(): string {
- return this.validators.some(validator => validator === Validators.required) ? '*' : '';
+ setTypeaheadValue(selectedOption: ABP.Option) {
+ this.typeaheadModel = selectedOption || { key: null, value: null };
+ const { key, value } = this.typeaheadModel;
+ const [keyControl, valueControl] = this.getTypeaheadControls();
+ keyControl.setValue(key);
+ valueControl.setValue(value);
+ valueControl.markAsDirty();
+ valueControl.markAsTouched();
}
- getComponent(prop: FormProp): string {
- if (prop.options && prop.type !== ePropType.MultiSelect) return 'select';
+ search = (text$: Observable) =>
+ text$
+ ? text$.pipe(
+ debounceTime(300),
+ distinctUntilChanged(),
+ switchMap(text => this.prop.options(this.data, text)),
+ )
+ : of([]);
+ typeaheadFormatter = (option: ABP.Option) => option.key;
+
+ get isInvalid() {
+ const control = this.form.get(this.prop.name);
+ return control.touched && control.invalid;
+ }
+
+ constructor(
+ public readonly cdRef: ChangeDetectorRef,
+ public readonly track: TrackByService,
+ groupDirective: FormGroupDirective,
+ ) {
+ this.form = groupDirective.form;
+ }
+
+ private getTypeaheadControls() {
+ const { name } = this.prop;
+ const textSuffix = '_Text';
+ const extraPropName = `${EXTRA_PROPERTIES_KEY}.${name}`;
+ const keyControl =
+ this.form.get(extraPropName + textSuffix) || this.form.get(name + textSuffix);
+ const valueControl = this.form.get(extraPropName) || this.form.get(name);
+ return [keyControl, valueControl];
+ }
+
+ private setAsterisk() {
+ this.asterisk = this.validators.some(v => v === Validators.required) ? '*' : '';
+ }
+
+ getComponent(prop: FormProp): string {
switch (prop.type) {
case ePropType.Boolean:
return 'checkbox';
@@ -62,14 +117,18 @@ export class ExtensibleFormPropComponent implements OnChanges {
return 'date';
case ePropType.DateTime:
return 'dateTime';
+ case ePropType.Hidden:
+ return 'hidden';
+ case ePropType.MultiSelect:
+ return 'multiselect';
case ePropType.Text:
return 'textarea';
case ePropType.Time:
return 'time';
- case ePropType.MultiSelect:
- return 'multiselect';
+ case ePropType.Typeahead:
+ return 'typeahead';
default:
- return 'input';
+ return prop.options ? 'select' : 'input';
}
}
@@ -92,14 +151,19 @@ export class ExtensibleFormPropComponent implements OnChanges {
}
ngOnChanges({ prop }: SimpleChanges) {
- const options = prop.currentValue.options;
- const readonly = prop.currentValue.readonly;
- const disabled = prop.currentValue.disabled;
- const validators = prop.currentValue.validators;
+ const currentProp = snq(() => prop.currentValue);
+ const { options, readonly, disabled, validators } = currentProp || {};
if (options) this.options$ = options(this.data);
if (readonly) this.readonly = readonly(this.data);
if (disabled) this.disabled = disabled(this.data);
- if (validators) this.validators = validators(this.data);
+ if (validators) {
+ this.validators = validators(this.data);
+ this.setAsterisk();
+ }
+
+ const [keyControl, valueControl] = this.getTypeaheadControls();
+ if (keyControl && valueControl)
+ this.typeaheadModel = { key: keyControl.value, value: valueControl.value };
}
}
diff --git a/npm/ng-packs/packages/theme-shared/extensions/src/lib/enums/props.enum.ts b/npm/ng-packs/packages/theme-shared/extensions/src/lib/enums/props.enum.ts
index a7c989569f..27cb4990a6 100644
--- a/npm/ng-packs/packages/theme-shared/extensions/src/lib/enums/props.enum.ts
+++ b/npm/ng-packs/packages/theme-shared/extensions/src/lib/enums/props.enum.ts
@@ -4,10 +4,12 @@ export const enum ePropType {
DateTime = 'dateTime',
Email = 'email',
Enum = 'enum',
+ Hidden = 'hidden',
+ MultiSelect = 'multiselect',
Number = 'number',
Password = 'password',
String = 'string',
Text = 'text',
Time = 'time',
- MultiSelect = 'multiselect',
+ Typeahead = 'typeahead',
}
diff --git a/npm/ng-packs/packages/theme-shared/extensions/src/lib/models/props.ts b/npm/ng-packs/packages/theme-shared/extensions/src/lib/models/props.ts
index 1e2fa9a0a0..ef37bee218 100644
--- a/npm/ng-packs/packages/theme-shared/extensions/src/lib/models/props.ts
+++ b/npm/ng-packs/packages/theme-shared/extensions/src/lib/models/props.ts
@@ -39,8 +39,8 @@ export abstract class Prop {
}
}
-export type PropCallback = (data?: Omit, 'data'>) => R;
-export type PropPredicate = (data?: Omit, 'data'>) => boolean;
+export type PropCallback = (data?: Omit, 'data'>, auxData?: any) => R;
+export type PropPredicate = (data?: Omit, 'data'>, auxData?: any) => boolean;
export abstract class PropsFactory> {
protected abstract _ctor: Type;
diff --git a/npm/ng-packs/packages/theme-shared/extensions/src/lib/ui-extensions.module.ts b/npm/ng-packs/packages/theme-shared/extensions/src/lib/ui-extensions.module.ts
index c0c93ce151..11f9ff9e4d 100644
--- a/npm/ng-packs/packages/theme-shared/extensions/src/lib/ui-extensions.module.ts
+++ b/npm/ng-packs/packages/theme-shared/extensions/src/lib/ui-extensions.module.ts
@@ -5,6 +5,7 @@ import {
NgbDatepickerModule,
NgbDropdownModule,
NgbTimepickerModule,
+ NgbTypeaheadModule,
} from '@ng-bootstrap/ng-bootstrap';
import { NgxValidateCoreModule } from '@ngx-validate/core';
import { DateTimePickerComponent } from './components/date-time-picker/date-time-picker.component';
@@ -43,6 +44,7 @@ import { PropDataDirective } from './directives/prop-data.directive';
NgbDatepickerModule,
NgbDropdownModule,
NgbTimepickerModule,
+ NgbTypeaheadModule,
],
})
export class UiExtensionsModule {}
diff --git a/npm/ng-packs/packages/theme-shared/extensions/src/lib/utils/case.util.ts b/npm/ng-packs/packages/theme-shared/extensions/src/lib/utils/case.util.ts
new file mode 100644
index 0000000000..5833b82de2
--- /dev/null
+++ b/npm/ng-packs/packages/theme-shared/extensions/src/lib/utils/case.util.ts
@@ -0,0 +1,37 @@
+// https://github.com/JamesNK/Newtonsoft.Json/blob/master/Src/Newtonsoft.Json/Utilities/StringUtils.cs#L155
+export function jsonNetCamelCase(str: string) {
+ if (!str || !isUpperCase(str[0])) return str;
+
+ const chars = str.split('');
+ const { length } = chars;
+
+ for (let i = 0; i < length; i++) {
+ if (i === 1 && !isUpperCase(chars[i])) break;
+
+ const hasNext = i + 1 < length;
+
+ if (i > 0 && hasNext && !isUpperCase(chars[i + 1])) {
+ if (isSeparator(chars[i + 1])) {
+ chars[i] = toLowerCase(chars[i]);
+ }
+
+ break;
+ }
+
+ chars[i] = toLowerCase(chars[i]);
+ }
+
+ return chars.join('');
+}
+
+function isSeparator(str = '') {
+ return /[\s\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,\-.\/:;<=>?@\[\]^_`{|}~]+/.test(str);
+}
+
+function isUpperCase(str = '') {
+ return /[A-Z]+/.test(str);
+}
+
+function toLowerCase(str = '') {
+ return str.toLowerCase();
+}
diff --git a/npm/ng-packs/packages/theme-shared/extensions/src/lib/utils/state.util.ts b/npm/ng-packs/packages/theme-shared/extensions/src/lib/utils/state.util.ts
index 141d503f46..938269e850 100644
--- a/npm/ng-packs/packages/theme-shared/extensions/src/lib/utils/state.util.ts
+++ b/npm/ng-packs/packages/theme-shared/extensions/src/lib/utils/state.util.ts
@@ -1,4 +1,9 @@
-import { ABP, ApplicationLocalizationConfigurationDto, ConfigStateService } from '@abp/ng.core';
+import {
+ ABP,
+ ApplicationLocalizationConfigurationDto,
+ ConfigStateService,
+ ExtensionPropertyUiLookupDto,
+} from '@abp/ng.core';
import { Observable, pipe, zip } from 'rxjs';
import { filter, map, switchMap, take } from 'rxjs/operators';
import { ePropType } from '../enums/props.enum';
@@ -6,9 +11,11 @@ import { EntityProp, EntityPropList } from '../models/entity-props';
import { FormProp, FormPropList } from '../models/form-props';
import { ObjectExtensions } from '../models/object-extensions';
import { PropCallback } from '../models/props';
+import { jsonNetCamelCase } from './case.util';
import { createEnum, createEnumOptions, createEnumValueResolver } from './enum.util';
import { createDisplayNameLocalizationPipeKeyGenerator } from './localization.util';
import { createExtraPropertyValueResolver } from './props.util';
+import { createTypeaheadOptions, getTypeaheadType } from './typeahead.util';
import { getValidatorsFromProperty } from './validation.util';
function selectObjectExtensions(
@@ -115,7 +122,9 @@ function createPropertiesToContributorsMapper(
Object.keys(properties).forEach((name: string) => {
const property = properties[name];
- const type = getTypeFromProperty(property);
+ const propName = jsonNetCamelCase(name);
+ const lookup = property.ui.lookup || ({} as ExtensionPropertyUiLookupDto);
+ const type = getTypeaheadType(lookup, name) || getTypeFromProperty(property);
const displayName = generateDisplayName(property.displayName, { name, resource });
if (property.ui.onTable.isVisible) {
@@ -123,12 +132,12 @@ function createPropertiesToContributorsMapper(
const columnWidth = type === ePropType.Boolean ? 150 : 250;
const valueResolver =
type === ePropType.Enum
- ? createEnumValueResolver(property.type, enums[property.type], name)
- : createExtraPropertyValueResolver(name);
+ ? createEnumValueResolver(property.type, enums[property.type], propName)
+ : createExtraPropertyValueResolver(propName);
const entityProp = new EntityProp({
type,
- name,
+ name: propName,
displayName,
sortable,
columnWidth,
@@ -147,11 +156,12 @@ function createPropertiesToContributorsMapper(
const defaultValue = property.defaultValue;
const validators = () => getValidatorsFromProperty(property);
let options: PropCallback[]>>;
- if (type === ePropType.Enum) options = createEnumOptions(name, enums[property.type]);
+ if (type === ePropType.Enum) options = createEnumOptions(propName, enums[property.type]);
+ else if (type === ePropType.Typeahead) options = createTypeaheadOptions(lookup);
const formProp = new FormProp({
type,
- name,
+ name: propName,
displayName,
options,
defaultValue,
diff --git a/npm/ng-packs/packages/theme-shared/extensions/src/lib/utils/typeahead.util.ts b/npm/ng-packs/packages/theme-shared/extensions/src/lib/utils/typeahead.util.ts
new file mode 100644
index 0000000000..be89c4a295
--- /dev/null
+++ b/npm/ng-packs/packages/theme-shared/extensions/src/lib/utils/typeahead.util.ts
@@ -0,0 +1,43 @@
+import { ABP, ExtensionPropertyUiLookupDto, RestService } from '@abp/ng.core';
+import { Observable, of } from 'rxjs';
+import { map } from 'rxjs/operators';
+import { ePropType } from '../enums/props.enum';
+import { PropCallback } from '../models/props';
+
+export function createTypeaheadOptions(
+ lookup: ExtensionPropertyUiLookupDto,
+): PropCallback[]>> {
+ return (data, searchText) =>
+ searchText
+ ? data
+ .getInjected(RestService)
+ .request(
+ {
+ method: 'GET',
+ url: lookup.url,
+ params: {
+ [lookup.filterParamName]: searchText,
+ },
+ },
+ { apiName: 'Default' },
+ )
+ .pipe(
+ map(response => {
+ const list = response[lookup.resultListPropertyName];
+ const mapToOption = (item: any) => ({
+ key: item[lookup.displayPropertyName],
+ value: item[lookup.valuePropertyName],
+ });
+ return list.map(mapToOption);
+ }),
+ )
+ : of([]);
+}
+
+export function getTypeaheadType(lookup: ExtensionPropertyUiLookupDto, name: string) {
+ return Boolean(lookup.url)
+ ? ePropType.Typeahead
+ : name.endsWith('_Text')
+ ? ePropType.Hidden
+ : undefined;
+}
diff --git a/npm/ng-packs/packages/theme-shared/extensions/src/tests/case.util.spec.ts b/npm/ng-packs/packages/theme-shared/extensions/src/tests/case.util.spec.ts
new file mode 100644
index 0000000000..db9f7b1de8
--- /dev/null
+++ b/npm/ng-packs/packages/theme-shared/extensions/src/tests/case.util.spec.ts
@@ -0,0 +1,18 @@
+import { jsonNetCamelCase } from '../lib/utils/case.util';
+
+describe('Case Utils', () => {
+ describe('#jsonNetCamelCase', () => {
+ test.each`
+ input | output
+ ${'Primary'} | ${'primary'}
+ ${'PrimaryRole'} | ${'primaryRole'}
+ ${'Primary Role'} | ${'primary Role'}
+ ${'PrimaryRole_Text'} | ${'primaryRole_Text'}
+ ${'ISBN'} | ${'isbn'}
+ ${''} | ${''}
+ ${'iMDB'} | ${'iMDB'}
+ `('should return $output when input is $input', ({ input, output }) => {
+ expect(jsonNetCamelCase(input)).toBe(output);
+ });
+ });
+});
diff --git a/npm/ng-packs/packages/theme-shared/extensions/src/tests/state.util.spec.ts b/npm/ng-packs/packages/theme-shared/extensions/src/tests/state.util.spec.ts
index 34acb30667..6f72a4a8b7 100644
--- a/npm/ng-packs/packages/theme-shared/extensions/src/tests/state.util.spec.ts
+++ b/npm/ng-packs/packages/theme-shared/extensions/src/tests/state.util.spec.ts
@@ -50,24 +50,29 @@ describe('State Utils', () => {
const propList = new EntityPropList();
contributors.prop.Role.forEach(callback => callback(propList));
- expect(propList.length).toBe(3);
- expect(propList.head.value.name).toBe('Title');
- expect(propList.head.next.value.name).toBe('IsHero');
- expect(propList.head.next.next.value.name).toBe('MyEnum');
+ expect(propList.length).toBe(4);
+ expect(propList.head.value.name).toBe('title');
+ expect(propList.head.next.value.name).toBe('isHero');
+ expect(propList.head.next.next.value.name).toBe('myEnum');
+ expect(propList.head.next.next.next.value.name).toBe('foo_Text');
const createFormList = new FormPropList();
contributors.createForm.Role.forEach(callback => callback(createFormList));
- expect(createFormList.length).toBe(2);
- expect(createFormList.head.value.name).toBe('Title');
- expect(createFormList.head.next.value.name).toBe('MyEnum');
+ expect(createFormList.length).toBe(4);
+ expect(createFormList.head.value.name).toBe('title');
+ expect(createFormList.head.next.value.name).toBe('myEnum');
+ expect(createFormList.head.next.next.value.name).toBe('foo');
+ expect(createFormList.head.next.next.next.value.name).toBe('foo_Text');
const editFormList = new FormPropList();
contributors.editForm.Role.forEach(callback => callback(editFormList));
- expect(editFormList.length).toBe(2);
- expect(editFormList.head.value.name).toBe('Title');
- expect(editFormList.head.next.value.name).toBe('IsHero');
+ expect(editFormList.length).toBe(4);
+ expect(editFormList.head.value.name).toBe('title');
+ expect(editFormList.head.next.value.name).toBe('isHero');
+ expect(editFormList.head.next.next.value.name).toBe('foo');
+ expect(editFormList.head.next.next.next.value.name).toBe('foo_Text');
});
});
});
@@ -275,6 +280,83 @@ function createMockEntities(): Record {
+ describe('#createTypeaheadOptions', () => {
+ it('should return observable empty array when search text does not exist', async () => {
+ const list = await createTypeaheadOptions(null)(null, null).toPromise();
+ expect(list).toEqual([]);
+ });
+
+ it('should call request method of RestService with lookup url, filter param and search text', async () => {
+ const data = createData([]);
+ const service = data.getInjected();
+ await createTypeaheadOptions(lookup)(data, 'x').toPromise();
+ expect(service.request).toHaveBeenCalledTimes(1);
+ expect(service.request).toHaveBeenCalledWith(
+ {
+ method: 'GET',
+ url: 'url',
+ params: {
+ filter: 'x',
+ },
+ },
+ { apiName: 'Default' },
+ );
+ });
+
+ it('should return options based on given lookup data', async () => {
+ const data = createData([
+ {
+ text: 'foo',
+ id: 'bar',
+ },
+ {
+ text: 'baz',
+ id: 'qux',
+ },
+ ]);
+
+ const options = await createTypeaheadOptions(lookup)(data, 'x').toPromise();
+ expect(options).toEqual([
+ {
+ key: 'foo',
+ value: 'bar',
+ },
+ {
+ key: 'baz',
+ value: 'qux',
+ },
+ ]);
+ });
+ });
+});
+
+function createData(list: { text: string; id: string }[]): any {
+ const service = { request: jest.fn(() => of({ list })) };
+
+ return {
+ getInjected: () => service,
+ index: 0,
+ record: null,
+ };
+}
diff --git a/npm/ng-packs/packages/theme-shared/src/lib/constants/styles.ts b/npm/ng-packs/packages/theme-shared/src/lib/constants/styles.ts
index a54aecf581..cd9ac2a928 100644
--- a/npm/ng-packs/packages/theme-shared/src/lib/constants/styles.ts
+++ b/npm/ng-packs/packages/theme-shared/src/lib/constants/styles.ts
@@ -2,6 +2,11 @@ export default `
.is-invalid .form-control {
border-color: #dc3545;
border-style: solid !important;
+ padding-right: calc(1.5em + .75rem);
+ background-image: url(data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e);
+ background-repeat: no-repeat;
+ background-position: right calc(.375em + .1875rem) center;
+ background-size: calc(.75em + .375rem) calc(.75em + .375rem);
}
.is-invalid .invalid-feedback,
@@ -144,6 +149,9 @@ export default `
.ngx-datatable.material {
box-shadow: none;
}
+ngb-typeahead-window {
+ width: 100%;
+}
@keyframes fadeInTop {
from {
diff --git a/npm/ng-packs/yarn.lock b/npm/ng-packs/yarn.lock
index d32e47137e..ca4a83fc40 100644
--- a/npm/ng-packs/yarn.lock
+++ b/npm/ng-packs/yarn.lock
@@ -2,12 +2,12 @@
# yarn lockfile v1
-"@abp/ng.core@~4.0.0-rc.3":
- version "4.0.0-rc.3"
- resolved "https://registry.yarnpkg.com/@abp/ng.core/-/ng.core-4.0.0-rc.3.tgz#fe85e2e7b727f88829e0242674b33336be7de2b3"
- integrity sha512-di4gGOb4y/G2vden4VMSTkRAC4J03w8qvFA2Wwmz4n7TSl3p5fP8/jnewJWJskaVJyuEiDk6EohEAkFmZd+rdg==
+"@abp/ng.core@~4.0.0-rc.4":
+ version "4.0.0-rc.4"
+ resolved "https://registry.yarnpkg.com/@abp/ng.core/-/ng.core-4.0.0-rc.4.tgz#f1cbb7d43662579a7977c9d98bf28f7a6726537f"
+ integrity sha512-EtvoUr52v4+DEn3j2mru4OiLJf9tcg5ptLRjwBg1psftz1t3atnmvP1F8+sIhOwnj/Zm5hlhqSqnedpTzdALPg==
dependencies:
- "@abp/utils" "^4.0.0-rc.2"
+ "@abp/utils" "^4.0.0-rc.3"
"@angular/localize" "~10.0.10"
"@ngxs/router-plugin" "^3.7.0"
"@ngxs/store" "^3.7.0"
@@ -18,29 +18,29 @@
ts-toolbelt "6.15.4"
tslib "^2.0.0"
-"@abp/ng.feature-management@~4.0.0-rc.3":
- version "4.0.0-rc.3"
- resolved "https://registry.yarnpkg.com/@abp/ng.feature-management/-/ng.feature-management-4.0.0-rc.3.tgz#cb8dbb03f4a51653d09959c34b11a6abccc9d0c4"
- integrity sha512-Ftmk6muh09IuIL3BadYHi6J75LANjTdCcGEjsXsYU1Gvv4cWffkRlrJmrVRdfQxW1XqFDdBV1+AB02g8NA3llw==
+"@abp/ng.feature-management@~4.0.0-rc.4":
+ version "4.0.0-rc.4"
+ resolved "https://registry.yarnpkg.com/@abp/ng.feature-management/-/ng.feature-management-4.0.0-rc.4.tgz#ab740e4327b8fd10ba4567bfeb24debbd4ffe8a5"
+ integrity sha512-PlWxAA2wECRrBGwqWeaWi+f3YPayIaOJhW4INTvD5JUFMIRJsOJZlxpmcz8x2pU64bUO42/YM26+Xy2TyVKFNg==
dependencies:
- "@abp/ng.theme.shared" "~4.0.0-rc.3"
+ "@abp/ng.theme.shared" "~4.0.0-rc.4"
tslib "^2.0.0"
-"@abp/ng.identity@~4.0.0-rc.3":
- version "4.0.0-rc.3"
- resolved "https://registry.yarnpkg.com/@abp/ng.identity/-/ng.identity-4.0.0-rc.3.tgz#0a8aba1ea0d4c7e4f59407bc4f6eb210250a450b"
- integrity sha512-nXXAdsbJsvc06/b5T5rR4nbApxInaK9fL9ItLCoSzPHB9vUl5FTZw+oQYg4cnZhIhouThrAoAVpr2CxRxmeApg==
+"@abp/ng.identity@~4.0.0-rc.4":
+ version "4.0.0-rc.4"
+ resolved "https://registry.yarnpkg.com/@abp/ng.identity/-/ng.identity-4.0.0-rc.4.tgz#5b8694b1d1d6f1a039e1a445add14dcc5d6eb5ad"
+ integrity sha512-nqx3ofuTT5kOdJHWAyrZyEmGGp08DZNNC7IIY7L1/NueiAcfjghKrAiGkNnt5SApdk86OzdrLdIvpELnZVCMzg==
dependencies:
- "@abp/ng.permission-management" "~4.0.0-rc.3"
- "@abp/ng.theme.shared" "~4.0.0-rc.3"
+ "@abp/ng.permission-management" "~4.0.0-rc.4"
+ "@abp/ng.theme.shared" "~4.0.0-rc.4"
tslib "^2.0.0"
-"@abp/ng.permission-management@~4.0.0-rc.3":
- version "4.0.0-rc.3"
- resolved "https://registry.yarnpkg.com/@abp/ng.permission-management/-/ng.permission-management-4.0.0-rc.3.tgz#92fb7a03b91d10816661d64126817375d33abf46"
- integrity sha512-NdOyytrzmIoewZlY3FeO1P7EQGzHySBgCUXFSmUstBmx5L8TWFRTsKmUZoXnRlO8bzLlSElpfgVmi4uEgLzKqg==
+"@abp/ng.permission-management@~4.0.0-rc.4":
+ version "4.0.0-rc.4"
+ resolved "https://registry.yarnpkg.com/@abp/ng.permission-management/-/ng.permission-management-4.0.0-rc.4.tgz#3d838528549860e2a8b6aba2c5f35f6764089322"
+ integrity sha512-2o/1dtfNQOkqHWzdHyI8Ske5E5VseCM+N3erJu4NSLIWrj5G3CG9wwbJm3BqEjHG7hzbcvR6fYxKpDUmqvQR0A==
dependencies:
- "@abp/ng.theme.shared" "~4.0.0-rc.3"
+ "@abp/ng.theme.shared" "~4.0.0-rc.4"
tslib "^2.0.0"
"@abp/ng.schematics@~3.3.1":
@@ -54,37 +54,37 @@
jsonc-parser "^2.3.0"
typescript "~3.9.2"
-"@abp/ng.setting-management@~4.0.0-rc.3":
- version "4.0.0-rc.3"
- resolved "https://registry.yarnpkg.com/@abp/ng.setting-management/-/ng.setting-management-4.0.0-rc.3.tgz#931227b7b81bd7e68ff0ad0db902269534df3bf4"
- integrity sha512-sdC4U05xiPAkqzweivz0MBF0ZEZBjFIijAIjA6s+1VReF49RwIKH8R+1nzf5XO0FZmwkWYza7TIxpJwuocZRZg==
+"@abp/ng.setting-management@~4.0.0-rc.4":
+ version "4.0.0-rc.4"
+ resolved "https://registry.yarnpkg.com/@abp/ng.setting-management/-/ng.setting-management-4.0.0-rc.4.tgz#45e7fe04a8069da19d644860617e5b5aeab39281"
+ integrity sha512-L7liYuB+DdWdcdJwG4OkQhBdb1bNqFO08TjfbRdkPARHje/tat+z8jtZ58yQVYOVCs9M2vJt3ydHnvZ+PQWpow==
dependencies:
- "@abp/ng.theme.shared" "~4.0.0-rc.3"
+ "@abp/ng.theme.shared" "~4.0.0-rc.4"
tslib "^2.0.0"
-"@abp/ng.tenant-management@~4.0.0-rc.3":
- version "4.0.0-rc.3"
- resolved "https://registry.yarnpkg.com/@abp/ng.tenant-management/-/ng.tenant-management-4.0.0-rc.3.tgz#ee40e557f648eab2f9a7d0da2984c190878ca828"
- integrity sha512-0UaGKS2htCA2vjZcrxMQk4oBHcQBoeAZgVZ93ehEZkhN5gW1JKlOZpzNX7uDtbbFYshD4srlBBrdhoYS4ENSCw==
+"@abp/ng.tenant-management@~4.0.0-rc.4":
+ version "4.0.0-rc.4"
+ resolved "https://registry.yarnpkg.com/@abp/ng.tenant-management/-/ng.tenant-management-4.0.0-rc.4.tgz#0978a65423b9f56df1fd58eaaa01fd912b2875ab"
+ integrity sha512-K7BCZMTs/nPoPrDo/yGu3IWZjXktZHcq0qg2pvjVZRqlfbgk0m+mih01H6WC+/tjKYfdb4PtWQJ36mGR17zvuQ==
dependencies:
- "@abp/ng.feature-management" "~4.0.0-rc.3"
- "@abp/ng.theme.shared" "~4.0.0-rc.3"
+ "@abp/ng.feature-management" "~4.0.0-rc.4"
+ "@abp/ng.theme.shared" "~4.0.0-rc.4"
tslib "^2.0.0"
-"@abp/ng.theme.basic@~4.0.0-rc.3":
- version "4.0.0-rc.3"
- resolved "https://registry.yarnpkg.com/@abp/ng.theme.basic/-/ng.theme.basic-4.0.0-rc.3.tgz#2f1d4ab66a6e7208a03086fe0cffcb86df0dfdf3"
- integrity sha512-C/mWx3UeXiohVCYC5cLEJJhqr0d/3q+udwUObiO668HUaJogHi76oseoVeCEWzGs3ldVus4kMQvtYSummZtV6g==
+"@abp/ng.theme.basic@~4.0.0-rc.4":
+ version "4.0.0-rc.4"
+ resolved "https://registry.yarnpkg.com/@abp/ng.theme.basic/-/ng.theme.basic-4.0.0-rc.4.tgz#438d73fed9962dae3d92b0d1f87f36e3601ab720"
+ integrity sha512-Gunzo6N1YoGZ3crLCYqflmvnuayekyV5Aa63dwCikOTloEBmfQy4FylAcUvncNo841BwmWOk7oDGmxQmrx+5bw==
dependencies:
- "@abp/ng.theme.shared" "~4.0.0-rc.3"
+ "@abp/ng.theme.shared" "~4.0.0-rc.4"
tslib "^2.0.0"
-"@abp/ng.theme.shared@~4.0.0-rc.3":
- version "4.0.0-rc.3"
- resolved "https://registry.yarnpkg.com/@abp/ng.theme.shared/-/ng.theme.shared-4.0.0-rc.3.tgz#aa4cf7516b2ecacd742916fdfb77019eae327ece"
- integrity sha512-z44kFjoI2ngunrnR58KNsWpliekt4K9FNino/ccoI6WpXoPGAsop9vz4x0T6my+Q56mV7hb08h7C6GTqBDEK5g==
+"@abp/ng.theme.shared@~4.0.0-rc.4":
+ version "4.0.0-rc.4"
+ resolved "https://registry.yarnpkg.com/@abp/ng.theme.shared/-/ng.theme.shared-4.0.0-rc.4.tgz#6341acbb647c8606c1147cad4387334a42908a2c"
+ integrity sha512-r3V+PIJC9pCA1OD7xL6I+sJ0AFeF/wcjyUJvn7ZRvevK+eDkHf6AqTXRCNgd+VTfCqtjIpiU5oC7rSOB1gGwPw==
dependencies:
- "@abp/ng.core" "~4.0.0-rc.3"
+ "@abp/ng.core" "~4.0.0-rc.4"
"@fortawesome/fontawesome-free" "^5.14.0"
"@ng-bootstrap/ng-bootstrap" "^7.0.0"
"@ngx-validate/core" "^0.0.12"
@@ -93,13 +93,20 @@
chart.js "^2.9.3"
tslib "^2.0.0"
-"@abp/utils@^4.0.0-rc.2", "@abp/utils@^4.0.0-rc.3":
+"@abp/utils@^4.0.0-rc.3":
version "4.0.0-rc.3"
resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-4.0.0-rc.3.tgz#95a67fc0f7c929e0404d33ee2ab8571c30e7f28d"
integrity sha512-6KH7Tddx5vQQ8j3vhDlveAyDw8VSnLlTpEKaNtQmIyJ+yZ025Faa3m+MKb83jXxDE9hPi3v8QGagEOT5TQjNHg==
dependencies:
just-compare "^1.3.0"
+"@abp/utils@^4.0.0-rc.4":
+ version "4.0.0-rc.4"
+ resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-4.0.0-rc.4.tgz#99573069c7dac8751e3124e60511a11a169df565"
+ integrity sha512-z1l6A07+rSgf7fzI/UTlZv1cJBiIUa0kpEvhcChe7mwlHB7oQ3SlGjZX37kzOqWcOusfMOANPuVulkZLSCOB/w==
+ dependencies:
+ just-compare "^1.3.0"
+
"@angular-builders/jest@^10.0.0":
version "10.0.1"
resolved "https://registry.yarnpkg.com/@angular-builders/jest/-/jest-10.0.1.tgz#a1a6fb5d11b5d54c051bdaa2012b5f046371560c"