diff --git a/backend/src/Squidex/wwwroot/scripts/editor-dialogs.html b/backend/src/Squidex/wwwroot/scripts/editor-dialogs.html new file mode 100644 index 000000000..d983224c0 --- /dev/null +++ b/backend/src/Squidex/wwwroot/scripts/editor-dialogs.html @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/backend/src/Squidex/wwwroot/scripts/editor-sdk.js b/backend/src/Squidex/wwwroot/scripts/editor-sdk.js index 34bbc0260..95e2216a0 100644 --- a/backend/src/Squidex/wwwroot/scripts/editor-sdk.js +++ b/backend/src/Squidex/wwwroot/scripts/editor-sdk.js @@ -76,7 +76,7 @@ function SquidexPlugin() { return context; }, - /* + /** * Notifies the parent to navigate to the path. */ navigate: function (url) { @@ -134,6 +134,8 @@ function SquidexFormField() { var language; var formValueHandler; var formValue; + var currentConfirm; + var currentPickAssets; var context; var timer; @@ -199,11 +201,27 @@ function SquidexFormField() { } else if (type === 'languageChanged') { language = event.data.language; - raiseLanguageChanged(); + raiseLanguageChanged(); } else if (type === 'init') { context = event.data.context; raiseInit(); + } else if (type === 'confirmResult') { + var correlationId = event.data.correlationId; + + if (currentConfirm && currentConfirm.correlationId === correlationId) { + if (typeof currentConfirm.callback === 'function') { + currentConfirm.callback(event.data.result); + } + } + } else if (type === 'pickAssetsResult') { + var correlationId = event.data.correlationId; + + if (currentPickAssets && currentPickAssets.correlationId === correlationId) { + if (typeof currentPickAssets.callback === 'function') { + currentPickAssets.callback(event.data.result); + } + } } } } @@ -234,21 +252,21 @@ function SquidexFormField() { return formValue; }, - /* + /** * Get the current field language. */ getLanguage: function () { return language; }, - /* + /** * Get the disabled state. */ isDisabled: function () { return disabled; }, - /* + /** * Get the fullscreen state. */ isFullscreen: function () { @@ -264,10 +282,10 @@ function SquidexFormField() { } }, - /* + /** * Notifies the parent to navigate to the path. * - * @params url: string: The url to navigate to. + * @param {string} url: The url to navigate to. */ navigate: function (url) { if (window.parent) { @@ -275,10 +293,8 @@ function SquidexFormField() { } }, - /* + /** * Notifies the parent to go to fullscreen mode. - * - * @params mode: boolean: The fullscreen mode. */ toggleFullscreen: function () { if (window.parent) { @@ -289,7 +305,7 @@ function SquidexFormField() { /** * Notifies the control container that the value has been changed. * - * @params newValue: any: The new field value. + * @param {any} newValue: The new field value. */ valueChanged: function (newValue) { value = newValue; @@ -299,6 +315,74 @@ function SquidexFormField() { } }, + /** + * Shows an info alert. + * + * @param {string} text: The info text. + */ + notifyInfo: function (text) { + if (window.parent) { + window.parent.postMessage({ type: 'notifyInfo', text: text }, '*'); + } + }, + + /** + * Shows an error alert. + * + * @param {string} text: error info text. + */ + notifyError: function (text) { + if (window.parent) { + window.parent.postMessage({ type: 'notifyError', text: text }, '*'); + } + }, + + /** + * Shows an confirm dialog. + * + * @param {string} title The title of the dialog. + * @param {string} text The text of the dialog. + * @param {function} callback The callback to invoke when the dialog is completed or closed. + */ + confirm: function (title, text, callback) { + if (!callback || typeof callback !== 'function') { + return; + } + + var correlationId = new Date().getTime().toString(); + + currentConfirm = { + correlationId: correlationId, + callback: callback + }; + + if (window.parent) { + window.parent.postMessage({ type: 'confirm', title: title, text: text, correlationId: correlationId }, '*'); + } + }, + + /** + * Shows the dialog to pick assets. + * + * @param {function} callback The callback to invoke when the dialog is completed or closed. + */ + pickAssets: function (callback) { + if (!callback || typeof callback !== 'function') { + return; + } + + var correlationId = new Date().getTime().toString(); + + currentPickAssets = { + correlationId: correlationId, + callback: callback + }; + + if (window.parent) { + window.parent.postMessage({ type: 'pickAssets', correlationId: correlationId }, '*'); + } + }, + /** * Register an function that is called when the field is initialized. */ diff --git a/frontend/app/features/administration/pages/cluster/cluster-page.component.html b/frontend/app/features/administration/pages/cluster/cluster-page.component.html index 017f7d501..52dd84476 100644 --- a/frontend/app/features/administration/pages/cluster/cluster-page.component.html +++ b/frontend/app/features/administration/pages/cluster/cluster-page.component.html @@ -2,6 +2,6 @@
- +
\ No newline at end of file diff --git a/frontend/app/features/content/declarations.ts b/frontend/app/features/content/declarations.ts index bd4a97fb3..d97edc633 100644 --- a/frontend/app/features/content/declarations.ts +++ b/frontend/app/features/content/declarations.ts @@ -27,6 +27,7 @@ export * from './shared/forms/array-item.component'; export * from './shared/forms/array-section.component'; export * from './shared/forms/assets-editor.component'; export * from './shared/forms/field-editor.component'; +export * from './shared/forms/iframe-editor.component'; export * from './shared/forms/stock-photo-editor.component'; export * from './shared/list/content-list-cell.directive'; export * from './shared/list/content-list-field.component'; diff --git a/frontend/app/features/content/module.ts b/frontend/app/features/content/module.ts index 15c14c6ba..062d34ccc 100644 --- a/frontend/app/features/content/module.ts +++ b/frontend/app/features/content/module.ts @@ -12,6 +12,7 @@ import { RouterModule, Routes } from '@angular/router'; import { CanDeactivateGuard, ContentMustExistGuard, LoadLanguagesGuard, SchemaMustExistPublishedGuard, SchemaMustNotBeSingletonGuard, SqxFrameworkModule, SqxSharedModule, UnsetContentGuard } from '@app/shared'; import { ArrayEditorComponent, ArrayItemComponent, ArraySectionComponent, AssetsEditorComponent, CommentsPageComponent, ContentComponent, ContentCreatorComponent, ContentEditorComponent, ContentEventComponent, ContentFieldComponent, ContentHistoryPageComponent, ContentListCellDirective, ContentListFieldComponent, ContentListHeaderComponent, ContentListWidthPipe, ContentPageComponent, ContentReferencesComponent, ContentsColumnsPipe, ContentSectionComponent, ContentSelectorComponent, ContentSelectorItemComponent, ContentsFiltersPageComponent, ContentsPageComponent, ContentStatusComponent, ContentValueComponent, ContentValueEditorComponent, CustomViewEditorComponent, DueTimeSelectorComponent, FieldEditorComponent, FieldLanguagesComponent, PreviewButtonComponent, ReferenceItemComponent, ReferencesEditorComponent, SchemasPageComponent, SidebarPageComponent, StockPhotoEditorComponent } from './declarations'; import { ContentExtensionComponent } from './shared/content-extension.component'; +import { IFrameEditorComponent } from './shared/forms/iframe-editor.component'; const routes: Routes = [ { @@ -114,6 +115,7 @@ const routes: Routes = [ DueTimeSelectorComponent, FieldEditorComponent, FieldLanguagesComponent, + IFrameEditorComponent, PreviewButtonComponent, ReferenceItemComponent, ReferencesEditorComponent, diff --git a/frontend/app/framework/angular/forms/editors/iframe-editor.component.html b/frontend/app/features/content/shared/forms/iframe-editor.component.html similarity index 51% rename from frontend/app/framework/angular/forms/editors/iframe-editor.component.html rename to frontend/app/features/content/shared/forms/iframe-editor.component.html index 706adf00c..c67d47698 100644 --- a/frontend/app/framework/angular/forms/editors/iframe-editor.component.html +++ b/frontend/app/features/content/shared/forms/iframe-editor.component.html @@ -4,3 +4,8 @@ + + + + diff --git a/frontend/app/framework/angular/forms/editors/iframe-editor.component.scss b/frontend/app/features/content/shared/forms/iframe-editor.component.scss similarity index 100% rename from frontend/app/framework/angular/forms/editors/iframe-editor.component.scss rename to frontend/app/features/content/shared/forms/iframe-editor.component.scss diff --git a/frontend/app/framework/angular/forms/editors/iframe-editor.component.ts b/frontend/app/features/content/shared/forms/iframe-editor.component.ts similarity index 76% rename from frontend/app/framework/angular/forms/editors/iframe-editor.component.ts rename to frontend/app/features/content/shared/forms/iframe-editor.component.ts index 354776a58..8a4420472 100644 --- a/frontend/app/framework/angular/forms/editors/iframe-editor.component.ts +++ b/frontend/app/features/content/shared/forms/iframe-editor.component.ts @@ -8,7 +8,8 @@ import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, forwardRef, Input, OnChanges, OnDestroy, Renderer2, SimpleChanges, ViewChild } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { Router } from '@angular/router'; -import { StatefulControlComponent, Types } from '@app/framework/internal'; +import { DialogModel, DialogService, StatefulControlComponent, Types } from '@app/framework/internal'; +import { AssetDto } from '@app/shared'; export const SQX_IFRAME_EDITOR_CONTROL_VALUE_ACCESSOR: any = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => IFrameEditorComponent), multi: true @@ -31,6 +32,7 @@ interface State { export class IFrameEditorComponent extends StatefulControlComponent implements OnChanges, OnDestroy, AfterViewInit { private value: any; private isInitialized = false; + private assetsCorrelationId: any; @ViewChild('iframe', { static: false }) public iframe: ElementRef; @@ -53,9 +55,12 @@ export class IFrameEditorComponent extends StatefulControlComponent @Input() public url: string; + public assetsDialog = new DialogModel(); + public fullscreen: boolean; constructor(changeDetector: ChangeDetectorRef, + private readonly dialogs: DialogService, private readonly renderer: Renderer2, private readonly router: Router ) { @@ -129,6 +134,33 @@ export class IFrameEditorComponent extends StatefulControlComponent } } else if (type === 'touched') { this.callTouched(); + } else if (type === 'notifyInfo') { + const { text } = event.data; + + if (Types.isString(text)) { + this.dialogs.notifyInfo(text); + } + } else if (type === 'notifyError') { + const { text } = event.data; + + if (Types.isString(text)) { + this.dialogs.notifyError(text); + } + } else if (type === 'confirm') { + const { text, title, correlationId } = event.data; + + if (Types.isString(text) && Types.isString(title) && correlationId) { + this.dialogs.confirm(title, text).subscribe(result => { + this.sendMessage('confirmResult', { correlationId, result }); + }); + } + } else if (type === 'pickAssets') { + const { correlationId } = event.data; + + if (correlationId) { + this.assetsCorrelationId = correlationId; + this.assetsDialog.show(); + } } this.detectChanges(); @@ -136,6 +168,16 @@ export class IFrameEditorComponent extends StatefulControlComponent })); } + public pickAssets(assets: ReadonlyArray) { + if (this.assetsCorrelationId) { + this.sendMessage('pickAssetsResult', { correlationId: this.assetsCorrelationId, result: assets }); + + this.assetsCorrelationId = null; + } + + this.assetsDialog.hide(); + } + public writeValue(obj: any) { this.value = obj; diff --git a/frontend/app/framework/declarations.ts b/frontend/app/framework/declarations.ts index 78ff55ff0..304bd4651 100644 --- a/frontend/app/framework/declarations.ts +++ b/frontend/app/framework/declarations.ts @@ -18,7 +18,6 @@ export * from './angular/forms/editors/code-editor.component'; export * from './angular/forms/editors/color-picker.component'; export * from './angular/forms/editors/date-time-editor.component'; export * from './angular/forms/editors/dropdown.component'; -export * from './angular/forms/editors/iframe-editor.component'; export * from './angular/forms/editors/localized-input.component'; export * from './angular/forms/editors/stars.component'; export * from './angular/forms/editors/tag-editor.component'; diff --git a/frontend/app/framework/module.ts b/frontend/app/framework/module.ts index a140e33c8..e27bf788a 100644 --- a/frontend/app/framework/module.ts +++ b/frontend/app/framework/module.ts @@ -12,7 +12,7 @@ import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { ModuleWithProviders, NgModule } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { ColorPickerModule } from 'ngx-color-picker'; -import { AnalyticsService, AutocompleteComponent, AvatarComponent, CachingInterceptor, CanDeactivateGuard, CheckboxGroupComponent, ClipboardService, CodeComponent, CodeEditorComponent, ColorPickerComponent, ConfirmClickDirective, ControlErrorsComponent, CopyDirective, DarkenPipe, DatePipe, DateTimeEditorComponent, DayOfWeekPipe, DayPipe, DialogRendererComponent, DialogService, DisplayNamePipe, DropdownComponent, DurationPipe, EditableTitleComponent, ExternalLinkDirective, FileDropDirective, FileSizePipe, FocusOnInitDirective, FormAlertComponent, FormErrorComponent, FormHintComponent, FromNowPipe, FullDateTimePipe, HighlightPipe, HoverBackgroundDirective, IFrameEditorComponent, ImageSourceDirective, IndeterminateValueDirective, ISODatePipe, KeysPipe, KNumberPipe, LanguageSelectorComponent, LightenPipe, ListViewComponent, LoadingInterceptor, LoadingService, LocalizedInputComponent, LocalStoreService, MarkdownInlinePipe, MarkdownPipe, MessageBus, ModalDialogComponent, ModalDirective, ModalPlacementDirective, MoneyPipe, MonthPipe, OnboardingService, OnboardingTooltipComponent, PagerComponent, PanelComponent, PanelContainerDirective, ParentLinkDirective, PopupLinkDirective, ProgressBarComponent, ResizedDirective, ResizeService, ResourceLoaderService, RootViewComponent, SafeHtmlPipe, SafeUrlPipe, ScrollActiveDirective, ShortcutComponent, ShortcutService, ShortDatePipe, ShortTimePipe, StarsComponent, StatusIconComponent, StopClickDirective, SyncScollingDirective, SyncWidthDirective, TabRouterlinkDirective, TagEditorComponent, TemplateWrapperDirective, TempService, TitleComponent, TitleService, ToggleComponent, TooltipDirective, TransformInputDirective, TranslatePipe, VideoPlayerComponent } from './declarations'; +import { AnalyticsService, AutocompleteComponent, AvatarComponent, CachingInterceptor, CanDeactivateGuard, CheckboxGroupComponent, ClipboardService, CodeComponent, CodeEditorComponent, ColorPickerComponent, ConfirmClickDirective, ControlErrorsComponent, CopyDirective, DarkenPipe, DatePipe, DateTimeEditorComponent, DayOfWeekPipe, DayPipe, DialogRendererComponent, DialogService, DisplayNamePipe, DropdownComponent, DurationPipe, EditableTitleComponent, ExternalLinkDirective, FileDropDirective, FileSizePipe, FocusOnInitDirective, FormAlertComponent, FormErrorComponent, FormHintComponent, FromNowPipe, FullDateTimePipe, HighlightPipe, HoverBackgroundDirective, ImageSourceDirective, IndeterminateValueDirective, ISODatePipe, KeysPipe, KNumberPipe, LanguageSelectorComponent, LightenPipe, ListViewComponent, LoadingInterceptor, LoadingService, LocalizedInputComponent, LocalStoreService, MarkdownInlinePipe, MarkdownPipe, MessageBus, ModalDialogComponent, ModalDirective, ModalPlacementDirective, MoneyPipe, MonthPipe, OnboardingService, OnboardingTooltipComponent, PagerComponent, PanelComponent, PanelContainerDirective, ParentLinkDirective, PopupLinkDirective, ProgressBarComponent, ResizedDirective, ResizeService, ResourceLoaderService, RootViewComponent, SafeHtmlPipe, SafeUrlPipe, ScrollActiveDirective, ShortcutComponent, ShortcutService, ShortDatePipe, ShortTimePipe, StarsComponent, StatusIconComponent, StopClickDirective, SyncScollingDirective, SyncWidthDirective, TabRouterlinkDirective, TagEditorComponent, TemplateWrapperDirective, TempService, TitleComponent, TitleService, ToggleComponent, TooltipDirective, TransformInputDirective, TranslatePipe, VideoPlayerComponent } from './declarations'; @NgModule({ imports: [ @@ -52,7 +52,6 @@ import { AnalyticsService, AutocompleteComponent, AvatarComponent, CachingInterc FullDateTimePipe, HighlightPipe, HoverBackgroundDirective, - IFrameEditorComponent, ImageSourceDirective, IndeterminateValueDirective, ISODatePipe, @@ -132,7 +131,6 @@ import { AnalyticsService, AutocompleteComponent, AvatarComponent, CachingInterc FullDateTimePipe, HighlightPipe, HoverBackgroundDirective, - IFrameEditorComponent, ImageSourceDirective, IndeterminateValueDirective, ISODatePipe,