From 80769d6e6c1fba0940ca0301ee6b9188e93de8a9 Mon Sep 17 00:00:00 2001 From: sowobm Date: Wed, 8 Nov 2017 16:43:10 +0200 Subject: [PATCH] rich text editor - insert external images - insert assets --- .../pages/content/content-field.component.ts | 12 +-- .../pages/content/content-page.component.html | 2 +- .../shared/components/asset-drop.handler.ts | 12 +-- .../shared/components/asset.component.html | 5 +- .../app/shared/components/asset.component.ts | 15 +++- .../components/rich-editor.component.html | 46 +--------- .../components/rich-editor.component.ts | 86 ++++--------------- src/Squidex/app/shared/utils/messages.ts | 13 +++ 8 files changed, 58 insertions(+), 133 deletions(-) diff --git a/src/Squidex/app/features/content/pages/content/content-field.component.ts b/src/Squidex/app/features/content/pages/content/content-field.component.ts index acefa3803..5e4e9a826 100644 --- a/src/Squidex/app/features/content/pages/content/content-field.component.ts +++ b/src/Squidex/app/features/content/pages/content/content-field.component.ts @@ -5,10 +5,11 @@ * Copyright (c) Sebastian Stehle. All rights reserved */ -import { Component, Input, OnInit, ViewChild, ElementRef } from '@angular/core'; +import { Component, Input, OnInit } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { AppLanguageDto, FieldDto } from 'shared'; +import { ActivatedRoute, Router } from '@angular/router'; @Component({ selector: 'sqx-content-field', @@ -16,6 +17,8 @@ import { AppLanguageDto, FieldDto } from 'shared'; templateUrl: './content-field.component.html' }) export class ContentFieldComponent implements OnInit { + constructor(private readonly router: Router, private readonly route: ActivatedRoute) { + } private masterLanguageCode: string; @Input() @@ -34,11 +37,8 @@ export class ContentFieldComponent implements OnInit { public fieldPartition: string; public richTextEditorOptions: any; - @ViewChild('assets') - public assetLink: ElementRef; - private buildRichTextEditorOptions() { - // const self = this; + const self = this; return { toolbar: 'undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | image assets', plugins: 'code,image', @@ -50,7 +50,7 @@ export class ContentFieldComponent implements OnInit { icon: 'browse', tooltip: 'Insert Assets', onclick: () => { - console.log(this.assetLink); + self.router.navigate(['assets'], { relativeTo: self.route }) } }); } diff --git a/src/Squidex/app/features/content/pages/content/content-page.component.html b/src/Squidex/app/features/content/pages/content/content-page.component.html index ba454af4a..eaf689467 100644 --- a/src/Squidex/app/features/content/pages/content/content-page.component.html +++ b/src/Squidex/app/features/content/pages/content/content-page.component.html @@ -49,7 +49,7 @@ - + diff --git a/src/Squidex/app/shared/components/asset-drop.handler.ts b/src/Squidex/app/shared/components/asset-drop.handler.ts index 69d846068..887f23d1c 100644 --- a/src/Squidex/app/shared/components/asset-drop.handler.ts +++ b/src/Squidex/app/shared/components/asset-drop.handler.ts @@ -17,16 +17,10 @@ export class AssetDropHandler { } public buildDroppedAssetData(asset: AssetDto, dragEvent: DragEvent) { - switch (asset.mimeType) { - - case 'image/jpeg': - case 'image/jpg': - case 'image/png': - case 'image/gif': - return this.handleImageAsset(asset, dragEvent); - default: - return ''; + if (asset.isImage) { + return this.handleImageAsset(asset, dragEvent); } + return ''; } private handleImageAsset(asset: AssetDto, dragEvent: DragEvent) { diff --git a/src/Squidex/app/shared/components/asset.component.html b/src/Squidex/app/shared/components/asset.component.html index 95fd99dd7..f7e6ebf7a 100644 --- a/src/Squidex/app/shared/components/asset.component.html +++ b/src/Squidex/app/shared/components/asset.component.html @@ -1,4 +1,7 @@ -
+
diff --git a/src/Squidex/app/shared/components/asset.component.ts b/src/Squidex/app/shared/components/asset.component.ts index 94b6415c1..0f9962091 100644 --- a/src/Squidex/app/shared/components/asset.component.ts +++ b/src/Squidex/app/shared/components/asset.component.ts @@ -14,6 +14,7 @@ import { AppsStoreService, AssetDto, AssetsService, + AssetDragged, AuthService, DateTime, DialogService, @@ -21,7 +22,8 @@ import { ModalView, UpdateAssetDto, Version, - Versioned + Versioned, + MessageBus } from './../declarations-base'; @Component({ @@ -76,7 +78,8 @@ export class AssetComponent extends AppComponentBase implements OnInit { constructor(apps: AppsStoreService, dialogs: DialogService, authService: AuthService, private readonly formBuilder: FormBuilder, - private readonly assetsService: AssetsService + private readonly assetsService: AssetsService, + private readonly messageBus: MessageBus ) { super(dialogs, apps, authService); } @@ -181,4 +184,12 @@ export class AssetComponent extends AppComponentBase implements OnInit { this.resetRenameForm(); } + + public onAssetDragStart(event: any) { + this.messageBus.emit(new AssetDragged(event.dragData, AssetDragged.DRAG_START, this)); + } + + public onAssetDragEnd(event: any) { + this.messageBus.emit(new AssetDragged(event.dragData, AssetDragged.DRAG_END, this)); + } } \ No newline at end of file diff --git a/src/Squidex/app/shared/components/rich-editor.component.html b/src/Squidex/app/shared/components/rich-editor.component.html index b9efa5ec6..eb0a1fafb 100644 --- a/src/Squidex/app/shared/components/rich-editor.component.html +++ b/src/Squidex/app/shared/components/rich-editor.component.html @@ -1,48 +1,6 @@
-
+

Drop asset in this zone to insert into content

-
- - \ No newline at end of file +
\ 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 index 0ea70500a..27f70132a 100644 --- a/src/Squidex/app/shared/components/rich-editor.component.ts +++ b/src/Squidex/app/shared/components/rich-editor.component.ts @@ -9,8 +9,7 @@ import { AfterViewInit, Component, forwardRef, ElementRef, OnDestroy, ViewChild, 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'; +import { ApiUrlConfig, ModalView, AppsStoreService, MessageBus, AssetDragged, DialogService, AuthService, Types, ResourceLoaderService } from './../declarations-base'; import { AssetDropHandler } from './asset-drop.handler'; declare var tinymce: any; @@ -32,13 +31,10 @@ export class RichEditorComponent extends AppComponentBase implements ControlValu 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; - private assetsMimeTypes: Array = ['image/png', 'image/jpeg', 'image/jpg', 'image/gif']; private assetDropHandler: AssetDropHandler; + public draggedOver = false; + private assetDraggedSubscription: any; @ViewChild('editor') public editor: ElementRef; @@ -53,23 +49,22 @@ export class RichEditorComponent extends AppComponentBase implements ControlValu constructor(dialogs: DialogService, apps: AppsStoreService, authService: AuthService, private readonly resourceLoader: ResourceLoaderService, private readonly formBuilder: FormBuilder, - private readonly assetsService: AssetsService, - private readonly apiUrlConfig: ApiUrlConfig + private readonly apiUrlConfig: ApiUrlConfig, + private readonly messageBus: MessageBus ) { super(dialogs, apps, authService); - this.assetUrlGenerator = new AssetUrlPipe(this.apiUrlConfig); this.assetDropHandler = new AssetDropHandler(this.apiUrlConfig); - } - private load() { - this.appNameOnce() - .switchMap(app => this.assetsService.getAssets(app, this.assetsPager.pageSize, this.assetsPager.skip, undefined, this.assetsMimeTypes)) - .subscribe(dtos => { - this.assetsItems = ImmutableArray.of(dtos.items); - this.assetsPager = this.assetsPager.setCount(dtos.total); - }, error => { - this.notifyError(error); - }); + this.assetDraggedSubscription = this.messageBus.of(AssetDragged).subscribe(message => { + // only handle images for now + if (message.assetDto.isImage) { + if (message.dragEvent === AssetDragged.DRAG_START) { + this.draggedOver = true; + } else { + this.draggedOver = false; + } + } + }); } private editorDefaultOptions() { @@ -93,26 +88,6 @@ export class RichEditorComponent extends AppComponentBase implements ControlValu self.callTouched(); }); - self.tinyEditor.on('init', () => { - let editorDoc = self.tinyEditor.iframeElement; - let dragTarget: any = null; - - editorDoc.ondragenter = (event: any) => { - console.log('dragenter'); - self.draggedOver = true; - dragTarget = event.target; - }; - - editorDoc.ondragleave = (event: any) => { - if (event.target === dragTarget) { - self.draggedOver = false; - console.log('dragleave'); - } else { - self.draggedOver = true; - } - }; - }); - // TODO: expose an observable to which we can subscribe to if (Types.isFunction(self.editorOptions.onSetup)) { self.editorOptions.onSetup(editor); @@ -127,22 +102,11 @@ export class RichEditorComponent extends AppComponentBase implements ControlValu }; } - 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); + this.assetDraggedSubscription.unsubscribe(); } public ngAfterViewInit() { @@ -150,7 +114,6 @@ export class RichEditorComponent extends AppComponentBase implements ControlValu this.resourceLoader.loadScript('https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.5.4/tinymce.min.js').then(() => { let editorOptions = { ...self.editorDefaultOptions(), ...self.editorOptions }; - console.log(editorOptions); tinymce.init(editorOptions); }); } @@ -179,24 +142,7 @@ export class RichEditorComponent extends AppComponentBase implements ControlValu 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(); - } - } - public onItemDropped(event: any) { - this.draggedOver = false; let content = this.assetDropHandler.buildDroppedAssetData(event.dragData, event.mouseEvent); if (content) { this.tinyEditor.execCommand('mceInsertContent', false, content); diff --git a/src/Squidex/app/shared/utils/messages.ts b/src/Squidex/app/shared/utils/messages.ts index 2f8c4aa83..543bd3caf 100644 --- a/src/Squidex/app/shared/utils/messages.ts +++ b/src/Squidex/app/shared/utils/messages.ts @@ -15,4 +15,17 @@ export class AssetUpdated { public readonly sender: any ) { } +} + +export class AssetDragged { + + public static readonly DRAG_START = 'Start'; + public static readonly DRAG_END = 'End'; + + constructor( + public readonly assetDto: AssetDto, + public readonly dragEvent: string, + public readonly sender: any + ) { + } } \ No newline at end of file