@paperbits/core
Version:
Paperbits core components.
255 lines (202 loc) • 9.27 kB
text/typescript
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";
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();
}
}