Browse Source

TS improvements

pull/107/head
Sebastian Stehle 9 years ago
parent
commit
2df3ce73af
  1. 2
      src/Squidex/app/features/content/pages/content/content-page.component.ts
  2. 4
      src/Squidex/app/features/content/pages/contents/contents-page.component.ts
  3. 21
      src/Squidex/app/features/content/shared/assets-editor.component.ts
  4. 21
      src/Squidex/app/features/content/shared/references-editor.component.ts
  5. 2
      src/Squidex/app/features/dashboard/pages/dashboard-page.component.ts
  6. 24
      src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts
  7. 3
      src/Squidex/app/features/schemas/pages/schemas/schema-form.component.ts
  8. 2
      src/Squidex/app/features/webhooks/pages/webhook-events-page.component.ts
  9. 2
      src/Squidex/app/features/webhooks/pages/webhook.component.ts
  10. 2
      src/Squidex/app/features/webhooks/pages/webhooks-page.component.ts
  11. 19
      src/Squidex/app/framework/angular/autocomplete.component.ts
  12. 12
      src/Squidex/app/framework/angular/confirm-click.directive.ts
  13. 3
      src/Squidex/app/framework/angular/copy.directive.ts
  14. 20
      src/Squidex/app/framework/angular/date-time-editor.component.ts
  15. 2
      src/Squidex/app/framework/angular/dialog-renderer.component.ts
  16. 13
      src/Squidex/app/framework/angular/dropdown.component.ts
  17. 31
      src/Squidex/app/framework/angular/geolocation-editor.component.ts
  18. 2
      src/Squidex/app/framework/angular/http-extensions-impl.ts
  19. 18
      src/Squidex/app/framework/angular/indeterminate-value.directive.ts
  20. 30
      src/Squidex/app/framework/angular/jscript-editor.component.ts
  21. 35
      src/Squidex/app/framework/angular/json-editor.component.ts
  22. 16
      src/Squidex/app/framework/angular/lowercase-input.directive.ts
  23. 24
      src/Squidex/app/framework/angular/markdown-editor.component.ts
  24. 4
      src/Squidex/app/framework/angular/modal-view.directive.ts
  25. 2
      src/Squidex/app/framework/angular/panel-container.directive.ts
  26. 24
      src/Squidex/app/framework/angular/rich-editor.component.ts
  27. 4
      src/Squidex/app/framework/angular/router-utils.ts
  28. 22
      src/Squidex/app/framework/angular/slider.component.ts
  29. 37
      src/Squidex/app/framework/angular/stars.component.ts
  30. 56
      src/Squidex/app/framework/angular/tag-editor.component.ts
  31. 21
      src/Squidex/app/framework/angular/toggle.component.ts
  32. 39
      src/Squidex/app/framework/angular/validators.ts
  33. 1
      src/Squidex/app/framework/declarations.ts
  34. 2
      src/Squidex/app/framework/services/local-cache.service.ts
  35. 92
      src/Squidex/app/framework/utils/types.spec.ts
  36. 70
      src/Squidex/app/framework/utils/types.ts
  37. 6
      src/Squidex/app/shared/components/asset.component.ts
  38. 4
      src/Squidex/app/shared/guards/resolve-app-languages.guard.ts
  39. 4
      src/Squidex/app/shared/guards/resolve-content.guard.ts
  40. 4
      src/Squidex/app/shared/guards/resolve-user.guard.ts
  41. 2
      src/Squidex/app/shared/interceptors/auth.interceptor.spec.ts
  42. 2
      src/Squidex/app/shared/interceptors/auth.interceptor.ts
  43. 6
      src/Squidex/app/shared/services/app-clients.service.ts
  44. 4
      src/Squidex/app/shared/services/app-contributors.service.ts
  45. 6
      src/Squidex/app/shared/services/app-languages.service.ts
  46. 19
      src/Squidex/app/shared/services/assets.service.spec.ts
  47. 23
      src/Squidex/app/shared/services/assets.service.ts
  48. 18
      src/Squidex/app/shared/services/auth.service.ts
  49. 16
      src/Squidex/app/shared/services/contents.service.spec.ts
  50. 14
      src/Squidex/app/shared/services/contents.service.ts
  51. 2
      src/Squidex/app/shared/services/plans.service.ts
  52. 32
      src/Squidex/app/shared/services/schemas.service.spec.ts
  53. 38
      src/Squidex/app/shared/services/schemas.service.ts
  54. 3
      src/Squidex/app/shared/services/ui.service.spec.ts
  55. 4
      src/Squidex/app/shared/services/webhooks.service.spec.ts
  56. 10
      src/Squidex/app/shared/services/webhooks.service.ts
  57. 6
      src/Squidex/app/shell/pages/internal/profile-menu.component.ts
  58. 2
      src/Squidex/tsconfig.json

2
src/Squidex/app/features/content/pages/content/content-page.component.ts

