diff options
-rw-r--r-- | src/client/documents/Documents.ts | 2 | ||||
-rw-r--r-- | src/client/northstar/dash-fields/HistogramField.ts | 2 | ||||
-rw-r--r-- | src/client/northstar/operations/HistogramOperation.ts | 4 | ||||
-rw-r--r-- | src/client/util/DragManager.ts | 14 | ||||
-rw-r--r-- | src/client/views/Main.tsx | 64 | ||||
-rw-r--r-- | src/client/views/collections/CollectionTreeView.tsx | 11 | ||||
-rw-r--r-- | src/client/views/collections/CollectionViewBase.tsx | 4 | ||||
-rw-r--r-- | src/fields/Document.ts | 30 | ||||
-rw-r--r-- | src/fields/KeyStore.ts | 105 |
9 files changed, 133 insertions, 103 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 1f0744782..7d2f9cde1 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -43,6 +43,7 @@ export interface DocumentOptions { layoutKeys?: Key[]; viewType?: number; backgroundColor?: string; + copyDraggedItems?: boolean; } export namespace Documents { @@ -86,6 +87,7 @@ export namespace Documents { if (options.ink !== undefined) { doc.Set(KeyStore.Ink, new InkField(options.ink)); } if (options.layout !== undefined) { doc.SetText(KeyStore.Layout, options.layout); } if (options.layoutKeys !== undefined) { doc.Set(KeyStore.LayoutKeys, new ListField(options.layoutKeys)); } + if (options.copyDraggedItems !== undefined) { doc.SetBoolean(KeyStore.CopyDraggedItems, options.copyDraggedItems); } return doc; } diff --git a/src/client/northstar/dash-fields/HistogramField.ts b/src/client/northstar/dash-fields/HistogramField.ts index 90be70b80..48731f52d 100644 --- a/src/client/northstar/dash-fields/HistogramField.ts +++ b/src/client/northstar/dash-fields/HistogramField.ts @@ -27,7 +27,7 @@ export class HistogramField extends BasicField<HistogramOperation> { } Copy(): Field { - return new HistogramField(this.Data); + return new HistogramField(this.Data.Copy()); } ToScriptString(): string { diff --git a/src/client/northstar/operations/HistogramOperation.ts b/src/client/northstar/operations/HistogramOperation.ts index e63de1632..840520235 100644 --- a/src/client/northstar/operations/HistogramOperation.ts +++ b/src/client/northstar/operations/HistogramOperation.ts @@ -42,6 +42,10 @@ export class HistogramOperation extends BaseOperation implements IBaseFilterCons this.SchemaName = schemaName; } + Copy(): HistogramOperation { + return new HistogramOperation(this.SchemaName, this.X, this.Y, this.V, this.Normalization); + } + Equals(other: Object): boolean { throw new Error("Method not implemented."); } diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 043932de5..c1919093e 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -10,7 +10,8 @@ import { DocumentView } from "../views/nodes/DocumentView"; export function setupDrag( _reference: React.RefObject<HTMLDivElement>, docFunc: () => Document, - removeFunc: (containingCollection: CollectionView) => void = () => { } + removeFunc: (containingCollection: CollectionView) => void = () => { }, + copyOnDrop: boolean = false ) { let onRowMove = action( (e: PointerEvent): void => { @@ -20,6 +21,7 @@ export function setupDrag( document.removeEventListener("pointermove", onRowMove); document.removeEventListener("pointerup", onRowUp); var dragData = new DragManager.DocumentDragData([docFunc()]); + dragData.copyOnDrop = copyOnDrop; dragData.removeDocument = removeFunc; DragManager.StartDocumentDrag([_reference.current!], dragData, e.x, e.y); } @@ -125,6 +127,7 @@ export namespace DragManager { xOffset?: number; yOffset?: number; aliasOnDrop?: boolean; + copyOnDrop?: boolean; removeDocument?: (collectionDrop: CollectionView) => void; [id: string]: any; } @@ -136,15 +139,12 @@ export namespace DragManager { downY: number, options?: DragOptions ) { - StartDrag( - eles, - dragData, - downX, downY, - options, + StartDrag(eles, dragData, downX, downY, options, (dropData: { [id: string]: any }) => (dropData.droppedDocuments = dragData.aliasOnDrop ? dragData.draggedDocuments.map(d => d.CreateAlias()) - : dragData.draggedDocuments) + : dragData.copyOnDrop ? dragData.draggedDocuments.map(d => d.Copy(true) as Document) : + dragData.draggedDocuments) ); } diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 237eb3b6e..b4ab9e21d 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -1,57 +1,41 @@ -import { action, configure, observable, runInAction, trace, computed, reaction } from 'mobx'; +import { IconName, library } from '@fortawesome/fontawesome-svg-core'; +import { faFilePdf, faFilm, faFont, faGlobeAsia, faImage, faMusic, faObjectGroup, faPenNib, faRedoAlt, faTable, faTree, faUndoAlt } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { action, computed, configure, observable, runInAction } from 'mobx'; +import { observer } from 'mobx-react'; import "normalize.css"; import * as React from 'react'; import * as ReactDOM from 'react-dom'; +import Measure from 'react-measure'; +import * as request from 'request'; import { Document } from '../../fields/Document'; +import { Field, FieldWaiting, Opt } from '../../fields/Field'; import { KeyStore } from '../../fields/KeyStore'; -import "./Main.scss"; +import { ListField } from '../../fields/ListField'; +import { WorkspacesMenu } from '../../server/authentication/controllers/WorkspacesMenu'; +import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils'; import { MessageStore } from '../../server/Message'; +import { RouteStore } from '../../server/RouteStore'; +import { ServerUtils } from '../../server/ServerUtil'; import { Utils } from '../../Utils'; -import * as request from 'request' -import * as rp from 'request-promise' import { Documents } from '../documents/Documents'; +import { ColumnAttributeModel } from '../northstar/core/attribute/AttributeModel'; +import { AttributeTransformationModel } from '../northstar/core/attribute/AttributeTransformationModel'; +import { Gateway, Settings } from '../northstar/manager/Gateway'; +import { AggregateFunction, Catalog } from '../northstar/model/idea/idea'; +import '../northstar/model/ModelExtensions'; +import { HistogramOperation } from '../northstar/operations/HistogramOperation'; +import '../northstar/utils/Extensions'; import { Server } from '../Server'; import { setupDrag } from '../util/DragManager'; import { Transform } from '../util/Transform'; -import { UndoManager, undoBatch } from '../util/UndoManager'; -import { WorkspacesMenu } from '../../server/authentication/controllers/WorkspacesMenu'; +import { UndoManager } from '../util/UndoManager'; import { CollectionDockingView } from './collections/CollectionDockingView'; import { ContextMenu } from './ContextMenu'; import { DocumentDecorations } from './DocumentDecorations'; -import { DocumentView } from './nodes/DocumentView'; -import "./Main.scss"; -import { observer } from 'mobx-react'; import { InkingControl } from './InkingControl'; -import { RouteStore } from '../../server/RouteStore'; -import { library, IconName } from '@fortawesome/fontawesome-svg-core'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { faFont } from '@fortawesome/free-solid-svg-icons'; -import { faImage } from '@fortawesome/free-solid-svg-icons'; -import { faFilePdf } from '@fortawesome/free-solid-svg-icons'; -import { faObjectGroup } from '@fortawesome/free-solid-svg-icons'; -import { faTable } from '@fortawesome/free-solid-svg-icons'; -import { faGlobeAsia } from '@fortawesome/free-solid-svg-icons'; -import { faUndoAlt } from '@fortawesome/free-solid-svg-icons'; -import { faRedoAlt } from '@fortawesome/free-solid-svg-icons'; -import { faPenNib } from '@fortawesome/free-solid-svg-icons'; -import { faFilm } from '@fortawesome/free-solid-svg-icons'; -import { faMusic } from '@fortawesome/free-solid-svg-icons'; -import { faTree } from '@fortawesome/free-solid-svg-icons'; -import Measure from 'react-measure'; -import { DashUserModel } from '../../server/authentication/models/user_model'; -import { ServerUtils } from '../../server/ServerUtil'; -import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils'; -import { Field, Opt, FieldWaiting } from '../../fields/Field'; -import { ListField } from '../../fields/ListField'; -import { Gateway, Settings } from '../northstar/manager/Gateway'; -import { Catalog, Schema, Attribute, AttributeGroup, AggregateFunction } from '../northstar/model/idea/idea'; -import { ArrayUtil } from '../northstar/utils/ArrayUtil'; -import '../northstar/model/ModelExtensions' -import '../northstar/utils/Extensions' -import { HistogramOperation } from '../northstar/operations/HistogramOperation'; -import { AttributeTransformationModel } from '../northstar/core/attribute/AttributeTransformationModel'; -import { ColumnAttributeModel } from '../northstar/core/attribute/AttributeModel'; -import { CollectionView } from './collections/CollectionView'; +import "./Main.scss"; +import { DocumentView } from './nodes/DocumentView'; @observer export class Main extends React.Component { @@ -247,7 +231,7 @@ export class Main extends React.Component { let addTextNode = action(() => Documents.TextDocument({ width: 200, height: 200, title: "a text note" })) let addColNode = action(() => Documents.FreeformDocument([], { width: 200, height: 200, title: "a freeform collection" })); let addSchemaNode = action(() => Documents.SchemaDocument([], { width: 200, height: 200, title: "a schema collection" })); - let addTreeNode = action(() => Documents.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas" })); + let addTreeNode = action(() => Documents.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas", copyDraggedItems: true })); let addVideoNode = action(() => Documents.VideoDocument(videourl, { width: 200, height: 200, title: "video node" })); let addPDFNode = action(() => Documents.PdfDocument(pdfurl, { width: 200, height: 200, title: "a schema collection" })); let addImageNode = action(() => Documents.ImageDocument(imgurl, { width: 200, height: 200, title: "an image of a cat" })); diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 70790af18..0b12f11fd 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -18,6 +18,7 @@ import React = require("react") export interface TreeViewProps { document: Document; deleteDoc: (doc: Document) => void; + copyOnDrag: boolean; } export enum BulletType { @@ -63,7 +64,7 @@ class TreeView extends React.Component<TreeViewProps> { */ renderTitle() { let reference = React.createRef<HTMLDivElement>(); - let onItemDown = setupDrag(reference, () => this.props.document, (containingCollection: CollectionView) => this.props.deleteDoc(this.props.document)); + let onItemDown = setupDrag(reference, () => this.props.document, (containingCollection: CollectionView) => this.props.deleteDoc(this.props.document), this.props.copyOnDrag); let editableView = (titleString: string) => (<EditableView display={"inline"} @@ -85,13 +86,12 @@ class TreeView extends React.Component<TreeViewProps> { render() { let bulletType = BulletType.List; let childElements: JSX.Element | undefined = undefined; - var children = this.props.document.GetT<ListField<Document>>(KeyStore.Data, ListField); if (children && children !== FieldWaiting) { // add children for a collection if (!this._collapsed) { bulletType = BulletType.Collapsible; childElements = <ul> - {children.Data.map(value => <TreeView key={value.Id} document={value} deleteDoc={this.remove} />)} + {children.Data.map(value => <TreeView key={value.Id} document={value} deleteDoc={this.remove} copyOnDrag={this.props.copyOnDrag} />)} </ul> } else bulletType = BulletType.Collapsed; @@ -118,10 +118,11 @@ export class CollectionTreeView extends CollectionViewBase { } render() { - var children = this.props.Document.GetT<ListField<Document>>(KeyStore.Data, ListField); + let children = this.props.Document.GetT<ListField<Document>>(KeyStore.Data, ListField); + let copyOnDrag = this.props.Document.GetBoolean(KeyStore.CopyDraggedItems, false); let childrenElement = !children || children === FieldWaiting ? (null) : (children.Data.map(value => - <TreeView document={value} key={value.Id} deleteDoc={this.remove} />) + <TreeView document={value} key={value.Id} deleteDoc={this.remove} copyOnDrag={copyOnDrag} />) ) return ( diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx index 458bae7ab..7cf49e215 100644 --- a/src/client/views/collections/CollectionViewBase.tsx +++ b/src/client/views/collections/CollectionViewBase.tsx @@ -82,13 +82,13 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps> @action protected drop(e: Event, de: DragManager.DropEvent): boolean { if (de.data instanceof DragManager.DocumentDragData) { - if (de.data.aliasOnDrop) { + if (de.data.aliasOnDrop || de.data.copyOnDrop) { [KeyStore.Width, KeyStore.Height, KeyStore.CurPage].map(key => de.data.draggedDocuments.map((draggedDocument: Document, i: number) => draggedDocument.GetTAsync(key, NumberField, (f: Opt<NumberField>) => f ? de.data.droppedDocuments[i].SetNumber(key, f.Data) : null))); } let added = de.data.droppedDocuments.reduce((added, d) => this.props.addDocument(d, false), true); - if (added && de.data.removeDocument && !de.data.aliasOnDrop) { + if (added && de.data.removeDocument && !de.data.aliasOnDrop && !de.data.copyOnDrop) { de.data.removeDocument(this.props.CollectionView); } e.stopPropagation(); diff --git a/src/fields/Document.ts b/src/fields/Document.ts index 538d4ada9..02004678d 100644 --- a/src/fields/Document.ts +++ b/src/fields/Document.ts @@ -10,6 +10,9 @@ import { Types } from "../server/Message"; import { UndoManager } from "../client/util/UndoManager"; import { HtmlField } from "./HtmlField"; import { BooleanField } from "./BooleanField"; +import { allLimit } from "async"; +import { prototype } from "nodemailer/lib/smtp-pool"; +import { HistogramField } from "../client/northstar/dash-fields/HistogramField"; export class Document extends Field { //TODO tfs: We should probably store FieldWaiting in fields when we request it from the server so that we don't set up multiple server gets for the same document and field @@ -343,7 +346,10 @@ export class Document extends Field { SetText(key: Key, value: string, replaceWrongType = true) { this.SetData(key, value, TextField, replaceWrongType); } - + @action + SetBoolean(key: Key, value: boolean, replaceWrongType = true) { + this.SetData(key, value, BooleanField, replaceWrongType); + } @action SetNumber(key: Key, value: number, replaceWrongType = true) { this.SetData(key, value, NumberField, replaceWrongType); @@ -393,8 +399,26 @@ export class Document extends Field { return title; //throw new Error("Method not implemented."); } - Copy(): Field { - throw new Error("Method not implemented."); + Copy(copyProto?: boolean, id?: string): Field { + let copy = new Document(); + this._proxies.forEach((fieldid, keyid) => { // copy each prototype field + let key = KeyStore.KeyLookup(keyid); + if (key) { + this.GetAsync(key, (field: Opt<Field>) => { + if (key === KeyStore.Prototype && copyProto) { // handle prototype field specially + if (field instanceof Document) { + copy.Set(key, field.Copy(false)); // only copying one level of prototypes for now... + } + } + else + if (field instanceof Document) // ... TODO bcz: should we copy documents or reference them + copy.Set(key!, field) + else if (field) + copy.Set(key!, field.Copy()) + }) + } + }); + return copy; } ToJson(): { type: Types; data: [string, string][]; _id: string } { diff --git a/src/fields/KeyStore.ts b/src/fields/KeyStore.ts index 6ed3b1604..42dc34c51 100644 --- a/src/fields/KeyStore.ts +++ b/src/fields/KeyStore.ts @@ -2,49 +2,64 @@ import { Key } from "./Key"; import { KeyTransfer } from "../server/Message"; export namespace KeyStore { - export const Prototype = new Key("Prototype"); - export const X = new Key("X"); - export const Y = new Key("Y"); - export const Page = new Key("Page"); - export const Title = new Key("Title"); - export const Author = new Key("Author"); - export const PanX = new Key("PanX"); - export const PanY = new Key("PanY"); - export const Scale = new Key("Scale"); - export const NativeWidth = new Key("NativeWidth"); - export const NativeHeight = new Key("NativeHeight"); - export const Width = new Key("Width"); - export const Height = new Key("Height"); - export const ZIndex = new Key("ZIndex"); - export const Data = new Key("Data"); - export const Annotations = new Key("Annotations"); - export const ViewType = new Key("ViewType"); - export const Layout = new Key("Layout"); - export const BackgroundColor = new Key("BackgroundColor"); - export const BackgroundLayout = new Key("BackgroundLayout"); - export const OverlayLayout = new Key("OverlayLayout"); - export const LayoutKeys = new Key("LayoutKeys"); - export const LayoutFields = new Key("LayoutFields"); - export const ColumnsKey = new Key("SchemaColumns"); - export const SchemaSplitPercentage = new Key("SchemaSplitPercentage"); - export const Caption = new Key("Caption"); - export const ActiveWorkspace = new Key("ActiveWorkspace"); - export const DocumentText = new Key("DocumentText"); - export const BrushingDocs = new Key("BrushingDocs"); - export const LinkedToDocs = new Key("LinkedToDocs"); - export const LinkedFromDocs = new Key("LinkedFromDocs"); - export const LinkDescription = new Key("LinkDescription"); - export const LinkTags = new Key("LinkTag"); - export const Thumbnail = new Key("Thumbnail"); - export const ThumbnailPage = new Key("ThumbnailPage"); - export const CurPage = new Key("CurPage"); - export const AnnotationOn = new Key("AnnotationOn"); - export const NumPages = new Key("NumPages"); - export const Ink = new Key("Ink"); - export const Cursors = new Key("Cursors"); - export const OptionalRightCollection = new Key("OptionalRightCollection"); - export const Archives = new Key("Archives"); - export const Updated = new Key("Updated"); - export const Workspaces = new Key("Workspaces"); - export const Minimized = new Key("Minimized"); + export const Prototype = new Key("Prototype"); + export const X = new Key("X"); + export const Y = new Key("Y"); + export const Page = new Key("Page"); + export const Title = new Key("Title"); + export const Author = new Key("Author"); + export const PanX = new Key("PanX"); + export const PanY = new Key("PanY"); + export const Scale = new Key("Scale"); + export const NativeWidth = new Key("NativeWidth"); + export const NativeHeight = new Key("NativeHeight"); + export const Width = new Key("Width"); + export const Height = new Key("Height"); + export const ZIndex = new Key("ZIndex"); + export const Data = new Key("Data"); + export const Annotations = new Key("Annotations"); + export const ViewType = new Key("ViewType"); + export const Layout = new Key("Layout"); + export const BackgroundColor = new Key("BackgroundColor"); + export const BackgroundLayout = new Key("BackgroundLayout"); + export const OverlayLayout = new Key("OverlayLayout"); + export const LayoutKeys = new Key("LayoutKeys"); + export const LayoutFields = new Key("LayoutFields"); + export const ColumnsKey = new Key("SchemaColumns"); + export const SchemaSplitPercentage = new Key("SchemaSplitPercentage"); + export const Caption = new Key("Caption"); + export const ActiveWorkspace = new Key("ActiveWorkspace"); + export const DocumentText = new Key("DocumentText"); + export const BrushingDocs = new Key("BrushingDocs"); + export const LinkedToDocs = new Key("LinkedToDocs"); + export const LinkedFromDocs = new Key("LinkedFromDocs"); + export const LinkDescription = new Key("LinkDescription"); + export const LinkTags = new Key("LinkTag"); + export const Thumbnail = new Key("Thumbnail"); + export const ThumbnailPage = new Key("ThumbnailPage"); + export const CurPage = new Key("CurPage"); + export const AnnotationOn = new Key("AnnotationOn"); + export const NumPages = new Key("NumPages"); + export const Ink = new Key("Ink"); + export const Cursors = new Key("Cursors"); + export const OptionalRightCollection = new Key("OptionalRightCollection"); + export const Archives = new Key("Archives"); + export const Workspaces = new Key("Workspaces"); + export const Minimized = new Key("Minimized"); + export const CopyDraggedItems = new Key("CopyDraggedItems"); + + export const KeyList: Key[] = [Prototype, X, Y, Page, Title, Author, PanX, PanY, Scale, NativeWidth, NativeHeight, + Width, Height, ZIndex, Data, Annotations, ViewType, Layout, BackgroundColor, BackgroundLayout, OverlayLayout, LayoutKeys, + LayoutFields, ColumnsKey, SchemaSplitPercentage, Caption, ActiveWorkspace, DocumentText, BrushingDocs, LinkedToDocs, LinkedFromDocs, + LinkDescription, LinkTags, Thumbnail, ThumbnailPage, CurPage, AnnotationOn, NumPages, Ink, Cursors, OptionalRightCollection, + Archives, Workspaces, Minimized, CopyDraggedItems + ]; + export function KeyLookup(keyid: string) { + for (let i = 0; i < KeyList.length; i++) { + let keylistid = KeyList[i].Id; + if (keylistid === keyid) + return KeyList[i]; + } + return null; + } } |