UNPKG

@paperbits/core

Version:
255 lines (202 loc) 9.27 kB
import * as ko from "knockout"; import * as Utils from "@paperbits/common/utils"; import template from "./dropbucket.html"; import { IContentDescriptor, IContentDropHandler, IDataTransfer } from "@paperbits/common/editing"; import { GlobalEventHandler } from "@paperbits/common/events"; import { Component } from "@paperbits/common/ko/decorators"; import { IMediaService, MediaContract } from "@paperbits/common/media"; import { ViewManager, ViewManagerMode } from "@paperbits/common/ui"; import { DropBucketItem } from "./dropbucketItem"; @Component({ selector: "dropbucket", template: template }) export class DropBucket { public droppedItems: ko.ObservableArray<DropBucketItem>; constructor( private readonly globalEventHandler: GlobalEventHandler, private readonly mediaService: IMediaService, private readonly dropHandlers: IContentDropHandler[], private readonly viewManager: ViewManager, ) { this.onDragDrop = this.onDragDrop.bind(this); this.onPaste = this.onPaste.bind(this); this.addPendingContent = this.addPendingContent.bind(this); this.uploadContentAsMedia = this.uploadContentAsMedia.bind(this); this.discardDroppedContent = this.discardDroppedContent.bind(this); this.handleDroppedContent = this.handleDroppedContent.bind(this); this.handleUnknownContent = this.handleUnknownContent.bind(this); this.globalEventHandler.addDragDropListener(this.onDragDrop); // globalEventHandler.addPasteListener(this.onPaste); this.dropHandlers = dropHandlers; this.droppedItems = ko.observableArray<DropBucketItem>(); } private canHandleDrop(event: DragEvent): boolean { return (event.dataTransfer.files && event.dataTransfer.files.length > 0) || event.dataTransfer.getData("url").length > 0; } private addPendingContent(item: DropBucketItem): void { this.droppedItems.push(item); } private async handleDroppedContent(contentDescriptor: IContentDescriptor): Promise<void> { const dropbucketItem = new DropBucketItem(); dropbucketItem.title = contentDescriptor.title; dropbucketItem.description = contentDescriptor.description; if (contentDescriptor.getWidgetOrder) { const widgetOrder = await contentDescriptor.getWidgetOrder(); dropbucketItem.widgetOrder(widgetOrder); } dropbucketItem.thumbnailUrl(contentDescriptor.iconUrl); if (contentDescriptor.getThumbnailUrl) { contentDescriptor.getThumbnailUrl().then(thumbnailUrl => { dropbucketItem.previewUrl(thumbnailUrl); dropbucketItem.thumbnailUrl(thumbnailUrl); }); } if (contentDescriptor.uploadables && contentDescriptor.uploadables.length) { for (const uploadable of contentDescriptor.uploadables) { dropbucketItem.uploadables.push(uploadable); } } this.addPendingContent(dropbucketItem); } private onDragDrop(event: DragEvent): void { if (this.viewManager.mode === ViewManagerMode.preview) { return; } if (!this.canHandleDrop(event)) { return; } this.droppedItems.removeAll(); const dataTransfer = event.dataTransfer; const files = Array.prototype.slice.call(dataTransfer.files); let items: IDataTransfer[]; if (dataTransfer.files.length > 0) { items = []; for (const file of files) { items.push({ source: file, name: file.name, mimeType: file.type }); } } else { const urlData = dataTransfer.getData("url"); const parts = urlData.split("/"); items = [{ source: urlData, name: parts[parts.length - 1] }]; } for (const item of items) { let handled = false; let contentDescriptor: IContentDescriptor = null; let j = 0; while (contentDescriptor === null && j < this.dropHandlers.length) { if (this.dropHandlers[j].getContentDescriptorFromDataTransfer) { contentDescriptor = this.dropHandlers[j].getContentDescriptorFromDataTransfer(item); } if (contentDescriptor) { this.handleDroppedContent(contentDescriptor); handled = true; } j++; } if (!handled) { // none found this.handleUnknownContent(dataTransfer); } } } private onPaste(event: ClipboardEvent): void { this.droppedItems.removeAll(); const text = event.clipboardData.getData("text"); let i = 0; let contentDescriptor: IContentDescriptor = null; while (contentDescriptor === null && i < this.dropHandlers.length) { contentDescriptor = this.dropHandlers[i].getContentDescriptorFromDataTransfer({ source: text, name: text.split("/").pop().split("?")[0] }); if (contentDescriptor) { this.handleDroppedContent(contentDescriptor); } i++; } } private handleUnknownContent(dataTransfer: DataTransfer): void { if (dataTransfer.files.length === 0) { return; } let title = "File"; let description = dataTransfer.files[0].name; if (dataTransfer.files.length > 1) { title = `${dataTransfer.files.length} files`; description = ""; } const files = Array.prototype.slice.call(dataTransfer.files); const dropbucketItem = new DropBucketItem(); const uploadables = []; for (const file of files) { uploadables.push(file); } dropbucketItem.title = title; dropbucketItem.description = description; dropbucketItem.uploadables(uploadables); this.addPendingContent(dropbucketItem); } // public onDragStart(item: DropBucketItem): HTMLElement { // if (this.viewManager.mode === ViewManagerMode.preview) { // return; // } // item.widgetFactoryResult = item.widgetOrder().createWidget(); // const widgetElement = item.widgetFactoryResult.element; // const widgetModel = item.widgetFactoryResult.widgetModel; // const widgetBinding = item.widgetFactoryResult.widgetBinding; // this.droppedItems.remove(item); // this.viewManager.beginDrag({ // sourceModel: widgetModel, // sourceBinding: widgetBinding // }); // return widgetElement; // } // public async onDragEnd(dropbucketItem: DropBucketItem): Promise<void> { // if (this.viewManager.mode === ViewManagerMode.preview) { // return; // } // dropbucketItem.widgetFactoryResult.element.remove(); // this.droppedItems.remove(dropbucketItem); // const uploadables = dropbucketItem.uploadables(); // if (uploadables && uploadables.length > 0) { // this.uploadContentAsMedia(dropbucketItem); // this.droppedItems.remove(dropbucketItem); // } // const dragSession = this.viewManager.getDragSession(); // const acceptorBinding = dragSession.targetBinding; // if (acceptorBinding) { // const widgetHandler = this.widgetService.getWidgetHandler(acceptorBinding); // widgetHandler.onDragDrop(dragSession); // } // this.eventManager.dispatchEvent(Events.VirtualDragEnd); // } public async uploadContentAsMedia(dropbucketItem: DropBucketItem): Promise<void> { const uploadables = dropbucketItem.uploadables(); this.droppedItems.remove(dropbucketItem); uploadables.forEach(async uploadable => { let uploadPromise: Promise<MediaContract>; if (typeof uploadable === "string") { const name = uploadable.split("/").pop().split("?")[0]; uploadPromise = Utils.downloadFile(uploadable).then(blob => this.mediaService.createMedia(name, blob)); this.viewManager.notifyProgress(uploadPromise, "Media library", `Uploading ${uploadable}...`); } else { // TODO: Restore const content = await Utils.readFileAsByteArray(uploadable); uploadPromise = this.mediaService.createMedia(uploadable.name, content, uploadable.type); this.viewManager.notifyProgress(uploadPromise, "Media library", `Uploading ${uploadable.name}...`); } }); } public discardDroppedContent(): void { this.droppedItems.removeAll(); } }