Browse Source

Update editor. (#1038)

* Update editor.

* Scroll down.
pull/1039/head
Sebastian Stehle 3 years ago
committed by GitHub
parent
commit
609819a861
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      backend/i18n/frontend_en.json
  2. 3
      backend/i18n/frontend_fr.json
  3. 3
      backend/i18n/frontend_it.json
  4. 3
      backend/i18n/frontend_nl.json
  5. 3
      backend/i18n/frontend_pt.json
  6. 3
      backend/i18n/frontend_zh.json
  7. 3
      backend/i18n/source/frontend_en.json
  8. 140
      backend/src/Squidex/wwwroot/editor/squidex-editor.js
  9. 23
      frontend/.eslintrc.js
  10. 16
      frontend/angular.json
  11. 1509
      frontend/package-lock.json
  12. 13
      frontend/package.json
  13. 4
      frontend/src/app/app.module.ts
  14. 11
      frontend/src/app/declarations.d.ts
  15. 2
      frontend/src/app/features/administration/pages/event-consumers/event-consumer.component.html
  16. 4
      frontend/src/app/features/administration/pages/event-consumers/event-consumer.component.ts
  17. 4
      frontend/src/app/features/administration/pages/event-consumers/event-consumers-page.component.html
  18. 2
      frontend/src/app/features/administration/pages/users/user.component.ts
  19. 2
      frontend/src/app/features/api/pages/graphql/graphql-page.component.html
  20. 6
      frontend/src/app/features/apps/pages/apps-page.component.html
  21. 2
      frontend/src/app/features/apps/pages/news-dialog.component.html
  22. 2
      frontend/src/app/features/apps/pages/news-dialog.component.ts
  23. 2
      frontend/src/app/features/apps/pages/onboarding-dialog.component.html
  24. 6
      frontend/src/app/features/apps/pages/onboarding-dialog.component.ts
  25. 2
      frontend/src/app/features/assets/pages/asset-tag-dialog.component.html
  26. 4
      frontend/src/app/features/assets/pages/asset-tag-dialog.component.ts
  27. 4
      frontend/src/app/features/assets/pages/asset-tags.component.html
  28. 2
      frontend/src/app/features/assets/pages/asset-tags.component.ts
  29. 3
      frontend/src/app/features/assets/pages/assets-filters-page.component.html
  30. 4
      frontend/src/app/features/assets/pages/assets-page.component.html
  31. 1
      frontend/src/app/features/content/declarations.ts
  32. 3
      frontend/src/app/features/content/module.ts
  33. 2
      frontend/src/app/features/content/pages/calendar/calendar-page.component.html
  34. 4
      frontend/src/app/features/content/pages/calendar/calendar-page.component.ts
  35. 4
      frontend/src/app/features/content/pages/contents/contents-page.component.html
  36. 4
      frontend/src/app/features/content/pages/contents/custom-view-editor.component.ts
  37. 2
      frontend/src/app/features/content/shared/content-extension.component.ts
  38. 2
      frontend/src/app/features/content/shared/due-time-selector.component.html
  39. 4
      frontend/src/app/features/content/shared/forms/assets-editor.component.html
  40. 109
      frontend/src/app/features/content/shared/forms/chat-dialog.component.html
  41. 2
      frontend/src/app/features/content/shared/forms/component.component.ts
  42. 6
      frontend/src/app/features/content/shared/forms/field-editor.component.html
  43. 4
      frontend/src/app/features/content/shared/forms/field-editor.component.ts
  44. 4
      frontend/src/app/features/content/shared/forms/iframe-editor.component.html
  45. 2
      frontend/src/app/features/content/shared/forms/iframe-editor.component.ts
  46. 2
      frontend/src/app/features/content/shared/forms/stock-photo-editor.component.html
  47. 5
      frontend/src/app/features/content/shared/list/content.component.ts
  48. 2
      frontend/src/app/features/content/shared/references/content-creator.component.html
  49. 6
      frontend/src/app/features/content/shared/references/content-creator.component.ts
  50. 2
      frontend/src/app/features/content/shared/references/reference-dropdown.component.html
  51. 2
      frontend/src/app/features/content/shared/references/reference-item.component.ts
  52. 4
      frontend/src/app/features/content/shared/references/references-editor.component.html
  53. 2
      frontend/src/app/features/content/shared/references/references-tags.component.html
  54. 2
      frontend/src/app/features/dashboard/pages/dashboard-config.component.html
  55. 2
      frontend/src/app/features/rules/pages/events/rule-event.component.ts
  56. 2
      frontend/src/app/features/rules/pages/simulator/simulated-rule-event.component.ts
  57. 2
      frontend/src/app/features/schemas/pages/schema/fields/field-wizard.component.html
  58. 4
      frontend/src/app/features/schemas/pages/schema/fields/field-wizard.component.ts
  59. 2
      frontend/src/app/features/schemas/pages/schema/fields/field.component.html
  60. 2
      frontend/src/app/features/schemas/pages/schema/fields/forms/field-form.component.html
  61. 2
      frontend/src/app/features/schemas/pages/schema/fields/forms/field-form.component.ts
  62. 2
      frontend/src/app/features/schemas/pages/schema/fields/schema-fields.component.html
  63. 2
      frontend/src/app/features/schemas/pages/schema/scripts/schema-scripts-form.component.ts
  64. 4
      frontend/src/app/features/schemas/pages/schemas/schema-form.component.html
  65. 4
      frontend/src/app/features/schemas/pages/schemas/schema-form.component.ts
  66. 2
      frontend/src/app/features/schemas/pages/schemas/schemas-page.component.html
  67. 2
      frontend/src/app/features/settings/pages/clients/client-connect-form.component.html
  68. 2
      frontend/src/app/features/settings/pages/clients/client-connect-form.component.ts
  69. 2
      frontend/src/app/features/settings/pages/clients/client.component.html
  70. 2
      frontend/src/app/features/settings/pages/contributors/contributor-add-form.component.html
  71. 2
      frontend/src/app/features/settings/pages/contributors/contributor.component.ts
  72. 4
      frontend/src/app/features/settings/pages/contributors/import-contributors-dialog.component.html
  73. 2
      frontend/src/app/features/settings/pages/contributors/import-contributors-dialog.component.ts
  74. 4
      frontend/src/app/features/settings/pages/roles/roles-page.component.ts
  75. 2
      frontend/src/app/features/teams/pages/contributors/contributor-add-form.component.html
  76. 2
      frontend/src/app/features/teams/pages/contributors/contributor.component.ts
  77. 4
      frontend/src/app/features/teams/pages/contributors/import-contributors-dialog.component.html
  78. 2
      frontend/src/app/features/teams/pages/contributors/import-contributors-dialog.component.ts
  79. 4
      frontend/src/app/framework/angular/compensate-scrollbar.directive.ts
  80. 2
      frontend/src/app/framework/angular/dropdown-menu.component.ts
  81. 3
      frontend/src/app/framework/angular/forms/editors/autocomplete.component.html
  82. 5
      frontend/src/app/framework/angular/forms/editors/date-time-editor.component.html
  83. 4
      frontend/src/app/framework/angular/forms/editors/date-time-editor.component.ts
  84. 8
      frontend/src/app/framework/angular/forms/editors/dropdown.component.ts
  85. 2
      frontend/src/app/framework/angular/forms/editors/dropdown.stories.ts
  86. 10
      frontend/src/app/framework/angular/forms/editors/localized-input.component.html
  87. 7
      frontend/src/app/framework/angular/forms/editors/tag-editor.component.html
  88. 14
      frontend/src/app/framework/angular/forms/editors/tag-editor.component.ts
  89. 2
      frontend/src/app/framework/angular/forms/editors/tag-editor.stories.ts
  90. 8
      frontend/src/app/framework/angular/forms/file-drop.directive.ts
  91. 2
      frontend/src/app/framework/angular/layout.component.ts
  92. 3
      frontend/src/app/framework/angular/long-hover.directive.ts
  93. 4
      frontend/src/app/framework/angular/modals/dialog-renderer.component.html
  94. 4
      frontend/src/app/framework/angular/modals/modal-dialog.component.html
  95. 2
      frontend/src/app/framework/angular/modals/modal-dialog.component.ts
  96. 2
      frontend/src/app/framework/angular/modals/modal.directive.ts
  97. 2
      frontend/src/app/framework/angular/modals/tooltip.directive.ts
  98. 4
      frontend/src/app/framework/angular/pipes/colors.pipes.ts
  99. 6
      frontend/src/app/framework/angular/resized.directive.ts
  100. 12
      frontend/src/app/framework/angular/scroll-active.directive.ts

3
backend/i18n/frontend_en.json

@ -170,7 +170,8 @@
"chat.answers": "Answers",
"chat.answersEmpty": "The ChatBot does not provide an answer or has not been configured yet.",
"chat.ask": "Ask",
"chat.description": "Use the ChatBot (usually OpenAI) to generate content. Just write a prompt and describe, what you need.\n\n\nAlso add the desired format (for example Markdown or HTML) to your prompt, dependending on the editor that you use.",
"chat.describeFormat": "Also add the desired format (for example Markdown or HTML) to your prompt, dependending on the editor that you use.",
"chat.description": "Use the ChatBot (usually OpenAI) to generate content. Just write a prompt and describe the content you want to generate.",
"chat.prompt": "Describe the content you want to generate",
"chat.title": "Chat Bot",
"chat.use": "Use",

3
backend/i18n/frontend_fr.json

@ -170,7 +170,8 @@
"chat.answers": "Answers",
"chat.answersEmpty": "The ChatBot does not provide an answer or has not been configured yet.",
"chat.ask": "Ask",
"chat.description": "Use the ChatBot (usually OpenAI) to generate content. Just write a prompt and describe, what you need.\n\n\nAlso add the desired format (for example Markdown or HTML) to your prompt, dependending on the editor that you use.",
"chat.describeFormat": "Also add the desired format (for example Markdown or HTML) to your prompt, dependending on the editor that you use.",
"chat.description": "Use the ChatBot (usually OpenAI) to generate content. Just write a prompt and describe the content you want to generate.",
"chat.prompt": "Describe the content you want to generate",
"chat.title": "Chat Bot",
"chat.use": "Use",

3
backend/i18n/frontend_it.json

@ -170,7 +170,8 @@
"chat.answers": "Answers",
"chat.answersEmpty": "The ChatBot does not provide an answer or has not been configured yet.",
"chat.ask": "Ask",
"chat.description": "Use the ChatBot (usually OpenAI) to generate content. Just write a prompt and describe, what you need.\n\n\nAlso add the desired format (for example Markdown or HTML) to your prompt, dependending on the editor that you use.",
"chat.describeFormat": "Also add the desired format (for example Markdown or HTML) to your prompt, dependending on the editor that you use.",
"chat.description": "Use the ChatBot (usually OpenAI) to generate content. Just write a prompt and describe the content you want to generate.",
"chat.prompt": "Describe the content you want to generate",
"chat.title": "Chat Bot",
"chat.use": "Use",

3
backend/i18n/frontend_nl.json

@ -170,7 +170,8 @@
"chat.answers": "Answers",
"chat.answersEmpty": "The ChatBot does not provide an answer or has not been configured yet.",
"chat.ask": "Ask",
"chat.description": "Use the ChatBot (usually OpenAI) to generate content. Just write a prompt and describe, what you need.\n\n\nAlso add the desired format (for example Markdown or HTML) to your prompt, dependending on the editor that you use.",
"chat.describeFormat": "Also add the desired format (for example Markdown or HTML) to your prompt, dependending on the editor that you use.",
"chat.description": "Use the ChatBot (usually OpenAI) to generate content. Just write a prompt and describe the content you want to generate.",
"chat.prompt": "Describe the content you want to generate",
"chat.title": "Chat Bot",
"chat.use": "Use",

3
backend/i18n/frontend_pt.json

@ -170,7 +170,8 @@
"chat.answers": "Answers",
"chat.answersEmpty": "The ChatBot does not provide an answer or has not been configured yet.",
"chat.ask": "Ask",
"chat.description": "Use the ChatBot (usually OpenAI) to generate content. Just write a prompt and describe, what you need.\n\n\nAlso add the desired format (for example Markdown or HTML) to your prompt, dependending on the editor that you use.",
"chat.describeFormat": "Also add the desired format (for example Markdown or HTML) to your prompt, dependending on the editor that you use.",
"chat.description": "Use the ChatBot (usually OpenAI) to generate content. Just write a prompt and describe the content you want to generate.",
"chat.prompt": "Describe the content you want to generate",
"chat.title": "Chat Bot",
"chat.use": "Use",

3
backend/i18n/frontend_zh.json

@ -170,7 +170,8 @@
"chat.answers": "Answers",
"chat.answersEmpty": "The ChatBot does not provide an answer or has not been configured yet.",
"chat.ask": "Ask",
"chat.description": "Use the ChatBot (usually OpenAI) to generate content. Just write a prompt and describe, what you need.\n\n\nAlso add the desired format (for example Markdown or HTML) to your prompt, dependending on the editor that you use.",
"chat.describeFormat": "Also add the desired format (for example Markdown or HTML) to your prompt, dependending on the editor that you use.",
"chat.description": "Use the ChatBot (usually OpenAI) to generate content. Just write a prompt and describe the content you want to generate.",
"chat.prompt": "Describe the content you want to generate",
"chat.title": "Chat Bot",
"chat.use": "Use",

3
backend/i18n/source/frontend_en.json

@ -170,7 +170,8 @@
"chat.answers": "Answers",
"chat.answersEmpty": "The ChatBot does not provide an answer or has not been configured yet.",
"chat.ask": "Ask",
"chat.description": "Use the ChatBot (usually OpenAI) to generate content. Just write a prompt and describe, what you need.\n\n\nAlso add the desired format (for example Markdown or HTML) to your prompt, dependending on the editor that you use.",
"chat.describeFormat": "Also add the desired format (for example Markdown or HTML) to your prompt, dependending on the editor that you use.",
"chat.description": "Use the ChatBot (usually OpenAI) to generate content. Just write a prompt and describe the content you want to generate.",
"chat.prompt": "Describe the content you want to generate",
"chat.title": "Chat Bot",
"chat.use": "Use",

140
backend/src/Squidex/wwwroot/editor/squidex-editor.js

File diff suppressed because one or more lines are too long

23
frontend/.eslintrc.js

@ -6,7 +6,9 @@ module.exports = {
"node": true
},
"extends": [
"airbnb-typescript/base"
"airbnb-typescript/base",
"plugin:@angular-eslint/recommended",
"plugin:@angular-eslint/template/process-inline-templates"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
@ -19,6 +21,25 @@ module.exports = {
],
"rules": {
"deprecation/deprecation": "warn",
"@angular-eslint/directive-selector": [
"error",
{
"type": "attribute",
"prefix": "sqx",
"style": "camelCase"
}
],
"@angular-eslint/component-selector": [
"error",
{
"type": "element",
"prefix": "sqx",
"style": "kebab-case"
}
],
"@angular-eslint/use-lifecycle-interface": [
"off"
],
"@typescript-eslint/dot-notation": "off",
"@typescript-eslint/indent": "off",
"@typescript-eslint/lines-between-class-members": "off",

16
frontend/angular.json

@ -154,11 +154,23 @@
"compodoc": false,
"outputDir": "storybook-static"
}
},
"lint": {
"builder": "@angular-eslint/builder:lint",
"options": {
"lintFilePatterns": [
"src/**/*.ts",
"src/**/*.html"
]
}
}
}
}
},
"cli": {
"analytics": "a157454d-c7c0-4947-986a-982746edc974"
"analytics": "a157454d-c7c0-4947-986a-982746edc974",
"schematicCollections": [
"@angular-eslint/schematics"
]
}
}
}

