Browse Source

Readonly array.

pull/422/head
Sebastian 7 years ago
parent
commit
30723473de
  1. 7
      src/Squidex/app/app.module.ts
  2. 2
      src/Squidex/app/features/administration/services/event-consumers.service.ts
  3. 6
      src/Squidex/app/features/administration/services/users.service.ts
  4. 2
      src/Squidex/app/features/apps/pages/apps-page.component.ts
  5. 2
      src/Squidex/app/features/apps/pages/news-dialog.component.ts
  6. 4
      src/Squidex/app/features/assets/pages/assets-filters-page.component.ts
  7. 2
      src/Squidex/app/features/assets/pages/assets-page.component.ts
  8. 4
      src/Squidex/app/features/content/pages/content/content-field.component.ts
  9. 4
      src/Squidex/app/features/content/pages/content/content-history-page.component.ts
  10. 2
      src/Squidex/app/features/content/pages/content/field-languages.component.ts
  11. 22
      src/Squidex/app/features/content/pages/contents/contents-page.component.ts
  12. 4
      src/Squidex/app/features/content/shared/array-editor.component.ts
  13. 4
      src/Squidex/app/features/content/shared/array-item.component.ts
  14. 16
      src/Squidex/app/features/content/shared/assets-editor.component.ts
  15. 12
      src/Squidex/app/features/content/shared/content-selector-item.component.ts
  16. 12
      src/Squidex/app/features/content/shared/content.component.ts
  17. 14
      src/Squidex/app/features/content/shared/contents-selector.component.ts
  18. 2
      src/Squidex/app/features/content/shared/field-editor.component.ts
  19. 1
      src/Squidex/app/features/content/shared/preview-button.component.ts
  20. 10
      src/Squidex/app/features/content/shared/reference-item.component.ts
  21. 22
      src/Squidex/app/features/content/shared/references-editor.component.ts
  22. 8
      src/Squidex/app/features/dashboard/pages/dashboard-page.component.ts
  23. 2
      src/Squidex/app/features/rules/pages/rules/actions/generic-action.component.ts
  24. 2
      src/Squidex/app/features/rules/pages/rules/triggers/content-changed-trigger.component.ts
  25. 2
      src/Squidex/app/features/schemas/pages/schema/field.component.ts
  26. 2
      src/Squidex/app/features/schemas/pages/schema/schema-page.component.ts
  27. 2
      src/Squidex/app/features/schemas/pages/schema/types/date-time-validation.component.ts
  28. 2
      src/Squidex/app/features/settings/pages/clients/client.component.ts
  29. 4
      src/Squidex/app/features/settings/pages/contributors/contributor-add-form.component.ts
  30. 2
      src/Squidex/app/features/settings/pages/contributors/contributors-page.component.ts
  31. 26
      src/Squidex/app/features/settings/pages/contributors/import-contributors-dialog.component.ts
  32. 2
      src/Squidex/app/features/settings/pages/more/more-page.component.ts
  33. 6
      src/Squidex/app/features/settings/pages/roles/roles-page.component.ts
  34. 6
      src/Squidex/app/features/settings/pages/workflows/workflow-step.component.ts
  35. 2
      src/Squidex/app/features/settings/pages/workflows/workflow-transition.component.ts
  36. 6
      src/Squidex/app/features/settings/pages/workflows/workflow.component.ts
  37. 2
      src/Squidex/app/features/settings/pages/workflows/workflows-page.component.ts
  38. 5
      src/Squidex/app/framework/angular/forms/autocomplete.component.ts
  39. 4
      src/Squidex/app/framework/angular/forms/checkbox-group.component.ts
  40. 5
      src/Squidex/app/framework/angular/forms/confirm-click.directive.ts
  41. 4
      src/Squidex/app/framework/angular/forms/control-errors.component.ts
  42. 5
      src/Squidex/app/framework/angular/forms/dropdown.component.ts
  43. 2
      src/Squidex/app/framework/angular/forms/error-formatting.ts
  44. 8
      src/Squidex/app/framework/angular/forms/file-drop.directive.ts
  45. 2
      src/Squidex/app/framework/angular/forms/forms-helper.ts
  46. 2
      src/Squidex/app/framework/angular/forms/stars.component.ts
  47. 15
      src/Squidex/app/framework/angular/forms/tag-editor.component.ts
  48. 8
      src/Squidex/app/framework/angular/forms/validators.ts
  49. 1
      src/Squidex/app/framework/angular/modals/dialog-renderer.component.ts
  50. 8
      src/Squidex/app/framework/angular/modals/modal.directive.ts
  51. 9
      src/Squidex/app/framework/angular/panel-container.directive.ts
  52. 20
      src/Squidex/app/framework/angular/pipes/colors.pipes.ts
  53. 4
      src/Squidex/app/framework/angular/routers/router-utils.ts
  54. 2
      src/Squidex/app/framework/angular/sorted.directive.ts
  55. 3
      src/Squidex/app/framework/angular/stateful.component.ts
  56. 2
      src/Squidex/app/framework/configurations.ts
  57. 2
      src/Squidex/app/framework/services/message-bus.service.ts
  58. 1
      src/Squidex/app/framework/services/title.service.ts
  59. 5
      src/Squidex/app/framework/state.ts
  60. 6
      src/Squidex/app/framework/utils/error.ts
  61. 6
      src/Squidex/app/framework/utils/hateos.ts
  62. 34
      src/Squidex/app/framework/utils/immutable-array.ts
  63. 2
      src/Squidex/app/framework/utils/interpolator.ts
  64. 18
      src/Squidex/app/framework/utils/math-helper.ts
  65. 8
      src/Squidex/app/framework/utils/picasso.ts
  66. 4
      src/Squidex/app/framework/utils/rxjs-extensions.ts
  67. 2
      src/Squidex/app/framework/utils/string-helper.ts
  68. 10
      src/Squidex/app/framework/utils/types.ts
  69. 2
      src/Squidex/app/shared/components/asset-dialog.component.ts
  70. 4
      src/Squidex/app/shared/components/asset-uploader.component.ts
  71. 2
      src/Squidex/app/shared/components/asset.component.ts
  72. 4
      src/Squidex/app/shared/components/assets-list.component.ts
  73. 4
      src/Squidex/app/shared/components/assets-selector.component.ts
  74. 8
      src/Squidex/app/shared/components/geolocation-editor.component.ts
  75. 4
      src/Squidex/app/shared/components/history.component.ts
  76. 2
      src/Squidex/app/shared/components/language-selector.component.ts
  77. 8
      src/Squidex/app/shared/components/markdown-editor.component.ts
  78. 3
      src/Squidex/app/shared/components/pipes.ts
  79. 2
      src/Squidex/app/shared/components/queries/filter-comparison.component.ts
  80. 1
      src/Squidex/app/shared/components/queries/filter-logical.component.ts
  81. 8
      src/Squidex/app/shared/components/references-dropdown.component.ts
  82. 10
      src/Squidex/app/shared/components/rich-editor.component.ts
  83. 4
      src/Squidex/app/shared/services/app-languages.service.spec.ts
  84. 6
      src/Squidex/app/shared/services/app-languages.service.ts
  85. 2
      src/Squidex/app/shared/services/apps.service.spec.ts
  86. 4
      src/Squidex/app/shared/services/apps.service.ts
  87. 2
      src/Squidex/app/shared/services/assets.service.spec.ts
  88. 6
      src/Squidex/app/shared/services/assets.service.ts
  89. 2
      src/Squidex/app/shared/services/backups.service.ts
  90. 2
      src/Squidex/app/shared/services/clients.service.spec.ts
  91. 2
      src/Squidex/app/shared/services/clients.service.ts
  92. 6
      src/Squidex/app/shared/services/comments.service.ts
  93. 12
      src/Squidex/app/shared/services/contents.service.ts
  94. 2
      src/Squidex/app/shared/services/contributors.service.spec.ts
  95. 2
      src/Squidex/app/shared/services/contributors.service.ts
  96. 2
      src/Squidex/app/shared/services/history.service.spec.ts
  97. 2
      src/Squidex/app/shared/services/history.service.ts
  98. 2
      src/Squidex/app/shared/services/languages.service.spec.ts
  99. 2
      src/Squidex/app/shared/services/languages.service.ts
  100. 2
      src/Squidex/app/shared/services/news.service.ts

7
src/Squidex/app/app.module.ts