@ -139,7 +139,7 @@ export class ContentPageComponent extends AppComponentBase implements CanCompone
this.appNameOnce()
.switchMap(app => this.contentsService.putContent(app, this.schema.name, this.contentId!, requestDto, this.version))
.subscribe(dto => {
this.content = this.content.update(dto, this.authService.user.token);
this.content = this.content.update(dto, this.authService.user!.token);
this.emitContentUpdated(this.content);
this.notifyInfo('Content saved successfully.');

4
src/Squidex/app/features/content/pages/contents/contents-page.component.ts

@ -123,7 +123,7 @@ export class ContentsPageComponent extends AppComponentBase implements OnDestroy
this.appNameOnce()
.switchMap(app => this.contentsService.publishContent(app, this.schema.name, content.id, content.version))
.subscribe(() => {
this.contentItems = this.contentItems.replaceBy('id', content.publish(this.authService.user.token));
this.contentItems = this.contentItems.replaceBy('id', content.publish(this.authService.user!.token));
}, error => {
this.notifyError(error);
});
@ -133,7 +133,7 @@ export class ContentsPageComponent extends AppComponentBase implements OnDestroy
this.appNameOnce()
.switchMap(app => this.contentsService.unpublishContent(app, this.schema.name, content.id, content.version))
.subscribe(() => {
this.contentItems = this.contentItems.replaceBy('id', content.unpublish(this.authService.user.token));
this.contentItems = this.contentItems.replaceBy('id', content.unpublish(this.authService.user!.token));
}, error => {
this.notifyError(error);
});

21
src/Squidex/app/features/content/shared/assets-editor.component.ts

@ -19,11 +19,10 @@ import {
AssetUpdated,
DialogService,
ImmutableArray,
MessageBus
MessageBus,
Types
} from 'shared';
const NOOP = () => { /* NOOP */ };
export const SQX_ASSETS_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => AssetsEditorComponent), multi: true
};
@ -36,8 +35,8 @@ export const SQX_ASSETS_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
})
export class AssetsEditorComponent extends AppComponentBase implements ControlValueAccessor, OnDestroy, OnInit {
private assetUpdatedSubscription: Subscription;
private changeCallback: (value: any) => void = NOOP;
private touchedCallback: () => void = NOOP;
private onChange = (v: any) => { /* NOOP */ };
private onTouched = () => { /* NOOP */ };
public newAssets = ImmutableArray.empty<File>();
public oldAssets = ImmutableArray.empty<AssetDto>();
@ -65,10 +64,10 @@ export class AssetsEditorComponent extends AppComponentBase implements ControlVa
this.assetUpdatedSubscription.unsubscribe();
}
public writeValue(value: any) {
public writeValue(value: string[]) {
this.oldAssets = ImmutableArray.empty<AssetDto>();
if (value && value.length > 0) {
if (Types.isArrayOfString(value) && value.length > 0) {
const assetIds: string[] = value;
this.appNameOnce()
@ -84,11 +83,11 @@ export class AssetsEditorComponent extends AppComponentBase implements ControlVa
}
public registerOnChange(fn: any) {
this.changeCallback = fn;
this.onChange = fn;
}
public registerOnTouched(fn: any) {
this.touchedCallback = fn;
this.onTouched = fn;
}
public addFiles(files: FileList) {
@ -143,7 +142,7 @@ export class AssetsEditorComponent extends AppComponentBase implements ControlVa
ids = null;
}
this.touchedCallback();
this.changeCallback(ids);
this.onTouched();
this.onChange(ids);
}
}

21
src/Squidex/app/features/content/shared/references-editor.component.ts

@ -19,11 +19,10 @@ import {
FieldDto,
ImmutableArray,
SchemaDetailsDto,
SchemasService
SchemasService,
Types
} from 'shared';
const NOOP = () => { /* NOOP */ };
export const SQX_REFERENCES_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => ReferencesEditorComponent), multi: true
};
@ -35,8 +34,8 @@ export const SQX_REFERENCES_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
providers: [SQX_REFERENCES_EDITOR_CONTROL_VALUE_ACCESSOR]
})
export class ReferencesEditorComponent extends AppComponentBase implements ControlValueAccessor, OnInit {
private changeCallback: (value: any) => void = NOOP;
private touchedCallback: () => void = NOOP;
private onChange = (v: any) => { /* NOOP */ };
private onTouched = () => { /* NOOP */ };
@Input()
public schemaId: string;
@ -73,10 +72,10 @@ export class ReferencesEditorComponent extends AppComponentBase implements Contr
});
}
public writeValue(value: any) {
public writeValue(value: string[]) {
this.contentItems = ImmutableArray.empty<ContentDto>();
if (value && value.length > 0) {
if (Types.isArrayOfString(value) && value.length > 0) {
const contentIds: string[] = value;
this.appNameOnce()
@ -92,11 +91,11 @@ export class ReferencesEditorComponent extends AppComponentBase implements Contr
}
public registerOnChange(fn: any) {
this.changeCallback = fn;
this.onChange = fn;
}
public registerOnTouched(fn: any) {
this.touchedCallback = fn;
this.onTouched = fn;
}
public canDrop() {
@ -138,8 +137,8 @@ export class ReferencesEditorComponent extends AppComponentBase implements Contr
ids = null;
}
this.touchedCallback();
this.changeCallback(ids);
this.onTouched();
this.onChange(ids);
}
private loadFields() {

2
src/Squidex/app/features/dashboard/pages/dashboard-page.component.ts

@ -146,7 +146,7 @@ export class DashboardPageComponent extends AppComponentBase implements OnInit {
};
});
this.profileDisplayName = this.authService.user.displayName;
this.profileDisplayName = this.authService.user!.displayName;
}
public showForum() {

24
src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts

@ -110,7 +110,7 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit {
this.appNameOnce()
.switchMap(app => this.schemasService.publishSchema(app, this.schema.name, this.schema.version)).retry(2)
.subscribe(() => {
this.updateSchema(this.schema.publish(this.authService.user.token));
this.updateSchema(this.schema.publish(this.authService.user!.token));
}, error => {
this.notifyError(error);
});
@ -120,7 +120,7 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit {
this.appNameOnce()
.switchMap(app => this.schemasService.unpublishSchema(app, this.schema.name, this.schema.version)).retry(2)
.subscribe(() => {
this.updateSchema(this.schema.unpublish(this.authService.user.token));
this.updateSchema(this.schema.unpublish(this.authService.user!.token));
}, error => {
this.notifyError(error);
});
@ -130,7 +130,7 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit {
this.appNameOnce()
.switchMap(app => this.schemasService.enableField(app, this.schema.name, field.fieldId, this.schema.version)).retry(2)
.subscribe(() => {
this.updateSchema(this.schema.updateField(field.enable(), this.authService.user.token));
this.updateSchema(this.schema.updateField(field.enable(), this.authService.user!.token));
}, error => {
this.notifyError(error);
});
@ -140,7 +140,7 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit {
this.appNameOnce()
.switchMap(app => this.schemasService.disableField(app, this.schema.name, field.fieldId, this.schema.version)).retry(2)
.subscribe(() => {
this.updateSchema(this.schema.updateField(field.disable(), this.authService.user.token));
this.updateSchema(this.schema.updateField(field.disable(), this.authService.user!.token));
}, error => {
this.notifyError(error);
});
@ -150,7 +150,7 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit {
this.appNameOnce()
.switchMap(app => this.schemasService.lockField(app, this.schema.name, field.fieldId, this.schema.version)).retry(2)
.subscribe(() => {
this.updateSchema(this.schema.updateField(field.lock(), this.authService.user.token));
this.updateSchema(this.schema.updateField(field.lock(), this.authService.user!.token));
}, error => {
this.notifyError(error);
});
@ -160,7 +160,7 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit {
this.appNameOnce()
.switchMap(app => this.schemasService.hideField(app, this.schema.name, field.fieldId, this.schema.version)).retry(2)
.subscribe(() => {
this.updateSchema(this.schema.updateField(field.hide(), this.authService.user.token));
this.updateSchema(this.schema.updateField(field.hide(), this.authService.user!.token));
}, error => {
this.notifyError(error);
});
@ -170,7 +170,7 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit {
this.appNameOnce()
.switchMap(app => this.schemasService.deleteField(app, this.schema.name, field.fieldId, this.schema.version)).retry(2)
.subscribe(() => {
this.updateSchema(this.schema.removeField(field, this.authService.user.token));
this.updateSchema(this.schema.removeField(field, this.authService.user!.token));
}, error => {
this.notifyError(error);
});
@ -180,7 +180,7 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit {
this.appNameOnce()
.switchMap(app => this.schemasService.putFieldOrdering(app, this.schema.name, fields.map(t => t.fieldId), this.schema.version)).retry(2)
.subscribe(() => {
this.updateSchema(this.schema.replaceFields(fields, this.authService.user.token));
this.updateSchema(this.schema.replaceFields(fields, this.authService.user!.token));
}, error => {
this.notifyError(error);
});
@ -192,7 +192,7 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit {
this.appNameOnce()
.switchMap(app => this.schemasService.putField(app, this.schema.name, field.fieldId, requestDto, this.schema.version)).retry(2)
.subscribe(() => {
this.updateSchema(this.schema.updateField(field, this.authService.user.token));
this.updateSchema(this.schema.updateField(field, this.authService.user!.token));
}, error => {
this.notifyError(error);
});
@ -223,7 +223,7 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit {
this.appNameOnce()
.switchMap(app => this.schemasService.postField(app, this.schema.name, requestDto, this.schema.version))
.subscribe(dto => {
this.updateSchema(this.schema.addField(dto, this.authService.user.token));
this.updateSchema(this.schema.addField(dto, this.authService.user!.token));
this.resetFieldForm();
}, error => {
this.notifyError(error);
@ -237,13 +237,13 @@ export class SchemaPageComponent extends AppComponentBase implements OnInit {
}
public onSchemaSaved(properties: SchemaPropertiesDto) {
this.updateSchema(this.schema.update(properties, this.authService.user.token));
this.updateSchema(this.schema.update(properties, this.authService.user!.token));
this.editSchemaDialog.hide();
}
public onSchemaScriptsSaved(scripts: UpdateSchemaScriptsDto) {
this.updateSchema(this.schema.configureScripts(scripts, this.authService.user.token));
this.updateSchema(this.schema.configureScripts(scripts, this.authService.user!.token));
this.configureScriptsDialog.hide();
}

3
src/Squidex/app/features/schemas/pages/schemas/schema-form.component.ts

@ -11,6 +11,7 @@ import { FormBuilder, Validators } from '@angular/forms';
import {
ApiUrlConfig,
AuthService,
DateTime,
fadeAnimation,
SchemaDetailsDto,
SchemasService,
@ -89,7 +90,7 @@ export class SchemaFormComponent {
const me = this.authService.user!.token;
this.schemas.postSchema(this.appName, requestDto, me, undefined, schemaVersion)
this.schemas.postSchema(this.appName, requestDto, me, DateTime.now(), schemaVersion)
.subscribe(dto => {
this.emitCreated(dto);
this.resetCreateForm();

2
src/Squidex/app/features/webhooks/pages/webhook-events-page.component.ts

@ -26,7 +26,7 @@ export class WebhookEventsPageComponent extends AppComponentBase implements OnIn
public eventsItems = ImmutableArray.empty<WebhookEventDto>();
public eventsPager = new Pager(0);
public selectedEventId: string;
public selectedEventId: string | null = null;
constructor(dialogs: DialogService, appsStore: AppsStoreService,
private readonly webhooksService: WebhooksService

2
src/Squidex/app/features/webhooks/pages/webhook.component.ts

@ -91,7 +91,7 @@ export class WebhookComponent implements OnInit {
} else {
return null;
}
}).filter(w => !!w)).sortByStringAsc(x => x.schema.name);
}).filter(w => w !== null).map(w => w!)).sortByStringAsc(x => x.schema.name);
this.schemasToAdd =
ImmutableArray.of(

2
src/Squidex/app/features/webhooks/pages/webhooks-page.component.ts

@ -91,7 +91,7 @@ export class WebhooksPageComponent extends AppComponentBase implements OnInit {
this.appNameOnce()
.switchMap(app => this.webhooksService.putWebhook(app, webhook.id, requestDto, webhook.version))
.subscribe(dto => {
this.webhooks = this.webhooks.replace(webhook, webhook.update(requestDto, this.authService.user.token));
this.webhooks = this.webhooks.replace(webhook, webhook.update(requestDto, this.authService.user!.token));
this.notifyInfo('Webhook saved.');
}, error => {

19
src/Squidex/app/framework/angular/autocomplete.component.ts

@ -17,7 +17,6 @@ const KEY_ENTER = 13;
const KEY_ESCAPE = 27;
const KEY_UP = 38;
const KEY_DOWN = 40;
const NOOP = () => { /* NOOP */ };
export const SQX_AUTOCOMPLETE_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => AutocompleteComponent), multi: true
@ -31,8 +30,8 @@ export const SQX_AUTOCOMPLETE_CONTROL_VALUE_ACCESSOR: any = {
})
export class AutocompleteComponent implements ControlValueAccessor, OnDestroy, OnInit {
private subscription: Subscription;
private changeCallback: (value: any) => void = NOOP;
private touchedCallback: () => void = NOOP;
private onChange = (v: any) => { /* NOOP */ };
private onTouched = () => { /* NOOP */ };
@Input()
public source: AutocompleteSource;
@ -57,7 +56,7 @@ export class AutocompleteComponent implements ControlValueAccessor, OnDestroy, O
public writeValue(value: any) {
if (!value) {
this.resetValue();
this.resetForm();
} else {
const item = this.items.find(i => i === value);
@ -79,11 +78,11 @@ export class AutocompleteComponent implements ControlValueAccessor, OnDestroy, O
}
public registerOnChange(fn: any) {
this.changeCallback = fn;
this.onChange = fn;
}
public registerOnTouched(fn: any) {
this.touchedCallback = fn;
this.onTouched = fn;
}
public ngOnDestroy() {
@ -119,7 +118,7 @@ export class AutocompleteComponent implements ControlValueAccessor, OnDestroy, O
this.down();
return false;
case KEY_ESCAPE:
this.resetValue();
this.resetForm();
this.reset();
return false;
case KEY_ENTER:
@ -135,7 +134,7 @@ export class AutocompleteComponent implements ControlValueAccessor, OnDestroy, O
public blur() {
this.reset();
this.touchedCallback();
this.onTouched();
}
public selectItem(selection: any | null = null) {
@ -154,7 +153,7 @@ export class AutocompleteComponent implements ControlValueAccessor, OnDestroy, O
} else {
this.queryInput.setValue(selection.toString(), { emitEvent: false });
}
this.changeCallback(selection);
this.onChange(selection);
} finally {
this.reset();
}
@ -181,7 +180,7 @@ export class AutocompleteComponent implements ControlValueAccessor, OnDestroy, O
this.selectIndex(this.selectedIndex + 1);
}
private resetValue() {
private resetForm() {
this.queryInput.setValue('');
}

12
src/Squidex/app/framework/angular/confirm-click.directive.ts

@ -10,11 +10,13 @@ import { Directive, EventEmitter, HostListener, Input, OnDestroy, Output } from
import { DialogService } from './../services/dialog.service';
class DelayEventEmitter<T> extends EventEmitter<T> {
private delayedNexts: any[] = [];
private delayedNexts: any[] | null = [];
public delayEmit() {
for (let callback of this.delayedNexts) {
callback();
if (this.delayedNexts) {
for (let callback of this.delayedNexts) {
callback();
}
}
}
@ -23,7 +25,9 @@ class DelayEventEmitter<T> extends EventEmitter<T> {
}
public subscribe(generatorOrNext?: any, error?: any, complete?: any): any {
this.delayedNexts.push(generatorOrNext);
if (this.delayedNexts) {
this.delayedNexts.push(generatorOrNext);
}
return super.subscribe(generatorOrNext, error, complete);
}

3
src/Squidex/app/framework/angular/copy.directive.ts

@ -7,6 +7,7 @@
import { Directive, HostListener, Input } from '@angular/core';
import { Types } from './../utils/types';
import { DialogService, Notification } from './../services/dialog.service';
@Directive({
@ -48,7 +49,7 @@ export class CopyDirective {
console.log('Copy failed');
}
if (currentFocus && typeof currentFocus.focus === 'function') {
if (currentFocus && Types.isFunction(currentFocus.focus)) {
currentFocus.focus();
}

20
src/Squidex/app/framework/angular/date-time-editor.component.ts

@ -12,8 +12,6 @@ import * as moment from 'moment';
let Pikaday = require('pikaday/pikaday');
const NOOP = () => { /* NOOP */ };
export const SQX_DATE_TIME_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => DateTimeEditorComponent), multi: true
};
@ -31,8 +29,8 @@ export class DateTimeEditorComponent implements ControlValueAccessor, OnDestroy,
private timeValue: any | null = null;
private dateValue: any | null = null;
private suppressEvents = false;
private changeCallback: (value: any) => void = NOOP;
private touchedCallback: () => void = NOOP;
private onChange = (v: any) => { /* NOOP */ };
private onTouched = () => { /* NOOP */ };
@Input()
public mode: string;
@ -116,11 +114,11 @@ export class DateTimeEditorComponent implements ControlValueAccessor, OnDestroy,
}
public registerOnChange(fn: any) {
this.changeCallback = fn;
this.onChange = fn;
}
public registerOnTouched(fn: any) {
this.touchedCallback = fn;
this.onTouched = fn;
}
public ngAfterViewInit() {
@ -140,7 +138,7 @@ export class DateTimeEditorComponent implements ControlValueAccessor, OnDestroy,
}
public touched() {
this.touchedCallback();
this.onTouched();
}
public writeNow() {
@ -159,14 +157,14 @@ export class DateTimeEditorComponent implements ControlValueAccessor, OnDestroy,
this.dateValue = null;
this.changeCallback(null);
this.touchedCallback();
this.onChange(null);
this.onTouched();
return false;
}
private updateValue() {
let result: string | null;
let result: string | null = null;
if ((this.dateValue && !this.dateValue.isValid()) || (this.timeValue && !this.timeValue.isValid())) {
result = 'Invalid DateTime';
@ -184,7 +182,7 @@ export class DateTimeEditorComponent implements ControlValueAccessor, OnDestroy,
}
}
this.changeCallback(result);
this.onChange(result);
}
private updateControls() {

2
src/Squidex/app/framework/angular/dialog-renderer.component.ts

@ -32,7 +32,7 @@ export class DialogRendererComponent implements OnDestroy, OnInit {
private notificationsSubscription: Subscription;
public dialogView = new ModalView(false, true);
public dialogRequest: DialogRequest;
public dialogRequest: DialogRequest | null = null;
public notifications: Notification[] = [];

13
src/Squidex/app/framework/angular/dropdown.component.ts

@ -12,7 +12,6 @@ const KEY_ENTER = 13;
const KEY_ESCAPE = 27;
const KEY_UP = 38;
const KEY_DOWN = 40;
const NOOP = () => { /* NOOP */ };
import { ModalView } from './../utils/modal-view';
@ -27,8 +26,8 @@ export const SQX_DROPDOWN_CONTROL_VALUE_ACCESSOR: any = {
providers: [SQX_DROPDOWN_CONTROL_VALUE_ACCESSOR]
})
export class DropdownComponent implements AfterContentInit, ControlValueAccessor {
private changeCallback: (value: any) => void = NOOP;
private touchedCallback: () => void = NOOP;
private onChange = (v: any) => { /* NOOP */ };
private onTouched = () => { /* NOOP */ };
@Input()
public items: any[] = [];
@ -69,11 +68,11 @@ export class DropdownComponent implements AfterContentInit, ControlValueAccessor
}
public registerOnChange(fn: any) {
this.changeCallback = fn;
this.onChange = fn;
}
public registerOnTouched(fn: any) {
this.touchedCallback = fn;
this.onTouched = fn;
}
public onKeyDown(event: KeyboardEvent) {
@ -95,7 +94,7 @@ export class DropdownComponent implements AfterContentInit, ControlValueAccessor
public open() {
this.dropdown.show();
this.touchedCallback();
this.onTouched();
}
public selectIndexAndClose(selectedIndex: number) {
@ -132,7 +131,7 @@ export class DropdownComponent implements AfterContentInit, ControlValueAccessor
this.selectedIndex = selectedIndex;
this.selectedItem = value;
this.changeCallback(value);
this.onChange(value);
}
}
}

31
src/Squidex/app/framework/angular/geolocation-editor.component.ts

@ -8,17 +8,22 @@
import { AfterViewInit, Component, ElementRef, forwardRef, ViewChild } from '@angular/core';
import { ControlValueAccessor, FormBuilder, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Types } from './../utils/types';
import { ResourceLoaderService } from './../services/resource-loader.service';
import { ValidatorsEx } from './validators';
const NOOP = () => { /* NOOP */ };
declare var L: any;
export const SQX_GEOLOCATION_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => GeolocationEditorComponent), multi: true
};
interface Geolocation {
latitude: number;
longitude: number;
}
@Component({
selector: 'sqx-geolocation-editor',
styleUrls: ['./geolocation-editor.component.scss'],
@ -26,11 +31,11 @@ export const SQX_GEOLOCATION_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
providers: [SQX_GEOLOCATION_EDITOR_CONTROL_VALUE_ACCESSOR]
})
export class GeolocationEditorComponent implements ControlValueAccessor, AfterViewInit {
private changeCallback: (value: any) => void = NOOP;
private touchedCallback: () => void = NOOP;
private onChange = (v: any) => { /* NOOP */ };
private onTouched = () => { /* NOOP */ };
private marker: any;
private map: any;
private value: any;
private value: Geolocation | null = null;
public get hasValue() {
return !!this.value;
@ -59,8 +64,12 @@ export class GeolocationEditorComponent implements ControlValueAccessor, AfterVi
) {
}
public writeValue(value: any) {
this.value = value;
public writeValue(value: Geolocation) {
if (Types.isObject(value) && Types.isNumber(value.latitude) && Types.isNumber(value.longitude)) {
this.value = value;
} else {
this.value = null;
}
if (this.marker) {
this.updateMarker(true, false);
@ -102,11 +111,11 @@ export class GeolocationEditorComponent implements ControlValueAccessor, AfterVi
}
public registerOnChange(fn: any) {
this.changeCallback = fn;
this.onChange = fn;
}
public registerOnTouched(fn: any) {
this.touchedCallback = fn;
this.onTouched = fn;
}
public updateValueByInput() {
@ -201,8 +210,8 @@ export class GeolocationEditorComponent implements ControlValueAccessor, AfterVi
}
if (fireEvent) {
this.changeCallback(this.value);
this.touchedCallback();
this.onChange(this.value);
this.onTouched();
}
}
}

2
src/Squidex/app/framework/angular/http-extensions-impl.ts

@ -78,7 +78,7 @@ export module HTTP {
}
}
function handleVersion(httpRequest: Observable<HttpResponse<any>>, version: Version): Observable<any> {
function handleVersion(httpRequest: Observable<HttpResponse<any>>, version?: Version): Observable<any> {
return httpRequest.do((response: HttpResponse<any>) => {
if (version && response.status.toString().indexOf('2') === 0 && response.headers) {
const etag = response.headers.get('etag');

18
src/Squidex/app/framework/angular/indeterminate-value.directive.ts

@ -8,7 +8,7 @@
import { Directive, forwardRef, ElementRef, HostListener, Renderer } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
const NOOP = () => { /* NOOP */ };
import { Types } from './../utils/types';
export const SQX_INDETERMINATE_VALUE_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => IndeterminateValueDirective), multi: true
@ -19,8 +19,8 @@ export const SQX_INDETERMINATE_VALUE_CONTROL_VALUE_ACCESSOR: any = {
providers: [SQX_INDETERMINATE_VALUE_CONTROL_VALUE_ACCESSOR]
})
export class IndeterminateValueDirective implements ControlValueAccessor {
private changeCallback: (value: any) => void = NOOP;
private touchedCallback: () => void = NOOP;
private onChange = (v: any) => { /* NOOP */ };
private onTouched = () => { /* NOOP */ };
constructor(
private readonly renderer: Renderer,
@ -30,16 +30,16 @@ export class IndeterminateValueDirective implements ControlValueAccessor {
@HostListener('change', ['$event.target.value'])
public onChange(value: any) {
this.changeCallback(value);
this.onChange(value);
}
@HostListener('blur')
public onTouched() {
this.touchedCallback();
this.onTouched();
}
public writeValue(value: any) {
if (value === undefined || value === null) {
public writeValue(value: boolean | number | undefined) {
if (!Types.isBoolean(value)) {
this.renderer.setElementProperty(this.element.nativeElement, 'indeterminate', true);
} else {
this.renderer.setElementProperty(this.element.nativeElement, 'checked', value);
@ -51,10 +51,10 @@ export class IndeterminateValueDirective implements ControlValueAccessor {
}
public registerOnChange(fn: any) {
this.changeCallback = fn;
this.onChange = fn;
}
public registerOnTouched(fn: any) {
this.touchedCallback = fn;
this.onTouched = fn;
}
}

30
src/Squidex/app/framework/angular/jscript-editor.component.ts

@ -9,12 +9,12 @@ import { AfterViewInit, Component, forwardRef, ElementRef, ViewChild } from '@an
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Subject } from 'rxjs';
import { Types } from './../utils/types';
import { ResourceLoaderService } from './../services/resource-loader.service';
declare var ace: any;
const NOOP = () => { /* NOOP */ };
export const SQX_JSCRIPT_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => JscriptEditorComponent), multi: true
};
@ -26,11 +26,11 @@ export const SQX_JSCRIPT_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
providers: [SQX_JSCRIPT_EDITOR_CONTROL_VALUE_ACCESSOR]
})
export class JscriptEditorComponent implements ControlValueAccessor, AfterViewInit {
private changeCallback: (value: any) => void = NOOP;
private touchedCallback: () => void = NOOP;
private onChange = (v: any) => { /* NOOP */ };
private onTouched = () => { /* NOOP */ };
private valueChanged = new Subject();
private aceEditor: any;
private oldValue: string;
private value: string;
private isDisabled = false;
@ViewChild('editor')
@ -41,11 +41,11 @@ export class JscriptEditorComponent implements ControlValueAccessor, AfterViewIn
) {
}
public writeValue(value: any) {
this.oldValue = value;
public writeValue(value: string) {
this.value = Types.isString(value) ? value : '';
if (this.aceEditor) {
this.setValue(value);
this.setValue(this.value);
}
}
@ -58,11 +58,11 @@ export class JscriptEditorComponent implements ControlValueAccessor, AfterViewIn
}
public registerOnChange(fn: any) {
this.changeCallback = fn;
this.onChange = fn;
}
public registerOnTouched(fn: any) {
this.touchedCallback = fn;
this.onTouched = fn;
}
public ngAfterViewInit() {
@ -78,11 +78,11 @@ export class JscriptEditorComponent implements ControlValueAccessor, AfterViewIn
this.aceEditor.setReadOnly(this.isDisabled);
this.aceEditor.setFontSize(14);
this.setValue(this.oldValue);
this.setValue(this.value);
this.aceEditor.on('blur', () => {
this.changeValue();
this.touchedCallback();
this.onTouched();
});
this.aceEditor.on('change', () => {
@ -94,11 +94,11 @@ export class JscriptEditorComponent implements ControlValueAccessor, AfterViewIn
private changeValue() {
const newValue = this.aceEditor.getValue();
if (this.oldValue !== newValue) {
this.changeCallback(newValue);
if (this.value !== newValue) {
this.onChange(newValue);
}
this.oldValue = newValue;
this.value = newValue;
}
private setValue(value: string) {

35
src/Squidex/app/framework/angular/json-editor.component.ts

@ -13,8 +13,6 @@ import { ResourceLoaderService } from './../services/resource-loader.service';
declare var ace: any;
const NOOP = () => { /* NOOP */ };
export const SQX_JSON_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => JsonEditorComponent), multi: true
};
@ -26,12 +24,12 @@ export const SQX_JSON_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
providers: [SQX_JSON_EDITOR_CONTROL_VALUE_ACCESSOR]
})
export class JsonEditorComponent implements ControlValueAccessor, AfterViewInit {
private changeCallback: (value: any) => void = NOOP;
private touchedCallback: () => void = NOOP;
private onChange = (v: any) => { /* NOOP */ };
private onTouched = () => { /* NOOP */ };
private valueChanged = new Subject();
private aceEditor: any;
private oldValue: any;
private oldValueString: string;
private value: any;
private valueString: string;
private isDisabled = false;
@ViewChild('editor')
@ -43,8 +41,13 @@ export class JsonEditorComponent implements ControlValueAccessor, AfterViewInit
}
public writeValue(value: any) {
this.oldValue = value;
this.oldValueString = JSON.stringify(value);
this.value = value;
try {
this.valueString = JSON.stringify(value);
} catch (e) {
this.valueString = '';
}
if (this.aceEditor) {
this.setValue(value);
@ -60,11 +63,11 @@ export class JsonEditorComponent implements ControlValueAccessor, AfterViewInit
}
public registerOnChange(fn: any) {
this.changeCallback = fn;
this.onChange = fn;
}
public registerOnTouched(fn: any) {
this.touchedCallback = fn;
this.onTouched = fn;
}
public ngAfterViewInit() {
@ -80,11 +83,11 @@ export class JsonEditorComponent implements ControlValueAccessor, AfterViewInit
this.aceEditor.setReadOnly(this.isDisabled);
this.aceEditor.setFontSize(14);
this.setValue(this.oldValue);
this.setValue(this.value);
this.aceEditor.on('blur', () => {
this.changeValue();
this.touchedCallback();
this.onTouched();
});
this.aceEditor.on('change', () => {
@ -108,12 +111,12 @@ export class JsonEditorComponent implements ControlValueAccessor, AfterViewInit
const newValueString = JSON.stringify(newValue);
if (this.oldValueString !== newValueString) {
this.changeCallback(newValue);
if (this.valueString !== newValueString) {
this.onChange(newValue);
}
this.oldValue = newValue;
this.oldValueString = newValueString;
this.value = newValue;
this.valueString = newValueString;
}
private setValue(value: any) {

16
src/Squidex/app/framework/angular/lowercase-input.directive.ts

@ -8,8 +8,6 @@
import { Directive, forwardRef, ElementRef, HostListener, Renderer } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
const NOOP = () => { /* NOOP */ };
export const SQX_LOWERCASE_INPUT_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => LowerCaseInputDirective), multi: true
};
@ -19,8 +17,8 @@ export const SQX_LOWERCASE_INPUT_VALUE_ACCESSOR: any = {
providers: [SQX_LOWERCASE_INPUT_VALUE_ACCESSOR]
})
export class LowerCaseInputDirective implements ControlValueAccessor {
private changeCallback: (value: any) => void = NOOP;
private touchedCallback: () => void = NOOP;
private onChange = (v: any) => { /* NOOP */ };
private onTouched = () => { /* NOOP */ };
constructor(
private readonly element: ElementRef,
@ -33,16 +31,16 @@ export class LowerCaseInputDirective implements ControlValueAccessor {
const normalizedValue = (value == null ? '' : value.toString()).toLowerCase();
this.renderer.setElementProperty(this.element.nativeElement, 'value', normalizedValue);
this.changeCallback(normalizedValue);
this.onChange(normalizedValue);
}
@HostListener('blur')
public onTouched() {
this.touchedCallback();
this.onTouched();
}
public writeValue(value: any) {
const normalizedValue = (value == null ? '' : value.toString()).toLowerCase();
const normalizedValue = value ? '' : value.toString().toLowerCase();
this.renderer.setElementProperty(this.element.nativeElement, 'value', normalizedValue);
}
@ -52,10 +50,10 @@ export class LowerCaseInputDirective implements ControlValueAccessor {
}
public registerOnChange(fn: any) {
this.changeCallback = fn;
this.onChange = fn;
}
public registerOnTouched(fn: any) {
this.touchedCallback = fn;
this.onTouched = fn;
}
}

24
src/Squidex/app/framework/angular/markdown-editor.component.ts

@ -8,12 +8,12 @@
import { AfterViewInit, Component, forwardRef, ElementRef, ViewChild } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Types } from './../utils/types';
import { ResourceLoaderService } from './../services/resource-loader.service';
declare var SimpleMDE: any;
const NOOP = () => { /* NOOP */ };
export const SQX_MARKDOWN_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => MarkdownEditorComponent), multi: true
};
@ -25,10 +25,10 @@ export const SQX_MARKDOWN_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
providers: [SQX_MARKDOWN_EDITOR_CONTROL_VALUE_ACCESSOR]
})
export class MarkdownEditorComponent implements ControlValueAccessor, AfterViewInit {
private changeCallback: (value: any) => void = NOOP;
private touchedCallback: () => void = NOOP;
private onChange = (v: any) => { /* NOOP */ };
private onTouched = () => { /* NOOP */ };
private simplemde: any;
private value: any;
private value: string;
private isDisabled = false;
@ViewChild('editor')
@ -48,11 +48,11 @@ export class MarkdownEditorComponent implements ControlValueAccessor, AfterViewI
this.resourceLoader.loadStyle('https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.css');
}
public writeValue(value: any) {
this.value = value;
public writeValue(value: string) {
this.value = Types.isString(value) ? value : '';
if (this.simplemde) {
this.simplemde.value(this.value || '');
this.simplemde.value(this.value);
}
}
@ -65,11 +65,11 @@ export class MarkdownEditorComponent implements ControlValueAccessor, AfterViewI
}
public registerOnChange(fn: any) {
this.changeCallback = fn;
this.onChange = fn;
}
public registerOnTouched(fn: any) {
this.touchedCallback = fn;
this.onTouched = fn;
}
public ngAfterViewInit() {
@ -84,12 +84,12 @@ export class MarkdownEditorComponent implements ControlValueAccessor, AfterViewI
if (this.value !== value) {
this.value = value;
this.changeCallback(value);
this.onChange(value);
}
});
this.simplemde.codemirror.on('blur', () => {
this.touchedCallback();
this.onTouched();
});
this.simplemde.codemirror.on('refresh', () => {

4
src/Squidex/app/framework/angular/modal-view.directive.ts

@ -16,8 +16,8 @@ import { RootViewService } from './../services/root-view.service';
selector: '[sqxModalView]'
})
export class ModalViewDirective implements OnChanges, OnDestroy {
private subscription: Subscription | null;
private clickHandler: Function | null;
private subscription: Subscription | null = null;
private clickHandler: Function | null = null;
private renderedView: EmbeddedViewRef<any> | null = null;
@Input('sqxModalView')

2
src/Squidex/app/framework/angular/panel-container.directive.ts

@ -49,7 +49,7 @@ export class PanelContainerDirective implements AfterViewInit, OnDestroy {
}
public invalidate(params?: { force: boolean, resize: boolean }) {
this.isInit = this.isInit || (params && params.force);
this.isInit = this.isInit || (params && params.force) === true;
if (!this.isInit) {
return;

24
src/Squidex/app/framework/angular/rich-editor.component.ts

@ -8,12 +8,12 @@
import { AfterViewInit, Component, forwardRef, ElementRef, OnDestroy, ViewChild } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Types } from './../utils/types';
import { ResourceLoaderService } from './../services/resource-loader.service';
declare var tinymce: any;
const NOOP = () => { /* NOOP */ };
export const SQX_RICH_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => RichEditorComponent), multi: true
};
@ -25,10 +25,10 @@ export const SQX_RICH_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
providers: [SQX_RICH_EDITOR_CONTROL_VALUE_ACCESSOR]
})
export class RichEditorComponent implements ControlValueAccessor, AfterViewInit, OnDestroy {
private changeCallback: (value: any) => void = NOOP;
private touchedCallback: () => void = NOOP;
private onChange = (v: any) => { /* NOOP */ };
private onTouched = () => { /* NOOP */ };
private tinyEditor: any;
private value: any;
private value: string;
private isDisabled = false;
@ViewChild('editor')
@ -39,11 +39,11 @@ export class RichEditorComponent implements ControlValueAccessor, AfterViewInit,
) {
}
public writeValue(value: any) {
this.value = value;
public writeValue(value: string) {
this.value = Types.isString(value) ? value : '';
if (this.tinyEditor) {
this.tinyEditor.setContent(value || '');
this.tinyEditor.setContent(this.value);
}
}
@ -56,11 +56,11 @@ export class RichEditorComponent implements ControlValueAccessor, AfterViewInit,
}
public registerOnChange(fn: any) {
this.changeCallback = fn;
this.onChange = fn;
}
public registerOnTouched(fn: any) {
this.touchedCallback = fn;
this.onTouched = fn;
}
public ngAfterViewInit() {
@ -78,12 +78,12 @@ export class RichEditorComponent implements ControlValueAccessor, AfterViewInit,
if (this.value !== value) {
this.value = value;
self.changeCallback(value);
self.onChange(value);
}
});
self.tinyEditor.on('blur', () => {
self.touchedCallback();
self.onTouched();
});
setTimeout(() => {

4
src/Squidex/app/framework/angular/router-utils.ts

@ -8,7 +8,7 @@
import { ActivatedRoute, ActivatedRouteSnapshot, Data, Params } from '@angular/router';
export function allData(value: ActivatedRouteSnapshot | ActivatedRoute): Data {
let snapshot: ActivatedRouteSnapshot = value['snapshot'] || value;
let snapshot: ActivatedRouteSnapshot | null = value['snapshot'] || value;
const result: { [key: string]: any } = { };
@ -25,7 +25,7 @@ export function allData(value: ActivatedRouteSnapshot | ActivatedRoute): Data {
return result;
}
export function allParams(value: ActivatedRouteSnapshot | ActivatedRoute): Params {
let snapshot: ActivatedRouteSnapshot = value['snapshot'] || value;
let snapshot: ActivatedRouteSnapshot | null = value['snapshot'] || value;
const result: { [key: string]: any } = { };

22
src/Squidex/app/framework/angular/slider.component.ts

@ -8,7 +8,7 @@
import { Component, ElementRef, forwardRef, Input, Renderer, ViewChild } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
const NOOP = () => { /* NOOP */ };
import { Types } from './../utils/types';
export const SQX_SLIDER_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SliderComponent), multi: true
@ -21,10 +21,10 @@ export const SQX_SLIDER_CONTROL_VALUE_ACCESSOR: any = {
providers: [SQX_SLIDER_CONTROL_VALUE_ACCESSOR]
})
export class SliderComponent implements ControlValueAccessor {
private changeCallback: (value: any) => void = NOOP;
private touchedCallback: () => void = NOOP;
private mouseMoveSubscription: Function | null;
private mouseUpSubscription: Function | null;
private onChange = (v: any) => { /* NOOP */ };
private onTouched = () => { /* NOOP */ };
private mouseMoveSubscription: Function | null = null;
private mouseUpSubscription: Function | null = null;
private centerStartOffset = 0;
private startValue: number;
private lastValue: number;
@ -50,8 +50,8 @@ export class SliderComponent implements ControlValueAccessor {
constructor(private readonly renderer: Renderer) { }
public writeValue(value: any) {
this.lastValue = this.value = value;
public writeValue(value: number) {
this.lastValue = this.value = Types.isNumber(value) ? value : 0;
this.updateThumbPosition();
}
@ -61,11 +61,11 @@ export class SliderComponent implements ControlValueAccessor {
}
public registerOnChange(fn: any) {
this.changeCallback = fn;
this.onChange = fn;
}
public registerOnTouched(fn: any) {
this.touchedCallback = fn;
this.onTouched = fn;
}
public onBarMouseClick(event: MouseEvent): boolean {
@ -157,14 +157,14 @@ export class SliderComponent implements ControlValueAccessor {
}
private updateTouched() {
this.touchedCallback();
this.onTouched();
}
private updateValue() {
if (this.lastValue !== this.value) {
this.lastValue = this.value;
this.changeCallback(this.value);
this.onChange(this.value);
}
}

37
src/Squidex/app/framework/angular/stars.component.ts

@ -8,7 +8,7 @@
import { Component, forwardRef, Input } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
const NOOP = () => { /* NOOP */ };
import { Types } from './../utils/types';
export const SQX_STARS_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => StarsComponent), multi: true
@ -21,19 +21,15 @@ export const SQX_STARS_CONTROL_VALUE_ACCESSOR: any = {
providers: [SQX_STARS_CONTROL_VALUE_ACCESSOR]
})
export class StarsComponent implements ControlValueAccessor {
private changeCallback: (value: any) => void = NOOP;
private touchedCallback: () => void = NOOP;
private onChange = (v: any) => { /* NOOP */ };
private onTouched = () => { /* NOOP */ };
private maximumStarsValue = 5;
@Input()
public set maximumStars(value: any) {
value = value || 5;
public set maximumStars(value: number) {
const maxStars: number = Types.isNumber(value) ? value : 5;
if (!(typeof value === 'number')) {
value = 5;
}
if (this.maximumStarsValue !== value) {
if (this.maximumStarsValue !== maxStars) {
this.maximumStarsValue = value;
this.starsArray = [];
@ -55,8 +51,13 @@ export class StarsComponent implements ControlValueAccessor {
public value: number | null = 1;
public writeValue(value: any) {
this.value = this.stars = value;
public writeValue(value: number | null | undefined) {
if (Types.isNumber(value)) {
this.value = this.stars = value!;
} else {
this.value = null;
this.stars = 0;
}
}
public setDisabledState(isDisabled: boolean): void {
@ -64,11 +65,11 @@ export class StarsComponent implements ControlValueAccessor {
}
public registerOnChange(fn: any) {
this.changeCallback = fn;
this.onChange = fn;
}
public registerOnTouched(fn: any) {
this.touchedCallback = fn;
this.onTouched = fn;
}
public setPreview(value: number) {
@ -96,8 +97,8 @@ export class StarsComponent implements ControlValueAccessor {
this.value = null;
this.stars = 0;
this.changeCallback(this.value);
this.touchedCallback();
this.onChange(this.value);
this.onTouched();
}
return false;
@ -111,8 +112,8 @@ export class StarsComponent implements ControlValueAccessor {
if (this.value !== value) {
this.value = this.stars = value;
this.changeCallback(this.value);
this.touchedCallback();
this.onChange(this.value);
this.onTouched();
}
return false;

56
src/Squidex/app/framework/angular/tag-editor.component.ts

@ -8,40 +8,54 @@
import { Component, forwardRef, Input } from '@angular/core';
import { ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Types } from './../utils/types';
const KEY_ENTER = 13;
const NOOP = () => { /* NOOP */ };
export interface Converter {
convert(input: string): any;
isValid(input: string): boolean;
isValidInput(input: string): boolean;
isValidValue(value: any): boolean;
}
export class IntConverter implements Converter {
public isValid(input: string): boolean {
public isValidInput(input: string): boolean {
return !!parseInt(input, 10) || input === '0';
}
public isValidValue(value: any): boolean {
return Types.isNumber(value);
}
public convert(input: string): any {
return parseInt(input, 10) || 0;
}
}
export class FloatConverter implements Converter {
public isValid(input: string): boolean {
public isValidInput(input: string): boolean {
return !!parseFloat(input) || input === '0';
}
public isValidValue(value: any): boolean {
return Types.isNumber(value);
}
public convert(input: string): any {
return parseFloat(input) || 0;
}
}
export class NoopConverter implements Converter {
public isValid(input: string): boolean {
export class StringConverter implements Converter {
public isValidInput(input: string): boolean {
return input.trim().length > 0;
}
public isValidValue(value: any): boolean {
return Types.isString(value);
}
public convert(input: string): any {
return input.trim();
}
@ -58,11 +72,11 @@ export const SQX_TAG_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
providers: [SQX_TAG_EDITOR_CONTROL_VALUE_ACCESSOR]
})
export class TagEditorComponent implements ControlValueAccessor {
private changeCallback: (value: any) => void = NOOP;
private touchedCallback: () => void = NOOP;
private onChange = (v: any) => { /* NOOP */ };
private onTouched = () => { /* NOOP */ };
@Input()
public converter: Converter = new NoopConverter();
public converter: Converter = new StringConverter();
@Input()
public useDefaultValue = true;
@ -74,10 +88,10 @@ export class TagEditorComponent implements ControlValueAccessor {
public addInput = new FormControl();
public writeValue(value: any) {
this.addInput.setValue('');
public writeValue(value: any[]) {
this.resetForm();
if (Array.isArray(value)) {
if (this.converter && Types.isArrayOf(value, v => this.converter.isValidValue(v))) {
this.items = value;
} else {
this.items = [];
@ -93,11 +107,11 @@ export class TagEditorComponent implements ControlValueAccessor {
}
public registerOnChange(fn: any) {
this.changeCallback = fn;
this.onChange = fn;
}
public registerOnTouched(fn: any) {
this.touchedCallback = fn;
this.onTouched = fn;
}
public remove(index: number) {
@ -105,18 +119,22 @@ export class TagEditorComponent implements ControlValueAccessor {
}
public markTouched() {
this.touchedCallback();
this.onTouched();
}
private resetForm() {
this.addInput.reset();
}
public onKeyDown(event: KeyboardEvent) {
if (event.keyCode === KEY_ENTER) {
const value = <string>this.addInput.value;
if (this.converter.isValid(value)) {
if (this.converter.isValidInput(value)) {
const converted = this.converter.convert(value);
this.updateItems([...this.items, converted]);
this.addInput.reset();
this.resetForm();
return false;
}
}
@ -128,9 +146,9 @@ export class TagEditorComponent implements ControlValueAccessor {
this.items = items;
if (items.length === 0 && this.useDefaultValue) {
this.changeCallback(undefined);
this.onChange(undefined);
} else {
this.changeCallback(this.items);
this.onChange(this.items);
}
}
}

21
src/Squidex/app/framework/angular/toggle.component.ts

@ -8,7 +8,7 @@
import { Component, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
const NOOP = () => { /* NOOP */ };
import { Types } from './../utils/types';
export const SQX_TOGGLE_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => ToggleComponent), multi: true
@ -21,14 +21,14 @@ export const SQX_TOGGLE_CONTROL_VALUE_ACCESSOR: any = {
providers: [SQX_TOGGLE_CONTROL_VALUE_ACCESSOR]
})
export class ToggleComponent implements ControlValueAccessor {
private changeCallback: (value: any) => void = NOOP;
private touchedCallback: () => void = NOOP;
private onChange = (v: any) => { /* NOOP */ };
private onTouched = () => { /* NOOP */ };
public isChecked: boolean | undefined = undefined;
public isChecked: boolean | null = null;
public isDisabled = false;
public writeValue(value: any) {
this.isChecked = value;
public writeValue(value: boolean | null | undefined) {
this.isChecked = Types.isBoolean(value) ? value! : null;
}
public setDisabledState(isDisabled: boolean): void {
@ -36,20 +36,21 @@ export class ToggleComponent implements ControlValueAccessor {
}
public registerOnChange(fn: any) {
this.changeCallback = fn;
this.onChange = fn;
}
public registerOnTouched(fn: any) {
this.touchedCallback = fn;
this.onTouched = fn;
}
public changeState() {
if (this.isDisabled) {
return;
}
this.isChecked = !(this.isChecked === true);
this.changeCallback(this.isChecked);
this.touchedCallback();
this.onChange(this.isChecked);
this.onTouched();
}
}

39
src/Squidex/app/framework/angular/validators.ts

@ -12,6 +12,7 @@ import {
} from '@angular/forms';
import { DateTime } from './../utils/date-time';
import { Types } from './../utils/types';
export module ValidatorsEx {
export function pattern(regex: string | RegExp, message?: string): ValidatorFn {
@ -30,7 +31,7 @@ export module ValidatorsEx {
regeExp = regex;
}
return (control: AbstractControl): { [key: string]: any } => {
return (control: AbstractControl) => {
const n: string = control.value;
if (n == null || n.length === 0) {
@ -49,16 +50,16 @@ export module ValidatorsEx {
};
}
export function match(otherControlName: string, message: string) {
let otherControl: AbstractControl = null;
export function match(otherControlName: string, message: string): ValidatorFn {
let otherControl: AbstractControl | null = null;
return (control: AbstractControl): { [key: string]: any } => {
return (control: AbstractControl) => {
if (!control.parent) {
return null;
}
if (otherControl === null) {
otherControl = control.parent.get(otherControlName) || undefined;
otherControl = control.parent.get(otherControlName);
if (!otherControl) {
throw new Error('matchValidator(): other control is not found in parent group');
@ -77,8 +78,8 @@ export module ValidatorsEx {
};
}
export function validDateTime() {
return (control: AbstractControl): { [key: string]: any } => {
export function validDateTime(): ValidatorFn {
return (control: AbstractControl) => {
const v: string = control.value;
if (v) {
@ -93,32 +94,32 @@ export module ValidatorsEx {
};
}
export function between(minValue?: number, maxValue?: number) {
export function between(minValue?: number, maxValue?: number): ValidatorFn {
if (!minValue || !maxValue) {
return Validators.nullValidator;
}
return (control: AbstractControl): { [key: string]: any } => {
const n: number = control.value;
return (control: AbstractControl) => {
const value: number = control.value;
if (typeof n !== 'number') {
if (!Types.isNumber(value)) {
return { validnumber: false };
} else if (minValue && n < minValue) {
return { minvalue: { minValue, actualValue: n } };
} else if (maxValue && n > maxValue) {
return { maxvalue: { maxValue, actualValue: n } };
} else if (minValue && value < minValue) {
return { minvalue: { minValue, actualValue: value } };
} else if (maxValue && value > maxValue) {
return { maxvalue: { maxValue, actualValue: value } };
}
return null;
};
}
export function validValues<T>(values: T[]) {
export function validValues<T>(values: T[]): ValidatorFn {
if (!values) {
return Validators.nullValidator;
}
return (control: AbstractControl): { [key: string]: any } => {
return (control: AbstractControl) => {
const n: T = control.value;
if (values.indexOf(n) < 0) {
@ -129,8 +130,8 @@ export module ValidatorsEx {
};
}
export function noop() {
return (control: AbstractControl): { [key: string]: any } => {
export function noop(): ValidatorFn {
return (control: AbstractControl) => {
return null;
};
}

1
src/Squidex/app/framework/declarations.ts

@ -71,4 +71,5 @@ export * from './utils/math-helper';
export * from './utils/modal-view';
export * from './utils/pager';
export * from './utils/string-helper';
export * from './utils/types';
export * from './utils/version';

2
src/Squidex/app/framework/services/local-cache.service.ts

@ -31,7 +31,7 @@ export class LocalCacheService {
}
}
public get<T>(key: string, now?: number): T {
public get<T>(key: string, now?: number): T | undefined {
const entry = this.entries[key];
if (entry) {

92
src/Squidex/app/framework/utils/types.spec.ts

@ -0,0 +1,92 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import { Types } from './../';
describe('Types', () => {
it('should make string check', () => {
expect(Types.isString('')).toBeTruthy();
expect(Types.isString('string')).toBeTruthy();
expect(Types.isString(false)).toBeFalsy();
});
it('should make number check', () => {
expect(Types.isNumber(0)).toBeTruthy();
expect(Types.isNumber(1)).toBeTruthy();
expect(Types.isNumber(NaN)).toBeFalsy();
expect(Types.isNumber(Infinity)).toBeFalsy();
expect(Types.isNumber(false)).toBeFalsy();
});
it('should make boolean check', () => {
expect(Types.isBoolean(true)).toBeTruthy();
expect(Types.isBoolean(false)).toBeTruthy();
expect(Types.isBoolean(0)).toBeFalsy();
expect(Types.isBoolean(1)).toBeFalsy();
});
it('should make number array check', () => {
expect(Types.isArrayOfNumber([])).toBeTruthy();
expect(Types.isArrayOfNumber([0, 1])).toBeTruthy();
expect(Types.isArrayOfNumber(['0', 1])).toBeFalsy();
});
it('should make string array check', () => {
expect(Types.isArrayOfString([])).toBeTruthy();
expect(Types.isArrayOfString(['0', '1'])).toBeTruthy();
expect(Types.isArrayOfString(['0', 1])).toBeFalsy();
});
it('should make array check', () => {
expect(Types.isArray([])).toBeTruthy();
expect(Types.isArray([0])).toBeTruthy();
expect(Types.isArray({})).toBeFalsy();
});
it('should make object check', () => {
expect(Types.isObject({})).toBeTruthy();
expect(Types.isObject({ v: 1 })).toBeTruthy();
expect(Types.isObject([])).toBeFalsy();
});
it('should make RegExp check', () => {
expect(Types.isRegExp(/[.*]/)).toBeTruthy();
expect(Types.isRegExp('/[.*]/')).toBeFalsy();
});
it('should make Date check', () => {
expect(Types.isDate(new Date())).toBeTruthy();
expect(Types.isDate(new Date().getDate())).toBeFalsy();
});
it('should make undefined check', () => {
expect(Types.isUndefined(undefined)).toBeTruthy();
expect(Types.isUndefined(null)).toBeFalsy();
});
it('should make null check', () => {
expect(Types.isNull(null)).toBeTruthy();
expect(Types.isNull(undefined)).toBeFalsy();
});
it('should make function check', () => {
expect(Types.isFunction(() => { /* NOOP */ })).toBeTruthy();
expect(Types.isFunction([])).toBeFalsy();
});
});

70
src/Squidex/app/framework/utils/types.ts

@ -0,0 +1,70 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
export module Types {
export function isString(value: any): boolean {
return typeof value === 'string' || value instanceof String;
}
export function isNumber(value: any): boolean {
return typeof value === 'number' && isFinite(value);
}
export function isArray(value: any): boolean {
return Array.isArray(value);
}
export function isFunction(value: any): boolean {
return typeof value === 'function';
}
export function isObject(value: any): boolean {
return value && typeof value === 'object' && value.constructor === Object;
}
export function isBoolean(value: any): boolean {
return typeof value === 'boolean';
};
export function isNull(value: any): boolean {
return value === null;
}
export function isUndefined(value: any): boolean {
return typeof value === 'undefined';
}
export function isRegExp(value: any): boolean {
return value && typeof value === 'object' && value.constructor === RegExp;
}
export function isDate(value: any): boolean {
return value instanceof Date;
}
export function isArrayOfNumber(value: any): boolean {
return isArrayOf(value, v => isNumber(v));
}
export function isArrayOfString(value: any): boolean {
return isArrayOf(value, v => isString(v));
}
export function isArrayOf(value: any, validator: (v: any) => boolean): boolean {
if (!Array.isArray(value)) {
return false;
}
for (let v of value) {
if (!validator(v)) {
return false;
}
}
return true;
}
}

6
src/Squidex/app/shared/components/asset.component.ts

@ -83,7 +83,7 @@ export class AssetComponent extends AppComponentBase implements OnInit {
if (initFile) {
this.appNameOnce()
.switchMap(app => this.assetsService.uploadFile(app, initFile, this.authService.user.token))
.switchMap(app => this.assetsService.uploadFile(app, initFile, this.authService.user!.token))
.subscribe(dto => {
if (dto instanceof AssetDto) {
this.emitLoaded(dto);
@ -104,7 +104,7 @@ export class AssetComponent extends AppComponentBase implements OnInit {
.switchMap(app => this.assetsService.replaceFile(app, this.asset.id, files[0], this.assetVersion))
.subscribe(dto => {
if (dto instanceof AssetReplacedDto) {
this.updateAsset(this.asset.update(dto, this.authService.user.token), true);
this.updateAsset(this.asset.update(dto, this.authService.user!.token), true);
} else {
this.setProgress(dto);
}
@ -126,7 +126,7 @@ export class AssetComponent extends AppComponentBase implements OnInit {
this.appNameOnce()
.switchMap(app => this.assetsService.putAsset(app, this.asset.id, requestDto, this.assetVersion))
.subscribe(() => {
this.updateAsset(this.asset.rename(requestDto.fileName, this.authService.user.token), true);
this.updateAsset(this.asset.rename(requestDto.fileName, this.authService.user!.token), true);
this.resetRenameForm();
}, error => {
this.notifyError(error);

4
src/Squidex/app/shared/guards/resolve-app-languages.guard.ts

@ -14,14 +14,14 @@ import { allParams } from 'framework';
import { AppLanguageDto, AppLanguagesService } from './../services/app-languages.service';
@Injectable()
export class ResolveAppLanguagesGuard implements Resolve<AppLanguageDto[]> {
export class ResolveAppLanguagesGuard implements Resolve<AppLanguageDto[] | null> {
constructor(
private readonly appLanguagesService: AppLanguagesService,
private readonly router: Router
) {
}
public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<AppLanguageDto[]> {
public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<AppLanguageDto[] | null> {
const params = allParams(route);
const appName = params['appName'];

4
src/Squidex/app/shared/guards/resolve-content.guard.ts

@ -14,14 +14,14 @@ import { allParams } from 'framework';
import { ContentDto, ContentsService } from './../services/contents.service';
@Injectable()
export class ResolveContentGuard implements Resolve<ContentDto> {
export class ResolveContentGuard implements Resolve<ContentDto | null> {
constructor(
private readonly contentsService: ContentsService,
private readonly router: Router
) {
}
public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<ContentDto> {
public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<ContentDto | null> {
const params = allParams(route);
const appName = params['appName'];

4
src/Squidex/app/shared/guards/resolve-user.guard.ts

@ -14,14 +14,14 @@ import { allParams } from 'framework';
import { UserDto, UserManagementService } from './../services/users.service';
@Injectable()
export class ResolveUserGuard implements Resolve<UserDto> {
export class ResolveUserGuard implements Resolve<UserDto | null> {
constructor(
private readonly userManagementService: UserManagementService,
private readonly router: Router
) {
}
public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<UserDto> {
public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<UserDto | null> {
const params = allParams(route);
const userId = params['userId'];

2
src/Squidex/app/shared/interceptors/auth.interceptor.spec.ts

@ -18,7 +18,7 @@ import {
} from './../';
describe('AuthInterceptor', () => {
let authService: IMock<AuthService> = null;
let authService: IMock<AuthService>;
beforeEach(() => {
authService = Mock.ofType(AuthService);

2
src/Squidex/app/shared/interceptors/auth.interceptor.ts

@ -32,7 +32,7 @@ export class AuthInterceptor implements HttpInterceptor {
}
}
private makeRequest(req: HttpRequest<any>, next: HttpHandler, user: Profile, renew = false): Observable<HttpEvent<any>> {
private makeRequest(req: HttpRequest<any>, next: HttpHandler, user: Profile | null, renew = false): Observable<HttpEvent<any>> {
const token = user ? user.authToken : '';
const authReq = req.clone({

6
src/Squidex/app/shared/services/app-clients.service.ts

@ -84,7 +84,7 @@ export class AppClientsService {
.pretifyError('Failed to load clients. Please reload.');
}
public postClient(appName: string, dto: CreateAppClientDto, version?: Version): Observable<AppClientDto> {
public postClient(appName: string, dto: CreateAppClientDto, version: Version): Observable<AppClientDto> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/clients`);
return HTTP.postVersioned(this.http, url, dto, version)
@ -98,14 +98,14 @@ export class AppClientsService {
.pretifyError('Failed to add client. Please reload.');
}
public updateClient(appName: string, id: string, dto: UpdateAppClientDto, version?: Version): Observable<any> {
public updateClient(appName: string, id: string, dto: UpdateAppClientDto, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/clients/${id}`);
return HTTP.putVersioned(this.http, url, dto, version)
.pretifyError('Failed to revoke client. Please reload.');
}
public deleteClient(appName: string, id: string, version?: Version): Observable<any> {
public deleteClient(appName: string, id: string, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/clients/${id}`);
return HTTP.deleteVersioned(this.http, url, version)

4
src/Squidex/app/shared/services/app-contributors.service.ts

@ -63,14 +63,14 @@ export class AppContributorsService {
.pretifyError('Failed to load contributors. Please reload.');
}
public postContributor(appName: string, dto: AppContributorDto, version?: Version): Observable<any> {
public postContributor(appName: string, dto: AppContributorDto, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/contributors`);
return HTTP.postVersioned(this.http, url, dto, version)
.pretifyError('Failed to add contributors. Please reload.');
}
public deleteContributor(appName: string, contributorId: string, version?: Version): Observable<any> {
public deleteContributor(appName: string, contributorId: string, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/contributors/${contributorId}`);
return HTTP.deleteVersioned(this.http, url, version)

6
src/Squidex/app/shared/services/app-languages.service.ts

@ -75,7 +75,7 @@ export class AppLanguagesService {
.pretifyError('Failed to load languages. Please reload.');
}
public postLanguages(appName: string, dto: AddAppLanguageDto, version?: Version): Observable<AppLanguageDto> {
public postLanguages(appName: string, dto: AddAppLanguageDto, version: Version): Observable<AppLanguageDto> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/languages`);
return HTTP.postVersioned(this.http, url, dto, version)
@ -90,14 +90,14 @@ export class AppLanguagesService {
.pretifyError('Failed to add language. Please reload.');
}
public updateLanguage(appName: string, languageCode: string, dto: UpdateAppLanguageDto, version?: Version): Observable<any> {
public updateLanguage(appName: string, languageCode: string, dto: UpdateAppLanguageDto, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/languages/${languageCode}`);
return HTTP.putVersioned(this.http, url, dto, version)
.pretifyError('Failed to change language. Please reload.');
}
public deleteLanguage(appName: string, languageCode: string, version?: Version): Observable<any> {
public deleteLanguage(appName: string, languageCode: string, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/languages/${languageCode}`);
return HTTP.deleteVersioned(this.http, url, version)

19
src/Squidex/app/shared/services/assets.service.spec.ts

@ -24,7 +24,7 @@ describe('AssetDto', () => {
it('should update name property and user info when renaming', () => {
const now = DateTime.now();
const asset_1 = new AssetDto('1', 'other', 'other', DateTime.today(), DateTime.today(), 'name.png', 'png', 1, 1, 'image/png', false, 1, 1, null);
const asset_1 = new AssetDto('1', 'other', 'other', DateTime.today(), DateTime.today(), 'name.png', 'png', 1, 1, 'image/png', false, 1, 1, new Version('1'));
const asset_2 = asset_1.rename('new-name.png', 'me', now);
expect(asset_2.fileName).toEqual('new-name.png');
@ -35,9 +35,9 @@ describe('AssetDto', () => {
it('should update file properties when uploading', () => {
const now = DateTime.now();
const update = new AssetReplacedDto(2, 2, 'image/jpeg', true, 2, 2, null);
const update = new AssetReplacedDto(2, 2, 'image/jpeg', true, 2, 2, new Version('1'));
const asset_1 = new AssetDto('1', 'other', 'other', DateTime.today(), DateTime.today(), 'name.png', 'png', 1, 1, 'image/png', false, 1, 1, null);
const asset_1 = new AssetDto('1', 'other', 'other', DateTime.today(), DateTime.today(), 'name.png', 'png', 1, 1, 'image/png', false, 1, 1, new Version('1'));
const asset_2 = asset_1.update(update, 'me', now);
expect(asset_2.fileSize).toEqual(2);
@ -48,6 +48,7 @@ describe('AssetDto', () => {
expect(asset_2.pixelHeight).toEqual(2);
expect(asset_2.lastModified).toEqual(now);
expect(asset_2.lastModifiedBy).toEqual('me');
expect(asset_2.version).toEqual(update);
});
});
@ -160,7 +161,7 @@ describe('AssetsService', () => {
let asset: AssetDto | null = null;
assetsService.getAsset('my-app', '123').subscribe(result => {
assetsService.getAsset('my-app', '123', version).subscribe(result => {
asset = result;
});
@ -211,14 +212,14 @@ describe('AssetsService', () => {
let asset: AssetDto | null = null;
assetsService.getAsset('my-app', '123').subscribe(result => {
assetsService.getAsset('my-app', '123', version).subscribe(result => {
asset = result;
});
const req = httpMock.expectOne('http://service/p/api/apps/my-app/assets/123');
expect(req.request.method).toEqual('GET');
expect(req.request.headers.get('If-Match')).toBeNull();
expect(req.request.headers.get('If-Match')).toEqual(version.value);
req.flush({}, { status: 404, statusText: '404' });
@ -246,7 +247,7 @@ describe('AssetsService', () => {
const req = httpMock.expectOne('http://service/p/api/apps/my-app/assets?mimeTypes=image/png,image/png&take=17&skip=13');
expect(req.request.method).toEqual('GET');
expect(req.request.headers.get('If-Match')).toBeNull();
expect(req.request.headers.get('If-Match')).toEqual(version.value);
req.flush({ total: 10, items: [] });
}));
@ -259,7 +260,7 @@ describe('AssetsService', () => {
const req = httpMock.expectOne('http://service/p/api/apps/my-app/assets?ids=12,23&take=17&skip=13');
expect(req.request.method).toEqual('GET');
expect(req.request.headers.get('If-Match')).toBeNull();
expect(req.request.headers.get('If-Match')).toEqual(version.value);
req.flush({ total: 10, items: [] });
}));
@ -276,7 +277,7 @@ describe('AssetsService', () => {
const req = httpMock.expectOne('http://service/p/api/apps/my-app/assets');
expect(req.request.method).toEqual('POST');
expect(req.request.headers.get('If-Match')).toBeNull();
expect(req.request.headers.get('If-Match')).toEqual(version.value);
req.flush({
id: 'id1',

23
src/Squidex/app/shared/services/assets.service.ts

@ -163,7 +163,7 @@ export class AssetsService {
return this.http.request(req)
.map(event => {
if (event.type === HttpEventType.UploadProgress) {
const percentDone = Math.round(100 * event.loaded / event.total);
const percentDone = event.total ? Math.round(100 * event.loaded / event.total) : 0;
return percentDone;
} else if (event instanceof HttpResponse) {
@ -235,20 +235,21 @@ export class AssetsService {
.pretifyError('Failed to load assets. Please reload.');
}
public replaceFile(appName: string, id: string, file: File, version?: Version): Observable<number | AssetReplacedDto> {
public replaceFile(appName: string, id: string, file: File, version: Version): Observable<number | AssetReplacedDto> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/assets/${id}/content`);
const req = new HttpRequest('PUT', url, getFormData(file), {
headers: new HttpHeaders({
'If-Match': version.value
}),
reportProgress: true
});
const headers = new HttpHeaders();
if (version) {
headers.set('If-Match', version.value);
}
const req = new HttpRequest('PUT', url, getFormData(file), { headers, reportProgress: true });
return this.http.request(req)
.map(event => {
if (event.type === HttpEventType.UploadProgress) {
const percentDone = Math.round(100 * event.loaded / event.total);
const percentDone = event.total ? Math.round(100 * event.loaded / event.total) : 0;
return percentDone;
} else if (event instanceof HttpResponse) {
@ -269,7 +270,7 @@ export class AssetsService {
.pretifyError('Failed to replace asset. Please reload.');
}
public deleteAsset(appName: string, id: string, version?: Version): Observable<any> {
public deleteAsset(appName: string, id: string, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/assets/${id}`);
return HTTP.deleteVersioned(this.http, url, version)
@ -279,7 +280,7 @@ export class AssetsService {
.pretifyError('Failed to delete asset. Please reload.');
}
public putAsset(appName: string, id: string, dto: UpdateAssetDto, version?: Version): Observable<any> {
public putAsset(appName: string, id: string, dto: UpdateAssetDto, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/assets/${id}`);
return HTTP.putVersioned(this.http, url, dto, version)

18
src/Squidex/app/shared/services/auth.service.ts

@ -39,7 +39,7 @@ export class Profile {
}
public get authToken(): string {
return `${this.user.token_type} ${this.user.access_token}`;
return `${this.user!.token_type} ${this.user.access_token}`;
}
public get token(): string {
@ -56,7 +56,7 @@ export class Profile {
export class AuthService {
private readonly userManager: UserManager;
private readonly user$ = new ReplaySubject<Profile | null>(1);
private currentUser: Profile = null;
private currentUser: Profile | null = null;
public get user(): Profile | null {
return this.currentUser;
@ -150,7 +150,7 @@ export class AuthService {
public loginSilent(): Observable<Profile> {
const observable: Observable<Profile> =
Observable.create((observer: Observer<Profile>) => {
Observable.create((observer: Observer<Profile | null>) => {
this.userManager.signinSilent()
.then(x => {
observer.next(this.createProfile(x));
@ -169,13 +169,17 @@ export class AuthService {
.concat(Observable.throw(new Error('Retry limit exceeded.'))));
}
private createProfile(user: User) {
return user ? new Profile(user) : null;
private createProfile(user: User): Profile {
return new Profile(user);
}
private checkState(promise: Promise<User>) {
private checkState(promise: Promise<User | null>) {
promise.then(user => {
this.user$.next(this.createProfile(user));
if (user) {
this.user$.next(this.createProfile(user));
} else {
this.user$.next(null);
}
return true;
}, err => {

16
src/Squidex/app/shared/services/contents.service.spec.ts

@ -22,7 +22,7 @@ describe('ContentDto', () => {
it('should update data property and user info when updating', () => {
const now = DateTime.now();
const content_1 = new ContentDto('1', false, false, 'other', 'other', DateTime.now(), DateTime.now(), { data: 1 }, null);
const content_1 = new ContentDto('1', false, false, 'other', 'other', DateTime.now(), DateTime.now(), { data: 1 }, new Version('1'));
const content_2 = content_1.update({ data: 2 }, 'me', now);
expect(content_2.data).toEqual({ data: 2 });
@ -33,7 +33,7 @@ describe('ContentDto', () => {
it('should update isPublished property and user info when publishing', () => {
const now = DateTime.now();
const content_1 = new ContentDto('1', false, false, 'other', 'other', DateTime.now(), DateTime.now(), { data: 1 }, null);
const content_1 = new ContentDto('1', false, false, 'other', 'other', DateTime.now(), DateTime.now(), { data: 1 }, new Version('1'));
const content_2 = content_1.publish('me', now);
expect(content_2.isPublished).toBeTruthy();
@ -44,7 +44,7 @@ describe('ContentDto', () => {
it('should update isPublished property and user info when unpublishing', () => {
const now = DateTime.now();
const content_1 = new ContentDto('1', true, false, 'other', 'other', DateTime.now(), DateTime.now(), { data: 1 }, null);
const content_1 = new ContentDto('1', true, false, 'other', 'other', DateTime.now(), DateTime.now(), { data: 1 }, new Version('1'));
const content_2 = content_1.unpublish('me', now);
expect(content_2.isPublished).toBeFalsy();
@ -55,7 +55,7 @@ describe('ContentDto', () => {
it('should update data property when setting data', () => {
const newData = {};
const content_1 = new ContentDto('1', true, false, 'other', 'other', DateTime.now(), DateTime.now(), { data: 1 }, null);
const content_1 = new ContentDto('1', true, false, 'other', 'other', DateTime.now(), DateTime.now(), { data: 1 }, new Version('1'));
const content_2 = content_1.setData(newData);
expect(content_2.data).toBe(newData);
@ -140,7 +140,7 @@ describe('ContentsService', () => {
it('should append query to get request as search',
inject([ContentsService, HttpTestingController], (contentsService: ContentsService, httpMock: HttpTestingController) => {
let contents: ContentsDto | null;
let contents: ContentsDto | null = null;
contentsService.getContents('my-app', 'my-schema', 17, 13, 'my-query').subscribe(result => {
contents = result;
@ -157,9 +157,9 @@ describe('ContentsService', () => {
it('should append ids to get request with ids',
inject([ContentsService, HttpTestingController], (contentsService: ContentsService, httpMock: HttpTestingController) => {
let contents: ContentsDto | null;
let contents: ContentsDto | null = null;
contentsService.getContents('my-app', 'my-schema', 17, 13, null, ['id1', 'id2']).subscribe(result => {
contentsService.getContents('my-app', 'my-schema', 17, 13, undefined, ['id1', 'id2']).subscribe(result => {
contents = result;
});
@ -174,7 +174,7 @@ describe('ContentsService', () => {
it('should append query to get request as plain query string',
inject([ContentsService, HttpTestingController], (contentsService: ContentsService, httpMock: HttpTestingController) => {
let contents: ContentsDto | null;
let contents: ContentsDto | null = null;
contentsService.getContents('my-app', 'my-schema', 17, 13, '$filter=my-filter').subscribe(result => {
contents = result;

14
src/Squidex/app/shared/services/contents.service.ts

@ -176,7 +176,7 @@ export class ContentsService {
.pretifyError('Failed to load content. Please reload.');
}
public postContent(appName: string, schemaName: string, dto: any, publish: boolean, version?: Version): Observable<ContentDto> {
public postContent(appName: string, schemaName: string, dto: any, publish: boolean, version: Version): Observable<ContentDto> {
const url = this.apiUrl.buildUrl(`/api/content/${appName}/${schemaName}?publish=${publish}`);
return HTTP.postVersioned(this.http, url, dto, version)
@ -197,7 +197,7 @@ export class ContentsService {
.pretifyError('Failed to create content. Please reload.');
}
public putContent(appName: string, schemaName: string, id: string, dto: any, version?: Version): Observable<any> {
public putContent(appName: string, schemaName: string, id: string, dto: any, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`/api/content/${appName}/${schemaName}/${id}`);
return HTTP.putVersioned(this.http, url, dto, version)
@ -207,8 +207,8 @@ export class ContentsService {
.pretifyError('Failed to update content. Please reload.');
}
public deleteContent(appName: string, schemaName: string, id: string, version?: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`/api/content/${appName}/${schemaName}/${id}`);
public deleteContent(appName: string, schemaName: string, id: string, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`/api/coentent/${appName}/${schemaName}/${id}`);
return HTTP.deleteVersioned(this.http, url, version)
.do(() => {
@ -217,21 +217,21 @@ export class ContentsService {
.pretifyError('Failed to delete content. Please reload.');
}
public getVersionData(appName: string, schemaName: string, id: string, version?: Version): Observable<any> {
public getVersionData(appName: string, schemaName: string, id: string, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`/api/content/${appName}/${schemaName}/${id}/${version.value}`);
return HTTP.getVersioned(this.http, url, version)
.pretifyError('Failed to load data. Please reload.');
}
public publishContent(appName: string, schemaName: string, id: string, version?: Version): Observable<any> {
public publishContent(appName: string, schemaName: string, id: string, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`/api/content/${appName}/${schemaName}/${id}/publish`);
return HTTP.putVersioned(this.http, url, {}, version)
.pretifyError('Failed to publish content. Please reload.');
}
public unpublishContent(appName: string, schemaName: string, id: string, version?: Version): Observable<any> {
public unpublishContent(appName: string, schemaName: string, id: string, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`/api/content/${appName}/${schemaName}/${id}/unpublish`);
return HTTP.putVersioned(this.http, url, {}, version)

2
src/Squidex/app/shared/services/plans.service.ts

@ -85,7 +85,7 @@ export class PlansService {
.pretifyError('Failed to load plans. Please reload.');
}
public putPlan(appName: string, dto: ChangePlanDto, version?: Version): Observable<PlanChangedDto> {
public putPlan(appName: string, dto: ChangePlanDto, version: Version): Observable<PlanChangedDto> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/plan`);
return HTTP.putVersioned(this.http, url, dto, version)

32
src/Squidex/app/shared/services/schemas.service.spec.ts

@ -27,12 +27,12 @@ import {
} from './../';
describe('SchemaDto', () => {
const properties = new SchemaPropertiesDto('Name', null);
const properties = new SchemaPropertiesDto('Name');
it('should update isPublished property and user info when publishing', () => {
const now = DateTime.now();
const schema_1 = new SchemaDto('1', 'name', properties, false, 'other', 'other', DateTime.now(), DateTime.now(), null);
const schema_1 = new SchemaDto('1', 'name', properties, false, 'other', 'other', DateTime.now(), DateTime.now(), new Version('1'));
const schema_2 = schema_1.publish('me', now);
expect(schema_2.isPublished).toBeTruthy();
@ -43,7 +43,7 @@ describe('SchemaDto', () => {
it('should update isPublished property and user info when unpublishing', () => {
const now = DateTime.now();
const schema_1 = new SchemaDto('1', 'name', properties, true, 'other', 'other', DateTime.now(), DateTime.now(), null);
const schema_1 = new SchemaDto('1', 'name', properties, true, 'other', 'other', DateTime.now(), DateTime.now(), new Version('1'));
const schema_2 = schema_1.unpublish('me', now);
expect(schema_2.isPublished).toBeFalsy();
@ -52,11 +52,11 @@ describe('SchemaDto', () => {
});
it('should update properties property and user info when updating', () => {
const newProperties = new SchemaPropertiesDto('New Name', null);
const newProperties = new SchemaPropertiesDto('New Name');
const now = DateTime.now();
const schema_1 = new SchemaDto('1', 'name', properties, false, 'other', 'other', DateTime.now(), DateTime.now(), null);
const schema_1 = new SchemaDto('1', 'name', properties, false, 'other', 'other', DateTime.now(), DateTime.now(), new Version('1'));
const schema_2 = schema_1.update(newProperties, 'me', now);
expect(schema_2.properties).toEqual(newProperties);
@ -76,7 +76,7 @@ describe('SchemaDto', () => {
const now = DateTime.now();
const schema_1 = new SchemaDetailsDto('1', 'name', properties, false, 'other', 'other', DateTime.now(), DateTime.now(), null, []);
const schema_1 = new SchemaDetailsDto('1', 'name', properties, false, 'other', 'other', DateTime.now(), DateTime.now(), new Version('1'), []);
const schema_2 = schema_1.configureScripts(newScripts, 'me', now);
expect(schema_2.scriptQuery).toEqual('<script-query>');
@ -91,12 +91,12 @@ describe('SchemaDto', () => {
});
describe('SchemaDetailsDto', () => {
const properties = new SchemaPropertiesDto('Name', null);
const properties = new SchemaPropertiesDto('Name');
it('should update isPublished property and user info when publishing', () => {
const now = DateTime.now();
const schema_1 = new SchemaDetailsDto('1', 'name', properties, false, 'other', 'other', DateTime.now(), DateTime.now(), null, []);
const schema_1 = new SchemaDetailsDto('1', 'name', properties, false, 'other', 'other', DateTime.now(), DateTime.now(), new Version('1'), []);
const schema_2 = schema_1.publish('me', now);
expect(schema_2.isPublished).toBeTruthy();
@ -107,7 +107,7 @@ describe('SchemaDetailsDto', () => {
it('should update isPublished property and user info when unpublishing', () => {
const now = DateTime.now();
const schema_1 = new SchemaDetailsDto('1', 'name', properties, true, 'other', 'other', DateTime.now(), DateTime.now(), null, []);
const schema_1 = new SchemaDetailsDto('1', 'name', properties, true, 'other', 'other', DateTime.now(), DateTime.now(), new Version('1'), []);
const schema_2 = schema_1.unpublish('me', now);
expect(schema_2.isPublished).toBeFalsy();
@ -116,11 +116,11 @@ describe('SchemaDetailsDto', () => {
});
it('should update properties property and user info when updating', () => {
const newProperties = new SchemaPropertiesDto('New Name', null);
const newProperties = new SchemaPropertiesDto('New Name');
const now = DateTime.now();
const schema_1 = new SchemaDetailsDto('1', 'name', properties, false, 'other', 'other', DateTime.now(), DateTime.now(), null, []);
const schema_1 = new SchemaDetailsDto('1', 'name', properties, false, 'other', 'other', DateTime.now(), DateTime.now(), new Version('1'), []);
const schema_2 = schema_1.update(newProperties, 'me', now);
expect(schema_2.properties).toEqual(newProperties);
@ -134,7 +134,7 @@ describe('SchemaDetailsDto', () => {
const now = DateTime.now();
const schema_1 = new SchemaDetailsDto('1', 'name', properties, false, 'other', 'other', DateTime.now(), DateTime.now(), null, [field1]);
const schema_1 = new SchemaDetailsDto('1', 'name', properties, false, 'other', 'other', DateTime.now(), DateTime.now(), new Version('1'), [field1]);
const schema_2 = schema_1.addField(field2, 'me', now);
expect(schema_2.fields).toEqual([field1, field2]);
@ -148,7 +148,7 @@ describe('SchemaDetailsDto', () => {
const now = DateTime.now();
const schema_1 = new SchemaDetailsDto('1', 'name', properties, false, 'other', 'other', DateTime.now(), DateTime.now(), null, [field1, field2]);
const schema_1 = new SchemaDetailsDto('1', 'name', properties, false, 'other', 'other', DateTime.now(), DateTime.now(), new Version('1'), [field1, field2]);
const schema_2 = schema_1.removeField(field1, 'me', now);
expect(schema_2.fields).toEqual([field2]);
@ -162,7 +162,7 @@ describe('SchemaDetailsDto', () => {
const now = DateTime.now();
const schema_1 = new SchemaDetailsDto('1', 'name', properties, false, 'other', 'other', DateTime.now(), DateTime.now(), null, [field1, field2]);
const schema_1 = new SchemaDetailsDto('1', 'name', properties, false, 'other', 'other', DateTime.now(), DateTime.now(), new Version('1'), [field1, field2]);
const schema_2 = schema_1.replaceFields([field2, field1], 'me', now);
expect(schema_2.fields).toEqual([field2, field1]);
@ -177,7 +177,7 @@ describe('SchemaDetailsDto', () => {
const now = DateTime.now();
const schema_1 = new SchemaDetailsDto('1', 'name', properties, false, 'other', 'other', DateTime.now(), DateTime.now(), null, [field1_0, field2_1]);
const schema_1 = new SchemaDetailsDto('1', 'name', properties, false, 'other', 'other', DateTime.now(), DateTime.now(), new Version('1'), [field1_0, field2_1]);
const schema_2 = schema_1.updateField(field2_2, 'me', now);
expect(schema_2.fields).toEqual([field1_0, field2_2]);
@ -461,7 +461,7 @@ describe('SchemasService', () => {
req.flush({ id: '1' });
expect(schema).toEqual(
new SchemaDetailsDto('1', dto.name, new SchemaPropertiesDto(null, null), false, user, user, now, now, version, []));
new SchemaDetailsDto('1', dto.name, new SchemaPropertiesDto(), false, user, user, now, now, version, []));
}));
it('should make post request to add field',

38
src/Squidex/app/shared/services/schemas.service.ts

@ -643,8 +643,8 @@ export class JsonFieldPropertiesDto extends FieldPropertiesDto {
export class SchemaPropertiesDto {
constructor(
public readonly label: string,
public readonly hints: string
public readonly label?: string,
public readonly hints?: string
) {
}
}
@ -781,7 +781,7 @@ export class SchemasService {
.pretifyError('Failed to load schema. Please reload.');
}
public postSchema(appName: string, dto: CreateSchemaDto, user: string, now?: DateTime, version?: Version): Observable<SchemaDetailsDto> {
public postSchema(appName: string, dto: CreateSchemaDto, user: string, now: DateTime, version: Version): Observable<SchemaDetailsDto> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas`);
return HTTP.postVersioned(this.http, url, dto, version)
@ -791,13 +791,13 @@ export class SchemasService {
return new SchemaDetailsDto(
response.id,
dto.name,
dto.properties || new SchemaPropertiesDto(null, null),
dto.properties || new SchemaPropertiesDto(),
false,
user,
user,
now,
now,
version,
version || new Version('0'),
dto.fields || [],
response.scriptQuery,
response.scriptCreate,
@ -813,7 +813,7 @@ export class SchemasService {
.pretifyError('Failed to create schema. Please reload.');
}
public postField(appName: string, schemaName: string, dto: AddFieldDto, version?: Version): Observable<FieldDto> {
public postField(appName: string, schemaName: string, dto: AddFieldDto, version: Version): Observable<FieldDto> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}/fields`);
return HTTP.postVersioned(this.http, url, dto, version)
@ -830,7 +830,7 @@ export class SchemasService {
.pretifyError('Failed to add field. Please reload.');
}
public deleteSchema(appName: string, schemaName: string, version?: Version): Observable<any> {
public deleteSchema(appName: string, schemaName: string, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}`);
return HTTP.deleteVersioned(this.http, url, version)
@ -840,84 +840,84 @@ export class SchemasService {
.pretifyError('Failed to delete schema. Please reload.');
}
public putSchemaScripts(appName: string, schemaName: string, dto: UpdateSchemaScriptsDto, version?: Version): Observable<any> {
public putSchemaScripts(appName: string, schemaName: string, dto: UpdateSchemaScriptsDto, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}/scripts`);
return HTTP.putVersioned(this.http, url, dto, version)
.pretifyError('Failed to update schema scripts. Please reload.');
}
public putSchema(appName: string, schemaName: string, dto: UpdateSchemaDto, version?: Version): Observable<any> {
public putSchema(appName: string, schemaName: string, dto: UpdateSchemaDto, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}`);
return HTTP.putVersioned(this.http, url, dto, version)
.pretifyError('Failed to update schema. Please reload.');
}
public putFieldOrdering(appName: string, schemaName: string, dto: number[], version?: Version): Observable<any> {
public putFieldOrdering(appName: string, schemaName: string, dto: number[], version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}/fields/ordering`);
return HTTP.putVersioned(this.http, url, { fieldIds: dto }, version)
.pretifyError('Failed to reorder fields. Please reload.');
}
public publishSchema(appName: string, schemaName: string, version?: Version): Observable<any> {
public publishSchema(appName: string, schemaName: string, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}/publish`);
return HTTP.putVersioned(this.http, url, {}, version)
.pretifyError('Failed to publish schema. Please reload.');
}
public unpublishSchema(appName: string, schemaName: string, version?: Version): Observable<any> {
public unpublishSchema(appName: string, schemaName: string, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}/unpublish`);
return HTTP.putVersioned(this.http, url, {}, version)
.pretifyError('Failed to unpublish schema. Please reload.');
}
public putField(appName: string, schemaName: string, fieldId: number, dto: UpdateFieldDto, version?: Version): Observable<any> {
public putField(appName: string, schemaName: string, fieldId: number, dto: UpdateFieldDto, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}/fields/${fieldId}`);
return HTTP.putVersioned(this.http, url, dto, version)
.pretifyError('Failed to update field. Please reload.');
}
public enableField(appName: string, schemaName: string, fieldId: number, version?: Version): Observable<any> {
public enableField(appName: string, schemaName: string, fieldId: number, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}/fields/${fieldId}/enable`);
return HTTP.putVersioned(this.http, url, {}, version)
.pretifyError('Failed to enable field. Please reload.');
}
public disableField(appName: string, schemaName: string, fieldId: number, version?: Version): Observable<any> {
public disableField(appName: string, schemaName: string, fieldId: number, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}/fields/${fieldId}/disable`);
return HTTP.putVersioned(this.http, url, {}, version)
.pretifyError('Failed to disable field. Please reload.');
}
public lockField(appName: string, schemaName: string, fieldId: number, version?: Version): Observable<any> {
public lockField(appName: string, schemaName: string, fieldId: number, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}/fields/${fieldId}/lock`);
return HTTP.putVersioned(this.http, url, {}, version)
.pretifyError('Failed to lock field. Please reload.');
}
public showField(appName: string, schemaName: string, fieldId: number, version?: Version): Observable<any> {
public showField(appName: string, schemaName: string, fieldId: number, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}/fields/${fieldId}/show`);
return HTTP.putVersioned(this.http, url, {}, version)
.pretifyError('Failed to show field. Please reload.');
}
public hideField(appName: string, schemaName: string, fieldId: number, version?: Version): Observable<any> {
public hideField(appName: string, schemaName: string, fieldId: number, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}/fields/${fieldId}/hide`);
return HTTP.putVersioned(this.http, url, {}, version)
.pretifyError('Failed to hide field. Please reload.');
}
public deleteField(appName: string, schemaName: string, fieldId: number, version?: Version): Observable<any> {
public deleteField(appName: string, schemaName: string, fieldId: number, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/schemas/${schemaName}/fields/${fieldId}`);
return HTTP.deleteVersioned(this.http, url, version)

3
src/Squidex/app/shared/services/ui.service.spec.ts

@ -74,6 +74,7 @@ describe('UIService', () => {
req.error(new ErrorEvent('500'));
expect(settings.regexSuggestions).toEqual([]);
expect(settings).toBeDefined();
expect(settings!.regexSuggestions).toEqual([]);
}));
});

4
src/Squidex/app/shared/services/webhooks.service.spec.ts

@ -67,14 +67,14 @@ describe('WebhooksService', () => {
let webhooks: WebhookDto[] | null = null;
webhooksService.getWebhooks('my-app', version).subscribe(result => {
webhooksService.getWebhooks('my-app').subscribe(result => {
webhooks = result;
});
const req = httpMock.expectOne('http://service/p/api/apps/my-app/webhooks');
expect(req.request.method).toEqual('GET');
expect(req.request.headers.get('If-Match')).toBe(version.value);
expect(req.request.headers.get('If-Match')).toBeNull();
req.flush([
{

10
src/Squidex/app/shared/services/webhooks.service.ts

@ -111,10 +111,10 @@ export class WebhooksService {
) {
}
public getWebhooks(appName: string, version?: Version): Observable<WebhookDto[]> {
public getWebhooks(appName: string): Observable<WebhookDto[]> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/webhooks`);
return HTTP.getVersioned(this.http, url, version)
return HTTP.getVersioned(this.http, url)
.map(response => {
const items: any[] = response;
@ -147,7 +147,7 @@ export class WebhooksService {
.pretifyError('Failed to load webhooks. Please reload.');
}
public postWebhook(appName: string, dto: CreateWebhookDto, user: string, now?: DateTime, version?: Version): Observable<WebhookDto> {
public postWebhook(appName: string, dto: CreateWebhookDto, user: string, now: DateTime, version: Version): Observable<WebhookDto> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/webhooks`);
return HTTP.postVersioned(this.http, url, dto, version)
@ -167,14 +167,14 @@ export class WebhooksService {
.pretifyError('Failed to create webhook. Please reload.');
}
public putWebhook(appName: string, id: string, dto: UpdateWebhookDto, version?: Version): Observable<any> {
public putWebhook(appName: string, id: string, dto: UpdateWebhookDto, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/webhooks/${id}`);
return HTTP.putVersioned(this.http, url, dto, version)
.pretifyError('Failed to update webhook. Please reload.');
}
public deleteWebhook(appName: string, id: string, version?: Version): Observable<any> {
public deleteWebhook(appName: string, id: string, version: Version): Observable<any> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/webhooks/${id}`);
return HTTP.deleteVersioned(this.http, url, version)

6
src/Squidex/app/shell/pages/internal/profile-menu.component.ts

@ -49,10 +49,10 @@ export class ProfileMenuComponent implements OnDestroy, OnInit {
this.authenticationSubscription =
this.authService.userChanges.filter(user => !!user)
.subscribe(user => {
this.profileId = user.id;
this.profileDisplayName = user.displayName;
this.profileId = user!.id;
this.profileDisplayName = user!.displayName;
this.isAdmin = user.isAdmin;
this.isAdmin = user!.isAdmin;
});
}

2
src/Squidex/tsconfig.json

@ -9,7 +9,7 @@
"noUnusedParameters": false,
"removeComments": false,
"sourceMap": true,
"strictNullChecks": false,
"strictNullChecks": true,
"suppressImplicitAnyIndexErrors": true,
"target": "es5",
"paths": {

Loading…
Cancel
Save