1509
frontend/package-lock.json

File diff suppressed because it is too large

13
frontend/package.json

@ -80,6 +80,11 @@
"devDependencies": {
"@angular-builders/custom-webpack": "^16.0.0",
"@angular-devkit/build-angular": "^16.1.7",
"@angular-eslint/builder": "16.2.0",
"@angular-eslint/eslint-plugin": "16.2.0",
"@angular-eslint/eslint-plugin-template": "16.2.0",
"@angular-eslint/schematics": "16.2.0",
"@angular-eslint/template-parser": "16.2.0",
"@angular/cli": "^16.1.7",
"@angular/compiler": "^16.1.8",
"@angular/compiler-cli": "^16.1.8",
@ -104,12 +109,12 @@
"@types/simplemde": "1.11.8",
"@types/tapable": "2.2.3",
"@types/ws": "8.5.5",
"@typescript-eslint/eslint-plugin": "6.2.1",
"@typescript-eslint/parser": "6.2.1",
"@typescript-eslint/eslint-plugin": "5.62.0",
"@typescript-eslint/parser": "5.62.0",
"@webcomponents/custom-elements": "^1.6.0",
"babel-loader": "^9.1.3",
"copy-webpack-plugin": "11.0.0",
"eslint": "8.46.0",
"eslint": "^8.49.0",
"eslint-config-airbnb-typescript": "17.1.0",
"eslint-plugin-deprecation": "^1.5.0",
"eslint-plugin-import": "2.28.0",
@ -136,4 +141,4 @@
"ng2-charts-schematics": "0.1.7"
}
}
}
}

4
frontend/src/app/app.module.ts

