diff --git a/src/Squidex/app/framework/angular/rich-editor.component.html b/src/Squidex/app/framework/angular/rich-editor.component.html
deleted file mode 100644
index bb84a4048..000000000
--- a/src/Squidex/app/framework/angular/rich-editor.component.html
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/src/Squidex/app/framework/angular/rich-editor.component.scss b/src/Squidex/app/framework/angular/rich-editor.component.scss
deleted file mode 100644
index 07b2c640b..000000000
--- a/src/Squidex/app/framework/angular/rich-editor.component.scss
+++ /dev/null
@@ -1,8 +0,0 @@
-@import '_mixins';
-@import '_vars';
-
-.editor {
- background: $color-dark-foreground;
- border: 1px solid $color-input;
- height: 30rem;
-}
\ No newline at end of file
diff --git a/src/Squidex/app/framework/angular/rich-editor.component.ts b/src/Squidex/app/framework/angular/rich-editor.component.ts
deleted file mode 100644
index 4e95a8152..000000000
--- a/src/Squidex/app/framework/angular/rich-editor.component.ts
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Squidex Headless CMS
- *
- * @license
- * Copyright (c) Sebastian Stehle. All rights reserved
- */
-
-import { AfterViewInit, Component, forwardRef, ElementRef, OnDestroy, ViewChild } from '@angular/core';
-import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
-
-import { Types } from './../utils/types';
-
-import { ResourceLoaderService } from './../services/resource-loader.service';
-
-declare var tinymce: any;
-
-export const SQX_RICH_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
- provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => RichEditorComponent), multi: true
-};
-
-@Component({
- selector: 'sqx-rich-editor',
- styleUrls: ['./rich-editor.component.scss'],
- templateUrl: './rich-editor.component.html',
- providers: [SQX_RICH_EDITOR_CONTROL_VALUE_ACCESSOR]
-})
-export class RichEditorComponent implements ControlValueAccessor, AfterViewInit, OnDestroy {
- private callChange = (v: any) => { /* NOOP */ };
- private callTouched = () => { /* NOOP */ };
- private tinyEditor: any;
- private tinyInitTimer: any;
- private value: string;
- private isDisabled = false;
-
- @ViewChild('editor')
- public editor: ElementRef;
-
- constructor(
- private readonly resourceLoader: ResourceLoaderService
- ) {
- }
-
- public ngOnDestroy() {
- clearTimeout(this.tinyInitTimer);
-
- tinymce.remove(this.editor);
- }
-
- public ngAfterViewInit() {
- const self = this;
-
- this.resourceLoader.loadScript('https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.5.4/tinymce.min.js').then(() => {
- tinymce.init({
- setup: (editor: any) => {
- self.tinyEditor = editor;
- self.tinyEditor.setMode(this.isDisabled ? 'readonly' : 'design');
-
- self.tinyEditor.on('change', () => {
- const value = editor.getContent();
-
- if (this.value !== value) {
- this.value = value;
-
- self.callChange(value);
- }
- });
-
- self.tinyEditor.on('blur', () => {
- self.callTouched();
- });
-
- this.tinyInitTimer =
- setTimeout(() => {
- self.tinyEditor.setContent(this.value || '');
- }, 500);
- },
- removed_menuitems: 'newdocument', plugins: 'code', target: this.editor.nativeElement
- });
- });
- }
-
- public writeValue(value: string) {
- this.value = Types.isString(value) ? value : '';
-
- if (this.tinyEditor) {
- this.tinyEditor.setContent(this.value);
- }
- }
-
- public setDisabledState(isDisabled: boolean): void {
- this.isDisabled = isDisabled;
-
- if (this.tinyEditor) {
- this.tinyEditor.setMode(isDisabled ? 'readonly' : 'design');
- }
- }
-
- public registerOnChange(fn: any) {
- this.callChange = fn;
- }
-
- public registerOnTouched(fn: any) {
- this.callTouched = fn;
- }
-}
\ No newline at end of file
diff --git a/src/Squidex/app/framework/declarations.ts b/src/Squidex/app/framework/declarations.ts
index 40c8b1d87..7ba82733d 100644
--- a/src/Squidex/app/framework/declarations.ts
+++ b/src/Squidex/app/framework/declarations.ts
@@ -36,7 +36,6 @@ export * from './angular/panel-container.directive';
export * from './angular/parent-link.directive';
export * from './angular/popup-link.directive';
export * from './angular/progress-bar.component';
-export * from './angular/rich-editor.component';
export * from './angular/root-view.directive';
export * from './angular/router-utils';
export * from './angular/scroll-active.directive';
diff --git a/src/Squidex/app/framework/module.ts b/src/Squidex/app/framework/module.ts
index 973635904..7a99b4dbc 100644
--- a/src/Squidex/app/framework/module.ts
+++ b/src/Squidex/app/framework/module.ts
@@ -54,7 +54,6 @@ import {
PopupLinkDirective,
ProgressBarComponent,
ResourceLoaderService,
- RichEditorComponent,
RootViewDirective,
RootViewService,
ScrollActiveDirective,
@@ -115,7 +114,6 @@ import {
ParentLinkDirective,
PopupLinkDirective,
ProgressBarComponent,
- RichEditorComponent,
RootViewDirective,
ScrollActiveDirective,
ShortcutComponent,
@@ -164,7 +162,6 @@ import {
ParentLinkDirective,
PopupLinkDirective,
ProgressBarComponent,
- RichEditorComponent,
RootViewDirective,
ScrollActiveDirective,
ShortcutComponent,
diff --git a/src/Squidex/app/shared/components/asset.component.html b/src/Squidex/app/shared/components/asset.component.html
index 88fc97799..96e1f7633 100644
--- a/src/Squidex/app/shared/components/asset.component.html
+++ b/src/Squidex/app/shared/components/asset.component.html
@@ -1,4 +1,4 @@
-
+
diff --git a/src/Squidex/app/shared/components/asset.component.ts b/src/Squidex/app/shared/components/asset.component.ts
index 85540c6cf..d559efba6 100644
--- a/src/Squidex/app/shared/components/asset.component.ts
+++ b/src/Squidex/app/shared/components/asset.component.ts
@@ -56,6 +56,9 @@ export class AssetComponent extends AppComponentBase implements OnInit {
@Output()
public deleting = new EventEmitter();
+ @Output()
+ public clicked = new EventEmitter();
+
@Output()
public failed = new EventEmitter();
diff --git a/src/Squidex/app/shared/components/rich-editor.component.html b/src/Squidex/app/shared/components/rich-editor.component.html
new file mode 100644
index 000000000..413c8e708
--- /dev/null
+++ b/src/Squidex/app/shared/components/rich-editor.component.html
@@ -0,0 +1,40 @@
+
+
+
\ No newline at end of file
diff --git a/src/Squidex/app/shared/components/rich-editor.component.scss b/src/Squidex/app/shared/components/rich-editor.component.scss
new file mode 100644
index 000000000..33c03a1e5
--- /dev/null
+++ b/src/Squidex/app/shared/components/rich-editor.component.scss
@@ -0,0 +1,36 @@
+@import '_mixins';
+@import '_vars';
+
+.editor {
+ background: $color-dark-foreground;
+ border: 1px solid $color-input;
+ height: 30rem;
+}
+.asset-selector {
+ z-index: 65560;
+
+ .modal-header {
+ background: transparent;
+ border-bottom: 1px solid #c5c5c5;
+
+ .modal-title {
+ text-decoration: none;
+ color: #333;
+ font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
+ text-shadow: none;
+ }
+ }
+
+ .modal-content {
+ width: 100%;
+ border-radius: 0;
+ -webkit-border-radius: 0;
+ }
+ .modal-dialog {
+ max-width: 900px;
+ }
+
+ .btn {
+ border-radius: 0;
+ }
+}
\ No newline at end of file
diff --git a/src/Squidex/app/shared/components/rich-editor.component.ts b/src/Squidex/app/shared/components/rich-editor.component.ts
new file mode 100644
index 000000000..b88b56988
--- /dev/null
+++ b/src/Squidex/app/shared/components/rich-editor.component.ts
@@ -0,0 +1,165 @@
+/*
+ * Squidex Headless CMS
+ *
+ * @license
+ * Copyright (c) Sebastian Stehle. All rights reserved
+ */
+
+import { AfterViewInit, Component, forwardRef, ElementRef, OnDestroy, ViewChild } from '@angular/core';
+import { ControlValueAccessor, NG_VALUE_ACCESSOR, FormBuilder } from '@angular/forms';
+
+import { AppComponentBase } from './app.component-base';
+import { AssetUrlPipe } from './pipes';
+import { ApiUrlConfig, ModalView, AppsStoreService, AssetDto, AssetsService, ImmutableArray, DialogService, AuthService, Pager, Types, ResourceLoaderService } from './../declarations-base';
+
+declare var tinymce: any;
+
+export const SQX_RICH_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
+ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => RichEditorComponent), multi: true
+};
+
+@Component({
+ selector: 'sqx-rich-editor',
+ styleUrls: ['./rich-editor.component.scss'],
+ templateUrl: './rich-editor.component.html',
+ providers: [SQX_RICH_EDITOR_CONTROL_VALUE_ACCESSOR]
+})
+export class RichEditorComponent extends AppComponentBase implements ControlValueAccessor, AfterViewInit, OnDestroy {
+ private callChange = (v: any) => { /* NOOP */ };
+ private callTouched = () => { /* NOOP */ };
+ private tinyEditor: any;
+ private tinyInitTimer: any;
+ private value: string;
+ private isDisabled = false;
+ private assetSelectorClickHandler: any = null;
+ public assetsItems: ImmutableArray;
+ public assetsPager = new Pager(0, 0, 12);
+ private assetUrlGenerator: AssetUrlPipe;
+
+ @ViewChild('editor')
+ public editor: ElementRef;
+
+ public assetsDialog = new ModalView();
+ public assetsForm = this.formBuilder.group({
+ name: ['']
+ });
+
+ constructor(dialogs: DialogService, apps: AppsStoreService, authService: AuthService,
+ private readonly resourceLoader: ResourceLoaderService,
+ private readonly formBuilder: FormBuilder,
+ private readonly assetsService: AssetsService,
+ private readonly apiUrlConfig: ApiUrlConfig
+ ) {
+ super(dialogs, apps, authService);
+ this.assetUrlGenerator = new AssetUrlPipe(this.apiUrlConfig);
+ }
+
+ private load() {
+ this.appNameOnce()
+ .switchMap(app => this.assetsService.getAssets(app, this.assetsPager.pageSize, this.assetsPager.skip))
+ .subscribe(dtos => {
+ this.assetsItems = ImmutableArray.of(dtos.items);
+ this.assetsPager = this.assetsPager.setCount(dtos.total);
+ }, error => {
+ this.notifyError(error);
+ });
+ }
+
+ public goNext() {
+ this.assetsPager = this.assetsPager.goNext();
+
+ this.load();
+ }
+
+ public goPrev() {
+ this.assetsPager = this.assetsPager.goPrev();
+
+ this.load();
+ }
+
+ public ngOnDestroy() {
+ clearTimeout(this.tinyInitTimer);
+
+ tinymce.remove(this.editor);
+ }
+
+ public ngAfterViewInit() {
+ const self = this;
+
+ this.resourceLoader.loadScript('https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.5.4/tinymce.min.js').then(() => {
+ tinymce.init({
+ setup: (editor: any) => {
+ self.tinyEditor = editor;
+ self.tinyEditor.setMode(this.isDisabled ? 'readonly' : 'design');
+
+ self.tinyEditor.on('change', () => {
+ const value = editor.getContent();
+
+ if (this.value !== value) {
+ this.value = value;
+
+ self.callChange(value);
+ }
+ });
+
+ self.tinyEditor.on('blur', () => {
+ self.callTouched();
+ });
+
+ this.tinyInitTimer =
+ setTimeout(() => {
+ self.tinyEditor.setContent(this.value || '');
+ }, 500);
+ },
+ removed_menuitems: 'newdocument', plugins: 'code,image', target: this.editor.nativeElement, file_picker_types: 'image', file_picker_callback: (cb: any, value: any, meta: any) => {
+ self.load();
+ self.assetsDialog.show();
+ self.assetSelectorClickHandler = {
+ cb: cb,
+ meta: meta
+ };
+ }
+ });
+ });
+ }
+
+ public writeValue(value: string) {
+ this.value = Types.isString(value) ? value : '';
+
+ if (this.tinyEditor) {
+ this.tinyEditor.setContent(this.value);
+ }
+ }
+
+ public setDisabledState(isDisabled: boolean): void {
+ this.isDisabled = isDisabled;
+
+ if (this.tinyEditor) {
+ this.tinyEditor.setMode(isDisabled ? 'readonly' : 'design');
+ }
+ }
+
+ public registerOnChange(fn: any) {
+ this.callChange = fn;
+ }
+
+ public registerOnTouched(fn: any) {
+ this.callTouched = fn;
+ }
+
+ public closeAssetDialog() {
+ this.assetsDialog.hide();
+ this.assetSelectorClickHandler = null;
+ }
+
+ public onAssetClicked(asset: AssetDto) {
+ if (this.assetSelectorClickHandler != null) {
+ this.assetSelectorClickHandler.cb(this.assetUrlGenerator.transform(asset), {
+ description: asset.fileName,
+ width: asset.pixelWidth,
+ height: asset.pixelHeight
+ });
+ this.closeAssetDialog();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Squidex/app/shared/declarations.ts b/src/Squidex/app/shared/declarations.ts
index 3e4313916..5fc29bd25 100644
--- a/src/Squidex/app/shared/declarations.ts
+++ b/src/Squidex/app/shared/declarations.ts
@@ -13,5 +13,6 @@ export * from './components/help.component';
export * from './components/history.component';
export * from './components/language-selector.component';
export * from './components/pipes';
+export * from './components/rich-editor.component';
export * from './declarations-base';
\ No newline at end of file
diff --git a/src/Squidex/app/shared/module.ts b/src/Squidex/app/shared/module.ts
index f67368770..6f229df77 100644
--- a/src/Squidex/app/shared/module.ts
+++ b/src/Squidex/app/shared/module.ts
@@ -57,7 +57,8 @@ import {
UserManagementService,
UsersProviderService,
UsersService,
- WebhooksService
+ WebhooksService,
+ RichEditorComponent
} from './declarations';
@NgModule({
@@ -81,7 +82,8 @@ import {
UserNamePipe,
UserNameRefPipe,
UserPicturePipe,
- UserPictureRefPipe
+ UserPictureRefPipe,
+ RichEditorComponent
],
exports: [
AppFormComponent,
@@ -99,7 +101,8 @@ import {
UserNamePipe,
UserNameRefPipe,
UserPicturePipe,
- UserPictureRefPipe
+ UserPictureRefPipe,
+ RichEditorComponent
]
})
export class SqxSharedModule {