@ -32,11 +32,12 @@ import { SqxShellModule } from './shell';
import { routing } from './app.routes'; import { routing } from './app.routes';
export function configApiUrl() { export function configApiUrl() {
let bases = document.getElementsByTagName('base'); const baseElements = document.getElementsByTagName('base');
let baseHref = null; let baseHref = null;
if (bases.length > 0) { if (baseElements.length > 0) {
baseHref = bases[0].href; baseHref = baseElements[0].href;
} }
if (!baseHref) { if (!baseHref) {

2
src/Squidex/app/features/administration/services/event-consumers.service.ts

@ -22,7 +22,7 @@ export class EventConsumersDto {
public readonly _links: ResourceLinks; public readonly _links: ResourceLinks;
constructor( constructor(
public readonly items: EventConsumerDto[], links?: ResourceLinks public readonly items: ReadonlyArray<EventConsumerDto>, links?: ResourceLinks
) { ) {
this._links = links || {}; this._links = links || {};
} }

6
src/Squidex/app/features/administration/services/users.service.ts

@ -36,7 +36,7 @@ export class UserDto {
public readonly id: string, public readonly id: string,
public readonly email: string, public readonly email: string,
public readonly displayName: string, public readonly displayName: string,
public readonly permissions: string[] = [], public readonly permissions: ReadonlyArray<string> = [],
public readonly isLocked?: boolean public readonly isLocked?: boolean
) { ) {
this._links = links; this._links = links;
@ -50,14 +50,14 @@ export class UserDto {
export interface CreateUserDto { export interface CreateUserDto {
readonly email: string; readonly email: string;
readonly displayName: string; readonly displayName: string;
readonly permissions: string[]; readonly permissions: ReadonlyArray<string>;
readonly password: string; readonly password: string;
} }
export interface UpdateUserDto { export interface UpdateUserDto {
readonly email: string; readonly email: string;
readonly displayName: string; readonly displayName: string;
readonly permissions: string[]; readonly permissions: ReadonlyArray<string>;
readonly password?: string; readonly password?: string;
} }

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

@ -32,7 +32,7 @@ export class AppsPageComponent implements OnInit {
public onboardingDialog = new DialogModel(); public onboardingDialog = new DialogModel();
public newsFeatures: FeatureDto[]; public newsFeatures: ReadonlyArray<FeatureDto>;
public newsDialog = new DialogModel(); public newsDialog = new DialogModel();
public info: string; public info: string;

2
src/Squidex/app/features/apps/pages/news-dialog.component.ts

@ -19,7 +19,7 @@ export class NewsDialogComponent {
public close = new EventEmitter(); public close = new EventEmitter();
@Input() @Input()
public features: FeatureDto[]; public features: ReadonlyArray<FeatureDto>;
public emitClose() { public emitClose() {
this.close.emit(); this.close.emit();

4
src/Squidex/app/features/assets/pages/assets-filters-page.component.ts

@ -37,7 +37,7 @@ export class AssetsFiltersPageComponent {
this.assetsState.search(query); this.assetsState.search(query);
} }
public selectTags(tags: string[]) { public selectTags(tags: ReadonlyArray<string>) {
this.assetsState.selectTags(tags); this.assetsState.selectTags(tags);
} }
@ -49,7 +49,7 @@ export class AssetsFiltersPageComponent {
this.assetsState.resetTags(); this.assetsState.resetTags();
} }
public trackByTag(tag: { name: string }) { public trackByTag(index: number, tag: { name: string }) {
return tag.name; return tag.name;
} }
} }

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

@ -51,7 +51,7 @@ export class AssetsPageComponent extends ResourceOwner implements OnInit {
this.assetsState.search(query); this.assetsState.search(query);
} }
public selectTags(tags: string[]) { public selectTags(tags: ReadonlyArray<string>) {
this.assetsState.selectTags(tags); this.assetsState.selectTags(tags);
} }

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

@ -55,7 +55,7 @@ export class ContentFieldComponent implements DoCheck, OnChanges {
public language: AppLanguageDto; public language: AppLanguageDto;
@Input() @Input()
public languages: AppLanguageDto[]; public languages: ReadonlyArray<AppLanguageDto>;
public selectedFormControl: AbstractControl; public selectedFormControl: AbstractControl;
public selectedFormControlCompare?: AbstractControl; public selectedFormControlCompare?: AbstractControl;
@ -145,7 +145,7 @@ export class ContentFieldComponent implements DoCheck, OnChanges {
if (masterValue) { if (masterValue) {
if (this.showAllControls) { if (this.showAllControls) {
for (let language of this.languages) { for (const language of this.languages) {
if (!language.isMaster) { if (!language.isMaster) {
this.translateValue(masterValue, masterCode, language.iso2Code); this.translateValue(masterValue, masterCode, language.iso2Code);
} }

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

@ -35,7 +35,7 @@ export class ContentHistoryPageComponent {
if (channelPath) { if (channelPath) {
const params = allParams(this.route); const params = allParams(this.route);
for (let key in params) { for (const key in params) {
if (params.hasOwnProperty(key)) { if (params.hasOwnProperty(key)) {
const value = params[key]; const value = params[key];
@ -47,7 +47,7 @@ export class ContentHistoryPageComponent {
return channelPath; return channelPath;
} }
public events: Observable<HistoryEventDto[]> = public events: Observable<ReadonlyArray<HistoryEventDto>> =
merge( merge(
timer(0, 10000), timer(0, 10000),
this.messageBus.of(HistoryChannelUpdated).pipe(delay(1000)) this.messageBus.of(HistoryChannelUpdated).pipe(delay(1000))

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

@ -48,5 +48,5 @@ export class FieldLanguagesComponent {
public language: AppLanguageDto; public language: AppLanguageDto;
@Input() @Input()
public languages: AppLanguageDto[]; public languages: ReadonlyArray<AppLanguageDto>;
} }

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

@ -42,7 +42,7 @@ export class ContentsPageComponent extends ResourceOwner implements OnInit {
public selectionCount = 0; public selectionCount = 0;
public selectionCanDelete = false; public selectionCanDelete = false;
public nextStatuses: string[] = []; public nextStatuses: ReadonlyArray<string> = [];
public language: AppLanguageDto; public language: AppLanguageDto;
public languages: ImmutableArray<AppLanguageDto>; public languages: ImmutableArray<AppLanguageDto>;
@ -126,7 +126,7 @@ export class ContentsPageComponent extends ResourceOwner implements OnInit {
this.contentsState.create(content.dataDraft, false); this.contentsState.create(content.dataDraft, false);
} }
private changeContentItems(contents: ContentDto[], action: string) { private changeContentItems(contents: ReadonlyArray<ContentDto>, action: string) {
if (contents.length === 0) { if (contents.length === 0) {
return; return;
} }
@ -180,15 +180,15 @@ export class ContentsPageComponent extends ResourceOwner implements OnInit {
this.selectedItems = {}; this.selectedItems = {};
if (isSelected) { if (isSelected) {
for (let content of this.contentsState.snapshot.contents.values) { this.contentsState.snapshot.contents.each(content => {
this.selectedItems[content.id] = true; this.selectedItems[content.id] = true;
} });
} }
this.updateSelectionSummary(); this.updateSelectionSummary();
} }
public trackByContent(content: ContentDto): string { public trackByContent(index: number, content: ContentDto): string {
return content.id; return content.id;
} }
@ -199,17 +199,17 @@ export class ContentsPageComponent extends ResourceOwner implements OnInit {
const allActions = {}; const allActions = {};
for (let content of this.contentsState.snapshot.contents.values) { this.contentsState.snapshot.contents.each(content => {
for (let info of content.statusUpdates) { for (const info of content.statusUpdates) {
allActions[info.status] = info.color; allActions[info.status] = info.color;
} }
} });
for (let content of this.contentsState.snapshot.contents.values) { this.contentsState.snapshot.contents.each(content => {
if (this.selectedItems[content.id]) { if (this.selectedItems[content.id]) {
this.selectionCount++; this.selectionCount++;
for (let action in allActions) { for (const action in allActions) {
if (!content.statusUpdates) { if (!content.statusUpdates) {
delete allActions[action]; delete allActions[action];
} }
@ -221,7 +221,7 @@ export class ContentsPageComponent extends ResourceOwner implements OnInit {
} else { } else {
this.selectedAll = false; this.selectedAll = false;
} }
} });
this.nextStatuses = Object.keys(allActions); this.nextStatuses = Object.keys(allActions);
} }

4
src/Squidex/app/features/content/shared/array-editor.component.ts

@ -39,7 +39,7 @@ export class ArrayEditorComponent extends StatefulComponent<State> {
public language: AppLanguageDto; public language: AppLanguageDto;
@Input() @Input()
public languages: AppLanguageDto[]; public languages: ReadonlyArray<AppLanguageDto>;
@Input() @Input()
public arrayControl: FormArray; public arrayControl: FormArray;
@ -62,7 +62,7 @@ export class ArrayEditorComponent extends StatefulComponent<State> {
this.form.arrayItemInsert(this.field, this.language, value); this.form.arrayItemInsert(this.field, this.language, value);
} }
public sort(controls: AbstractControl[]) { public sort(controls: ReadonlyArray<AbstractControl>) {
for (let i = 0; i < controls.length; i++) { for (let i = 0; i < controls.length; i++) {
this.arrayControl.setControl(i, controls[i]); this.arrayControl.setControl(i, controls[i]);
} }

4
src/Squidex/app/features/content/shared/array-item.component.ts

@ -67,11 +67,11 @@ export class ArrayItemComponent implements OnChanges {
public language: AppLanguageDto; public language: AppLanguageDto;
@Input() @Input()
public languages: AppLanguageDto[]; public languages: ReadonlyArray<AppLanguageDto>;
public isInvalid: Observable<boolean>; public isInvalid: Observable<boolean>;
public fieldControls: { field: FieldDto, control: AbstractControl }[]; public fieldControls: ReadonlyArray<{ field: FieldDto, control: AbstractControl }>;
public ngOnChanges(changes: SimpleChanges) { public ngOnChanges(changes: SimpleChanges) {
if (changes['itemForm']) { if (changes['itemForm']) {

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

@ -47,6 +47,7 @@ interface State {
providers: [SQX_ASSETS_EDITOR_CONTROL_VALUE_ACCESSOR], providers: [SQX_ASSETS_EDITOR_CONTROL_VALUE_ACCESSOR],
changeDetection: ChangeDetectionStrategy.OnPush changeDetection: ChangeDetectionStrategy.OnPush
}) })
// tslint:disable-next-line: readonly-array
export class AssetsEditorComponent extends StatefulControlComponent<State, string[]> implements OnInit { export class AssetsEditorComponent extends StatefulControlComponent<State, string[]> implements OnInit {
@Input() @Input()
public isCompact = false; public isCompact = false;
@ -105,13 +106,13 @@ export class AssetsEditorComponent extends StatefulControlComponent<State, strin
this.next(s => ({ ...s, assets })); this.next(s => ({ ...s, assets }));
} }
public addFiles(files: File[]) { public addFiles(files: ReadonlyArray<File>) {
for (let file of files) { for (const file of files) {
this.next(s => ({ ...s, assetFiles: s.assetFiles.pushFront(file) })); this.next(s => ({ ...s, assetFiles: s.assetFiles.pushFront(file) }));
} }
} }
public selectAssets(assets: AssetDto[]) { public selectAssets(assets: ReadonlyArray<AssetDto>) {
this.setAssets(this.snapshot.assets.push(...assets)); this.setAssets(this.snapshot.assets.push(...assets));
if (assets.length > 0) { if (assets.length > 0) {
@ -133,7 +134,7 @@ export class AssetsEditorComponent extends StatefulControlComponent<State, strin
} }
} }
public sortAssets(assets: AssetDto[]) { public sortAssets(assets: ReadonlyArray<AssetDto>) {
if (assets) { if (assets) {
this.setAssets(ImmutableArray.of(assets)); this.setAssets(ImmutableArray.of(assets));
@ -160,14 +161,15 @@ export class AssetsEditorComponent extends StatefulControlComponent<State, strin
} }
private updateValue() { private updateValue() {
let ids: string[] | null = this.snapshot.assets.values.map(x => x.id); const ids = this.snapshot.assets.values.map(x => x.id);
if (ids.length === 0) { if (ids.length === 0) {
ids = null; this.callChange(null);
} else {
this.callChange(ids);
} }
this.callTouched(); this.callTouched();
this.callChange(ids);
} }
public trackByAsset(index: number, asset: AssetDto) { public trackByAsset(index: number, asset: AssetDto) {

12
src/Squidex/app/features/content/shared/content-selector-item.component.ts

@ -65,12 +65,12 @@ export class ContentSelectorItemComponent implements OnChanges {
public language: AppLanguageDto; public language: AppLanguageDto;
@Input() @Input()
public fields: RootFieldDto[]; public fields: ReadonlyArray<RootFieldDto>;
@Input('sqxContentSelectorItem') @Input('sqxContentSelectorItem')
public content: ContentDto; public content: ContentDto;
public values: any[] = []; public values: ReadonlyArray<any> = [];
public ngOnChanges(changes: SimpleChanges) { public ngOnChanges(changes: SimpleChanges) {
if (changes['content'] || changes['language']) { if (changes['content'] || changes['language']) {
@ -89,12 +89,14 @@ export class ContentSelectorItemComponent implements OnChanges {
} }
private updateValues() { private updateValues() {
this.values = []; const values = [];
for (let field of this.fields) { for (const field of this.fields) {
const { formatted } = getContentValue(this.content, this.language, field); const { formatted } = getContentValue(this.content, this.language, field);
this.values.push(formatted); values.push(formatted);
} }
this.values = values;
} }
} }

12
src/Squidex/app/features/content/shared/content.component.ts

@ -54,7 +54,7 @@ export class ContentComponent implements OnChanges {
public schema: SchemaDetailsDto; public schema: SchemaDetailsDto;
@Input() @Input()
public schemaFields: RootFieldDto[]; public schemaFields: ReadonlyArray<RootFieldDto>;
@Input() @Input()
public canClone: boolean; public canClone: boolean;
@ -75,7 +75,7 @@ export class ContentComponent implements OnChanges {
public dropdown = new ModalModel(); public dropdown = new ModalModel();
public values: any[] = []; public values: ReadonlyArray<any> = [];
public get isDirty() { public get isDirty() {
return this.patchForm && this.patchForm.form.dirty; return this.patchForm && this.patchForm.form.dirty;
@ -148,12 +148,12 @@ export class ContentComponent implements OnChanges {
} }
private updateValues() { private updateValues() {
this.values = []; const values = [];
for (let field of this.schemaFields) { for (const field of this.schemaFields) {
const { value, formatted } = getContentValue(this.content, this.language, field); const { value, formatted } = getContentValue(this.content, this.language, field);
this.values.push(formatted); values.push(formatted);
if (this.patchForm) { if (this.patchForm) {
const formControl = this.patchForm.form.controls[field.name]; const formControl = this.patchForm.form.controls[field.name];
@ -163,6 +163,8 @@ export class ContentComponent implements OnChanges {
} }
} }
} }
this.values = values;
} }
public trackByField(index: number, field: FieldDto) { public trackByField(index: number, field: FieldDto) {

14
src/Squidex/app/features/content/shared/contents-selector.component.ts

@ -31,25 +31,25 @@ import {
}) })
export class ContentsSelectorComponent extends ResourceOwner implements OnInit { export class ContentsSelectorComponent extends ResourceOwner implements OnInit {
@Output() @Output()
public select = new EventEmitter<ContentDto[]>(); public select = new EventEmitter<ReadonlyArray<ContentDto>>();
@Input() @Input()
public schemaIds: string[]; public schemaIds: ReadonlyArray<string>;
@Input() @Input()
public language: LanguageDto; public language: LanguageDto;
@Input() @Input()
public languages: LanguageDto[]; public languages: ReadonlyArray<LanguageDto>;
@Input() @Input()
public allowDuplicates: boolean; public allowDuplicates: boolean;
@Input() @Input()
public alreadySelected: ContentDto[]; public alreadySelected: ReadonlyArray<ContentDto>;
public schema: SchemaDetailsDto; public schema: SchemaDetailsDto;
public schemas: SchemaDto[] = []; public schemas: ReadonlyArray<SchemaDto> = [];
public queryModel: QueryModel; public queryModel: QueryModel;
@ -147,7 +147,7 @@ export class ContentsSelectorComponent extends ResourceOwner implements OnInit {
this.selectedItems = {}; this.selectedItems = {};
if (isSelected) { if (isSelected) {
for (let content of this.contentsState.snapshot.contents.values) { for (const content of this.contentsState.snapshot.contents.values) {
if (!this.isItemAlreadySelected(content)) { if (!this.isItemAlreadySelected(content)) {
this.selectedItems[content.id] = content; this.selectedItems[content.id] = content;
} }
@ -178,7 +178,7 @@ export class ContentsSelectorComponent extends ResourceOwner implements OnInit {
} }
} }
public trackByContent(content: ContentDto): string { public trackByContent(index: number, content: ContentDto): string {
return content.id; return content.id;
} }
} }

2
src/Squidex/app/features/content/shared/field-editor.component.ts

@ -37,7 +37,7 @@ export class FieldEditorComponent {
public language: AppLanguageDto; public language: AppLanguageDto;
@Input() @Input()
public languages: AppLanguageDto[]; public languages: ReadonlyArray<AppLanguageDto>;
@Input() @Input()
public isCompact = false; public isCompact = false;

1
src/Squidex/app/features/content/shared/preview-button.component.ts

@ -20,6 +20,7 @@ import {
interface State { interface State {
selectedName?: string; selectedName?: string;
// tslint:disable-next-line: readonly-array
alternativeNames: string[]; alternativeNames: string[];
} }

10
src/Squidex/app/features/content/shared/reference-item.component.ts

@ -74,7 +74,7 @@ export class ReferenceItemComponent implements OnChanges {
@Input('sqxReferenceItem') @Input('sqxReferenceItem')
public content: ContentDto; public content: ContentDto;
public values: any[] = []; public values: ReadonlyArray<any> = [];
public ngOnChanges(changes: SimpleChanges) { public ngOnChanges(changes: SimpleChanges) {
this.updateValues(); this.updateValues();
@ -85,7 +85,7 @@ export class ReferenceItemComponent implements OnChanges {
} }
private updateValues() { private updateValues() {
this.values = []; const values = [];
for (let i = 0; i < this.columnCount; i++) { for (let i = 0; i < this.columnCount; i++) {
const field = this.content.referenceFields[i]; const field = this.content.referenceFields[i];
@ -93,10 +93,12 @@ export class ReferenceItemComponent implements OnChanges {
if (field) { if (field) {
const { formatted } = getContentValue(this.content, this.language, field); const { formatted } = getContentValue(this.content, this.language, field);
this.values.push(formatted); values.push(formatted);
} else { } else {
this.values.push(''); values.push('');
} }
} }
this.values = values;
} }
} }

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

@ -23,7 +23,7 @@ export const SQX_REFERENCES_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
}; };
interface State { interface State {
contentItems: ContentDto[]; contentItems: ReadonlyArray<ContentDto>;
columnCount: number; columnCount: number;
} }
@ -35,15 +35,16 @@ interface State {
providers: [SQX_REFERENCES_EDITOR_CONTROL_VALUE_ACCESSOR], providers: [SQX_REFERENCES_EDITOR_CONTROL_VALUE_ACCESSOR],
changeDetection: ChangeDetectionStrategy.OnPush changeDetection: ChangeDetectionStrategy.OnPush
}) })
// tslint:disable-next-line: readonly-array
export class ReferencesEditorComponent extends StatefulControlComponent<State, string[]> { export class ReferencesEditorComponent extends StatefulControlComponent<State, string[]> {
@Input() @Input()
public schemaIds: string[]; public schemaIds: ReadonlyArray<string>;
@Input() @Input()
public language: AppLanguageDto; public language: AppLanguageDto;
@Input() @Input()
public languages: AppLanguageDto[]; public languages: ReadonlyArray<AppLanguageDto>;
@Input() @Input()
public isCompact = false; public isCompact = false;
@ -84,17 +85,17 @@ export class ReferencesEditorComponent extends StatefulControlComponent<State, s
} }
} }
public setContentItems(contentItems: ContentDto[]) { public setContentItems(contentItems: ReadonlyArray<ContentDto>) {
let columnCount = 1; let columnCount = 1;
for (let content of contentItems) { for (const content of contentItems) {
columnCount = Math.max(columnCount, content.referenceFields.length); columnCount = Math.max(columnCount, content.referenceFields.length);
} }
this.next(s => ({ ...s, contentItems, columnCount })); this.next(s => ({ ...s, contentItems, columnCount }));
} }
public select(contents: ContentDto[]) { public select(contents: ReadonlyArray<ContentDto>) {
this.setContentItems([...this.snapshot.contentItems, ...contents]); this.setContentItems([...this.snapshot.contentItems, ...contents]);
if (contents.length > 0) { if (contents.length > 0) {
@ -112,7 +113,7 @@ export class ReferencesEditorComponent extends StatefulControlComponent<State, s
} }
} }
public sort(contents: ContentDto[]) { public sort(contents: ReadonlyArray<ContentDto>) {
if (contents) { if (contents) {
this.setContentItems(contents); this.setContentItems(contents);
@ -121,14 +122,15 @@ export class ReferencesEditorComponent extends StatefulControlComponent<State, s
} }
private updateValue() { private updateValue() {
let ids: string[] | null = this.snapshot.contentItems.map(x => x.id); const ids = this.snapshot.contentItems.map(x => x.id);
if (ids.length === 0) { if (ids.length === 0) {
ids = null; this.callChange(null);
} else {
this.callChange(ids);
} }
this.callTouched(); this.callTouched();
this.callChange(ids);
} }
public trackByContent(index: number, content: ContentDto) { public trackByContent(index: number, content: ContentDto) {

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

@ -19,7 +19,7 @@ import {
UsagesService UsagesService
} from '@app/shared'; } from '@app/shared';
const COLORS = [ const COLORS: ReadonlyArray<string> = [
' 51, 137, 213', ' 51, 137, 213',
'211, 50, 50', '211, 50, 50',
'131, 211, 50', '131, 211, 50',
@ -85,7 +85,7 @@ export class DashboardPageComponent extends ResourceOwner implements OnInit {
maintainAspectRatio: false maintainAspectRatio: false
}; };
public history: HistoryEventDto[] = []; public history: ReadonlyArray<HistoryEventDto> = [];
public assetsCurrent = 0; public assetsCurrent = 0;
public assetsMax = 0; public assetsMax = 0;
@ -207,10 +207,10 @@ function label(category: string) {
return category === '*' ? 'anonymous' : category; return category === '*' ? 'anonymous' : category;
} }
function createLabels(dtos: { date: DateTime }[]): string[] { function createLabels(dtos: ReadonlyArray<{ date: DateTime }>): ReadonlyArray<string> {
return dtos.map(d => d.date.toStringFormat('M-DD')); return dtos.map(d => d.date.toStringFormat('M-DD'));
} }
function createLabelsFromSet(dtos: { [category: string]: { date: DateTime }[] }): string[] { function createLabelsFromSet(dtos: { [category: string]: ReadonlyArray<{ date: DateTime }> }): ReadonlyArray<string> {
return createLabels(dtos[Object.keys(dtos)[0]]); return createLabels(dtos[Object.keys(dtos)[0]]);
} }

2
src/Squidex/app/features/rules/pages/rules/actions/generic-action.component.ts

@ -29,7 +29,7 @@ export class GenericActionComponent implements OnInit {
public actionFormSubmitted = false; public actionFormSubmitted = false;
public ngOnInit() { public ngOnInit() {
for (let property of this.definition.properties) { for (const property of this.definition.properties) {
const validators = []; const validators = [];
if (property.isRequired) { if (property.isRequired) {

2
src/Squidex/app/features/rules/pages/rules/triggers/content-changed-trigger.component.ts

@ -57,7 +57,7 @@ export class ContentChangedTriggerComponent implements OnInit {
const schemas: TriggerSchemaForm[] = []; const schemas: TriggerSchemaForm[] = [];
if (this.trigger.schemas) { if (this.trigger.schemas) {
for (let triggerSchema of this.trigger.schemas) { for (const triggerSchema of this.trigger.schemas) {
const schema = this.schemas.find(s => s.id === triggerSchema.schemaId); const schema = this.schemas.find(s => s.id === triggerSchema.schemaId);
if (schema) { if (schema) {

2
src/Squidex/app/features/schemas/pages/schema/field.component.ts

@ -99,7 +99,7 @@ export class FieldComponent implements OnChanges {
this.schemasState.hideField(this.schema, this.field); this.schemasState.hideField(this.schema, this.field);
} }
public sortFields(fields: NestedFieldDto[]) { public sortFields(fields: ReadonlyArray<NestedFieldDto>) {
this.schemasState.orderFields(this.schema, fields, <any>this.field).subscribe(); this.schemasState.orderFields(this.schema, fields, <any>this.field).subscribe();
} }

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

@ -79,7 +79,7 @@ export class SchemaPageComponent extends ResourceOwner implements OnInit {
this.schemasState.unpublish(this.schema).subscribe(); this.schemasState.unpublish(this.schema).subscribe();
} }
public sortFields(fields: FieldDto[]) { public sortFields(fields: ReadonlyArray<FieldDto>) {
this.schemasState.orderFields(this.schema, fields).subscribe(); this.schemasState.orderFields(this.schema, fields).subscribe();
} }

2
src/Squidex/app/features/schemas/pages/schema/types/date-time-validation.component.ts

@ -34,7 +34,7 @@ export class DateTimeValidationComponent implements OnInit {
public showDefaultValues: Observable<boolean>; public showDefaultValues: Observable<boolean>;
public showDefaultValue: Observable<boolean>; public showDefaultValue: Observable<boolean>;
public calculatedDefaultValues = ['Now', 'Today']; public calculatedDefaultValues: ReadonlyArray<string> = ['Now', 'Today'];
public ngOnInit() { public ngOnInit() {
this.editForm.setControl('calculatedDefaultValue', this.editForm.setControl('calculatedDefaultValue',

2
src/Squidex/app/features/settings/pages/clients/client.component.ts

@ -34,7 +34,7 @@ export class ClientComponent implements OnChanges {
public client: ClientDto; public client: ClientDto;
@Input() @Input()
public clientRoles: RoleDto[]; public clientRoles: ReadonlyArray<RoleDto>;
public connectToken: AccessTokenDto; public connectToken: AccessTokenDto;
public connectDialog = new DialogModel(); public connectDialog = new DialogModel();

4
src/Squidex/app/features/settings/pages/contributors/contributor-add-form.component.ts

@ -29,12 +29,12 @@ export class UsersDataSource implements AutocompleteSource {
) { ) {
} }
public find(query: string): Observable<any[]> { public find(query: string): Observable<ReadonlyArray<any>> {
return this.usersService.getUsers(query).pipe( return this.usersService.getUsers(query).pipe(
withLatestFrom(this.contributorsState.contributors, (users, contributors) => { withLatestFrom(this.contributorsState.contributors, (users, contributors) => {
const results: any[] = []; const results: any[] = [];
for (let user of users) { for (const user of users) {
if (!contributors!.find(t => t.contributorId === user.id)) { if (!contributors!.find(t => t.contributorId === user.id)) {
results.push(user); results.push(user);
} }

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

@ -50,7 +50,7 @@ export class ContributorsPageComponent implements OnInit {
this.contributorsState.search(query); this.contributorsState.search(query);
} }
public trackByContributor(contributor: ContributorDto) { public trackByContributor(index: number, contributor: ContributorDto) {
return contributor.contributorId; return contributor.contributorId;
} }
} }

26
src/Squidex/app/features/settings/pages/contributors/import-contributors-dialog.component.ts

@ -18,12 +18,12 @@ import {
RoleDto RoleDto
} from '@app/shared'; } from '@app/shared';
interface ImportStatus { type ImportStatus = {
email: string; email: string;
result: 'Pending' | 'Failed' | 'Success'; result: 'Pending' | 'Failed' | 'Success';
resultText: string; resultText: string;
role: string; role: string;
} };
@Component({ @Component({
selector: 'sqx-import-contributors-dialog', selector: 'sqx-import-contributors-dialog',
@ -40,7 +40,7 @@ export class ImportContributorsDialogComponent {
public roles: ImmutableArray<RoleDto>; public roles: ImmutableArray<RoleDto>;
public importForm = new ImportContributorsForm(this.formBuilder); public importForm = new ImportContributorsForm(this.formBuilder);
public importStatus: ImportStatus[] = []; public importStatus: ReadonlyArray<ImportStatus> = [];
public importStage: 'Start' | 'Change' | 'Wait' = 'Start'; public importStage: 'Start' | 'Change' | 'Wait' = 'Start';
constructor( constructor(
@ -54,15 +54,13 @@ export class ImportContributorsDialogComponent {
const contributors = this.importForm.submit(); const contributors = this.importForm.submit();
if (contributors && contributors.length > 0) { if (contributors) {
for (let contributor of contributors) { this.importStatus = contributors.map(contributor => ({
this.importStatus.push({ email: contributor.contributorId,
email: contributor.contributorId, result: 'Pending',
result: 'Pending', resultText: 'Pending',
resultText: 'Pending', role: 'Developer'
role: 'Developer' }));
});
}
} }
} }
@ -73,7 +71,7 @@ export class ImportContributorsDialogComponent {
mergeMap(s => mergeMap(s =>
this.contributorsState.assign(createRequest(s), { silent: true }).pipe( this.contributorsState.assign(createRequest(s), { silent: true }).pipe(
tap(created => { tap(created => {
let status = this.importStatus.find(x => x.email === s.email); const status = this.importStatus.find(x => x.email === s.email);
if (status) { if (status) {
status.resultText = getSuccess(created); status.resultText = getSuccess(created);
@ -81,7 +79,7 @@ export class ImportContributorsDialogComponent {
} }
}), }),
catchError((error: ErrorDto) => { catchError((error: ErrorDto) => {
let status = this.importStatus.find(x => x.email === s.email); const status = this.importStatus.find(x => x.email === s.email);
if (status) { if (status) {
status.resultText = getError(error); status.resultText = getError(error);

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

@ -74,7 +74,7 @@ export class MorePageComponent extends ResourceOwner implements OnInit {
} }
} }
public uploadImage(file: File[]) { public uploadImage(file: ReadonlyArray<File>) {
if (!this.isImageEditable) { if (!this.isImageEditable) {
return; return;
} }

6
src/Squidex/app/features/settings/pages/roles/roles-page.component.ts

@ -17,13 +17,13 @@ import {
} from '@app/shared'; } from '@app/shared';
class PermissionsAutocomplete implements AutocompleteSource { class PermissionsAutocomplete implements AutocompleteSource {
private permissions: string[] = []; private permissions: ReadonlyArray<string> = [];
constructor(appsState: AppsState, rolesService: RolesService) { constructor(appsState: AppsState, rolesService: RolesService) {
rolesService.getPermissions(appsState.appName).subscribe(x => this.permissions = x); rolesService.getPermissions(appsState.appName).subscribe(x => this.permissions = x);
} }
public find(query: string): Observable<any[]> { public find(query: string): Observable<ReadonlyArray<any>> {
return of(this.permissions.filter(y => y.indexOf(query) === 0)); return of(this.permissions.filter(y => y.indexOf(query) === 0));
} }
} }
@ -51,7 +51,7 @@ export class RolesPageComponent implements OnInit {
this.rolesState.load(true); this.rolesState.load(true);
} }
public trackByRole(role: RoleDto) { public trackByRole(index: number, role: RoleDto) {
return role.name; return role.name;
} }
} }

6
src/Squidex/app/features/settings/pages/workflows/workflow-step.component.ts

@ -51,17 +51,17 @@ export class WorkflowStepComponent implements OnChanges {
public step: WorkflowStep; public step: WorkflowStep;
@Input() @Input()
public roles: RoleDto[]; public roles: ReadonlyArray<RoleDto>;
@Input() @Input()
public disabled: boolean; public disabled: boolean;
public onBlur = { updateOn: 'blur' }; public onBlur = { updateOn: 'blur' };
public openSteps: WorkflowStep[]; public openSteps: ReadonlyArray<WorkflowStep>;
public openStep: WorkflowStep; public openStep: WorkflowStep;
public transitions: WorkflowTransitionView[]; public transitions: ReadonlyArray<WorkflowTransitionView>;
public ngOnChanges(changes: SimpleChanges) { public ngOnChanges(changes: SimpleChanges) {
if (changes['workflow'] || changes['step'] || false) { if (changes['workflow'] || changes['step'] || false) {

2
src/Squidex/app/features/settings/pages/workflows/workflow-transition.component.ts

@ -29,7 +29,7 @@ export class WorkflowTransitionComponent {
public transition: WorkflowTransitionView; public transition: WorkflowTransitionView;
@Input() @Input()
public roles: RoleDto[]; public roles: ReadonlyArray<RoleDto>;
@Input() @Input()
public disabled: boolean; public disabled: boolean;

6
src/Squidex/app/features/settings/pages/workflows/workflow.component.ts

@ -5,6 +5,8 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/ */
// tslint:disable: readonly-array
import { Component, Input, OnChanges } from '@angular/core'; import { Component, Input, OnChanges } from '@angular/core';
import { import {
@ -30,7 +32,7 @@ export class WorkflowComponent implements OnChanges {
public workflow: WorkflowDto; public workflow: WorkflowDto;
@Input() @Input()
public roles: RoleDto[]; public roles: ReadonlyArray<RoleDto>;
@Input() @Input()
public schemasSource: SchemaTagConverter; public schemasSource: SchemaTagConverter;
@ -73,7 +75,7 @@ export class WorkflowComponent implements OnChanges {
} }
public addStep() { public addStep() {
let index = this.workflow.steps.length; const index = this.workflow.steps.length;
for (let i = index; i < index + 100; i++) { for (let i = index; i < index + 100; i++) {
const name = `Step${i}`; const name = `Step${i}`;

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

@ -37,7 +37,7 @@ export class WorkflowsPageComponent implements OnInit {
this.workflowsState.load(true); this.workflowsState.load(true);
} }
public trackByWorkflow(workflow: WorkflowDto) { public trackByWorkflow(index: number, workflow: WorkflowDto) {
return workflow.id; return workflow.id;
} }
} }

5
src/Squidex/app/framework/angular/forms/autocomplete.component.ts

@ -17,7 +17,7 @@ import {
} from '@app/framework/internal'; } from '@app/framework/internal';
export interface AutocompleteSource { export interface AutocompleteSource {
find(query: string): Observable<any[]>; find(query: string): Observable<ReadonlyArray<any>>;
} }
const NO_EMIT = { emitEvent: false }; const NO_EMIT = { emitEvent: false };
@ -27,7 +27,7 @@ export const SQX_AUTOCOMPLETE_CONTROL_VALUE_ACCESSOR: any = {
}; };
interface State { interface State {
suggestedItems: any[]; suggestedItems: ReadonlyArray<any>;
suggestedIndex: number; suggestedIndex: number;
} }
@ -41,6 +41,7 @@ interface State {
], ],
changeDetection: ChangeDetectionStrategy.OnPush changeDetection: ChangeDetectionStrategy.OnPush
}) })
// tslint:disable-next-line: readonly-array
export class AutocompleteComponent extends StatefulControlComponent<State, any[]> implements OnInit { export class AutocompleteComponent extends StatefulControlComponent<State, any[]> implements OnInit {
@Input() @Input()
public source: AutocompleteSource; public source: AutocompleteSource;

4
src/Squidex/app/framework/angular/forms/checkbox-group.component.ts

@ -19,6 +19,7 @@ export const SQX_CHECKBOX_GROUP_CONTROL_VALUE_ACCESSOR: any = {
}; };
interface State { interface State {
// tslint:disable-next-line: readonly-array
checkedValues: string[]; checkedValues: string[];
} }
@ -29,11 +30,12 @@ interface State {
providers: [SQX_CHECKBOX_GROUP_CONTROL_VALUE_ACCESSOR], providers: [SQX_CHECKBOX_GROUP_CONTROL_VALUE_ACCESSOR],
changeDetection: ChangeDetectionStrategy.OnPush changeDetection: ChangeDetectionStrategy.OnPush
}) })
// tslint:disable-next-line: readonly-array
export class CheckboxGroupComponent extends StatefulControlComponent<State, string[]> { export class CheckboxGroupComponent extends StatefulControlComponent<State, string[]> {
public readonly controlId = MathHelper.guid(); public readonly controlId = MathHelper.guid();
@Input() @Input()
public values: string[] = []; public values: ReadonlyArray<string> = [];
constructor(changeDetector: ChangeDetectorRef) { constructor(changeDetector: ChangeDetectorRef) {
super(changeDetector, { super(changeDetector, {

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

@ -10,11 +10,12 @@ import { Directive, EventEmitter, HostListener, Input, OnDestroy, Output } from
import { DialogService } from '@app/framework/internal'; import { DialogService } from '@app/framework/internal';
class DelayEventEmitter<T> extends EventEmitter<T> { class DelayEventEmitter<T> extends EventEmitter<T> {
// tslint:disable-next-line: readonly-array
private delayedNexts: any[] | null = []; private delayedNexts: any[] | null = [];
public delayEmit() { public delayEmit() {
if (this.delayedNexts) { if (this.delayedNexts) {
for (let callback of this.delayedNexts) { for (const callback of this.delayedNexts) {
callback(); callback();
} }
} }
@ -71,7 +72,7 @@ export class ConfirmClickDirective implements OnDestroy {
this.isOpen = true; this.isOpen = true;
let subscription = const subscription =
this.dialogs.confirm(this.confirmTitle, this.confirmText) this.dialogs.confirm(this.confirmTitle, this.confirmText)
.subscribe(result => { .subscribe(result => {
this.isOpen = false; this.isOpen = false;

4
src/Squidex/app/framework/angular/forms/control-errors.component.ts

@ -18,7 +18,7 @@ import {
import { formatError } from './error-formatting'; import { formatError } from './error-formatting';
interface State { interface State {
errorMessages: string[]; errorMessages: ReadonlyArray<string>;
} }
@Component({ @Component({
@ -123,7 +123,7 @@ export class ControlErrorsComponent extends StatefulComponent<State> implements
const errors: string[] = []; const errors: string[] = [];
if (this.control && this.control.invalid && ((this.control.touched && !this.submitOnly) || this.submitted) && this.control.errors) { if (this.control && this.control.invalid && ((this.control.touched && !this.submitOnly) || this.submitted) && this.control.errors) {
for (let key in <any>this.control.errors) { for (const key in <any>this.control.errors) {
if (this.control.errors.hasOwnProperty(key)) { if (this.control.errors.hasOwnProperty(key)) {
const message = formatError(this.displayFieldName, key, this.control.errors[key], this.control.value, this.errors); const message = formatError(this.displayFieldName, key, this.control.errors[key], this.control.value, this.errors);

5
src/Squidex/app/framework/angular/forms/dropdown.component.ts

@ -21,7 +21,7 @@ export const SQX_DROPDOWN_CONTROL_VALUE_ACCESSOR: any = {
}; };
interface State { interface State {
suggestedItems: any[]; suggestedItems: ReadonlyArray<any>;
selectedItem: any; selectedItem: any;
selectedIndex: number; selectedIndex: number;
query?: RegExp; query?: RegExp;
@ -34,9 +34,10 @@ interface State {
providers: [SQX_DROPDOWN_CONTROL_VALUE_ACCESSOR], providers: [SQX_DROPDOWN_CONTROL_VALUE_ACCESSOR],
changeDetection: ChangeDetectionStrategy.OnPush changeDetection: ChangeDetectionStrategy.OnPush
}) })
// tslint:disable-next-line: readonly-array
export class DropdownComponent extends StatefulControlComponent<State, any[]> implements AfterContentInit, ControlValueAccessor, OnChanges, OnInit { export class DropdownComponent extends StatefulControlComponent<State, any[]> implements AfterContentInit, ControlValueAccessor, OnChanges, OnInit {
@Input() @Input()
public items: any[] = []; public items: ReadonlyArray<any> = [];
@Input() @Input()
public searchProperty = 'name'; public searchProperty = 'name';

2
src/Squidex/app/framework/angular/forms/error-formatting.ts

@ -59,7 +59,7 @@ export function formatError(field: string, type: string, properties: any, value:
return null; return null;
} }
for (let property in properties) { for (const property in properties) {
if (properties.hasOwnProperty(property)) { if (properties.hasOwnProperty(property)) {
message = message.replace(`{${property.toLowerCase()}}`, properties[property]); message = message.replace(`{${property.toLowerCase()}}`, properties[property]);
} }

8
src/Squidex/app/framework/angular/forms/file-drop.directive.ts

@ -11,7 +11,7 @@ import { Directive, ElementRef, EventEmitter, HostListener, Input, Output, Rende
import { Types } from '@app/framework/internal'; import { Types } from '@app/framework/internal';
const ImageTypes = [ const ImageTypes: ReadonlyArray<string> = [
'image/jpeg', 'image/jpeg',
'image/png', 'image/png',
'image/jpg', 'image/jpg',
@ -25,7 +25,7 @@ export class FileDropDirective {
private dragCounter = 0; private dragCounter = 0;
@Input() @Input()
public allowedFiles: string[]; public allowedFiles: ReadonlyArray<string>;
@Input() @Input()
public onlyImages: boolean; public onlyImages: boolean;
@ -37,7 +37,7 @@ export class FileDropDirective {
public disabled = false; public disabled = false;
@Output('sqxDropFile') @Output('sqxDropFile')
public drop = new EventEmitter<File[]>(); public drop = new EventEmitter<ReadonlyArray<File>>();
constructor( constructor(
private readonly element: ElementRef, private readonly element: ElementRef,
@ -128,7 +128,7 @@ export class FileDropDirective {
return null; return null;
} }
let files: File[] = []; const files: File[] = [];
for (let i = 0; i < dataTransfer.files.length; i++) { for (let i = 0; i < dataTransfer.files.length; i++) {
const file = dataTransfer.files.item(i); const file = dataTransfer.files.item(i);

2
src/Squidex/app/framework/angular/forms/forms-helper.ts

@ -11,7 +11,7 @@ import { distinctUntilChanged, map, startWith } from 'rxjs/operators';
import { Types } from './../../utils/types'; import { Types } from './../../utils/types';
export function formControls(form: AbstractControl): AbstractControl[] { export function formControls(form: AbstractControl): ReadonlyArray<AbstractControl> {
if (Types.is(form, FormGroup)) { if (Types.is(form, FormGroup)) {
return Object.values(form.controls); return Object.values(form.controls);
} else if (Types.is(form, FormArray)) { } else if (Types.is(form, FormArray)) {

2
src/Squidex/app/framework/angular/forms/stars.component.ts

@ -16,7 +16,7 @@ export const SQX_STARS_CONTROL_VALUE_ACCESSOR: any = {
interface State { interface State {
stars: number; stars: number;
starsArray: number[]; starsArray: ReadonlyArray<number>;
value: number | null; value: number | null;
} }

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

@ -129,10 +129,10 @@ let CACHED_FONT: string;
interface State { interface State {
hasFocus: boolean; hasFocus: boolean;
suggestedItems: TagValue[]; suggestedItems: ReadonlyArray<TagValue>;
suggestedIndex: number; suggestedIndex: number;
items: TagValue[]; items: ReadonlyArray<TagValue>;
} }
@Component({ @Component({
@ -145,6 +145,7 @@ interface State {
fadeAnimation fadeAnimation
] ]
}) })
// tslint:disable-next-line: readonly-array
export class TagEditorComponent extends StatefulControlComponent<State, any[]> implements AfterViewInit, OnInit { export class TagEditorComponent extends StatefulControlComponent<State, any[]> implements AfterViewInit, OnInit {
@ViewChild('form', { static: false }) @ViewChild('form', { static: false })
public formElement: ElementRef<HTMLElement>; public formElement: ElementRef<HTMLElement>;
@ -153,7 +154,7 @@ export class TagEditorComponent extends StatefulControlComponent<State, any[]> i
public inputElement: ElementRef<HTMLInputElement>; public inputElement: ElementRef<HTMLInputElement>;
@Input() @Input()
public suggestedValues: TagValue[] = []; public suggestedValues: ReadonlyArray<TagValue> = [];
@Input() @Input()
public converter: Converter = new StringConverter(); public converter: Converter = new StringConverter();
@ -183,7 +184,7 @@ export class TagEditorComponent extends StatefulControlComponent<State, any[]> i
public inputName = 'tag-editor'; public inputName = 'tag-editor';
@Input() @Input()
public set suggestions(value: string[]) { public set suggestions(value: ReadonlyArray<string>) {
if (value) { if (value) {
this.suggestedValues = value.map(x => new TagValue(x, x, x)); this.suggestedValues = value.map(x => new TagValue(x, x, x));
} else { } else {
@ -254,7 +255,7 @@ export class TagEditorComponent extends StatefulControlComponent<State, any[]> i
const items: any[] = []; const items: any[] = [];
if (this.converter && Types.isArray(obj)) { if (this.converter && Types.isArray(obj)) {
for (let value of obj) { for (const value of obj) {
if (Types.is(value, TagValue)) { if (Types.is(value, TagValue)) {
items.push(value); items.push(value);
} else { } else {
@ -466,7 +467,7 @@ export class TagEditorComponent extends StatefulControlComponent<State, any[]> i
const values = [...this.snapshot.items]; const values = [...this.snapshot.items];
for (let part of value.split(',')) { for (const part of value.split(',')) {
const converted = this.converter.convertInput(part); const converted = this.converter.convertInput(part);
if (converted) { if (converted) {
@ -488,7 +489,7 @@ export class TagEditorComponent extends StatefulControlComponent<State, any[]> i
return s && e && (e - s) > 0; return s && e && (e - s) > 0;
} }
private updateItems(items: TagValue[]) { private updateItems(items: ReadonlyArray<TagValue>) {
this.next(s => ({ ...s, items })); this.next(s => ({ ...s, items }));
if (items.length === 0 && this.undefinedWhenEmpty) { if (items.length === 0 && this.undefinedWhenEmpty) {

8
src/Squidex/app/framework/angular/forms/validators.ts

@ -140,7 +140,7 @@ export module ValidatorsEx {
} }
} }
export function validValues<T>(values: T[]): ValidatorFn { export function validValues<T>(values: ReadonlyArray<T>): ValidatorFn {
if (!values) { if (!values) {
return Validators.nullValidator; return Validators.nullValidator;
} }
@ -156,7 +156,7 @@ export module ValidatorsEx {
}; };
} }
export function validArrayValues<T>(values: T[]): ValidatorFn { export function validArrayValues<T>(values: ReadonlyArray<T>): ValidatorFn {
if (!values) { if (!values) {
return Validators.nullValidator; return Validators.nullValidator;
} }
@ -165,7 +165,7 @@ export module ValidatorsEx {
const ns: T[] = control.value; const ns: T[] = control.value;
if (ns) { if (ns) {
for (let n of ns) { for (const n of ns) {
if (values.indexOf(n) < 0) { if (values.indexOf(n) < 0) {
return { validarrayvalues: { invalidvalue: n } }; return { validarrayvalues: { invalidvalue: n } };
} }
@ -185,7 +185,7 @@ export module ValidatorsEx {
const a: string[] = control.value; const a: string[] = control.value;
const unique: { [key: string]: boolean } = {}; const unique: { [key: string]: boolean } = {};
for (let value of a) { for (const value of a) {
if (unique[value]) { if (unique[value]) {
return { uniquestrings: false }; return { uniquestrings: false };
} else { } else {

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

@ -21,6 +21,7 @@ import {
interface State { interface State {
dialogRequest?: DialogRequest | null; dialogRequest?: DialogRequest | null;
// tslint:disable-next-line: readonly-array
notifications: Notification[]; notifications: Notification[];
tooltip?: Tooltip | null; tooltip?: Tooltip | null;

8
src/Squidex/app/framework/angular/modals/modal.directive.ts

@ -27,7 +27,7 @@ export class ModalDirective implements OnDestroy {
private readonly eventsModel = new ResourceOwner(); private readonly eventsModel = new ResourceOwner();
private currentModel: DialogModel | ModalModel | null = null; private currentModel: DialogModel | ModalModel | null = null;
private renderedView: EmbeddedViewRef<any> | null = null; private renderedView: EmbeddedViewRef<any> | null = null;
private renderRoots: HTMLElement[] | null; private renderRoots: ReadonlyArray<HTMLElement> | null;
private isOpen: boolean; private isOpen: boolean;
@Input('sqxModal') @Input('sqxModal')
@ -102,7 +102,7 @@ export class ModalDirective implements OnDestroy {
private setupStyles() { private setupStyles() {
if (this.renderRoots) { if (this.renderRoots) {
for (let node of this.renderRoots) { for (const node of this.renderRoots) {
this.renderer.setStyle(node, 'display', 'block'); this.renderer.setStyle(node, 'display', 'block');
} }
} }
@ -134,7 +134,7 @@ export class ModalDirective implements OnDestroy {
} }
if (this.closeAlways && this.renderRoots) { if (this.closeAlways && this.renderRoots) {
for (let node of this.renderRoots) { for (const node of this.renderRoots) {
this.eventsView.own(this.renderer.listen(node, 'click', this.elementListener)); this.eventsView.own(this.renderer.listen(node, 'click', this.elementListener));
} }
} }
@ -162,7 +162,7 @@ export class ModalDirective implements OnDestroy {
return false; return false;
} }
for (let node of this.renderRoots) { for (const node of this.renderRoots) {
if (node.contains(<Node>event.target)) { if (node.contains(<Node>event.target)) {
return true; return true;
} }

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

@ -13,6 +13,7 @@ import { PanelComponent } from './panel.component';
selector: '[sqxPanelContainer]' selector: '[sqxPanelContainer]'
}) })
export class PanelContainerDirective implements AfterViewInit { export class PanelContainerDirective implements AfterViewInit {
// tslint:disable-next-line: readonly-array
private readonly panels: PanelComponent[] = []; private readonly panels: PanelComponent[] = [];
private isViewInit = false; private isViewInit = false;
private containerWidth = 0; private containerWidth = 0;
@ -55,7 +56,7 @@ export class PanelContainerDirective implements AfterViewInit {
const panels = this.panels; const panels = this.panels;
for (let panel of panels) { for (const panel of panels) {
if (!panel.isViewInit) { if (!panel.isViewInit) {
return; return;
} }
@ -64,7 +65,7 @@ export class PanelContainerDirective implements AfterViewInit {
let currentSize = 0; let currentSize = 0;
let panelsWidthSpread = 0; let panelsWidthSpread = 0;
for (let panel of panels) { for (const panel of panels) {
if (panel.desiredWidth !== '*') { if (panel.desiredWidth !== '*') {
const layoutWidth = panel.desiredWidth; const layoutWidth = panel.desiredWidth;
@ -76,7 +77,7 @@ export class PanelContainerDirective implements AfterViewInit {
} }
} }
for (let panel of panels) { for (const panel of panels) {
if (panel.desiredWidth === '*') { if (panel.desiredWidth === '*') {
const layoutWidth = (this.containerWidth - currentSize) / panelsWidthSpread; const layoutWidth = (this.containerWidth - currentSize) / panelsWidthSpread;
@ -89,7 +90,7 @@ export class PanelContainerDirective implements AfterViewInit {
let currentPosition = 0; let currentPosition = 0;
let currentLayer = panels.length * 10; let currentLayer = panels.length * 10;
for (let panel of panels) { for (const panel of panels) {
panel.arrange(currentPosition + 'px', currentLayer.toString()); panel.arrange(currentPosition + 'px', currentLayer.toString());
currentPosition += panel.renderWidth; currentPosition += panel.renderWidth;

20
src/Squidex/app/framework/angular/pipes/colors.pipes.ts

@ -19,13 +19,13 @@ interface HSVColor {
v: number; v: number;
} }
interface IColorDefinition { interface ColorDefinition {
regex: RegExp; regex: RegExp;
process(bots: RegExpExecArray): RGBColor; process(bots: RegExpExecArray): RGBColor;
} }
const ColorDefinitions: IColorDefinition[] = [ const ColorDefinitions: ReadonlyArray<ColorDefinition> = [
{ {
regex: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, regex: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
process: (bits) => ({ process: (bits) => ({
@ -59,7 +59,7 @@ function parseColor(value: string) {
value = value.replace(/ /g, '').toLowerCase(); value = value.replace(/ /g, '').toLowerCase();
for (let colorDefinition of ColorDefinitions) { for (const colorDefinition of ColorDefinitions) {
const bits = colorDefinition.regex.exec(value); const bits = colorDefinition.regex.exec(value);
if (bits) { if (bits) {
@ -75,9 +75,9 @@ function rgbToHsv({ r, g, b }: RGBColor): HSVColor {
const min = Math.min(r, g, b); const min = Math.min(r, g, b);
let h = 0; let h = 0;
let d = max - min; const d = max - min;
let s = max === 0 ? 0 : d / max; const s = max === 0 ? 0 : d / max;
let v = max; const v = max;
if (max === min) { if (max === min) {
h = 0; h = 0;
@ -98,10 +98,10 @@ function hsvToRgb({ h, s, v }: HSVColor): RGBColor {
let r = 0, g = 0, b = 0; let r = 0, g = 0, b = 0;
let i = Math.floor(h * 6); let i = Math.floor(h * 6);
let f = h * 6 - i; const f = h * 6 - i;
let p = v * (1 - s); const p = v * (1 - s);
let q = v * (1 - f * s); const q = v * (1 - f * s);
let t = v * (1 - (1 - f) * s); const t = v * (1 - (1 - f) * s);
switch (i % 6) { switch (i % 6) {
case 0: r = v, g = t, b = p; break; case 0: r = v, g = t, b = p; break;

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

@ -13,7 +13,7 @@ export function allData(value: ActivatedRouteSnapshot | ActivatedRoute): Data {
const result: { [key: string]: any } = {}; const result: { [key: string]: any } = {};
while (snapshot) { while (snapshot) {
for (let key in snapshot.data) { for (const key in snapshot.data) {
if (snapshot.data.hasOwnProperty(key) && !result[key]) { if (snapshot.data.hasOwnProperty(key) && !result[key]) {
result[key] = snapshot.data[key]; result[key] = snapshot.data[key];
} }
@ -30,7 +30,7 @@ export function allParams(value: ActivatedRouteSnapshot | ActivatedRoute): Param
const result: { [key: string]: any } = {}; const result: { [key: string]: any } = {};
while (snapshot) { while (snapshot) {
for (let key in snapshot.params) { for (const key in snapshot.params) {
if (snapshot.params.hasOwnProperty(key) && !result[key]) { if (snapshot.params.hasOwnProperty(key) && !result[key]) {
result[key] = snapshot.params[key]; result[key] = snapshot.params[key];
} }

2
src/Squidex/app/framework/angular/sorted.directive.ts

@ -5,6 +5,8 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/ */
// tslint:disable: readonly-array
import { Directive, ElementRef, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output } from '@angular/core'; import { Directive, ElementRef, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output } from '@angular/core';
import Sortable from 'sortablejs'; import Sortable from 'sortablejs';

3
src/Squidex/app/framework/angular/stateful.component.ts

@ -17,6 +17,7 @@ import { State } from './../state';
declare type UnsubscribeFunction = () => void; declare type UnsubscribeFunction = () => void;
export class ResourceOwner implements OnDestroy { export class ResourceOwner implements OnDestroy {
// tslint:disable-next-line: readonly-array
private subscriptions: (Subscription | UnsubscribeFunction)[] = []; private subscriptions: (Subscription | UnsubscribeFunction)[] = [];
public own<T>(subscription: Subscription | UnsubscribeFunction | Observable<T>) { public own<T>(subscription: Subscription | UnsubscribeFunction | Observable<T>) {
@ -37,7 +38,7 @@ export class ResourceOwner implements OnDestroy {
public unsubscribeAll() { public unsubscribeAll() {
try { try {
for (let subscription of this.subscriptions) { for (const subscription of this.subscriptions) {
if (Types.isFunction(subscription)) { if (Types.isFunction(subscription)) {
subscription(); subscription();
} else { } else {

2
src/Squidex/app/framework/configurations.ts

@ -21,7 +21,7 @@ export class UIOptions {
if (value) { if (value) {
const parts = path.split('.'); const parts = path.split('.');
for (let part of parts) { for (const part of parts) {
value = value[part]; value = value[part];
if (!value) { if (!value) {

2
src/Squidex/app/framework/services/message-bus.service.ts

@ -28,7 +28,7 @@ export class MessageBus {
this.message$.next({ channel: channel, data: message }); this.message$.next({ channel: channel, data: message });
} }
public of<T>(messageType: { new(...args: any[]): T }): Observable<T> { public of<T>(messageType: { new(...args: ReadonlyArray<any>): T }): Observable<T> {
const channel = (<any>messageType).name; const channel = (<any>messageType).name;
return this.message$.pipe(filter(m => m.channel === channel), map(m => m.data)); return this.message$.pipe(filter(m => m.channel === channel), map(m => m.data));

1
src/Squidex/app/framework/services/title.service.ts

@ -22,6 +22,7 @@ export const TitleServiceFactory = (titles: TitlesConfig) => {
@Injectable() @Injectable()
export class TitleService { export class TitleService {
// tslint:disable-next-line: readonly-array
private readonly stack: any[] = []; private readonly stack: any[] = [];
constructor(private readonly titles: TitlesConfig) { constructor(private readonly titles: TitlesConfig) {

5
src/Squidex/app/framework/state.ts

@ -117,6 +117,7 @@ export class Model<T> {
protected clone<V>(update: ((v: any) => V) | Partial<V>, validOnly = false): V { protected clone<V>(update: ((v: any) => V) | Partial<V>, validOnly = false): V {
let values: Partial<V>; let values: Partial<V>;
if (Types.isFunction(update)) { if (Types.isFunction(update)) {
values = update(<any>this); values = update(<any>this);
} else { } else {
@ -125,7 +126,7 @@ export class Model<T> {
const clone = Object.assign(Object.create(Object.getPrototypeOf(this)), this); const clone = Object.assign(Object.create(Object.getPrototypeOf(this)), this);
for (let key in values) { for (const key in values) {
if (values.hasOwnProperty(key)) { if (values.hasOwnProperty(key)) {
let value = values[key]; let value = values[key];
@ -148,7 +149,7 @@ export class ResultSet<T> {
constructor( constructor(
public readonly total: number, public readonly total: number,
public readonly items: T[], public readonly items: ReadonlyArray<T>,
links?: ResourceLinks links?: ResourceLinks
) { ) {
this._links = links || {}; this._links = links || {};

6
src/Squidex/app/framework/utils/error.ts

@ -13,7 +13,7 @@ export class ErrorDto {
constructor( constructor(
public readonly statusCode: number, public readonly statusCode: number,
public readonly message: string, public readonly message: string,
public readonly details: string[] = [], public readonly details: ReadonlyArray<string> = [],
public readonly inner?: any public readonly inner?: any
) { ) {
this.displayMessage = formatMessage(message, details); this.displayMessage = formatMessage(message, details);
@ -34,7 +34,7 @@ export function getDisplayMessage(error?: string | ErrorDto) {
} }
} }
function formatMessage(message: string, details?: string[]) { function formatMessage(message: string, details?: ReadonlyArray<string>) {
const appendLast = (row: string, char: string) => { const appendLast = (row: string, char: string) => {
const last = row[row.length - 1]; const last = row[row.length - 1];
@ -58,7 +58,7 @@ function formatMessage(message: string, details?: string[]) {
if (details && details.length > 1) { if (details && details.length > 1) {
let result = appendLast(message, '.') + '<ul>'; let result = appendLast(message, '.') + '<ul>';
for (let detail of details) { for (const detail of details) {
result += `<li>${appendLast(detail, '.')}</li>`; result += `<li>${appendLast(detail, '.')}</li>`;
} }

6
src/Squidex/app/framework/utils/hateos.ts

@ -17,14 +17,14 @@ export type ResourceLink = { href: string; method: ResourceMethod; metadata?: st
export type Metadata = { [rel: string]: string }; export type Metadata = { [rel: string]: string };
export function getLinkUrl(value: Resource | ResourceLinks, ...rels: string[]) { export function getLinkUrl(value: Resource | ResourceLinks, ...rels: ReadonlyArray<string>) {
if (!value) { if (!value) {
return false; return false;
} }
const links = value._links || value; const links = value._links || value;
for (let rel of rels) { for (const rel of rels) {
const link = links[rel]; const link = links[rel];
if (link && link.method && link.href) { if (link && link.method && link.href) {
@ -35,7 +35,7 @@ export function getLinkUrl(value: Resource | ResourceLinks, ...rels: string[])
return undefined; return undefined;
} }
export function hasAnyLink(value: Resource | ResourceLinks, ...rels: string[]) { export function hasAnyLink(value: Resource | ResourceLinks, ...rels: ReadonlyArray<string>) {
return !!getLinkUrl(value, ...rels); return !!getLinkUrl(value, ...rels);
} }

34
src/Squidex/app/framework/utils/immutable-array.ts

@ -9,8 +9,8 @@ export interface IdField {
id: string; id: string;
} }
function freeze<T>(items: T[]): T[] { function freeze<T>(items: ReadonlyArray<T>): ReadonlyArray<T> {
for (let item of items) { for (const item of items) {
Object.freeze(item); Object.freeze(item);
} }
@ -19,7 +19,7 @@ function freeze<T>(items: T[]): T[] {
export class ImmutableArray<T> implements Iterable<T> { export class ImmutableArray<T> implements Iterable<T> {
private static readonly EMPTY = new ImmutableArray<any>([]); private static readonly EMPTY = new ImmutableArray<any>([]);
private readonly items: T[]; private readonly items: ReadonlyArray<T>;
public [Symbol.iterator](): Iterator<T> { public [Symbol.iterator](): Iterator<T> {
return this.items.values(); return this.items.values();
@ -29,15 +29,15 @@ export class ImmutableArray<T> implements Iterable<T> {
return this.items.length; return this.items.length;
} }
public get values(): T[] { public get values(): ReadonlyArray<T> {
return [...this.items]; return [...this.items];
} }
public get mutableValues(): T[] { public get mutableValues(): ReadonlyArray<T> {
return this.items; return this.items;
} }
private constructor(items: T[]) { private constructor(items: ReadonlyArray<T>) {
this.items = items; this.items = items;
} }
@ -45,7 +45,7 @@ export class ImmutableArray<T> implements Iterable<T> {
return ImmutableArray.EMPTY; return ImmutableArray.EMPTY;
} }
public static of<V>(items?: V[]): ImmutableArray<V> { public static of<V>(items?: ReadonlyArray<V>): ImmutableArray<V> {
if (!items || items.length === 0) { if (!items || items.length === 0) {
return ImmutableArray.EMPTY; return ImmutableArray.EMPTY;
} else { } else {
@ -54,7 +54,13 @@ export class ImmutableArray<T> implements Iterable<T> {
} }
public at(index: number) { public at(index: number) {
return this.values[index]; return this.items[index];
}
public each(action: (item: T, index?: number) => void) {
for (let i = 0; i < this.items.length; i++) {
action(this.items[i], i);
}
} }
public map<R>(projection: (item: T) => R): ImmutableArray<R> { public map<R>(projection: (item: T) => R): ImmutableArray<R> {
@ -69,6 +75,10 @@ export class ImmutableArray<T> implements Iterable<T> {
return this.items.find(predicate); return this.items.find(predicate);
} }
public slice(start?: number, end?: number) {
return new ImmutableArray<T>(this.items.slice(start, end));
}
public sort(compareFn?: (a: T, b: T) => number): ImmutableArray<T> { public sort(compareFn?: (a: T, b: T) => number): ImmutableArray<T> {
const clone = [...this.items]; const clone = [...this.items];
@ -93,28 +103,28 @@ export class ImmutableArray<T> implements Iterable<T> {
return this.sort((a, b) => compareNumbersDesc(filter(a), filter(b))); return this.sort((a, b) => compareNumbersDesc(filter(a), filter(b)));
} }
public pushFront(...items: T[]): ImmutableArray<T> { public pushFront(...items: ReadonlyArray<T>): ImmutableArray<T> {
if (items.length === 0) { if (items.length === 0) {
return this; return this;
} }
return new ImmutableArray<T>([...freeze(items), ...this.items]); return new ImmutableArray<T>([...freeze(items), ...this.items]);
} }
public push(...items: T[]): ImmutableArray<T> { public push(...items: ReadonlyArray<T>): ImmutableArray<T> {
if (items.length === 0) { if (items.length === 0) {
return this; return this;
} }
return new ImmutableArray<T>([...this.items, ...freeze(items)]); return new ImmutableArray<T>([...this.items, ...freeze(items)]);
} }
public remove(...items: T[]): ImmutableArray<T> { public remove(...items: ReadonlyArray<T>): ImmutableArray<T> {
if (items.length === 0) { if (items.length === 0) {
return this; return this;
} }
const copy = this.items.slice(); const copy = this.items.slice();
for (let item of items) { for (const item of items) {
const index = copy.indexOf(item); const index = copy.indexOf(item);
if (index >= 0) { if (index >= 0) {

2
src/Squidex/app/framework/utils/interpolator.ts

@ -16,7 +16,7 @@ export function interpolate(pattern: string, value?: any, shortcut?: string, fal
const path = match.substr(2, match.length - 3).split('.'); const path = match.substr(2, match.length - 3).split('.');
for (let segment of path) { for (const segment of path) {
if (!replaced) { if (!replaced) {
return false; return false;
} }

18
src/Squidex/app/framework/utils/math-helper.ts

@ -9,7 +9,7 @@
import { Types } from './types'; import { Types } from './types';
interface IColorDefinition { interface ColorDefinition {
regex: RegExp; regex: RegExp;
process(bots: RegExpExecArray): Color; process(bots: RegExpExecArray): Color;
@ -22,7 +22,7 @@ export interface Color {
a: number; a: number;
} }
const ColorDefinitions: IColorDefinition[] = [ const ColorDefinitions: ReadonlyArray<ColorDefinition> = [
{ {
regex: /^rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*([\d\.]{1,})\)$/, regex: /^rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*([\d\.]{1,})\)$/,
process: (bits) => { process: (bits) => {
@ -62,9 +62,11 @@ const ColorDefinitions: IColorDefinition[] = [
export module MathHelper { export module MathHelper {
export const EMPTY_GUID = '00000000-0000-0000-0000-000000000000'; export const EMPTY_GUID = '00000000-0000-0000-0000-000000000000';
const CRC32_TABLE: number[] = []; const CRC32_TABLE: ReadonlyArray<number> = createCrc32Table();
function createCrc32Table() {
const crc: number[] = [];
function ensureCrc32Table() {
for (let n = 0; n < 256; n++) { for (let n = 0; n < 256; n++) {
let c = n; let c = n;
@ -72,11 +74,11 @@ export module MathHelper {
c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
} }
CRC32_TABLE[n] = c; crc[n] = c;
} }
}
ensureCrc32Table(); return crc;
}
export function crc32(str: string): number { export function crc32(str: string): number {
let crc = 0 ^ (-1); let crc = 0 ^ (-1);
@ -147,7 +149,7 @@ export module MathHelper {
value = value.replace(/ /g, '').toLowerCase(); value = value.replace(/ /g, '').toLowerCase();
for (let colorDefinition of ColorDefinitions) { for (const colorDefinition of ColorDefinitions) {
const bits = colorDefinition.regex.exec(value); const bits = colorDefinition.regex.exec(value);
if (bits) { if (bits) {

8
src/Squidex/app/framework/utils/picasso.ts

@ -1,6 +1,6 @@
import MersenneTwister from 'mersenne-twister'; import MersenneTwister from 'mersenne-twister';
const ALL_COLORS = [ const ALL_COLORS: ReadonlyArray<string> = [
'rgb(226,27,12)', 'rgb(226,27,12)',
'rgb(192,19,78)', 'rgb(192,19,78)',
'rgb(125,31,141)', 'rgb(125,31,141)',
@ -20,10 +20,10 @@ const ALL_COLORS = [
const LAYERS = 3; const LAYERS = 3;
const RADIUSES = [20, 25, 30, 35, 40, 45, 50]; const RADIUSES: ReadonlyArray<number> = [20, 25, 30, 35, 40, 45, 50];
const X_CENTERS = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]; const X_CENTERS: ReadonlyArray<number> = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100];
const Y_CENTERS = [30, 40, 50, 60, 70]; const Y_CENTERS: ReadonlyArray<number> = [30, 40, 50, 60, 70];
function hash(str: string) { function hash(str: string) {
if (str.length === 0) { if (str.length === 0) {

4
src/Squidex/app/framework/utils/rxjs-extensions.ts

@ -62,9 +62,9 @@ export function switchSafe<T, R>(project: (source: T) => Observable<R>) {
}; };
} }
export function ofForever<T>(...values: T[]) { export function ofForever<T>(...values: ReadonlyArray<T>) {
return new Observable<T>(s => { return new Observable<T>(s => {
for (let value of values) { for (const value of values) {
s.next(value); s.next(value);
} }
}); });

2
src/Squidex/app/framework/utils/string-helper.ts

@ -6,7 +6,7 @@
*/ */
export module StringHelper { export module StringHelper {
export function firstNonEmpty(...values: (string | undefined | null)[]) { export function firstNonEmpty(...values: ReadonlyArray<(string | undefined | null)>) {
for (let value of values) { for (let value of values) {
if (value) { if (value) {
value = value.trim(); value = value.trim();

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

@ -5,6 +5,8 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/ */
// tslint:disable: readonly-array
export module Types { export module Types {
export function hash(value: any): string { export function hash(value: any): string {
try { try {
@ -71,7 +73,7 @@ export module Types {
return false; return false;
} }
for (let v of value) { for (const v of value) {
if (!validator(v)) { if (!validator(v)) {
return false; return false;
} }
@ -84,7 +86,7 @@ export module Types {
return hash(lhs) === hash(rhs); return hash(lhs) === hash(rhs);
} }
export function isEquals<T>(lhs: T[], rhs: T[]) { export function isEquals<T>(lhs: ReadonlyArray<T>, rhs: ReadonlyArray<T>) {
if (!lhs && !rhs) { if (!lhs && !rhs) {
return true; return true;
} }
@ -104,7 +106,7 @@ export module Types {
export function isEmpty(value: any): boolean { export function isEmpty(value: any): boolean {
if (Types.isArray(value)) { if (Types.isArray(value)) {
for (let v of value) { for (const v of value) {
if (!isEmpty(v)) { if (!isEmpty(v)) {
return false; return false;
} }
@ -114,7 +116,7 @@ export module Types {
} }
if (Types.isObject(value)) { if (Types.isObject(value)) {
for (let key in value) { for (const key in value) {
if (value.hasOwnProperty(key)) { if (value.hasOwnProperty(key)) {
if (!isEmpty(value[key])) { if (!isEmpty(value[key])) {
return false; return false;

2
src/Squidex/app/shared/components/asset-dialog.component.ts

@ -33,7 +33,7 @@ export class AssetDialogComponent extends StatefulComponent implements OnInit {
public asset: AssetDto; public asset: AssetDto;
@Input() @Input()
public allTags: string[]; public allTags: ReadonlyArray<string>;
public isEditable = false; public isEditable = false;

4
src/Squidex/app/shared/components/asset-uploader.component.ts

@ -35,8 +35,8 @@ export class AssetUploaderComponent {
) { ) {
} }
public addFiles(files: File[]) { public addFiles(files: ReadonlyArray<File>) {
for (let file of files) { for (const file of files) {
this.assetUploader.uploadFile(file, this.assetsState); this.assetUploader.uploadFile(file, this.assetsState);
} }

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

@ -75,7 +75,7 @@ export class AssetComponent extends StatefulComponent<State> implements OnInit {
public isListView = false; public isListView = false;
@Input() @Input()
public allTags: string[]; public allTags: ReadonlyArray<string>;
public editDialog = new DialogModel(); public editDialog = new DialogModel();

4
src/Squidex/app/shared/components/assets-list.component.ts

@ -89,8 +89,8 @@ export class AssetsListComponent {
this.newFiles = this.newFiles.remove(file); this.newFiles = this.newFiles.remove(file);
} }
public addFiles(files: File[]) { public addFiles(files: ReadonlyArray<File>) {
for (let file of files) { for (const file of files) {
this.newFiles = this.newFiles.pushFront(file); this.newFiles = this.newFiles.pushFront(file);
} }

4
src/Squidex/app/shared/components/assets-selector.component.ts

@ -34,7 +34,7 @@ interface State {
}) })
export class AssetsSelectorComponent extends StatefulComponent<State> implements OnInit { export class AssetsSelectorComponent extends StatefulComponent<State> implements OnInit {
@Output() @Output()
public select = new EventEmitter<AssetDto[]>(); public select = new EventEmitter<ReadonlyArray<AssetDto>>();
constructor(changeDector: ChangeDetectorRef, constructor(changeDector: ChangeDetectorRef,
public readonly assetsState: AssetsState, public readonly assetsState: AssetsState,
@ -67,7 +67,7 @@ export class AssetsSelectorComponent extends StatefulComponent<State> implements
this.select.emit(Object.values(this.snapshot.selectedAssets)); this.select.emit(Object.values(this.snapshot.selectedAssets));
} }
public selectTags(tags: string[]) { public selectTags(tags: ReadonlyArray<string>) {
this.assetsState.selectTags(tags); this.assetsState.selectTags(tags);
} }

8
src/Squidex/app/shared/components/geolocation-editor.component.ts

@ -235,18 +235,18 @@ export class GeolocationEditorComponent extends StatefulControlComponent<Snapsho
}); });
searchBox.addListener('places_changed', () => { searchBox.addListener('places_changed', () => {
let places = searchBox.getPlaces(); const places = searchBox.getPlaces();
if (places.length === 1) { if (places.length === 1) {
let place = places[0]; const place = places[0];
if (!place.geometry) { if (!place.geometry) {
return; return;
} }
if (!this.snapshot.isDisabled) { if (!this.snapshot.isDisabled) {
let lat = place.geometry.location.lat(); const lat = place.geometry.location.lat();
let lng = place.geometry.location.lng(); const lng = place.geometry.location.lng();
this.updateValue(lat, lng); this.updateValue(lat, lng);
this.updateMarker(false, true); this.updateMarker(false, true);

4
src/Squidex/app/shared/components/history.component.ts

@ -29,7 +29,7 @@ import {
export class HistoryComponent { export class HistoryComponent {
private readonly channel = this.calculateChannel(); private readonly channel = this.calculateChannel();
public events: Observable<HistoryEventDto[]> = public events: Observable<ReadonlyArray<HistoryEventDto>> =
merge( merge(
timer(0, 10000), timer(0, 10000),
this.messageBus.of(HistoryChannelUpdated).pipe(delay(1000)) this.messageBus.of(HistoryChannelUpdated).pipe(delay(1000))
@ -50,7 +50,7 @@ export class HistoryComponent {
if (channel) { if (channel) {
const params = allParams(this.route); const params = allParams(this.route);
for (let key in params) { for (const key in params) {
if (params.hasOwnProperty(key)) { if (params.hasOwnProperty(key)) {
const value = params[key]; const value = params[key];

2
src/Squidex/app/shared/components/language-selector.component.ts

@ -29,7 +29,7 @@ export class LanguageSelectorComponent implements OnChanges, OnInit {
public size: string; public size: string;
@Input() @Input()
public languages: Language[] = []; public languages: ReadonlyArray<Language> = [];
@Input() @Input()
public selectedLanguage: Language; public selectedLanguage: Language;

8
src/Squidex/app/shared/components/markdown-editor.component.ts

@ -203,10 +203,10 @@ export class MarkdownEditorComponent extends StatefulControlComponent<State, str
}); });
} }
public insertAssets(assets: AssetDto[]) { public insertAssets(assets: ReadonlyArray<AssetDto>) {
let content = ''; let content = '';
for (let asset of assets) { for (const asset of assets) {
content += `![${asset.fileName}](${asset.fullUrl(this.apiUrl)} '${asset.fileName}')`; content += `![${asset.fileName}](${asset.fullUrl(this.apiUrl)} '${asset.fileName}')`;
} }
@ -217,10 +217,10 @@ export class MarkdownEditorComponent extends StatefulControlComponent<State, str
this.assetsDialog.hide(); this.assetsDialog.hide();
} }
public insertFiles(files: File[]) { public insertFiles(files: ReadonlyArray<File>) {
const doc = this.simplemde.codemirror.getDoc(); const doc = this.simplemde.codemirror.getDoc();
for (let file of files) { for (const file of files) {
this.uploadFile(doc, file); this.uploadFile(doc, file);
} }
} }

3
src/Squidex/app/shared/components/pipes.ts

@ -260,7 +260,8 @@ export class FileIconPipe implements PipeTransform {
]; ];
let mimeIcon: string; let mimeIcon: string;
let mimeParts = asset.mimeType.split('/');
const mimeParts = asset.mimeType.split('/');
if (mimeParts.length === 2 && mimeParts[0].toLowerCase() === 'video') { if (mimeParts.length === 2 && mimeParts[0].toLowerCase() === 'video') {
mimeIcon = 'video'; mimeIcon = 'video';

2
src/Squidex/app/shared/components/queries/filter-comparison.component.ts

@ -48,7 +48,7 @@ export class FilterComparisonComponent implements OnChanges {
} }
} }
public getStatus(statuses: StatusInfo[]) { public getStatus(statuses: ReadonlyArray<StatusInfo>) {
return statuses.find(x => x.status === this.filter.value); return statuses.find(x => x.status === this.filter.value);
} }

1
src/Squidex/app/shared/components/queries/filter-logical.component.ts

@ -52,6 +52,7 @@ export class FilterLogicalComponent {
return this.filterValue; return this.filterValue;
} }
// tslint:disable-next-line: readonly-array
public filters: FilterNode[] = []; public filters: FilterNode[] = [];
public addComparison() { public addComparison() {

8
src/Squidex/app/shared/components/references-dropdown.component.ts

@ -24,8 +24,8 @@ export const SQX_REFERENCES_DROPDOWN_CONTROL_VALUE_ACCESSOR: any = {
}; };
interface State { interface State {
contents: ContentDto[]; contents: ReadonlyArray<ContentDto>;
contentNames: ContentName[]; contentNames: ReadonlyArray<ContentName>;
selectedItem?: ContentName; selectedItem?: ContentName;
} }
@ -48,7 +48,7 @@ const NO_EMIT = { emitEvent: false };
providers: [SQX_REFERENCES_DROPDOWN_CONTROL_VALUE_ACCESSOR], providers: [SQX_REFERENCES_DROPDOWN_CONTROL_VALUE_ACCESSOR],
changeDetection: ChangeDetectionStrategy.OnPush changeDetection: ChangeDetectionStrategy.OnPush
}) })
export class ReferencesDropdownComponent extends StatefulControlComponent<State, string[] | string> implements OnInit { export class ReferencesDropdownComponent extends StatefulControlComponent<State, ReadonlyArray<string> | string> implements OnInit {
private languageField: AppLanguageDto; private languageField: AppLanguageDto;
private selectedId: string | undefined; private selectedId: string | undefined;
private itemCount: number; private itemCount: number;
@ -145,7 +145,7 @@ export class ReferencesDropdownComponent extends StatefulControlComponent<State,
this.selectionControl.setValue(undefined, NO_EMIT); this.selectionControl.setValue(undefined, NO_EMIT);
} }
private createContentNames(contents: ContentDto[]): ContentName[] { private createContentNames(contents: ReadonlyArray<ContentDto>): ReadonlyArray<ContentName> {
if (contents.length === 0) { if (contents.length === 0) {
return []; return [];
} }

10
src/Squidex/app/shared/components/rich-editor.component.ts

@ -27,7 +27,7 @@ export const SQX_RICH_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => RichEditorComponent), multi: true provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => RichEditorComponent), multi: true
}; };
const ImageTypes = [ const ImageTypes: ReadonlyArray<any> = [
'image/jpeg', 'image/jpeg',
'image/png', 'image/png',
'image/jpg', 'image/jpg',
@ -188,10 +188,10 @@ export class RichEditorComponent extends StatefulControlComponent<undefined, str
} }
} }
public insertAssets(assets: AssetDto[]) { public insertAssets(assets: ReadonlyArray<AssetDto>) {
let content = ''; let content = '';
for (let asset of assets) { for (const asset of assets) {
content += `<img src="${asset.fullUrl(this.apiUrl)}" alt="${asset.fileName}" />`; content += `<img src="${asset.fullUrl(this.apiUrl)}" alt="${asset.fileName}" />`;
} }
@ -202,8 +202,8 @@ export class RichEditorComponent extends StatefulControlComponent<undefined, str
this.assetsDialog.hide(); this.assetsDialog.hide();
} }
public insertFiles(files: File[]) { public insertFiles(files: ReadonlyArray<File>) {
for (let file of files) { for (const file of files) {
this.uploadFile(file); this.uploadFile(file);
} }
} }

4
src/Squidex/app/shared/services/app-languages.service.spec.ts

@ -167,7 +167,7 @@ describe('AppLanguagesService', () => {
} }
}); });
export function createLanguages(...codes: string[]): AppLanguagesPayload { export function createLanguages(...codes: ReadonlyArray<string>): AppLanguagesPayload {
return { return {
items: codes.map((code, i) => createLanguage(code, codes, i)), items: codes.map((code, i) => createLanguage(code, codes, i)),
_links: { _links: {
@ -176,7 +176,7 @@ export function createLanguages(...codes: string[]): AppLanguagesPayload {
canCreate: true canCreate: true
}; };
} }
function createLanguage(code: string, codes: string[], i: number) { function createLanguage(code: string, codes: ReadonlyArray<string>, i: number) {
const links: ResourceLinks = { const links: ResourceLinks = {
update: { method: 'PUT', href: `/languages/${code}` } update: { method: 'PUT', href: `/languages/${code}` }
}; };

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

@ -25,7 +25,7 @@ import {
export type AppLanguagesDto = Versioned<AppLanguagesPayload>; export type AppLanguagesDto = Versioned<AppLanguagesPayload>;
export type AppLanguagesPayload = { export type AppLanguagesPayload = {
readonly items: AppLanguageDto[]; readonly items: ReadonlyArray<AppLanguageDto>;
readonly canCreate: boolean; readonly canCreate: boolean;
} & Resource; } & Resource;
@ -42,7 +42,7 @@ export class AppLanguageDto {
public readonly englishName: string, public readonly englishName: string,
public readonly isMaster: boolean, public readonly isMaster: boolean,
public readonly isOptional: boolean, public readonly isOptional: boolean,
public readonly fallback: string[] public readonly fallback: ReadonlyArray<string>
) { ) {
this._links = links; this._links = links;
@ -58,7 +58,7 @@ export interface AddAppLanguageDto {
export interface UpdateAppLanguageDto { export interface UpdateAppLanguageDto {
readonly isMaster?: boolean; readonly isMaster?: boolean;
readonly isOptional?: boolean; readonly isOptional?: boolean;
readonly fallback?: string[]; readonly fallback?: ReadonlyArray<string>;
} }
@Injectable() @Injectable()

2
src/Squidex/app/shared/services/apps.service.spec.ts

@ -43,7 +43,7 @@ describe('AppsService', () => {
it('should make get request to get apps', it('should make get request to get apps',
inject([AppsService, HttpTestingController], (appsService: AppsService, httpMock: HttpTestingController) => { inject([AppsService, HttpTestingController], (appsService: AppsService, httpMock: HttpTestingController) => {
let apps: AppDto[]; let apps: ReadonlyArray<AppDto>;
appsService.getApps().subscribe(result => { appsService.getApps().subscribe(result => {
apps = result; apps = result;

4
src/Squidex/app/shared/services/apps.service.ts

@ -56,7 +56,7 @@ export class AppDto {
public readonly name: string, public readonly name: string,
public readonly label: string | undefined, public readonly label: string | undefined,
public readonly description: string | undefined, public readonly description: string | undefined,
public readonly permissions: string[], public readonly permissions: ReadonlyArray<string>,
public readonly created: DateTime, public readonly created: DateTime,
public readonly lastModified: DateTime, public readonly lastModified: DateTime,
public readonly canAccessApi: boolean, public readonly canAccessApi: boolean,
@ -107,7 +107,7 @@ export class AppsService {
) { ) {
} }
public getApps(): Observable<AppDto[]> { public getApps(): Observable<ReadonlyArray<AppDto>> {
const url = this.apiUrl.buildUrl('/api/apps'); const url = this.apiUrl.buildUrl('/api/apps');
return this.http.get<any[]>(url).pipe( return this.http.get<any[]>(url).pipe(

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

@ -325,7 +325,7 @@ describe('AssetsService', () => {
} }
}); });
export function createAsset(id: number, tags?: string[], suffix = '') { export function createAsset(id: number, tags?: ReadonlyArray<string>, suffix = '') {
const links: ResourceLinks = { const links: ResourceLinks = {
update: { method: 'PUT', href: `/assets/${id}` } update: { method: 'PUT', href: `/assets/${id}` }
}; };

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

@ -69,7 +69,7 @@ export class AssetDto {
public readonly pixelWidth: number | null | undefined, public readonly pixelWidth: number | null | undefined,
public readonly pixelHeight: number | null | undefined, public readonly pixelHeight: number | null | undefined,
public readonly slug: string, public readonly slug: string,
public readonly tags: string[], public readonly tags: ReadonlyArray<string>,
public readonly version: Version public readonly version: Version
) { ) {
this.canPreview = this.isImage || (this.mimeType === 'image/svg+xml' && this.fileSize < 100 * 1024); this.canPreview = this.isImage || (this.mimeType === 'image/svg+xml' && this.fileSize < 100 * 1024);
@ -91,7 +91,7 @@ export class AssetDto {
export interface AnnotateAssetDto { export interface AnnotateAssetDto {
readonly fileName?: string; readonly fileName?: string;
readonly slug?: string; readonly slug?: string;
readonly tags?: string[]; readonly tags?: ReadonlyArray<string>;
} }
@Injectable() @Injectable()
@ -109,7 +109,7 @@ export class AssetsService {
return this.http.get<{ [name: string]: number }>(url); return this.http.get<{ [name: string]: number }>(url);
} }
public getAssets(appName: string, take: number, skip: number, query?: Query, tags?: string[], ids?: string[]): Observable<AssetsDto> { public getAssets(appName: string, take: number, skip: number, query?: Query, tags?: ReadonlyArray<string>, ids?: ReadonlyArray<string>): Observable<AssetsDto> {
let fullQuery = ''; let fullQuery = '';
if (ids) { if (ids) {

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

@ -62,7 +62,7 @@ export class RestoreDto {
public readonly started: DateTime, public readonly started: DateTime,
public readonly stopped: DateTime | null, public readonly stopped: DateTime | null,
public readonly status: string, public readonly status: string,
public readonly log: string[] public readonly log: ReadonlyArray<string>
) { ) {
} }
} }

2
src/Squidex/app/shared/services/clients.service.spec.ts

@ -188,7 +188,7 @@ describe('ClientsService', () => {
} }
}); });
export function createClients(...ids: number[]): ClientsPayload { export function createClients(...ids: ReadonlyArray<number>): ClientsPayload {
return { return {
items: ids.map(id => createClient(id)), items: ids.map(id => createClient(id)),
_links: { _links: {

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

@ -25,7 +25,7 @@ import {
export type ClientsDto = Versioned<ClientsPayload>; export type ClientsDto = Versioned<ClientsPayload>;
export type ClientsPayload = { export type ClientsPayload = {
readonly items: ClientDto[]; readonly items: ReadonlyArray<ClientDto>;
readonly canCreate: boolean; readonly canCreate: boolean;
} & Resource; } & Resource;

6
src/Squidex/app/shared/services/comments.service.ts

@ -20,9 +20,9 @@ import {
export class CommentsDto extends Model<CommentsDto> { export class CommentsDto extends Model<CommentsDto> {
constructor( constructor(
public readonly createdComments: CommentDto[], public readonly createdComments: ReadonlyArray<CommentDto>,
public readonly updatedComments: CommentDto[], public readonly updatedComments: ReadonlyArray<CommentDto>,
public readonly deletedComments: string[], public readonly deletedComments: ReadonlyArray<string>,
public readonly version: Version public readonly version: Version
) { ) {
super(); super();

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

@ -42,9 +42,9 @@ export type StatusInfo = { status: string; color: string; };
export class ContentsDto extends ResultSet<ContentDto> { export class ContentsDto extends ResultSet<ContentDto> {
constructor( constructor(
public readonly statuses: StatusInfo[], public readonly statuses: ReadonlyArray<StatusInfo>,
total: number, total: number,
items: ContentDto[], items: ReadonlyArray<ContentDto>,
links?: ResourceLinks links?: ResourceLinks
) { ) {
super(total, items, links); super(total, items, links);
@ -67,7 +67,7 @@ export type ContentData = { [fieldName: string ]: ContentFieldData };
export class ContentDto { export class ContentDto {
public readonly _links: ResourceLinks; public readonly _links: ResourceLinks;
public readonly statusUpdates: StatusInfo[]; public readonly statusUpdates: ReadonlyArray<StatusInfo>;
public readonly canDelete: boolean; public readonly canDelete: boolean;
public readonly canDraftDiscard: boolean; public readonly canDraftDiscard: boolean;
@ -91,7 +91,7 @@ export class ContentDto {
public readonly schemaName: string, public readonly schemaName: string,
public readonly schemaDisplayName: string, public readonly schemaDisplayName: string,
public readonly referenceData: ContentReferences, public readonly referenceData: ContentReferences,
public readonly referenceFields: RootFieldDto[], public readonly referenceFields: ReadonlyArray<RootFieldDto>,
public readonly version: Version public readonly version: Version
) { ) {
this._links = links; this._links = links;
@ -116,7 +116,7 @@ export class ContentsService {
) { ) {
} }
public getContents(appName: string, schemaName: string, take: number, skip: number, query?: Query, ids?: string[]): Observable<ContentsDto> { public getContents(appName: string, schemaName: string, take: number, skip: number, query?: Query, ids?: ReadonlyArray<string>): Observable<ContentsDto> {
const queryParts: string[] = []; const queryParts: string[] = [];
if (ids && ids.length > 0) { if (ids && ids.length > 0) {
@ -160,7 +160,7 @@ export class ContentsService {
pretifyError('Failed to load contents. Please reload.')); pretifyError('Failed to load contents. Please reload.'));
} }
public getContentsByIds(appName: string, ids: string[]): Observable<ContentsDto> { public getContentsByIds(appName: string, ids: ReadonlyArray<string>): Observable<ContentsDto> {
const url = this.apiUrl.buildUrl(`/api/content/${appName}/?ids=${ids.join(',')}`); const url = this.apiUrl.buildUrl(`/api/content/${appName}/?ids=${ids.join(',')}`);
return this.http.get<{ total: number, items: [], statuses: StatusInfo[] } & Resource>(url).pipe( return this.http.get<{ total: number, items: [], statuses: StatusInfo[] } & Resource>(url).pipe(

2
src/Squidex/app/shared/services/contributors.service.spec.ts

@ -138,7 +138,7 @@ describe('ContributorsService', () => {
} }
}); });
export function createContributors(...ids: number[]): ContributorsPayload { export function createContributors(...ids: ReadonlyArray<number>): ContributorsPayload {
return { return {
items: ids.map(id => createContributor(id)), items: ids.map(id => createContributor(id)),
maxContributors: ids.length * 13, maxContributors: ids.length * 13,

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

@ -25,7 +25,7 @@ import {
export type ContributorsDto = Versioned<ContributorsPayload>; export type ContributorsDto = Versioned<ContributorsPayload>;
export type ContributorsPayload = { export type ContributorsPayload = {
readonly items: ContributorDto[]; readonly items: ReadonlyArray<ContributorDto>;
readonly maxContributors: number; readonly maxContributors: number;

2
src/Squidex/app/shared/services/history.service.spec.ts

@ -35,7 +35,7 @@ describe('HistoryService', () => {
it('should make get request to get history events', it('should make get request to get history events',
inject([HistoryService, HttpTestingController], (historyService: HistoryService, httpMock: HttpTestingController) => { inject([HistoryService, HttpTestingController], (historyService: HistoryService, httpMock: HttpTestingController) => {
let events: HistoryEventDto[]; let events: ReadonlyArray<HistoryEventDto>;
historyService.getHistory('my-app', 'settings.contributors').subscribe(result => { historyService.getHistory('my-app', 'settings.contributors').subscribe(result => {
events = result; events = result;

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

@ -78,7 +78,7 @@ export class HistoryService {
) { ) {
} }
public getHistory(appName: string, channel: string): Observable<HistoryEventDto[]> { public getHistory(appName: string, channel: string): Observable<ReadonlyArray<HistoryEventDto>> {
const url = this.apiUrl.buildUrl(`api/apps/${appName}/history?channel=${channel}`); const url = this.apiUrl.buildUrl(`api/apps/${appName}/history?channel=${channel}`);
return this.http.get<any[]>(url).pipe( return this.http.get<any[]>(url).pipe(

2
src/Squidex/app/shared/services/languages.service.spec.ts

@ -34,7 +34,7 @@ describe('LanguageService', () => {
it('should make get request to get languages', it('should make get request to get languages',
inject([LanguagesService, HttpTestingController], (languagesService: LanguagesService, httpMock: HttpTestingController) => { inject([LanguagesService, HttpTestingController], (languagesService: LanguagesService, httpMock: HttpTestingController) => {
let languages: LanguageDto[]; let languages: ReadonlyArray<LanguageDto>;
languagesService.getLanguages().subscribe(result => { languagesService.getLanguages().subscribe(result => {
languages = result; languages = result;

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

@ -28,7 +28,7 @@ export class LanguagesService {
) { ) {
} }
public getLanguages(): Observable<LanguageDto[]> { public getLanguages(): Observable<ReadonlyArray<LanguageDto>> {
const url = this.apiUrl.buildUrl('api/languages'); const url = this.apiUrl.buildUrl('api/languages');
return this.http.get<any[]>(url).pipe( return this.http.get<any[]>(url).pipe(

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

@ -22,7 +22,7 @@ export class FeatureDto {
export class FeaturesDto { export class FeaturesDto {
constructor( constructor(
public readonly features: FeatureDto[], public readonly features: ReadonlyArray<FeatureDto>,
public readonly version: number public readonly version: number
) { ) {
} }

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save