@ -10,7 +10,7 @@
import { APP_BASE_HREF, CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';
import { ApplicationRef, NgModule } from '@angular/core';
import { ApplicationRef, DoBootstrap, NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
@ -117,7 +117,7 @@ export class AppRouteReuseStrategy extends BaseRouteReuseStrategy {
{ provide: APP_BASE_HREF, useValue: basePath() },
],
})
export class AppModule {
export class AppModule implements DoBootstrap {
public ngDoBootstrap(appRef: ApplicationRef) {
try {
appRef.bootstrap(AppComponent);

11
frontend/src/app/declarations.d.ts

@ -42,6 +42,7 @@ type Content = {
title: string;
};
type OnSelectAIText = () => Promise<string | undefined | null>;
type OnSelectAssets = () => Promise<Asset[]>;
type OnSelectContents = () => Promise<Content[]>;
@ -67,11 +68,14 @@ interface EditorProps {
// Called when the value has been changed.
onChange?: OnChange;
// Called when AI text selected.
onSelectAIText?: OnSelectAIText;
// Called when assets are selected.
onSelectAssets: OnSelectAssets;
onSelectAssets?: OnSelectAssets;
// Called when content items should be selected.
onSelectContents: OnSelectContents;
onSelectContents?: OnSelectContents;
// Called when a file needs to be uploaded.
onUpload?: (images: UploadRequest[]) => DelayedPromiseCreator<Asset>[];
@ -79,6 +83,9 @@ interface EditorProps {
// True, if disabled.
isDisabled?: boolean;
// Indicates whether AI text can be selected.
canSelectAIText?: boolean;
// Indicates whether assets can be selected.
canSelectAssets?: boolean;

2
frontend/src/app/features/administration/pages/event-consumers/event-consumer.component.html

@ -1,7 +1,7 @@
<tr [class.faulted]="eventConsumer.error && eventConsumer.error && eventConsumer.error.length > 0">
<td class="cell-auto">
<span class="truncate">
<i class="faulted-icon icon icon-bug" (click)="error.emit()" [class.hidden]="!eventConsumer.error || eventConsumer.error.length === 0"></i>
<i class="faulted-icon icon icon-bug" (click)="failure.emit()" [class.hidden]="!eventConsumer.error || eventConsumer.error.length === 0"></i>
{{eventConsumer.name}}
</span>

4
frontend/src/app/features/administration/pages/event-consumers/event-consumer.component.ts

@ -5,6 +5,8 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
/* eslint-disable @angular-eslint/component-selector */
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
import { EventConsumerDto, EventConsumersState } from '@app/features/administration/internal';
@ -16,7 +18,7 @@ import { EventConsumerDto, EventConsumersState } from '@app/features/administrat
})
export class EventConsumerComponent {
@Output()
public error = new EventEmitter();
public failure = new EventEmitter();
@Input('sqxEventConsumer')
public eventConsumer!: EventConsumerDto;

4
frontend/src/app/features/administration/pages/event-consumers/event-consumers-page.component.html

@ -33,7 +33,7 @@
<ng-container>
<table class="table table-items table-fixed" [sqxSyncWidth]="header">
<tbody *ngFor="let eventConsumer of eventConsumersState.eventConsumers | async; trackBy: trackByEventConsumer"
[sqxEventConsumer]="eventConsumer" (error)="showError(eventConsumer)">
[sqxEventConsumer]="eventConsumer" (failure)="showError(eventConsumer)">
</tbody>
</table>
</ng-container>
@ -57,7 +57,7 @@
<router-outlet></router-outlet>
<sqx-modal-dialog *sqxModal="eventConsumerErrorDialog" (close)="eventConsumerErrorDialog.hide()">
<sqx-modal-dialog *sqxModal="eventConsumerErrorDialog" (dialogClose)="eventConsumerErrorDialog.hide()">
<ng-container title>
{{ 'common.error' | sqxTranslate }}
</ng-container>

2
frontend/src/app/features/administration/pages/users/user.component.ts

@ -5,6 +5,8 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
/* eslint-disable @angular-eslint/component-selector */
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { UserDto, UsersState } from '@app/features/administration/internal';

2
frontend/src/app/features/api/pages/graphql/graphql-page.component.html

@ -8,7 +8,7 @@
</button>
</sqx-layout>
<sqx-modal-dialog *sqxModal="clientsDialog" (close)="clientsDialog.hide()">
<sqx-modal-dialog *sqxModal="clientsDialog" (dialogClose)="clientsDialog.hide()">
<ng-container title>
{{ 'api.selectClient' | sqxTranslate }}
</ng-container>

6
frontend/src/app/features/apps/pages/apps-page.component.html

@ -67,13 +67,13 @@
</div>
<sqx-app-form *sqxModal="addAppDialog"
(close)="addAppDialog.hide()" [template]="addAppTemplate">
(dialogClose)="addAppDialog.hide()" [template]="addAppTemplate">
</sqx-app-form>
<sqx-onboarding-dialog *sqxModal="onboardingDialog"
(close)="onboardingDialog.hide()">
(dialogClose)="onboardingDialog.hide()">
</sqx-onboarding-dialog>
<sqx-news-dialog *sqxModal="newsDialog" [features]="newsFeatures!"
(close)="newsDialog.hide()">
(dialogClose)="newsDialog.hide()">
</sqx-news-dialog>

2
frontend/src/app/features/apps/pages/news-dialog.component.html

@ -1,4 +1,4 @@
<sqx-modal-dialog size="lg" (close)="close.emit()">
<sqx-modal-dialog size="lg" (dialogClose)="dialogClose.emit()">
<ng-container title>
{{ 'news.title' | sqxTranslate }}
</ng-container>

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

@ -15,7 +15,7 @@ import { FeatureDto } from '@app/shared';
})
export class NewsDialogComponent {
@Output()
public close = new EventEmitter();
public dialogClose = new EventEmitter();
@Input({ required: true })
public features!: ReadonlyArray<FeatureDto>;

2
frontend/src/app/features/apps/pages/onboarding-dialog.component.html

@ -6,7 +6,7 @@
</ng-container>
<ng-container content>
<a class="header-right modal-close force" (click)="close.emit()">{{ 'tour.skip' | sqxTranslate }}</a>
<a class="header-right modal-close force" (click)="dialogClose.emit()">{{ 'tour.skip' | sqxTranslate }}</a>
<div class="onboarding-step " *ngIf="step === 0">
<img @fade class="header-left" src="./images/logo-white-small.png">

6
frontend/src/app/features/apps/pages/onboarding-dialog.component.ts

@ -21,7 +21,7 @@ import { TourState, UsersService } from '@app/shared';
export class OnboardingDialogComponent {
@Output()
public close = new EventEmitter();
public dialogClose = new EventEmitter();
public answersForm =
this.formBuilder.group({
@ -46,12 +46,12 @@ export class OnboardingDialogComponent {
public start() {
this.tourState.start();
this.close.emit();
this.dialogClose.emit();
}
public cancel() {
this.tourState.complete();
this.close.emit();
this.dialogClose.emit();
}
public next() {

2
frontend/src/app/features/assets/pages/asset-tag-dialog.component.html

@ -1,5 +1,5 @@
<form [formGroup]="editForm.form" (ngSubmit)="renameAssetTag()">
<sqx-modal-dialog (close)="emitClose()">
<sqx-modal-dialog (dialogClose)="emitClose()">
<ng-container title>
{{ 'common.renameTag' | sqxTranslate }}
</ng-container>

4
frontend/src/app/features/assets/pages/asset-tag-dialog.component.ts

@ -15,7 +15,7 @@ import { AssetsState, RenameAssetTagForm } from '@app/shared/internal';
})
export class AssetTagDialogComponent implements OnInit {
@Output()
public close = new EventEmitter();
public dialogClose = new EventEmitter();
@Input({ required: true })
public tagName!: string;
@ -32,7 +32,7 @@ export class AssetTagDialogComponent implements OnInit {
}
public emitClose() {
this.close.emit();
this.dialogClose.emit();
}
public renameAssetTag() {

4
frontend/src/app/features/assets/pages/asset-tags.component.html

@ -1,6 +1,6 @@
<div class="nav nav-light flex-column">
<div class="nav-item">
<a class="nav-link" (click)="reset.emit()" [class.active]="isEmpty()">
<a class="nav-link" (click)="tagsReset.emit()" [class.active]="isEmpty()">
{{ 'common.tagsAll' | sqxTranslate }}
</a>
</div>
@ -24,5 +24,5 @@
</div>
<sqx-asset-tag-dialog *sqxModal="tagRenameDialog"
(close)="tagRenameDialog.hide()" [tagName]="tagRenaming!.name">
(dialogClose)="tagRenameDialog.hide()" [tagName]="tagRenaming!.name">
</sqx-asset-tag-dialog>

2
frontend/src/app/features/assets/pages/asset-tags.component.ts

@ -18,7 +18,7 @@ import { DialogModel, TagItem, TagsSelected } from '@app/shared';
})
export class AssetTagsComponent {
@Output()
public reset = new EventEmitter();
public tagsReset = new EventEmitter();
@Output()
public toggle = new EventEmitter<string>();

3
frontend/src/app/features/assets/pages/assets-filters-page.component.html

@ -1,9 +1,10 @@
<sqx-layout titleText="i18n:common.filters" width="20" white="true" padding="true" overflow="true">
<h3>{{ 'common.tags' | sqxTranslate }}</h3>
<sqx-asset-tags (reset)="resetTags()"
<sqx-asset-tags
[canRename]="(assetsState.canRenameTag | async)!"
[tags]="(assetsState.tags | async)!"
(tagsReset)="resetTags()"
[tagsSelected]="(assetsState.tagsSelected | async)!"
(toggle)="toggleTag($event)">
</sqx-asset-tags>

4
frontend/src/app/features/assets/pages/assets-page.component.html

@ -89,12 +89,12 @@
<router-outlet></router-outlet>
<sqx-asset-folder-dialog *sqxModal="addAssetFolderDialog"
(close)="addAssetFolderDialog.hide()">
(dialogClose)="addAssetFolderDialog.hide()">
</sqx-asset-folder-dialog>
<sqx-asset-dialog *sqxModal="editAsset;isDialog:true"
[asset]="editAsset!"
(assetUpdated)="replaceAsset($event)"
(assetReplaced)="replaceAsset($event)"
(close)="editDone()">
(dialogClose)="editDone()">
</sqx-asset-dialog>

1
frontend/src/app/features/content/declarations.ts

@ -28,7 +28,6 @@ export * from './shared/due-time-selector.component';
export * from './shared/forms/array-editor.component';
export * from './shared/forms/array-item.component';
export * from './shared/forms/assets-editor.component';
export * from './shared/forms/chat-dialog.component';
export * from './shared/forms/component-section.component';
export * from './shared/forms/component.component';
export * from './shared/forms/field-editor.component';

3
frontend/src/app/features/content/module.ts

@ -9,7 +9,7 @@ import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { VirtualScrollerModule } from '@iharbeck/ngx-virtual-scroller';
import { CanDeactivateGuard, ContentMustExistGuard, LoadLanguagesGuard, LoadSchemasGuard, SchemaMustExistPublishedGuard, SchemaMustNotBeSingletonGuard, SqxFrameworkModule, SqxSharedModule } from '@app/shared';
import { ArrayEditorComponent, ArrayItemComponent, AssetsEditorComponent, CalendarPageComponent, ChatDialogComponent, CommentsPageComponent, ComponentComponent, ComponentSectionComponent, ContentComponent, ContentCreatorComponent, ContentEditorComponent, ContentEventComponent, ContentExtensionComponent, ContentFieldComponent, ContentHistoryPageComponent, ContentInspectionComponent, ContentPageComponent, ContentReferencesComponent, ContentSectionComponent, ContentsFiltersPageComponent, ContentsPageComponent, CustomViewEditorComponent, DueTimeSelectorComponent, FieldCopyButtonComponent, FieldEditorComponent, FieldLanguagesComponent, IFrameEditorComponent, PreviewButtonComponent, ReferenceDropdownComponent, ReferenceItemComponent, ReferencesCheckboxesComponent, ReferencesEditorComponent, ReferencesPageComponent, ReferencesTagsComponent, SchemasPageComponent, SidebarPageComponent, StockPhotoEditorComponent } from './declarations';
import { ArrayEditorComponent, ArrayItemComponent, AssetsEditorComponent, CalendarPageComponent, CommentsPageComponent, ComponentComponent, ComponentSectionComponent, ContentComponent, ContentCreatorComponent, ContentEditorComponent, ContentEventComponent, ContentExtensionComponent, ContentFieldComponent, ContentHistoryPageComponent, ContentInspectionComponent, ContentPageComponent, ContentReferencesComponent, ContentSectionComponent, ContentsFiltersPageComponent, ContentsPageComponent, CustomViewEditorComponent, DueTimeSelectorComponent, FieldCopyButtonComponent, FieldEditorComponent, FieldLanguagesComponent, IFrameEditorComponent, PreviewButtonComponent, ReferenceDropdownComponent, ReferenceItemComponent, ReferencesCheckboxesComponent, ReferencesEditorComponent, ReferencesPageComponent, ReferencesTagsComponent, SchemasPageComponent, SidebarPageComponent, StockPhotoEditorComponent } from './declarations';
const routes: Routes = [
{
@ -97,7 +97,6 @@ const routes: Routes = [
ArrayItemComponent,
AssetsEditorComponent,
CalendarPageComponent,
ChatDialogComponent,
CommentsPageComponent,
ComponentComponent,
ComponentSectionComponent,

2
frontend/src/app/features/content/pages/calendar/calendar-page.component.html

@ -23,7 +23,7 @@
</ng-container>
</sqx-layout>
<sqx-modal-dialog *sqxModal="contentDialog" (close)="contentDialog.hide()">
<sqx-modal-dialog *sqxModal="contentDialog" (dialogClose)="contentDialog.hide()">
<ng-container title>
{{ 'common.content' | sqxTranslate }}
</ng-container>

4
frontend/src/app/features/content/pages/calendar/calendar-page.component.ts

@ -5,7 +5,7 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { AfterViewInit, ChangeDetectorRef, Component, ElementRef, HostListener, OnDestroy, ViewChild } from '@angular/core';
import { AfterViewInit, ChangeDetectorRef, Component, ElementRef, HostListener, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { AppsState, ContentDto, ContentsService, DateTime, DialogModel, getContentValue, LanguageDto, LanguagesState, LocalizerService, ResourceLoaderService } from '@app/shared';
declare const tui: any;
@ -17,7 +17,7 @@ type ViewMode = 'day' | 'week' | 'month';
styleUrls: ['./calendar-page.component.scss'],
templateUrl: './calendar-page.component.html',
})
export class CalendarPageComponent implements AfterViewInit, OnDestroy {
export class CalendarPageComponent implements AfterViewInit, OnDestroy, OnInit {
private calendar: any;
private language!: LanguageDto;

4
frontend/src/app/features/content/pages/contents/contents-page.component.html

@ -72,8 +72,8 @@
<sqx-custom-view-editor
[allFields]="tableSettings.schemaFields"
(listFieldsChange)="tableSettings.updateFields($event)"
[listFields]="$any(tableFields)"
(reset)="tableSettings.reset()">
(listFieldsReset)="tableSettings.reset()"
[listFields]="$any(tableFields)">
</sqx-custom-view-editor>
</sqx-dropdown-menu>
</div>

4
frontend/src/app/features/content/pages/contents/custom-view-editor.component.ts

@ -17,7 +17,7 @@ import { TableField } from '@app/shared';
})
export class CustomViewEditorComponent {
@Output()
public reset = new EventEmitter();
public listFieldsReset = new EventEmitter();
@Output()
public listFieldsChange = new EventEmitter<ReadonlyArray<TableField>>();
@ -53,6 +53,6 @@ export class CustomViewEditorComponent {
}
public resetDefault() {
this.reset.emit();
this.listFieldsReset.emit();
}
}

2
frontend/src/app/features/content/shared/content-extension.component.ts

@ -16,7 +16,7 @@ import { AppsState, AuthService, computeEditorUrl, ContentDto, SchemaDto, TypedS
templateUrl: './content-extension.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ContentExtensionComponent {
export class ContentExtensionComponent {
private readonly context: any;
private isInitialized = false;

2
frontend/src/app/features/content/shared/due-time-selector.component.html

@ -1,4 +1,4 @@
<sqx-modal-dialog *sqxModal="dueTimeDialog" (close)="cancelStatusChange()">
<sqx-modal-dialog *sqxModal="dueTimeDialog" (dialogClose)="cancelStatusChange()">
<ng-container title>
{{ 'contents.changeStatusTo' | sqxTranslate: { action: dueTimeAction } }}
</ng-container>

4
frontend/src/app/features/content/shared/forms/assets-editor.component.html

@ -82,12 +82,12 @@
</div>
<sqx-asset-selector *sqxModal="assetsDialog"
(select)="selectAssets($event)">
(assetSelect)="selectAssets($event)">
</sqx-asset-selector>
<sqx-asset-dialog *sqxModal="snapshot.editAsset;isDialog:true"
[asset]="snapshot.editAsset!"
(assetReplaced)="notifyOthers($event)"
(assetUpdated)="notifyOthers($event)"
(close)="editDone()">
(dialogClose)="editDone()">
</sqx-asset-dialog>

109
frontend/src/app/features/content/shared/forms/chat-dialog.component.html

@ -1,109 +0,0 @@
<sqx-modal-dialog size="lg" (close)="close.emit()" fullHeight="true">
<ng-container title>
{{ 'chat.title' | sqxTranslate }}
</ng-container>
<ng-container content>
<div class="item">
<div class="row">
<div class="col-auto">
<div class="squid squid-sm d-flex align-items-center justify-content-center">
<img src="./images/squid.svg">
</div>
</div>
<div class="col">
<div class="bubble bubble-right">
<span [sqxMarkdown]="'chat.description' | sqxTranslate" inline="false"></span>
</div>
</div>
</div>
</div>
<div class="item" *ngFor="let item of snapshot.chatTalk">
<div class="row mt-3" *ngIf="item.type === 'user'">
<div class="col">
<div class="bubble bubble-left">
{{item.text}}
</div>
</div>
<div class="col-auto">
<img class="user-picture" title="{{user.displayName}}" [src]="user.id | sqxUserIdPicture" />
</div>
</div>
<div class="row mt-3" *ngIf="item.type === 'system'">
<div class="col-auto">
<div class="squid squid-sm d-flex align-items-center justify-content-center">
<img src="./images/squid.svg">
</div>
</div>
<div class="col">
<div class="bubble bubble-right">
{{ item.text | sqxTranslate}}
</div>
</div>
</div>
<div class="row mt-3" *ngIf="item.type === 'bot'">
<div class="col-auto">
<div class="squid squid-sm d-flex align-items-center justify-content-center">
<img src="./images/squid.svg">
</div>
</div>
<div class="col">
<div class="bubble bubble-right">
<div class="mb-2">
{{ 'chat.answer' | sqxTranslate}}
</div>
<textarea class="form-control" readonly [ngModel]="item.text"></textarea>
<div class="mt-2">
<button type="button" class="btn btn-primary" (click)="select.emit(item.text)">
{{ 'chat.use' | sqxTranslate }}
</button>
</div>
</div>
</div>
</div>
</div>
<div class="row mt-3" *ngIf="snapshot.isRunning">
<div class="col-auto">
<div class="squid squid-sm d-flex align-items-center justify-content-center">
<img src="./images/squid.svg">
</div>
</div>
<div class="col">
<div class="bubble bubble-right">
<svg height="40" width="40" class="loader">
<circle class="dot" cx="10" cy="20" r="3" />
<circle class="dot" cx="20" cy="20" r="3" />
<circle class="dot" cx="30" cy="20" r="3" />
</svg>
</div>
</div>
</div>
</ng-container>
<ng-container footer>
<form (ngSubmit)="ask()">
<div class="row row-cols-0 g-2">
<div class="col">
<input class="form-control" #input
placeholder="{{ 'chat.prompt' | sqxTranslate }}"
sqxFocusOnInit
(ngModelChange)="setQuestion($event)"
[ngModel]="snapshot.chatQuestion"
[ngModelOptions]="{ standalone: true }"
[disabled]="snapshot.isRunning" />
</div>
<div class="col-auto">
<button type="submit" class="btn btn-secondary" [disabled]="snapshot.isRunning">
{{ 'chat.ask' | sqxTranslate }}
</button>
</div>
</div>
</form>
</ng-container>
</sqx-modal-dialog>

2
frontend/src/app/features/content/shared/forms/component.component.ts

@ -16,7 +16,7 @@ import { ComponentSectionComponent } from './component-section.component';
templateUrl: './component.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ComponentComponent {
export class ComponentComponent {
private readonly subscriptions = new Subscriptions();
@Input({ required: true })

6
frontend/src/app/features/content/shared/forms/field-editor.component.html

@ -197,6 +197,7 @@
mode="Html"
[formControl]="$any(fieldForm)"
[folderId]="field.rawProperties.folderId"
[hasChatBot]="hasChatBot"
[language]="language"
[languages]="languages"
[schemaIds]="field.rawProperties.schemaIds">
@ -210,6 +211,7 @@
mode="Markdown"
[formControl]="$any(fieldForm)"
[folderId]="field.rawProperties.folderId"
[hasChatBot]="hasChatBot"
[language]="language"
[languages]="languages"
[schemaIds]="field.rawProperties.schemaIds">
@ -259,6 +261,6 @@
</sqx-form-hint>
</div>
<sqx-chat-dialog *sqxModal="chatDialog"
(close)="chatDialog.hide()" (select)="setValue($event)">
<sqx-chat-dialog *sqxModal="chatDialog" showFormatHint="true"
(select)="setValue($event)">
</sqx-chat-dialog>

4
frontend/src/app/features/content/shared/forms/field-editor.component.ts

@ -101,7 +101,9 @@ export class FieldEditorComponent {
}
public setValue(value: any) {
this.formModel.setValue(value);
if (value) {
this.formModel.setValue(value);
}
this.chatDialog.hide();
}

4
frontend/src/app/features/content/shared/forms/iframe-editor.component.html

@ -5,11 +5,11 @@
</div>
<sqx-asset-selector *sqxModal="assetsDialog"
(select)="pickAssets($event)">
(assetSelect)="pickAssets($event)">
</sqx-asset-selector>
<sqx-content-selector *sqxModal="contentsDialog"
(select)="pickContents($event)"
(contentSelect)="pickContents($event)"
[query]="contentsQuery"
[language]="language"
[languages]="languages"

2
frontend/src/app/features/content/shared/forms/iframe-editor.component.ts

@ -22,7 +22,7 @@ interface State {
templateUrl: './iframe-editor.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class IFrameEditorComponent extends StatefulComponent<State> implements OnDestroy {
export class IFrameEditorComponent extends StatefulComponent<State> implements OnDestroy {
private readonly subscriptions = new Subscriptions();
private value: any;
private isInitialized = false;

2
frontend/src/app/features/content/shared/forms/stock-photo-editor.component.html

@ -17,7 +17,7 @@
<sqx-loader color="white" *ngIf="snapshot.thumbnailStatus !== 'Loaded'"></sqx-loader>
</div>
<sqx-modal-dialog *sqxModal="searchDialog" size="lg" fullHeight="true" (close)="searchDialog.hide()">
<sqx-modal-dialog *sqxModal="searchDialog" size="lg" fullHeight="true" (dialogClose)="searchDialog.hide()">
<ng-container title>
<input class="form-control search" [formControl]="stockPhotoSearch" sqxFocusOnInit placeholder="{{ 'contents.stockPhotoSearch' | sqxTranslate }}">

5
frontend/src/app/features/content/shared/list/content.component.ts

@ -1,3 +1,4 @@
/*
* Squidex Headless CMS
*
@ -5,11 +6,11 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
/* eslint-disable @angular-eslint/component-selector */
import { booleanAttribute, ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, Output, QueryList, ViewChildren } from '@angular/core';
import { AppLanguageDto, ContentDto, ContentListFieldComponent, ContentsState, ModalModel, PatchContentForm, SchemaDto, TableField, TableSettings, TypedSimpleChanges } from '@app/shared';
/* tslint:disable: component-selector */
@Component({
selector: '[sqxContent][language][languages][tableFields][schema][tableSettings]',
styleUrls: ['./content.component.scss'],

2
frontend/src/app/features/content/shared/references/content-creator.component.html

@ -1,4 +1,4 @@
-<sqx-modal-dialog (close)="emitClose()" size="lg" showFooter="false">
-<sqx-modal-dialog (dialogClose)="emitClose()" size="lg" showFooter="false">
<ng-container title>
<select class="form-select" [ngModel]="schema" (ngModelChange)="selectSchema($event)" *ngIf="schemas.length > 1">
<option *ngFor="let schema of schemas" [ngValue]="schema">

6
frontend/src/app/features/content/shared/references/content-creator.component.ts

@ -20,7 +20,7 @@ import { AppLanguageDto, ComponentContentsState, ContentDto, EditContentForm, Re
})
export class ContentCreatorComponent implements OnInit {
@Output()
public select = new EventEmitter<ReadonlyArray<ContentDto>>();
public contentCreate = new EventEmitter<ReadonlyArray<ContentDto>>();
@Input()
public initialData: any;
@ -122,10 +122,10 @@ export class ContentCreatorComponent implements OnInit {
}
public emitClose() {
this.select.emit([]);
this.contentCreate.emit([]);
}
public emitSelect(content: ContentDto) {
this.select.emit([content]);
this.contentCreate.emit([content]);
}
}

2
frontend/src/app/features/content/shared/references/reference-dropdown.component.html

@ -1,4 +1,4 @@
<sqx-dropdown [formControl]="control" [items]="snapshot.contentNames" [itemsLoading]="snapshot.isLoading" valueProperty="id" (open)="onOpened()">
<sqx-dropdown [formControl]="control" [items]="snapshot.contentNames" [itemsLoading]="snapshot.isLoading" valueProperty="id" (dropdownOpen)="onOpened()">
<ng-template let-content="$implicit" let-context="context">
<span class="truncate" [innerHTML]="content.name | sqxHighlight:context | sqxSafeHtml"></span>
</ng-template>

2
frontend/src/app/features/content/shared/references/reference-item.component.ts

@ -5,7 +5,7 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
/* tslint:disable: component-selector */
/* eslint-disable @angular-eslint/component-selector */
import { booleanAttribute, ChangeDetectionStrategy, Component, EventEmitter, Input, numberAttribute, Output } from '@angular/core';
import { ContentDto, getContentValue, LanguageDto, META_FIELDS } from '@app/shared';

4
frontend/src/app/features/content/shared/references/references-editor.component.html

@ -37,7 +37,7 @@
</div>
<sqx-content-creator *sqxModal="contentCreatorDialog"
(select)="select($event)"
(contentCreate)="select($event)"
[formContext]="formContext"
[initialData]="clonedContent?.data"
[language]="language"
@ -47,7 +47,7 @@
</sqx-content-creator>
<sqx-content-selector *sqxModal="contentSelectorDialog"
(select)="select($event)"
(contentSelect)="select($event)"
[allowDuplicates]="allowDuplicates"
[alreadySelected]="snapshot.contentItems"
[language]="language"

2
frontend/src/app/features/content/shared/references/references-tags.component.html

@ -1,5 +1,5 @@
<sqx-tag-editor placeholder="{{ 'common.tagAddReference' | sqxTranslate }}"
(open)="onOpened()"
(dropdownOpen)="onOpened()"
allowDuplicates="false"
allowOpen="true"
[formControl]="control"

2
frontend/src/app/features/dashboard/pages/dashboard-config.component.html

@ -35,7 +35,7 @@
</a>
</sqx-dropdown-menu>
<sqx-modal-dialog *sqxModal="expertDialog" (close)="expertDialog.hide()" fullHeight="true" size="lg">
<sqx-modal-dialog *sqxModal="expertDialog" (dialogClose)="expertDialog.hide()" fullHeight="true" size="lg">
<ng-container title>
{{ 'dashboard.editConfig' | sqxTranslate }}
</ng-container>

2
frontend/src/app/features/rules/pages/events/rule-event.component.ts

@ -5,6 +5,8 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
/* eslint-disable @angular-eslint/component-selector */
import { booleanAttribute, ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
import { RuleEventDto } from '@app/shared';

2
frontend/src/app/features/rules/pages/simulator/simulated-rule-event.component.ts

@ -5,6 +5,8 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
/* eslint-disable @angular-eslint/component-selector */
import { booleanAttribute, ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
import { SimulatedRuleEventDto } from '@app/shared';

2
frontend/src/app/features/schemas/pages/schema/fields/field-wizard.component.html

@ -1,4 +1,4 @@
<sqx-modal-dialog (close)="emitClose()" size="lg" tourId="fieldForm">
<sqx-modal-dialog (dialogClose)="emitClose()" size="lg" tourId="fieldForm">
<ng-container title>
<ng-container *ngIf="parent; else noParent">
{{ 'schemas.addNestedField' | sqxTranslate }}

4
frontend/src/app/features/schemas/pages/schema/fields/field-wizard.component.ts

@ -29,7 +29,7 @@ export class FieldWizardComponent implements OnInit {
public parent: RootFieldDto | null | undefined;
@Output()
public close = new EventEmitter();
public dialogClose = new EventEmitter();
public fieldTypes = fieldTypes;
public field!: FieldDto;
@ -55,7 +55,7 @@ export class FieldWizardComponent implements OnInit {
}
public emitClose() {
this.close.emit();
this.dialogClose.emit();
}
public addField(addNew: boolean, edit = false) {

2
frontend/src/app/features/schemas/pages/schema/fields/field.component.html

@ -130,7 +130,7 @@
[parent]="$any(field)"
[schema]="schema"
[settings]="settings"
(close)="fieldWizard.hide()">
(dialogClose)="fieldWizard.hide()">
</sqx-field-wizard>
</ng-container>
</div>

2
frontend/src/app/features/schemas/pages/schema/fields/forms/field-form.component.html

@ -23,7 +23,7 @@
</ul>
<div class="float-end" *ngIf="showButtons">
<button [disabled]="field.isLocked" type="reset" class="btn btn-text-secondary" (click)="close.emit()">
<button [disabled]="field.isLocked" type="reset" class="btn btn-text-secondary" (click)="dialogClose.emit()">
{{ 'common.cancel' | sqxTranslate }}
</button>

2
frontend/src/app/features/schemas/pages/schema/fields/forms/field-form.component.ts

@ -40,7 +40,7 @@ export class FieldFormComponent implements AfterViewInit {
public isLocalizable?: boolean | null;
@Output()
public close = new EventEmitter();
public dialogClose = new EventEmitter();
public selectedTab = 0;

2
frontend/src/app/features/schemas/pages/schema/fields/schema-fields.component.html

@ -26,6 +26,6 @@
<sqx-field-wizard *sqxModal="fieldWizard"
[settings]="settings"
[schema]="schema"
(close)="fieldWizard.hide()">
(dialogClose)="fieldWizard.hide()">
</sqx-field-wizard>
</ng-container>

2
frontend/src/app/features/schemas/pages/schema/scripts/schema-scripts-form.component.ts

@ -7,7 +7,7 @@
import { Component, Input } from '@angular/core';
import { EMPTY, Observable, shareReplay } from 'rxjs';
import { AppsState, EditSchemaScriptsForm, ScriptCompletions, SchemaDto, SchemasService, SchemasState } from '@app/shared';
import { AppsState, EditSchemaScriptsForm, SchemaDto, SchemasService, SchemasState, ScriptCompletions } from '@app/shared';
@Component({
selector: 'sqx-schema-scripts-form',

4
frontend/src/app/features/schemas/pages/schemas/schema-form.component.html

@ -1,5 +1,5 @@
<form [formGroup]="createForm.form" (ngSubmit)="createSchema()">
<sqx-modal-dialog (close)="emitClose()" tourId="schemaForm">
<sqx-modal-dialog (dialogClose)="emitClose()" tourId="schemaForm">
<ng-container title>
<ng-container *ngIf="import; else noImport">
{{ 'schemas.clone' | sqxTranslate }}
@ -110,7 +110,7 @@
</ng-container>
<ng-container footer>
<button type="button" class="btn btn-text-secondary" (click)="close.emit()">
<button type="button" class="btn btn-text-secondary" (click)="dialogClose.emit()">
{{ 'common.cancel' | sqxTranslate }}
</button>

4
frontend/src/app/features/schemas/pages/schemas/schema-form.component.ts

@ -18,7 +18,7 @@ export class SchemaFormComponent implements OnInit {
public create = new EventEmitter<SchemaDto>();
@Output()
public close = new EventEmitter();
public dialogClose = new EventEmitter();
@Input()
public import: any;
@ -51,7 +51,7 @@ export class SchemaFormComponent implements OnInit {
}
public emitClose() {
this.close.emit();
this.dialogClose.emit();
}
public createSchema() {

2
frontend/src/app/features/schemas/pages/schemas/schemas-page.component.html

@ -33,7 +33,7 @@
</sqx-layout>
<sqx-schema-form *sqxModal="addSchemaDialog"
(close)="addSchemaDialog.hide()" (create)="redirectSchema($event)" [import]="import">
(dialogClose)="addSchemaDialog.hide()" (create)="redirectSchema($event)" [import]="import">
</sqx-schema-form>
<router-outlet></router-outlet>

2
frontend/src/app/features/settings/pages/clients/client-connect-form.component.html

@ -1,4 +1,4 @@
<sqx-modal-dialog (close)="close.emit()" size="lg">
<sqx-modal-dialog (dialogClose)="dialogClose.emit()" size="lg">
<ng-container title>
{{ 'clients.connect' | sqxTranslate }}
</ng-container>

2
frontend/src/app/features/settings/pages/clients/client-connect-form.component.ts

@ -15,7 +15,7 @@ import { AccessTokenDto, ApiUrlConfig, AppsState, ClientDto, ClientsService, Cli
})
export class ClientConnectFormComponent implements OnInit {
@Output()
public close = new EventEmitter();
public dialogClose = new EventEmitter();
@Input({ required: true })
public client!: ClientDto;

2
frontend/src/app/features/settings/pages/clients/client.component.html

@ -108,5 +108,5 @@
</div>
<sqx-client-connect-form *sqxModal="connectDialog"
(close)="connectDialog.hide()" [client]="client">
(dialogClose)="connectDialog.hide()" [client]="client">
</sqx-client-connect-form>

2
frontend/src/app/features/settings/pages/contributors/contributor-add-form.component.html

@ -35,5 +35,5 @@
</div>
<sqx-import-contributors-dialog *sqxModal="importDialog"
(close)="importDialog.hide()" [roles]="roles" >
(dialogClose)="importDialog.hide()" [roles]="roles" >
</sqx-import-contributors-dialog>

2
frontend/src/app/features/settings/pages/contributors/contributor.component.ts

@ -5,6 +5,8 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
/* eslint-disable @angular-eslint/component-selector */
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { ContributorDto, ContributorsState, RoleDto } from '@app/shared';

4
frontend/src/app/features/settings/pages/contributors/import-contributors-dialog.component.html

@ -1,5 +1,5 @@
<form [formGroup]="importForm.form" (ngSubmit)="detect()">
<sqx-modal-dialog (close)="close.emit()">
<sqx-modal-dialog (dialogClose)="dialogClose.emit()">
<ng-container title>
{{ 'contributors.importTitle' | sqxTranslate }}
</ng-container>
@ -47,7 +47,7 @@
</ng-container>
<ng-container footer>
<button type="button" class="btn btn-text-secondary" (click)="close.emit()">
<button type="button" class="btn btn-text-secondary" (click)="dialogClose.emit()">
{{ 'common.cancel' | sqxTranslate }}
</button>

2
frontend/src/app/features/settings/pages/contributors/import-contributors-dialog.component.ts

@ -24,7 +24,7 @@ type ImportStatus = {
})
export class ImportContributorsDialogComponent {
@Output()
public close = new EventEmitter();
public dialogClose = new EventEmitter();
@Input({ required: true })
public roles!: ReadonlyArray<RoleDto>;

4
frontend/src/app/features/settings/pages/roles/roles-page.component.ts

@ -5,12 +5,12 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
/* eslint-disable no-return-assign */
import { Component, OnInit } from '@angular/core';
import { Observable, of } from 'rxjs';
import { AppsState, AutocompleteSource, RoleDto, RolesService, RolesState, SchemasState } from '@app/shared';
/* eslint-disable no-return-assign */
class PermissionsAutocomplete implements AutocompleteSource {
private permissions: ReadonlyArray<string> = [];

2
frontend/src/app/features/teams/pages/contributors/contributor-add-form.component.html

@ -30,5 +30,5 @@
</div>
<sqx-import-contributors-dialog *sqxModal="importDialog"
(close)="importDialog.hide()">
(dialogClose)="importDialog.hide()">
</sqx-import-contributors-dialog>

2
frontend/src/app/features/teams/pages/contributors/contributor.component.ts

@ -5,6 +5,8 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
/* eslint-disable @angular-eslint/component-selector */
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { TeamContributorsState } from '@app/features/teams/internal';
import { ContributorDto } from '@app/shared';

4
frontend/src/app/features/teams/pages/contributors/import-contributors-dialog.component.html

@ -1,5 +1,5 @@
<form [formGroup]="importForm.form" (ngSubmit)="detect()">
<sqx-modal-dialog (close)="close.emit()">
<sqx-modal-dialog (dialogClose)="dialogClose.emit()">
<ng-container title>
{{ 'contributors.importTitle' | sqxTranslate }}
</ng-container>
@ -41,7 +41,7 @@
</ng-container>
<ng-container footer>
<button type="button" class="btn btn-text-secondary" (click)="close.emit()">
<button type="button" class="btn btn-text-secondary" (click)="dialogClose.emit()">
{{ 'common.cancel' | sqxTranslate }}
</button>

2
frontend/src/app/features/teams/pages/contributors/import-contributors-dialog.component.ts

@ -25,7 +25,7 @@ type ImportStatus = {
})
export class ImportContributorsDialogComponent {
@Output()
public close = new EventEmitter();
public dialogClose = new EventEmitter();
public importForm = new ImportContributorsForm();
public importStatus: ReadonlyArray<ImportStatus> = [];

4
frontend/src/app/framework/angular/compensate-scrollbar.directive.ts

@ -5,13 +5,13 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { booleanAttribute, Directive, ElementRef, HostListener, Input, Renderer2 } from '@angular/core';
import { AfterViewInit, booleanAttribute, Directive, ElementRef, HostListener, Input, Renderer2 } from '@angular/core';
import { ResizeListener, ResizeService, Subscriptions } from '@app/framework/internal';
@Directive({
selector: '[sqxCompensateScrollbar]',
})
export class CompensateScrollbarDirective implements ResizeListener {
export class CompensateScrollbarDirective implements AfterViewInit, ResizeListener {
private readonly subscriptions = new Subscriptions();
private previousScrollbarWidth = -1;

2
frontend/src/app/framework/angular/dropdown-menu.component.ts

@ -5,6 +5,8 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
/* eslint-disable @angular-eslint/no-host-metadata-property */
import { ChangeDetectionStrategy, Component, ElementRef, HostBinding } from '@angular/core';
import { fadeAnimation } from './animations';

3
frontend/src/app/framework/angular/forms/editors/autocomplete.component.html

@ -1,6 +1,7 @@
<div class="control-container">
<input class="form-control" #input
(blur)="blur()" (keydown)="onKeyDown($event)"
(blur)="blur()"
(keydown)="onKeyDown($event)"
[sqxFocusOnInit]="autoFocus"
autocapitalize="off"
autocomplete="off"

5
frontend/src/app/framework/angular/forms/editors/date-time-editor.component.html

@ -11,7 +11,10 @@
<div class="input-group flex-grow">
<input class="form-control form-date" [formControl]="dateControl" placeholder="{{ 'common.date' | sqxTranslate }}"
[class.with-buttons]="isDateTimeMode && shouldShowDateTimeModeButton"
(blur)="callTouched()" maxlength="10" #dateInput>
(blur)="callTouched()"
minlength="0"
maxlength="10"
#dateInput>
<input class="form-control form-time" [formControl]="timeControl" placeholder="{{ 'common.time' | sqxTranslate }}" (blur)="callTouched()" *ngIf="isDateTimeMode">
</div>

4
frontend/src/app/framework/angular/forms/editors/date-time-editor.component.ts

@ -42,7 +42,7 @@ export class DateTimeEditorComponent extends StatefulControlComponent<State, str
private suppressEvents = false;
@Output()
public blur = new EventEmitter();
public editorBlur = new EventEmitter();
@Input()
public mode: 'DateTime' | 'Date' = 'Date';
@ -120,7 +120,7 @@ export class DateTimeEditorComponent extends StatefulControlComponent<State, str
}
public callTouched() {
this.blur.next(true);
this.editorBlur.next(true);
super.callTouched();
}

8
frontend/src/app/framework/angular/forms/editors/dropdown.component.ts

@ -42,10 +42,10 @@ export class DropdownComponent extends StatefulControlComponent<State, ReadonlyA
private value: any;
@Output()
public open = new EventEmitter();
public dropdownOpen = new EventEmitter();
@Output()
public close = new EventEmitter();
public dropdownClose = new EventEmitter();
@Input({ transform: booleanAttribute })
public itemsLoading?: boolean | null;
@ -191,7 +191,7 @@ export class DropdownComponent extends StatefulControlComponent<State, ReadonlyA
}
if (!this.dropdown.isOpen) {
this.open.emit();
this.dropdownOpen.emit();
this.dropdown.show();
}
@ -207,7 +207,7 @@ export class DropdownComponent extends StatefulControlComponent<State, ReadonlyA
public closeModal() {
if (this.dropdown.isOpen) {
this.close.emit();
this.dropdownClose.emit();
this.dropdown.hide();
}

2
frontend/src/app/framework/angular/forms/editors/dropdown.stories.ts

@ -23,7 +23,7 @@ const TRANSLATIONS = {
[allowOpen]="true"
[items]="items"
[itemsLoading]="itemsLoading"
(open)="load()">
(dropdownOpen)="load()">
</sqx-dropdown>
</sqx-root-view>
`,

10
frontend/src/app/framework/angular/forms/editors/localized-input.component.html

@ -30,30 +30,30 @@
<sqx-tag-editor
[ngModel]="currentValue"
(ngModelChange)="setValue($event)"
(blur)="callTouched()">
(editorBlur)="callTouched()">
</sqx-tag-editor>
</ng-container>
<ng-container *ngSwitchCase="'datetime'">
<sqx-date-time-editor mode="DateTime"
[ngModel]="currentValue"
(ngModelChange)="setValue($event)"
(blur)="callTouched()">
(editorBlur)="callTouched()">
</sqx-date-time-editor>
</ng-container>
<ng-container *ngSwitchCase="'date'">
<sqx-date-time-editor mode="Date"
[ngModel]="currentValue"
(ngModelChange)="setValue($event)"
(blur)="callTouched()">
(editorBlur)="callTouched()">
</sqx-date-time-editor>
</ng-container>
<ng-container *ngSwitchCase="'boolean'">
<div class="form-check">
<input class="form-check-input" type="checkbox" [attr.id]="id"
sqxIndeterminateValue
[ngModel]="currentValue"
(ngModelChange)="setValue($event)"
(blur)="callTouched()"
sqxIndeterminateValue>
(blur)="callTouched()">
<label class="form-check-label" [attr.for]="id"></label>
</div>

7
frontend/src/app/framework/angular/forms/editors/tag-editor.component.html

@ -14,7 +14,12 @@
</span>
<input class="blank text-input" #input
(blur)="markTouched()" (copy)="onCopy($event)" (cut)="onCut($event)" (focus)="focus()" (keydown)="onKeyDown($event)" (paste)="onPaste($event)"
(blur)="markTouched()"
(copy)="onCopy($event)"
(cut)="onCut($event)"
(focus)="focus()"
(keydown)="onKeyDown($event)"
(paste)="onPaste($event)"
[placeholder]="placeholder | sqxTranslate"
autocomplete="off"
autocorrect="off"

14
frontend/src/app/framework/angular/forms/editors/tag-editor.component.ts

@ -50,13 +50,13 @@ export class TagEditorComponent extends StatefulControlComponent<State, Readonly
public inputElement!: ElementRef<HTMLInputElement>;
@Output()
public open = new EventEmitter();
public dropdownOpen = new EventEmitter();
@Output()
public close = new EventEmitter();
public dropdownClose = new EventEmitter();
@Output()
public blur = new EventEmitter();
public editorBlur = new EventEmitter();
@Input()
public itemConverter = StringConverter.INSTANCE;
@ -164,7 +164,7 @@ export class TagEditorComponent extends StatefulControlComponent<State, Readonly
if (!query) {
this.resetAutocompletion();
} else if (!this.latestInput) {
this.open.emit();
this.dropdownOpen.emit();
}
this.latestInput = query;
@ -373,7 +373,7 @@ export class TagEditorComponent extends StatefulControlComponent<State, Readonly
public closeModal() {
if (this.itemsModal.isOpen) {
this.close.emit();
this.dropdownClose.emit();
this.itemsModal.hide();
}
@ -381,14 +381,14 @@ export class TagEditorComponent extends StatefulControlComponent<State, Readonly
public openModal() {
if (!this.itemsModal.isOpen) {
this.open.emit();
this.dropdownOpen.emit();
this.itemsModal.show();
}
}
public callTouched() {
this.blur.next(true);
this.editorBlur.next(true);
super.callTouched();
}

2
frontend/src/app/framework/angular/forms/editors/tag-editor.stories.ts

@ -24,7 +24,7 @@ const TRANSLATIONS = {
[allowOpen]="true"
[itemsSource]="itemsSource"
[itemsSourceLoading]="itemsSourceLoading"
(open)="load()">
(dropdownOpen)="load()">
</sqx-tag-editor>
</sqx-root-view>
`,

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

@ -5,6 +5,8 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
/* eslint-disable @angular-eslint/no-input-rename */
import { booleanAttribute, Directive, ElementRef, EventEmitter, HostListener, Input, Output, Renderer2 } from '@angular/core';
import { Types } from '@app/framework/internal';
@ -27,7 +29,7 @@ export class FileDropDirective {
public disabled = false;
@Output('sqxDropFile')
public drop = new EventEmitter<ReadonlyArray<File>>();
public fileDrop = new EventEmitter<ReadonlyArray<File>>();
constructor(
private readonly element: ElementRef,
@ -43,7 +45,7 @@ export class FileDropDirective {
const files = await this.getAllowedFiles(event.clipboardData);
if (files && !this.disabled) {
this.drop.emit(files);
this.fileDrop.emit(files);
}
}
}
@ -84,7 +86,7 @@ export class FileDropDirective {
const files = await this.getAllowedFiles(event.dataTransfer);
if (files && !this.disabled) {
this.drop.emit(files);
this.fileDrop.emit(files);
}
}
}

2
frontend/src/app/framework/angular/layout.component.ts

@ -5,8 +5,6 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
/* eslint-disable import/no-cycle */
import { AfterViewInit, booleanAttribute, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, Input, numberAttribute, OnDestroy, OnInit, Optional, Renderer2, ViewChild } from '@angular/core';
import { ActivatedRoute, NavigationEnd, QueryParamsHandling, Router } from '@angular/router';
import { concat, defer, filter, map, of } from 'rxjs';

3
frontend/src/app/framework/angular/long-hover.directive.ts

@ -5,6 +5,9 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
/* eslint-disable @angular-eslint/no-input-rename */
/* eslint-disable @angular-eslint/no-output-rename */
import { Directive, EventEmitter, HostListener, Input, numberAttribute, Output, Renderer2 } from '@angular/core';
@Directive({

4
frontend/src/app/framework/angular/modals/dialog-renderer.component.html

@ -1,7 +1,7 @@
<ng-content></ng-content>
<ng-container *sqxModal="dialogView">
<sqx-modal-dialog [showClose]="false" (close)="cancel()" *ngIf="snapshot.dialogRequest; let request">
<sqx-modal-dialog [showClose]="false" (dialogClose)="cancel()" *ngIf="snapshot.dialogRequest; let request">
<ng-container title>
{{request.title | sqxTranslate}}
</ng-container>
@ -32,7 +32,7 @@
<div class="notification-container notification-container-bottom-right">
<div class="alert alert-dismissible alert-{{notification.messageType}} shadowed" *ngFor="let notification of snapshot.notifications" (click)="close(notification)" @fade>
<button type="button" class="btn-close" data-dismiss="alert" (close)="close(notification)"></button>
<button type="button" class="btn-close" data-dismiss="alert" (dialogClose)="close(notification)"></button>
<div class="shadow"></div>
<div class="shadowed" [innerHTML]="notification.message | sqxTranslate | sqxMarkdown | sqxSafeHtml"></div>

4
frontend/src/app/framework/angular/modals/modal-dialog.component.html

@ -8,7 +8,7 @@
<ng-content select="[plainTitle]"></ng-content>
<button type="button" class="btn btn-close" (click)="close.emit()"></button>
<button type="button" class="btn btn-close" (click)="dialogClose.emit()"></button>
</div>
<div class="modal-tabs clearfix" #tabsElement>
@ -26,4 +26,4 @@
</div>
</div>
<sqx-shortcut keys="escape" (trigger)="close.emit()"></sqx-shortcut>
<sqx-shortcut keys="escape" (trigger)="dialogClose.emit()"></sqx-shortcut>

2
frontend/src/app/framework/angular/modals/modal-dialog.component.ts

@ -19,7 +19,7 @@ import { fadeAnimation } from '@app/framework/internal';
})
export class ModalDialogComponent implements AfterViewInit {
@Output()
public close = new EventEmitter();
public dialogClose = new EventEmitter();
@Input({ transform: booleanAttribute })
public showClose?: boolean | null = true;

2
frontend/src/app/framework/angular/modals/modal.directive.ts

@ -5,6 +5,8 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
/* eslint-disable @angular-eslint/no-input-rename */
import { booleanAttribute, ChangeDetectorRef, Directive, EmbeddedViewRef, Input, OnDestroy, Renderer2, TemplateRef, ViewContainerRef } from '@angular/core';
import { DialogModel, ModalModel, Subscriptions, Types } from '@app/framework/internal';
import { RootViewComponent } from './root-view.component';

2
frontend/src/app/framework/angular/modals/tooltip.directive.ts

@ -5,6 +5,8 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
/* eslint-disable @angular-eslint/directive-selector */
import { Directive, ElementRef, HostListener, Input, numberAttribute, OnDestroy, Renderer2 } from '@angular/core';
import { DialogService, FloatingPlacement, Tooltip } from '@app/framework/internal';

4
frontend/src/app/framework/angular/pipes/colors.pipes.ts

@ -5,10 +5,6 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
/* eslint-disable one-var-declaration-per-line */
/* eslint-disable one-var */
/* eslint-disable no-sequences */
import { Pipe, PipeTransform } from '@angular/core';
import { ColorHelper } from '@app/framework/utils/color-helper';

6
frontend/src/app/framework/angular/resized.directive.ts

@ -5,6 +5,8 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
/* eslint-disable @angular-eslint/no-input-rename */
import { Directive, ElementRef, EventEmitter, Input, NgZone, numberAttribute, Output } from '@angular/core';
import { ResizeListener, ResizeService, Subscriptions } from '@app/framework/internal';
@ -26,7 +28,7 @@ export class ResizedDirective implements ResizeListener {
public resizeCondition = new EventEmitter<boolean>();
@Output('sqxResized')
public resize = new EventEmitter<DOMRect>();
public resizeChange = new EventEmitter<DOMRect>();
constructor(resizeService: ResizeService, element: ElementRef,
private readonly zone: NgZone,
@ -62,7 +64,7 @@ export class ResizedDirective implements ResizeListener {
}
} else {
this.zone.run(() => {
this.resize.emit(rect);
this.resizeChange.emit(rect);
});
}
}

12
frontend/src/app/framework/angular/scroll-active.directive.ts

@ -5,6 +5,8 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
/* eslint-disable @angular-eslint/no-input-rename */
import { AfterViewInit, booleanAttribute, Directive, ElementRef, Input, Renderer2 } from '@angular/core';
@Directive({
@ -43,17 +45,17 @@ export class ScrollActiveDirective implements AfterViewInit {
const body = document.body;
const scrollOffset = (targetRect.top + body.scrollTop) - (parentRect.top + body.scrollTop);
const scrollDiff = (targetRect.top + body.scrollTop) - (parentRect.top + body.scrollTop);
const scrollTop = parent.scrollTop;
if (scrollOffset < 0) {
this.renderer.setProperty(parent, 'scrollTop', scrollTop + scrollOffset);
if (scrollDiff < 0) {
this.renderer.setProperty(parent, 'scrollTop', scrollTop + scrollDiff);
} else {
const targetHeight = targetRect.height;
const parentHeight = parentRect.height;
if ((scrollOffset + targetHeight) > parentHeight) {
this.renderer.setProperty(parent, 'scrollTop', scrollTop + scrollOffset - parentHeight + targetHeight);
if ((scrollDiff + targetHeight) > parentHeight) {
this.renderer.setProperty(parent, 'scrollTop', scrollTop + scrollDiff - parentHeight + targetHeight);
}
}
}

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

Loading…
Cancel
Save