diff --git a/backend/src/Squidex/wwwroot/scripts/editor-sdk.js b/backend/src/Squidex/wwwroot/scripts/editor-sdk.js
index 142442f47..baa25ec4e 100644
--- a/backend/src/Squidex/wwwroot/scripts/editor-sdk.js
+++ b/backend/src/Squidex/wwwroot/scripts/editor-sdk.js
@@ -124,6 +124,8 @@ function SquidexFormField() {
var initCalled = false;
var disabledHandler;
var disabled = false;
+ var fullscreen = false;
+ var fullscreenHandler = false;
var valueHandler;
var value;
var formValueHandler;
@@ -149,6 +151,12 @@ function SquidexFormField() {
}
}
+ function raiseFullscreen() {
+ if (fullscreenHandler) {
+ fullscreenHandler(fullscreen);
+ }
+ }
+
function raiseInit() {
if (initHandler && !initCalled && context) {
initHandler(context);
@@ -174,6 +182,10 @@ function SquidexFormField() {
formValue = event.data.formValue;
raiseFormValueChanged();
+ } else if (type === 'fullscreenChanged') {
+ fullscreen = event.data.fullscreen;
+
+ raiseFullscreen();
} else if (type === 'init') {
context = event.data.context;
@@ -219,6 +231,8 @@ function SquidexFormField() {
/*
* Notifies the parent to navigate to the path.
+ *
+ * @params url: string: The url to navigate to.
*/
navigate: function (url) {
if (window.parent) {
@@ -226,8 +240,21 @@ function SquidexFormField() {
}
},
+ /*
+ * Notifies the parent to go to fullscreen mode.
+ *
+ * @params mode: boolean: The fullscreen mode.
+ */
+ toggleFullscreen: function () {
+ if (window.parent) {
+ window.parent.postMessage({ type: 'fullscreen', mode: !fullscreen }, '*');
+ }
+ },
+
/**
* Notifies the control container that the value has been changed.
+ *
+ * @params newValue: any: The new field value.
*/
valueChanged: function (newValue) {
value = newValue;
@@ -272,6 +299,15 @@ function SquidexFormField() {
raiseFormValueChanged();
},
+
+ /**
+ * Register the fullscreen changed handler.
+ */
+ onFullscreen: function (callback) {
+ fullscreenHandler = callback;
+
+ raiseFullscreen();
+ },
/**
* Clean the editor SDK.
diff --git a/backend/src/Squidex/wwwroot/scripts/editor-simple.html b/backend/src/Squidex/wwwroot/scripts/editor-simple.html
index ef07e44a3..a63869b46 100644
--- a/backend/src/Squidex/wwwroot/scripts/editor-simple.html
+++ b/backend/src/Squidex/wwwroot/scripts/editor-simple.html
@@ -12,10 +12,37 @@
.ck-editor__editable {
min-height: 250px;
}
+
+ .fullscreen {
+ height: 100vh;
+ }
+
+ .fullscreen .ck-editor {
+ position: fixed !important;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 1000;
+ }
+
+ .fullscreen .ck-editor .ck-editor__editable.ck-rounded-corners.ck-editor__editable_inline,
+ .fullscreen .ck-editor .ck.ck-editor__main {
+ height: 100%;
+ }
+
+ #fullscreenButton {
+ position: absolute;
+ z-index: 10000;
+ right: 10px;
+ top: 10px;
+ }
+ Toggle fullscreen
+
diff --git a/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleElementRegistryTests.cs b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleElementRegistryTests.cs
index c446ab897..a21b7632c 100644
--- a/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleElementRegistryTests.cs
+++ b/backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/HandleRules/RuleElementRegistryTests.cs
@@ -159,7 +159,7 @@ namespace Squidex.Domain.Apps.Core.Operations.HandleRules
Display = "Enum",
Description = null,
Editor = RuleActionPropertyEditor.Dropdown,
- IsRequired = true,
+ IsRequired = false,
Options = new[] { "Yes", "No" }
});
diff --git a/frontend/app/framework/angular/forms/editors/iframe-editor.component.html b/frontend/app/framework/angular/forms/editors/iframe-editor.component.html
index 19adae7f7..706adf00c 100644
--- a/frontend/app/framework/angular/forms/editors/iframe-editor.component.html
+++ b/frontend/app/framework/angular/forms/editors/iframe-editor.component.html
@@ -1 +1,6 @@
-
+
+
diff --git a/frontend/app/framework/angular/forms/editors/iframe-editor.component.scss b/frontend/app/framework/angular/forms/editors/iframe-editor.component.scss
index ae2678456..105411a21 100644
--- a/frontend/app/framework/angular/forms/editors/iframe-editor.component.scss
+++ b/frontend/app/framework/angular/forms/editors/iframe-editor.component.scss
@@ -2,4 +2,16 @@ iframe {
background: 0;
border: 0;
overflow: hidden;
+}
+
+.fullscreen {
+ @include fixed(0, 0, 0, 0);
+ background: $panel-light-background;
+ border: 0;
+ border-radius: 0;
+ z-index: 1040;
+
+ iframe {
+ height: 100% !important;
+ }
}
\ No newline at end of file
diff --git a/frontend/app/framework/angular/forms/editors/iframe-editor.component.ts b/frontend/app/framework/angular/forms/editors/iframe-editor.component.ts
index f0c9e7ea2..b3fa7063a 100644
--- a/frontend/app/framework/angular/forms/editors/iframe-editor.component.ts
+++ b/frontend/app/framework/angular/forms/editors/iframe-editor.component.ts
@@ -5,7 +5,7 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
-import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, forwardRef, Input, OnChanges, Renderer2, SimpleChanges, ViewChild } from '@angular/core';
+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';
@@ -14,6 +14,11 @@ export const SQX_IFRAME_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => IFrameEditorComponent), multi: true
};
+interface State {
+ // True, when the editor is shown as fullscreen.
+ isFullscreen: boolean;
+}
+
@Component({
selector: 'sqx-iframe-editor',
styleUrls: ['./iframe-editor.component.scss'],
@@ -23,7 +28,7 @@ export const SQX_IFRAME_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
],
changeDetection: ChangeDetectionStrategy.OnPush
})
-export class IFrameEditorComponent extends StatefulControlComponent implements OnChanges, AfterViewInit {
+export class IFrameEditorComponent extends StatefulControlComponent implements OnChanges, OnDestroy, AfterViewInit {
private value: any;
private isDisabled = false;
private isInitialized = false;
@@ -31,6 +36,12 @@ export class IFrameEditorComponent extends StatefulControlComponent im
@ViewChild('iframe', { static: false })
public iframe: ElementRef;
+ @ViewChild('container', { static: false })
+ public container: ElementRef;
+
+ @ViewChild('inner', { static: false })
+ public inner: ElementRef;
+
@Input()
public context: any = {};
@@ -40,11 +51,19 @@ export class IFrameEditorComponent extends StatefulControlComponent im
@Input()
public url: string;
+ public fullscreen: boolean;
+
constructor(changeDetector: ChangeDetectorRef,
private readonly renderer: Renderer2,
private readonly router: Router
) {
- super(changeDetector, {});
+ super(changeDetector, {
+ isFullscreen: false
+ });
+ }
+
+ public ngOnDestroy() {
+ this.toggleFullscreen(false);
}
public ngOnChanges(changes: SimpleChanges) {
@@ -75,17 +94,24 @@ export class IFrameEditorComponent extends StatefulControlComponent im
this.isInitialized = true;
this.sendInit();
+ this.sendFullscreen();
this.sendFormValue();
this.sendDisabled();
this.sendValue();
} else if (type === 'resize') {
const { height } = event.data;
- this.iframe.nativeElement.height = height + 'px';
+ this.renderer.setStyle(this.iframe.nativeElement, 'height', height + 'px');
} else if (type === 'navigate') {
const { url } = event.data;
this.router.navigateByUrl(url);
+ } else if (type === 'fullscreen') {
+ const { mode } = event.data;
+
+ if (mode !== this.snapshot.isFullscreen) {
+ this.toggleFullscreen(mode);
+ }
} else if (type === 'valueChanged') {
const { value } = event.data;
@@ -97,6 +123,8 @@ export class IFrameEditorComponent extends StatefulControlComponent im
} else if (type === 'touched') {
this.callTouched();
}
+
+ this.detectChanges();
}
}));
}
@@ -121,6 +149,10 @@ export class IFrameEditorComponent extends StatefulControlComponent im
this.sendMessage('valueChanged', { value: this.value });
}
+ private sendFullscreen() {
+ this.sendMessage('fullscreenChanged', { fullscreen: this.snapshot.isFullscreen });
+ }
+
private sendDisabled() {
this.sendMessage('disabled', { isDisabled: this.isDisabled });
}
@@ -129,6 +161,20 @@ export class IFrameEditorComponent extends StatefulControlComponent im
this.sendMessage('formValueChanged', { formValue: this.formValue });
}
+ private toggleFullscreen(isFullscreen: boolean) {
+ this.next(s => ({ ...s, isFullscreen }));
+
+ let target = this.container.nativeElement;
+
+ if (isFullscreen) {
+ target = document.body;
+ }
+
+ this.renderer.appendChild(target, this.inner.nativeElement);
+
+ this.sendFullscreen();
+ }
+
private sendMessage(type: string, payload: any) {
if (!this.iframe) {
return;
diff --git a/frontend/app/shared/components/forms/markdown-editor.component.ts b/frontend/app/shared/components/forms/markdown-editor.component.ts
index 286b4bd23..3faaf8edb 100644
--- a/frontend/app/shared/components/forms/markdown-editor.component.ts
+++ b/frontend/app/shared/components/forms/markdown-editor.component.ts
@@ -18,7 +18,7 @@ export const SQX_MARKDOWN_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
interface State {
// True, when the editor is shown as fullscreen.
- isFullscreen: false;
+ isFullscreen: boolean;
}
@Component({
@@ -187,15 +187,7 @@ export class MarkdownEditorComponent extends StatefulControlComponent {
const isFullscreen = this.simplemde.isFullscreenActive();
- let target = this.container.nativeElement;
-
- if (isFullscreen) {
- target = document.body;
- }
-
- this.renderer.appendChild(target, this.inner.nativeElement);
-
- this.next(s => ({ ...s, isFullscreen }));
+ this.toggleFullscreen(isFullscreen);
});
this.simplemde.codemirror.on('blur', () => {
@@ -277,4 +269,16 @@ export class MarkdownEditorComponent extends StatefulControlComponent ({ ...s, isFullscreen }));
+ }
}
\ No newline at end of file
diff --git a/frontend/app/shell/pages/internal/profile-menu.component.ts b/frontend/app/shell/pages/internal/profile-menu.component.ts
index a1eb8972b..ad392c401 100644
--- a/frontend/app/shell/pages/internal/profile-menu.component.ts
+++ b/frontend/app/shell/pages/internal/profile-menu.component.ts
@@ -22,6 +22,17 @@ interface State {
profileUrl: string;
}
+const ALL_LANGUAGES: ReadonlyArray<{ code: string, name: string }> = [{
+ code: 'en',
+ name: 'English'
+}, {
+ code: 'nl',
+ name: 'Nederlands'
+}, {
+ code: 'it',
+ name: 'Italiano'
+}];
+
@Component({
selector: 'sqx-profile-menu',
styleUrls: ['./profile-menu.component.scss'],
@@ -37,16 +48,7 @@ export class ProfileMenuComponent extends StatefulComponent implements On
public showSubmenu = false;
public language = this.uiOptions.get('more.culture');
- public languages: ReadonlyArray<{ code: string, name: string }> = [{
- code: 'en',
- name: 'English'
- }, {
- code: 'nl',
- name: 'Hollandske'
- }, {
- code: 'it',
- name: 'Italiano'
- }];
+ public languages = ALL_LANGUAGES;
constructor(changeDetector: ChangeDetectorRef, apiUrl: ApiUrlConfig,
public readonly uiState: UIState,