Browse Source

Better handle of empty strings.

pull/492/head
Sebastian 6 years ago
parent
commit
b6eb98df7d
  1. 3
      frontend/app/framework/angular/forms/forms-helper.spec.ts
  2. 4
      frontend/app/framework/angular/forms/forms-helper.ts
  3. 26
      frontend/app/framework/angular/forms/string-form-control.spec.ts
  4. 39
      frontend/app/framework/angular/forms/string-form-control.ts
  5. 1
      frontend/app/framework/declarations.ts
  6. 2
      frontend/app/framework/utils/pager.spec.ts
  7. 20
      frontend/app/framework/utils/types.spec.ts
  8. 16
      frontend/app/framework/utils/types.ts
  9. 2
      frontend/app/shared/components/forms/references-dropdown.component.ts
  10. 22
      frontend/app/shared/state/contents.forms.ts
  11. 6
      frontend/app/shared/state/table-fields.spec.ts
  12. 224
      frontend/package-lock.json
  13. 50
      frontend/package.json

3
frontend/app/framework/angular/forms/forms-helper.spec.ts

@ -26,7 +26,7 @@ describe('FormHelpers', () => {
expect(values).toEqual(['1', '2', '3']);
});
it('should not trigger on disable', () => {
it('should also trigger on disable', () => {
const form = new FormControl('1', Validators.required);
const values: any[] = [];
@ -39,6 +39,7 @@ describe('FormHelpers', () => {
form.enable();
form.setValue('3');
form.disable();
form.setValue('4');
expect(values).toEqual(['1', '2', '3']);
});

4
frontend/app/framework/angular/forms/forms-helper.ts

@ -7,7 +7,7 @@
import { AbstractControl, FormArray, FormGroup } from '@angular/forms';
import { Observable } from 'rxjs';
import { distinctUntilChanged, filter, map, startWith } from 'rxjs/operators';
import { distinctUntilChanged, map, startWith } from 'rxjs/operators';
import { Types } from './../../utils/types';
@ -30,7 +30,7 @@ export function invalid$(form: AbstractControl): Observable<boolean> {
}
export function value$<T = any>(form: AbstractControl): Observable<T> {
return form.valueChanges.pipe(startWith(form.value), filter(_ => form.enabled), distinctUntilChanged());
return form.valueChanges.pipe(startWith(form.value), distinctUntilChanged());
}
export function hasValue$(form: AbstractControl): Observable<boolean> {

26
frontend/app/framework/angular/forms/string-form-control.spec.ts

@ -0,0 +1,26 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { StringFormControl } from './string-form-control';
describe('StringFormControl', () => {
it('should convert empty string to undefined', () => {
const formControl = new StringFormControl();
formControl.setValue('');
expect(formControl.value).toBeUndefined();
});
it('should convert empty string to undefined when patching', () => {
const formControl = new StringFormControl();
formControl.patchValue('');
expect(formControl.value).toBeUndefined();
});
});

39
frontend/app/framework/angular/forms/string-form-control.ts

@ -0,0 +1,39 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
// tslint:disable: readonly-array
import { AbstractControlOptions, AsyncValidatorFn, FormControl, ValidatorFn } from '@angular/forms';
type ValueOptions = {
onlySelf?: boolean;
emitEvent?: boolean;
emitModelToViewChange?: boolean;
emitViewToModelChange?: boolean;
};
export class StringFormControl extends FormControl {
constructor(formState?: any, validatorOrOpts?: ValidatorFn | ValidatorFn[] | AbstractControlOptions | null, asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[] | null) {
super(formState, validatorOrOpts, asyncValidator);
}
public setValue(value: any, options?: ValueOptions) {
if (value === '') {
value = undefined;
}
super.setValue(value, options);
}
public patchValue(value: any, options?: ValueOptions) {
if (value === '') {
value = undefined;
}
super.patchValue(value, options);
}
}

1
frontend/app/framework/declarations.ts

@ -29,6 +29,7 @@ export * from './angular/forms/form-hint.component';
export * from './angular/forms/forms-helper';
export * from './angular/forms/indeterminate-value.directive';
export * from './angular/forms/progress-bar.component';
export * from './angular/forms/string-form-control';
export * from './angular/forms/transform-input.directive';
export * from './angular/forms/validators';

2
frontend/app/framework/utils/pager.spec.ts

@ -235,5 +235,7 @@ describe('Pager', () => {
pager.saveTo('my', localStore.object);
localStore.verify(x => x.setInt('my.pageSize', 25), Times.once());
expect().nothing();
});
});

20
frontend/app/framework/utils/types.spec.ts

@ -173,6 +173,26 @@ describe('Types', () => {
expect(Types.equals({ a: [1, 2] }, { a: [1, 2] })).toBeTruthy();
});
const FalsyValues = [false, null, 0];
it('should compare empty string with undefined', () => {
expect(Types.equals('', undefined, true)).toBeTruthy();
expect(Types.equals('', undefined, false)).toBeFalsy();
expect(Types.equals(undefined, '', true)).toBeTruthy();
expect(Types.equals(undefined, '', false)).toBeFalsy();
});
FalsyValues.forEach(x => {
it(`should compare empty string with {x}`, () => {
expect(Types.equals('', x, true)).toBeFalsy();
expect(Types.equals('', x, false)).toBeFalsy();
expect(Types.equals(x, '', true)).toBeFalsy();
expect(Types.equals(x, '', false)).toBeFalsy();
});
});
it('should clone array', () => {
const source = [1, 2, 3];
const result = Types.clone(source);

16
frontend/app/framework/utils/types.ts

@ -126,11 +126,21 @@ export module Types {
return lhs;
}
export function equals(lhs: any, rhs: any) {
export function equals(lhs: any, rhs: any, lazyString = false) {
if (lhs === rhs || (lhs !== lhs && rhs !== rhs)) {
return true;
}
if (lazyString) {
const result =
(lhs === '' && Types.isUndefined(rhs) ||
(rhs === '' && Types.isUndefined(lhs)));
if (result) {
return true;
}
}
if (!lhs || !rhs) {
return false;
}
@ -141,7 +151,7 @@ export module Types {
}
for (let i = 0; i < lhs.length; i++) {
if (!equals(lhs[i], rhs[i])) {
if (!equals(lhs[i], rhs[i], lazyString)) {
return false;
}
}
@ -154,7 +164,7 @@ export module Types {
for (let key in lhs) {
if (lhs.hasOwnProperty(key)) {
if (!equals(lhs[key], rhs[key])) {
if (!equals(lhs[key], rhs[key], lazyString)) {
return false;
}
}

2
frontend/app/shared/components/forms/references-dropdown.component.ts

@ -86,6 +86,7 @@ export class ReferencesDropdownComponent extends StatefulControlComponent<State,
this.own(
value$(this.selectionControl)
.subscribe((value: ContentName) => {
if (this.selectionControl.enabled) {
if (value && value.id) {
this.callTouched();
@ -103,6 +104,7 @@ export class ReferencesDropdownComponent extends StatefulControlComponent<State,
this.callChange([]);
}
}
}
}));
}

22
frontend/app/shared/state/contents.forms.ts

@ -7,13 +7,14 @@
// tslint:disable:prefer-for-of
import { FormArray, FormBuilder, FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms';
import { FormArray, FormBuilder, FormGroup, ValidatorFn, Validators } from '@angular/forms';
import { BehaviorSubject } from 'rxjs';
import {
DateTime,
Form,
formControls,
StringFormControl,
Types,
ValidatorsEx,
value$
@ -483,11 +484,12 @@ export class EditContentForm extends Form<FormGroup, any> {
for (const { key, isOptional } of this.partitions.getAll(field)) {
const fieldValidators = FieldsValidators.create(field, isOptional);
if (field.isArray) {
fieldForm.setControl(key, new FormArray([], fieldValidators));
} else {
fieldForm.setControl(key, new FormControl(fieldDefault, fieldValidators));
}
const control =
field.isArray ?
new FormArray([], fieldValidators) :
new StringFormControl(fieldDefault, fieldValidators);
fieldForm.setControl(key, control);
}
this.form.setControl(field.name, fieldForm);
@ -501,13 +503,13 @@ export class EditContentForm extends Form<FormGroup, any> {
public hasChanged() {
const currentValue = this.form.getRawValue();
return !Types.equals(this.initialData, currentValue);
return !Types.equals(this.initialData, currentValue, true);
}
public hasChanges(changes: any) {
const currentValue = this.form.getRawValue();
return !Types.equals(changes, currentValue);
return !Types.equals(changes, currentValue, true);
}
public arrayItemRemove(field: RootFieldDto, language: AppLanguageDto, index: number) {
@ -546,7 +548,7 @@ export class EditContentForm extends Form<FormGroup, any> {
}
const nestedValidators = FieldsValidators.create(nestedField, partition.isOptional);
const nestedForm = new FormControl(value, nestedValidators);
const nestedForm = new StringFormControl(value, nestedValidators);
if (nestedField.isDisabled) {
nestedForm.disable(NO_EMIT);
@ -673,7 +675,7 @@ export class PatchContentForm extends Form<FormGroup, any> {
for (const field of this.editableFields) {
const validators = FieldsValidators.create(field, this.language.isOptional);
this.form.setControl(field.name, new FormControl(undefined, validators));
this.form.setControl(field.name, new StringFormControl(undefined, validators));
}
}

6
frontend/app/shared/state/table-fields.spec.ts

@ -20,7 +20,7 @@ import {
UIState
} from '@app/shared/internal';
describe('TableFielsd', () => {
describe('TableFields', () => {
let uiState: IMock<UIState>;
const schema =
@ -82,6 +82,8 @@ describe('TableFielsd', () => {
tableFields.updateFields(test.fields, true);
uiState.verify(x => x.removeUser('schemas.my-schema.view'), Times.once());
expect().nothing();
});
});
@ -119,5 +121,7 @@ describe('TableFielsd', () => {
tableFields.updateFields(config, true);
uiState.verify(x => x.set('schemas.my-schema.view', [MetaFields.version], true), Times.once());
expect().nothing();
});
});

224
frontend/package-lock.json

@ -5,9 +5,9 @@
"requires": true,
"dependencies": {
"@angular-devkit/build-optimizer": {
"version": "0.900.1",
"resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.900.1.tgz",
"integrity": "sha512-EnIU+ogiJrUPf8+fuPE5xQ+j/qUZDZ/SmLs8XAOmvoOBpZ0vPNedrHBHCxmV+ACbCxHGmIKQ/ZL29XUYVasteg==",
"version": "0.900.3",
"resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.900.3.tgz",
"integrity": "sha512-VLAWtAXpOzOoYUJrN6sT90UdIdvrVIipkzGz7nfI1kscDvxUFwVZnsNNHtFinaY2SfZAunHhYQOA/B9FJ8WPdQ==",
"dev": true,
"requires": {
"loader-utils": "1.2.3",
@ -76,9 +76,9 @@
}
},
"@angular-devkit/core": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-9.0.1.tgz",
"integrity": "sha512-HboJI/x+SJD9clSOAMjHRv0eXAGRAdEaqJGmjDfdFMP2wznfsBiC6cgcHC17oM4jRWFhmWMR8Omc7CjLZJawJg==",
"version": "9.0.3",
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-9.0.3.tgz",
"integrity": "sha512-3+abmv9K9d+BVgUAolYgoOqlGAA2Jb1pWo2biapSDG6KjUZHUCJdnsKigLtLorCdv0SrjTp56FFplkcqKsFQgA==",
"dev": true,
"requires": {
"ajv": "6.10.2",
@ -148,33 +148,33 @@
}
},
"@angular/animations": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@angular/animations/-/animations-9.0.0.tgz",
"integrity": "sha512-jB8+SC3vMztW5zt5UYVmtVwqIWE33UyEjbP5JPba3I3bLRK5E059LcJmN1rSdJHItgIAdG9Y1I0WJ6aiSFyp4Q=="
"version": "9.0.2",
"resolved": "https://registry.npmjs.org/@angular/animations/-/animations-9.0.2.tgz",
"integrity": "sha512-vj4N8nSLytQI45TtGy2tJb0Yc7uqlyap+qhghc+jdyG41w18KQUnIneEWKOfHWnp8VJEfzgzaY7zr/1QPlxWgA=="
},
"@angular/cdk": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-9.0.0.tgz",
"integrity": "sha512-2kYpyYbewIB6fubSIDMvSprJLNplRZoL/AtXW3od4dLyRxtzX+7iWTAtzUG/dhq8CKev0lpd1HENh5lLR/Lhjw==",
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-9.0.1.tgz",
"integrity": "sha512-slhYG9lOX7JoxcULdfIvXspkDRjYTBG8PH6B2Slxi8CpV42x0t+yQnBQxp/U3ud1m1BWVrlxwKZywaPFe1tSeA==",
"requires": {
"parse5": "^5.0.0"
}
},
"@angular/common": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@angular/common/-/common-9.0.0.tgz",
"integrity": "sha512-ZMmEClGtUNJwV5CBlqcSHPIsNyz6WU/GvKWFzJ5VZc68oeg1e7lqfNMNIC47TjyolNJ7VSpNlyrKjzfdBlmqVw=="
"version": "9.0.2",
"resolved": "https://registry.npmjs.org/@angular/common/-/common-9.0.2.tgz",
"integrity": "sha512-KYOov8fg5WX/bAMkemlcAZxqiq/6ga1BoxjaiZXBj07KDq8i5Nwcm6RmNkeDByCuXd2UHVm1w5t897wEUi6fnw=="
},
"@angular/compiler": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-9.0.0.tgz",
"integrity": "sha512-ctjwuntPfZZT2mNj2NDIVu51t9cvbhl/16epc5xEwyzyDt76pX9UgwvY+MbXrf/C/FWwdtmNtfP698BKI+9leQ==",
"version": "9.0.2",
"resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-9.0.2.tgz",
"integrity": "sha512-IWlKn5v3y7k1Z2K2wfNNzbn9xgA4fFlWyPe9QpdS8iy6/bPe5GfKhHbMYIza5eIhPXDN93zdEptiAIXGP3kLBQ==",
"dev": true
},
"@angular/compiler-cli": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-9.0.0.tgz",
"integrity": "sha512-6L3swd3Z2ceAapmioml6z7yu3bYC2aVm3/rgK7eCoZtPcevuvTpGnXcFSVvNgByV51GntgInThPbMx0xY23Rvw==",
"version": "9.0.2",
"resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-9.0.2.tgz",
"integrity": "sha512-2AAZr1jX72OG9k1viVShiDGAwV9PZEcoDt80PXkUjLTUwWxicuSBKYauph47PzK/qzqWhdbvMbh8wCWHSLq0Qg==",
"dev": true,
"requires": {
"canonical-path": "1.0.0",
@ -199,38 +199,38 @@
}
},
"@angular/core": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@angular/core/-/core-9.0.0.tgz",
"integrity": "sha512-6Pxgsrf0qF9iFFqmIcWmjJGkkCaCm6V5QNnxMy2KloO3SDq6QuMVRbN9RtC8Urmo25LP+eZ6ZgYqFYpdD8Hd9w=="
"version": "9.0.2",
"resolved": "https://registry.npmjs.org/@angular/core/-/core-9.0.2.tgz",
"integrity": "sha512-ccVPR6RZo2s9O9phO0TJ60QZ0WA7qfUMzo0xnpBW0XGcbTzLEn9upvs+0PX64f9UpnHz/MQo0wsqYvTLuoz7Yw=="
},
"@angular/forms": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@angular/forms/-/forms-9.0.0.tgz",
"integrity": "sha512-SIYJc0Rgaihow1t+iiwSFGEvvRgssgUuxwIYbMfCp1Sx513K+JX9nVFXqU+dcGj/eF1u5wwYwbvlVyuMQLzmXg=="
"version": "9.0.2",
"resolved": "https://registry.npmjs.org/@angular/forms/-/forms-9.0.2.tgz",
"integrity": "sha512-qXEth7yeCd+5i6QyvllXnh/Rkzh16raFX5nfI7mgKHjWMik15Ua8wkVhDX9b5gizWeEyZtZcMGsTbbOQy0Ft3Q=="
},
"@angular/platform-browser": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-9.0.0.tgz",
"integrity": "sha512-2PR/o57HjZvKEnAF8ODeqxmeC90oth9dLTMrJNoI5MET0IeErKeI/9Sl5cLQuXC+lSVN5rOMCvDb74VWSno5yw=="
"version": "9.0.2",
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-9.0.2.tgz",
"integrity": "sha512-RMivdtJtspYLH/96AzLwLj3v0O9ck0sL6R1uh5JacfBkmedqJzmLn+AOxTdjaGdIpFtw9tisT+0Aw/nkG14vlA=="
},
"@angular/platform-browser-dynamic": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-9.0.0.tgz",
"integrity": "sha512-F1kbEpmDottTemRPEOAz2Te5ABVJ7wypfzBllxqXbdxPHvYLfL8db2dXyiGqABQ3ZFHPLNilrkUTy0sbuuU4OA=="
"version": "9.0.2",
"resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-9.0.2.tgz",
"integrity": "sha512-RJa+Y83hIFcf7pFcbbaCi7M5Y9nUUcQVuazWbQtiUe+BY5pikyug4RsF2B10pctcxb6LFLElfmkvatmmwEQ9aQ=="
},
"@angular/platform-server": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-9.0.0.tgz",
"integrity": "sha512-wIHZdv7WCtuZ6pgj1n/H2V7KbUxUBfrb1PJzVnCWzpMQDIf+jrMxLlB2irpYb/HHh4tOem6dHX5JV45A2sJ5/w==",
"version": "9.0.2",
"resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-9.0.2.tgz",
"integrity": "sha512-GXpEKMACf648vEGt5n/5XXHWd5Tf5D/x4sjbPCasgZ4uIrtSy3SDrJrQl8rxvFQkv804eBnC5CH9ckEFj8g9QQ==",
"requires": {
"domino": "^2.1.2",
"xhr2": "^0.1.4"
}
},
"@angular/router": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@angular/router/-/router-9.0.0.tgz",
"integrity": "sha512-yyOcStpgN5t8wGRNO85mo0jplXkntP+v2tmSxNx45pahqmofSFm+QCEFa2zHQuMr7NoiGERhd0Tae7NDCCjtjA=="
"version": "9.0.2",
"resolved": "https://registry.npmjs.org/@angular/router/-/router-9.0.2.tgz",
"integrity": "sha512-jDKq9K0pOgaMtocg7VCfIQX8jTyBSb+0hjOcj6kXQVCcmnxeBzGPRX2THQyFkyzG8owTBZlHIrJA3H2thDU2LQ=="
},
"@babel/code-frame": {
"version": "7.8.3",
@ -408,12 +408,12 @@
"dev": true
},
"@ngtools/webpack": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-9.0.1.tgz",
"integrity": "sha512-SG1MDVSC7pIuaX1QYTh94k/YJa6w2OR2RNbghkDXToDzDv6bKnTQYoJPyXk+gwfDTVD4V5z2dKSNbxFzWleFpg==",
"version": "9.0.3",
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-9.0.3.tgz",
"integrity": "sha512-pMIXfq1IJLbvwmkPonGs7nrpuBCXrlZTf9A4OYsMBZcfU8JMn0pRdx7G2+bC9Q/f+uSw2uvPSv76xJXLBOntmA==",
"dev": true,
"requires": {
"@angular-devkit/core": "9.0.1",
"@angular-devkit/core": "9.0.3",
"enhanced-resolve": "4.1.1",
"rxjs": "6.5.3",
"webpack-sources": "1.4.3"
@ -462,9 +462,9 @@
}
},
"@types/core-js": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/@types/core-js/-/core-js-2.5.2.tgz",
"integrity": "sha512-+NPqjXgyA02xTHKJDeDca9u8Zr42ts6jhdND4C3PrPeQ35RJa0dmfAedXW7a9K4N1QcBbuWI1nSfGK4r1eVFCQ==",
"version": "2.5.3",
"resolved": "https://registry.npmjs.org/@types/core-js/-/core-js-2.5.3.tgz",
"integrity": "sha512-F9RHpjuPSit4dCCRXgi7XcqA01DAjy9QY+v9yICoxXsjXD9cgQpyZyL2eSZnTkBGXGaQnea8waZOZTogLDB+rA==",
"dev": true
},
"@types/events": {
@ -485,9 +485,9 @@
}
},
"@types/jasmine": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.5.3.tgz",
"integrity": "sha512-LRJ21f/BO4QNZ3YDaMP0OEurOfE77x8mi8MfEnUsei5IKfmZL0GKl7juhABMdUIJHhVS9OCLotKHfsFNAuJ+DA==",
"version": "3.5.5",
"resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.5.5.tgz",
"integrity": "sha512-LlhwGivHkUV8ehNmaXjGGXopLm91G9ORIRcjw7Ya47jVAIGudewFZM2PdPXBvueZfRWwYzLt083wiPfKRXrSlg==",
"dev": true
},
"@types/json5": {
@ -521,9 +521,9 @@
"dev": true
},
"@types/node": {
"version": "13.7.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-13.7.0.tgz",
"integrity": "sha512-GnZbirvmqZUzMgkFn70c74OQpTTUcCzlhQliTzYjQMqg+hVKcDnxdL19Ne3UdYzdMA/+W3eb646FWn/ZaT1NfQ==",
"version": "13.7.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-13.7.4.tgz",
"integrity": "sha512-oVeL12C6gQS/GAExndigSaLxTrKpQPxewx9bOcwfvJiJge4rr7wNaph4J+ns5hrmIV2as5qxqN8YKthn9qh0jw==",
"dev": true
},
"@types/prop-types": {
@ -539,9 +539,9 @@
"dev": true
},
"@types/react": {
"version": "16.9.19",
"resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.19.tgz",
"integrity": "sha512-LJV97//H+zqKWMms0kvxaKYJDG05U2TtQB3chRLF8MPNs+MQh/H1aGlyDUxjaHvu08EAGerdX2z4LTBc7ns77A==",
"version": "16.9.21",
"resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.21.tgz",
"integrity": "sha512-xpmenCMeBwJRct8vmIfczlgdOXWIWASoOM857kxKfHlVQvDltRh7IFRVfGws79iO2jkNPXOeWREyKoClzhBaQA==",
"dev": true,
"requires": {
"@types/prop-types": "*",
@ -1735,14 +1735,14 @@
}
},
"browserslist": {
"version": "4.8.6",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.8.6.tgz",
"integrity": "sha512-ZHao85gf0eZ0ESxLfCp73GG9O/VTytYDIkIiZDlURppLTI9wErSM/5yAKEq6rcUdxBLjMELmrYUJGg5sxGKMHg==",
"version": "4.8.7",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.8.7.tgz",
"integrity": "sha512-gFOnZNYBHrEyUML0xr5NJ6edFaaKbTFX9S9kQHlYfCP0Rit/boRIz4G+Avq6/4haEKJXdGGUnoolx+5MWW2BoA==",
"dev": true,
"requires": {
"caniuse-lite": "^1.0.30001023",
"electron-to-chromium": "^1.3.341",
"node-releases": "^1.1.47"
"caniuse-lite": "^1.0.30001027",
"electron-to-chromium": "^1.3.349",
"node-releases": "^1.1.49"
}
},
"buffer": {
@ -1988,9 +1988,9 @@
}
},
"caniuse-lite": {
"version": "1.0.30001025",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001025.tgz",
"integrity": "sha512-SKyFdHYfXUZf5V85+PJgLYyit27q4wgvZuf8QTOk1osbypcROihMBlx9GRar2/pIcKH2r4OehdlBr9x6PXetAQ==",
"version": "1.0.30001028",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001028.tgz",
"integrity": "sha512-Vnrq+XMSHpT7E+LWoIYhs3Sne8h9lx9YJV3acH3THNCwU/9zV93/ta4xVfzTtnqd3rvnuVpVjE3DFqf56tr3aQ==",
"dev": true
},
"canonical-path": {
@ -2065,9 +2065,9 @@
}
},
"chownr": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz",
"integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==",
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
"dev": true
},
"chrome-trace-event": {
@ -3045,9 +3045,9 @@
}
},
"csstype": {
"version": "2.6.8",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.8.tgz",
"integrity": "sha512-msVS9qTuMT5zwAGCVm4mxfrZ18BNc6Csd0oJAtiFMZ1FAx1CCvy2+5MDmYoix63LM/6NDbNtodCiGYGmFgO0dA==",
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.9.tgz",
"integrity": "sha512-xz39Sb4+OaTsULgUERcCk+TJj8ylkL4aSVDQiX/ksxbELSqwkgt4d4RD7fovIdgJGSuNYqwZEiVjYY5l0ask+Q==",
"dev": true
},
"currently-unhandled": {
@ -3536,9 +3536,9 @@
"dev": true
},
"electron-to-chromium": {
"version": "1.3.345",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.345.tgz",
"integrity": "sha512-f8nx53+Z9Y+SPWGg3YdHrbYYfIJAtbUjpFfW4X1RwTZ94iUG7geg9tV8HqzAXX7XTNgyWgAFvce4yce8ZKxKmg==",
"version": "1.3.355",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.355.tgz",
"integrity": "sha512-zKO/wS+2ChI/jz9WAo647xSW8t2RmgRLFdbUb/77cORkUTargO+SCj4ctTHjBn2VeNFrsLgDT7IuDVrd3F8mLQ==",
"dev": true
},
"elliptic": {
@ -4285,12 +4285,12 @@
}
},
"file-loader": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/file-loader/-/file-loader-5.0.2.tgz",
"integrity": "sha512-QMiQ+WBkGLejKe81HU8SZ9PovsU/5uaLo0JdTCEXOYv7i7jfAjHZi1tcwp9tSASJPOmmHZtbdCervFmXMH/Dcg==",
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/file-loader/-/file-loader-5.1.0.tgz",
"integrity": "sha512-u/VkLGskw3Ue59nyOwUwXI/6nuBCo7KBkniB/l7ICwr/7cPNGsL1WCXUp3GB0qgOOKU1TiP49bv4DZF/LJqprg==",
"dev": true,
"requires": {
"loader-utils": "^1.2.3",
"loader-utils": "^1.4.0",
"schema-utils": "^2.5.0"
},
"dependencies": {
@ -4318,6 +4318,12 @@
"integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
"dev": true
},
"emojis-list": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
"integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
"dev": true
},
"fast-deep-equal": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
@ -4340,13 +4346,13 @@
}
},
"loader-utils": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz",
"integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==",
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
"integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
"dev": true,
"requires": {
"big.js": "^5.2.2",
"emojis-list": "^2.0.0",
"emojis-list": "^3.0.0",
"json5": "^1.0.1"
}
},
@ -4430,9 +4436,9 @@
},
"dependencies": {
"make-dir": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz",
"integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==",
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.2.tgz",
"integrity": "sha512-rYKABKutXa6vXTXhoV18cBE7PaewPXHe/Bdq4v+ZLMhxbWApkFFplT0LcbMW+6BbjnQXzZ/sAvSE/JdguApG5w==",
"dev": true,
"requires": {
"semver": "^6.0.0"
@ -6788,9 +6794,9 @@
}
},
"karma-jasmine": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-3.1.0.tgz",
"integrity": "sha512-IVGbC8gap5x5NNCEOsAE77ic8rZtHDt6wmO0fFC5yT5FeB8qKnGTeud2mtKyQ41xl7vZkZ7ZxKr4wMGR6tWN+A==",
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-3.1.1.tgz",
"integrity": "sha512-pxBmv5K7IkBRLsFSTOpgiK/HzicQT3mfFF+oHAC7nxMfYKhaYFgxOa5qjnHW4sL5rUnmdkSajoudOnnOdPyW4Q==",
"dev": true,
"requires": {
"jasmine-core": "^3.5.0"
@ -7752,9 +7758,9 @@
}
},
"node-releases": {
"version": "1.1.48",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.48.tgz",
"integrity": "sha512-Hr8BbmUl1ujAST0K0snItzEA5zkJTQup8VNTKNfT6Zw8vTJkIiagUPNfxHmgDOyfFYNfKAul40sD0UEYTvwebw==",
"version": "1.1.49",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.49.tgz",
"integrity": "sha512-xH8t0LS0disN0mtRCh+eByxFPie+msJUBL/lJDBuap53QGiYPa9joh83K4pCZgWJ+2L4b9h88vCVdXQ60NO2bg==",
"dev": true,
"requires": {
"semver": "^6.3.0"
@ -10444,9 +10450,9 @@
"dev": true
},
"rimraf": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.1.tgz",
"integrity": "sha512-IQ4ikL8SjBiEDZfk+DFVwqRK8md24RWMEJkdSlgNLkyyAImcjf8SWvU1qFMDOb4igBClbTQ/ugPqXcRwdFTxZw==",
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dev": true,
"requires": {
"glob": "^7.1.3"
@ -12125,9 +12131,9 @@
}
},
"terser-webpack-plugin": {
"version": "2.3.4",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.4.tgz",
"integrity": "sha512-Nv96Nws2R2nrFOpbzF6IxRDpIkkIfmhvOws+IqMvYdFLO7o6wAILWFKONFgaYy8+T4LVz77DQW0f7wOeDEAjrg==",
"version": "2.3.5",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.5.tgz",
"integrity": "sha512-WlWksUoq+E4+JlJ+h+U+QUzXpcsMSSNXkDy9lBVkSqDn1w23Gg29L/ary9GeJVYCGiNJJX7LnVc4bwL1N3/g1w==",
"dev": true,
"requires": {
"cacache": "^13.0.1",
@ -13651,9 +13657,9 @@
}
},
"webpack": {
"version": "4.41.5",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.5.tgz",
"integrity": "sha512-wp0Co4vpyumnp3KlkmpM5LWuzvZYayDwM2n17EHFr4qxBBbRokC7DJawPJC7TfSFZ9HZ6GsdH40EBj4UV0nmpw==",
"version": "4.41.6",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.6.tgz",
"integrity": "sha512-yxXfV0Zv9WMGRD+QexkZzmGIh54bsvEs+9aRWxnN8erLWEOehAKUTeNBoUbA6HPEZPlRo7KDi2ZcNveoZgK9MA==",
"dev": true,
"requires": {
"@webassemblyjs/ast": "1.8.5",
@ -13763,6 +13769,12 @@
"y18n": "^4.0.0"
}
},
"emojis-list": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
"integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
"dev": true
},
"fast-deep-equal": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
@ -13859,13 +13871,13 @@
}
},
"loader-utils": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz",
"integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==",
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
"integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
"dev": true,
"requires": {
"big.js": "^5.2.2",
"emojis-list": "^2.0.0",
"emojis-list": "^3.0.0",
"json5": "^1.0.1"
}
},
@ -14037,9 +14049,9 @@
}
},
"webpack-cli": {
"version": "3.3.10",
"resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.10.tgz",
"integrity": "sha512-u1dgND9+MXaEt74sJR4PR7qkPxXUSQ0RXYq8x1L6Jg1MYVEmGPrH6Ah6C4arD4r0J1P5HKjRqpab36k0eIzPqg==",
"version": "3.3.11",
"resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.11.tgz",
"integrity": "sha512-dXlfuml7xvAFwYUPsrtQAA9e4DOe58gnzSxhgrO/ZM/gyXTBowrsYeubyN4mqGhYdpXMFNyQ6emjJS9M7OBd4g==",
"dev": true,
"requires": {
"chalk": "2.4.2",

50
frontend/package.json

@ -16,15 +16,15 @@
"postinstall": "ngcc --properties es2015 browser module main --first-only --create-ivy-entry-points"
},
"dependencies": {
"@angular/animations": "9.0.0",
"@angular/cdk": "9.0.0",
"@angular/common": "9.0.0",
"@angular/core": "9.0.0",
"@angular/forms": "9.0.0",
"@angular/platform-browser": "9.0.0",
"@angular/platform-browser-dynamic": "9.0.0",
"@angular/platform-server": "9.0.0",
"@angular/router": "9.0.0",
"@angular/animations": "9.0.2",
"@angular/cdk": "9.0.1",
"@angular/common": "9.0.2",
"@angular/core": "9.0.2",
"@angular/forms": "9.0.2",
"@angular/platform-browser": "9.0.2",
"@angular/platform-browser-dynamic": "9.0.2",
"@angular/platform-server": "9.0.2",
"@angular/router": "9.0.2",
"angular-mentions": "^1.1.3",
"angular2-chartjs": "0.5.1",
"babel-polyfill": "6.26.0",
@ -50,26 +50,26 @@
"zone.js": "0.10.2"
},
"devDependencies": {
"@angular-devkit/build-optimizer": "^0.900.1",
"@angular/compiler": "9.0.0",
"@angular/compiler-cli": "9.0.0",
"@ngtools/webpack": "9.0.1",
"@types/core-js": "2.5.2",
"@types/jasmine": "3.5.3",
"@angular-devkit/build-optimizer": "^0.900.3",
"@angular/compiler": "9.0.2",
"@angular/compiler-cli": "9.0.2",
"@ngtools/webpack": "9.0.3",
"@types/core-js": "2.5.3",
"@types/jasmine": "3.5.5",
"@types/marked": "0.7.2",
"@types/mersenne-twister": "1.1.2",
"@types/mousetrap": "1.6",
"@types/node": "13.7.0",
"@types/react": "16.9.19",
"@types/node": "13.7.4",
"@types/react": "16.9.21",
"@types/react-dom": "16.9.5",
"browserslist": "4.8.6",
"caniuse-lite": "1.0.30001025",
"browserslist": "4.8.7",
"caniuse-lite": "1.0.30001028",
"circular-dependency-plugin": "5.2.0",
"codelyzer": "5.2.1",
"css-loader": "3.4.2",
"cssnano": "^4.1.10",
"entities": "^2.0.0",
"file-loader": "5.0.2",
"file-loader": "5.1.0",
"html-loader": "0.5.5",
"html-webpack-plugin": "3.2.0",
"ignore-loader": "0.1.2",
@ -80,7 +80,7 @@
"karma-cli": "2.0.0",
"karma-coverage-istanbul-reporter": "2.1.1",
"karma-htmlfile-reporter": "0.3.8",
"karma-jasmine": "3.1.0",
"karma-jasmine": "3.1.1",
"karma-jasmine-html-reporter": "1.5.2",
"karma-mocha-reporter": "2.2.5",
"karma-sourcemap-loader": "0.3.7",
@ -93,14 +93,14 @@
"postcss-preset-env": "^6.7.0",
"raw-loader": "4.0.0",
"resize-observer-polyfill": "^1.5.1",
"rimraf": "3.0.1",
"rimraf": "3.0.2",
"rxjs-tslint": "0.1.7",
"sass-lint": "^1.13.1",
"sass-lint-webpack": "^1.0.2",
"sass-loader": "8.0.2",
"style-loader": "1.1.3",
"sugarss": "^2.0.0",
"terser-webpack-plugin": "2.3.4",
"terser-webpack-plugin": "2.3.5",
"ts-loader": "6.2.1",
"tsconfig-paths-webpack-plugin": "3.2.0",
"tslint": "6.0.0",
@ -109,9 +109,9 @@
"typemoq": "2.1.0",
"typescript": "3.7.5",
"underscore": "1.9.2",
"webpack": "4.41.5",
"webpack": "4.41.6",
"webpack-bundle-analyzer": "^3.6.0",
"webpack-cli": "3.3.10",
"webpack-cli": "3.3.11",
"webpack-dev-server": "3.10.3"
}
}

Loading…
Cancel
Save