From 945fb1c28fa94ee1d2448381d7dd55b99214aad4 Mon Sep 17 00:00:00 2001 From: Monika Hedman Date: Mon, 1 Apr 2019 22:04:42 -0400 Subject: icon not working --- src/client/views/nodes/DocumentView.tsx | 669 ++++++++++++++++++++------------ 1 file changed, 411 insertions(+), 258 deletions(-) (limited to 'src/client/views/nodes/DocumentView.tsx') diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 1195128dc..085307461 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1,4 +1,13 @@ -import { action, computed, IReactionDisposer, reaction, runInAction } from "mobx"; +import { + action, + computed, + IReactionDisposer, + reaction, + runInAction, + observable +} from "mobx"; +import { library } from "@fortawesome/fontawesome-svg-core"; +import { faSquare } from "@fortawesome/free-solid-svg-icons"; import { observer } from "mobx-react"; import { Document } from "../../../fields/Document"; import { Field, Opt, FieldWaiting } from "../../../fields/Field"; @@ -13,30 +22,35 @@ import { DragManager } from "../../util/DragManager"; import { SelectionManager } from "../../util/SelectionManager"; import { Transform } from "../../util/Transform"; import { CollectionDockingView } from "../collections/CollectionDockingView"; -import { CollectionView, CollectionViewType } from "../collections/CollectionView"; +import { + CollectionView, + CollectionViewType +} from "../collections/CollectionView"; import { ContextMenu } from "../ContextMenu"; import { DocumentContentsView } from "./DocumentContentsView"; import "./DocumentView.scss"; import React = require("react"); import { ServerUtils } from "../../../server/ServerUtil"; +import { DocumentDecorations } from "../DocumentDecorations"; +library.add(faSquare); export interface DocumentViewProps { - ContainingCollectionView: Opt; - Document: Document; - AddDocument?: (doc: Document, allowDuplicates: boolean) => boolean; - RemoveDocument?: (doc: Document) => boolean; - ScreenToLocalTransform: () => Transform; - isTopMost: boolean; - ContentScaling: () => number; - PanelWidth: () => number; - PanelHeight: () => number; - focus: (doc: Document) => void; - SelectOnLoad: boolean; + ContainingCollectionView: Opt; + Document: Document; + AddDocument?: (doc: Document, allowDuplicates: boolean) => boolean; + RemoveDocument?: (doc: Document) => boolean; + ScreenToLocalTransform: () => Transform; + isTopMost: boolean; + ContentScaling: () => number; + PanelWidth: () => number; + PanelHeight: () => number; + focus: (doc: Document) => void; + SelectOnLoad: boolean; } export interface JsxArgs extends DocumentViewProps { - Keys: { [name: string]: Key } - Fields: { [name: string]: Field } + Keys: { [name: string]: Key }; + Fields: { [name: string]: Field }; } /* @@ -55,287 +69,426 @@ Example usage of this function: } */ export function FakeJsxArgs(keys: string[], fields: string[] = []): JsxArgs { - let Keys: { [name: string]: any } = {} - let Fields: { [name: string]: any } = {} - for (const key of keys) { - let fn = () => { } - Object.defineProperty(fn, "name", { value: key + "Key" }) - Keys[key] = fn; - } - for (const field of fields) { - let fn = () => { } - Object.defineProperty(fn, "name", { value: field }) - Fields[field] = fn; - } - let args: JsxArgs = { - Document: function Document() { }, - DocumentView: function DocumentView() { }, - Keys, - Fields - } as any; - return args; + let Keys: { [name: string]: any } = {}; + let Fields: { [name: string]: any } = {}; + for (const key of keys) { + let fn = () => {}; + Object.defineProperty(fn, "name", { value: key + "Key" }); + Keys[key] = fn; + } + for (const field of fields) { + let fn = () => {}; + Object.defineProperty(fn, "name", { value: field }); + Fields[field] = fn; + } + let args: JsxArgs = { + Document: function Document() {}, + DocumentView: function DocumentView() {}, + Keys, + Fields + } as any; + return args; } export interface JsxBindings { - Document: Document; - isSelected: () => boolean; - select: (isCtrlPressed: boolean) => void; - isTopMost: boolean; - SelectOnLoad: boolean; - [prop: string]: any; + Document: Document; + isSelected: () => boolean; + select: (isCtrlPressed: boolean) => void; + isTopMost: boolean; + SelectOnLoad: boolean; + [prop: string]: any; } - - @observer export class DocumentView extends React.Component { - private _mainCont = React.createRef(); - private _downX: number = 0; - private _downY: number = 0; - private _reactionDisposer: Opt; - @computed get active(): boolean { return SelectionManager.IsSelected(this) || !this.props.ContainingCollectionView || this.props.ContainingCollectionView.active(); } - @computed get topMost(): boolean { return !this.props.ContainingCollectionView || this.props.ContainingCollectionView.collectionViewType == CollectionViewType.Docking; } - @computed get layout(): string { return this.props.Document.GetText(KeyStore.Layout, "

Error loading layout data

"); } - @computed get layoutKeys(): Key[] { return this.props.Document.GetData(KeyStore.LayoutKeys, ListField, new Array()); } - @computed get layoutFields(): Key[] { return this.props.Document.GetData(KeyStore.LayoutFields, ListField, new Array()); } - screenRect = (): ClientRect | DOMRect => this._mainCont.current ? this._mainCont.current.getBoundingClientRect() : new DOMRect(); - onPointerDown = (e: React.PointerEvent): void => { - this._downX = e.clientX; - this._downY = e.clientY; - if (e.shiftKey && e.buttons === 2) { - if (this.props.isTopMost) { - this.startDragging(e.pageX, e.pageY, e.altKey || e.ctrlKey); - } - else CollectionDockingView.Instance.StartOtherDrag([this.props.Document], e); - e.stopPropagation(); - } else { - if (this.active && !e.isDefaultPrevented()) { - e.stopPropagation(); - document.removeEventListener("pointermove", this.onPointerMove) - document.addEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp) - document.addEventListener("pointerup", this.onPointerUp); - } - } + private _mainCont = React.createRef(); + private _downX: number = 0; + private _downY: number = 0; + + @observable + private minimized: boolean = false; + + private _reactionDisposer: Opt; + @computed get active(): boolean { + return ( + SelectionManager.IsSelected(this) || + !this.props.ContainingCollectionView || + this.props.ContainingCollectionView.active() + ); + } + @computed get topMost(): boolean { + return ( + !this.props.ContainingCollectionView || + this.props.ContainingCollectionView.collectionViewType == + CollectionViewType.Docking + ); + } + @computed get layout(): string { + return this.props.Document.GetText( + KeyStore.Layout, + "

Error loading layout data

" + ); + } + @computed get layoutKeys(): Key[] { + return this.props.Document.GetData( + KeyStore.LayoutKeys, + ListField, + new Array() + ); + } + @computed get layoutFields(): Key[] { + return this.props.Document.GetData( + KeyStore.LayoutFields, + ListField, + new Array() + ); + } + screenRect = (): ClientRect | DOMRect => + this._mainCont.current + ? this._mainCont.current.getBoundingClientRect() + : new DOMRect(); + onPointerDown = (e: React.PointerEvent): void => { + this._downX = e.clientX; + this._downY = e.clientY; + if (e.shiftKey && e.buttons === 2) { + if (this.props.isTopMost) { + this.startDragging(e.pageX, e.pageY, e.altKey || e.ctrlKey); + } else + CollectionDockingView.Instance.StartOtherDrag([this.props.Document], e); + e.stopPropagation(); + } else { + if (this.active && !e.isDefaultPrevented()) { + e.stopPropagation(); + document.removeEventListener("pointermove", this.onPointerMove); + document.addEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); + document.addEventListener("pointerup", this.onPointerUp); + } } + }; - private dropDisposer?: DragManager.DragDropDisposer; + private dropDisposer?: DragManager.DragDropDisposer; - componentDidMount() { - if (this._mainCont.current) { - this.dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, { handlers: { drop: this.drop.bind(this) } }); - } - runInAction(() => DocumentManager.Instance.DocumentViews.push(this)) - this._reactionDisposer = reaction( - () => this.props.ContainingCollectionView && this.props.ContainingCollectionView.SelectedDocs.slice(), - () => { - if (this.props.ContainingCollectionView && this.props.ContainingCollectionView.SelectedDocs.indexOf(this.props.Document.Id) != -1) - SelectionManager.SelectDoc(this, true); - }); + componentDidMount() { + if (this._mainCont.current) { + this.dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, { + handlers: { drop: this.drop.bind(this) } + }); } + runInAction(() => DocumentManager.Instance.DocumentViews.push(this)); + this._reactionDisposer = reaction( + () => + this.props.ContainingCollectionView && + this.props.ContainingCollectionView.SelectedDocs.slice(), + () => { + if ( + this.props.ContainingCollectionView && + this.props.ContainingCollectionView.SelectedDocs.indexOf( + this.props.Document.Id + ) != -1 + ) + SelectionManager.SelectDoc(this, true); + } + ); + } - componentDidUpdate() { - if (this.dropDisposer) { - this.dropDisposer(); - } - if (this._mainCont.current) { - this.dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, { handlers: { drop: this.drop.bind(this) } }); - } + componentDidUpdate() { + if (this.dropDisposer) { + this.dropDisposer(); + } + if (this._mainCont.current) { + this.dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, { + handlers: { drop: this.drop.bind(this) } + }); } + } - componentWillUnmount() { - if (this.dropDisposer) { - this.dropDisposer(); - } - runInAction(() => DocumentManager.Instance.DocumentViews.splice(DocumentManager.Instance.DocumentViews.indexOf(this), 1)) - if (this._reactionDisposer) { - this._reactionDisposer(); - } + componentWillUnmount() { + if (this.dropDisposer) { + this.dropDisposer(); + } + runInAction(() => + DocumentManager.Instance.DocumentViews.splice( + DocumentManager.Instance.DocumentViews.indexOf(this), + 1 + ) + ); + if (this._reactionDisposer) { + this._reactionDisposer(); } + } - startDragging(x: number, y: number, dropAliasOfDraggedDoc: boolean) { - if (this._mainCont.current) { - const [left, top] = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0); - let dragData = new DragManager.DocumentDragData([this.props.Document]); - dragData.aliasOnDrop = dropAliasOfDraggedDoc; - dragData.xOffset = x - left; - dragData.yOffset = y - top; - dragData.removeDocument = (dropCollectionView: CollectionView) => { - if (this.props.RemoveDocument && this.props.ContainingCollectionView !== dropCollectionView) { - this.props.RemoveDocument(this.props.Document); - } - } - DragManager.StartDocumentDrag([this._mainCont.current], dragData, { - handlers: { - dragComplete: action(() => { }), - }, - hideSource: !dropAliasOfDraggedDoc - }) + startDragging(x: number, y: number, dropAliasOfDraggedDoc: boolean) { + if (this._mainCont.current) { + const [left, top] = this.props + .ScreenToLocalTransform() + .inverse() + .transformPoint(0, 0); + let dragData = new DragManager.DocumentDragData([this.props.Document]); + dragData.aliasOnDrop = dropAliasOfDraggedDoc; + dragData.xOffset = x - left; + dragData.yOffset = y - top; + dragData.removeDocument = (dropCollectionView: CollectionView) => { + if ( + this.props.RemoveDocument && + this.props.ContainingCollectionView !== dropCollectionView + ) { + this.props.RemoveDocument(this.props.Document); } + }; + DragManager.StartDocumentDrag([this._mainCont.current], dragData, { + handlers: { + dragComplete: action(() => {}) + }, + hideSource: !dropAliasOfDraggedDoc + }); } + } - onPointerMove = (e: PointerEvent): void => { - if (e.cancelBubble) { - return; - } - if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) { - document.removeEventListener("pointermove", this.onPointerMove) - document.removeEventListener("pointerup", this.onPointerUp); - if (!this.topMost || e.buttons == 2 || e.altKey) { - this.startDragging(e.x, e.y, e.ctrlKey || e.altKey); - } - } - e.stopPropagation(); - e.preventDefault(); + onPointerMove = (e: PointerEvent): void => { + if (e.cancelBubble) { + return; } - onPointerUp = (e: PointerEvent): void => { - document.removeEventListener("pointermove", this.onPointerMove) - document.removeEventListener("pointerup", this.onPointerUp) - e.stopPropagation(); - if (Math.abs(e.clientX - this._downX) < 4 && Math.abs(e.clientY - this._downY) < 4) { - SelectionManager.SelectDoc(this, e.ctrlKey); - } + if ( + Math.abs(this._downX - e.clientX) > 3 || + Math.abs(this._downY - e.clientY) > 3 + ) { + document.removeEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); + if (!this.topMost || e.buttons == 2 || e.altKey) { + this.startDragging(e.x, e.y, e.ctrlKey || e.altKey); + } } - stopPropogation = (e: React.SyntheticEvent) => { - e.stopPropagation(); + e.stopPropagation(); + e.preventDefault(); + }; + onPointerUp = (e: PointerEvent): void => { + document.removeEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); + e.stopPropagation(); + if ( + Math.abs(e.clientX - this._downX) < 4 && + Math.abs(e.clientY - this._downY) < 4 + ) { + SelectionManager.SelectDoc(this, e.ctrlKey); } + }; + stopPropogation = (e: React.SyntheticEvent) => { + e.stopPropagation(); + }; - deleteClicked = (): void => { - if (this.props.RemoveDocument) { - this.props.RemoveDocument(this.props.Document); - } + deleteClicked = (): void => { + if (this.props.RemoveDocument) { + this.props.RemoveDocument(this.props.Document); } + }; - fieldsClicked = (e: React.MouseEvent): void => { - if (this.props.AddDocument) { - this.props.AddDocument(Documents.KVPDocument(this.props.Document, { width: 300, height: 300 }), false); - } - } - fullScreenClicked = (e: React.MouseEvent): void => { - CollectionDockingView.Instance.OpenFullScreen(this.props.Document); - ContextMenu.Instance.clearItems(); - ContextMenu.Instance.addItem({ description: "Close Full Screen", event: this.closeFullScreenClicked }); - ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) + fieldsClicked = (e: React.MouseEvent): void => { + if (this.props.AddDocument) { + this.props.AddDocument( + Documents.KVPDocument(this.props.Document, { width: 300, height: 300 }), + false + ); } + }; + fullScreenClicked = (e: React.MouseEvent): void => { + CollectionDockingView.Instance.OpenFullScreen(this.props.Document); + ContextMenu.Instance.clearItems(); + ContextMenu.Instance.addItem({ + description: "Close Full Screen", + event: this.closeFullScreenClicked + }); + ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); + }; - closeFullScreenClicked = (e: React.MouseEvent): void => { - CollectionDockingView.Instance.CloseFullScreen(); - ContextMenu.Instance.clearItems(); - ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked }) - ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) - } + closeFullScreenClicked = (e: React.MouseEvent): void => { + CollectionDockingView.Instance.CloseFullScreen(); + ContextMenu.Instance.clearItems(); + ContextMenu.Instance.addItem({ + description: "Full Screen", + event: this.fullScreenClicked + }); + ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); + }; - @action - drop = (e: Event, de: DragManager.DropEvent) => { - if (de.data instanceof DragManager.LinkDragData) { - let sourceDoc: Document = de.data.linkSourceDocumentView.props.Document; - let destDoc: Document = this.props.Document; - if (this.props.isTopMost) { - return; - } - let linkDoc: Document = new Document(); + @action + minimize = (e: React.MouseEvent): void => { + this.minimized = true; + SelectionManager.DeselectAll(); + }; - destDoc.GetTAsync(KeyStore.Prototype, Document).then((protoDest) => - sourceDoc.GetTAsync(KeyStore.Prototype, Document).then((protoSrc) => runInAction(() => { - linkDoc.Set(KeyStore.Title, new TextField("New Link")); - linkDoc.Set(KeyStore.LinkDescription, new TextField("")); - linkDoc.Set(KeyStore.LinkTags, new TextField("Default")); + @action + drop = (e: Event, de: DragManager.DropEvent) => { + if (de.data instanceof DragManager.LinkDragData) { + let sourceDoc: Document = de.data.linkSourceDocumentView.props.Document; + let destDoc: Document = this.props.Document; + if (this.props.isTopMost) { + return; + } + let linkDoc: Document = new Document(); - let dstTarg = (protoDest ? protoDest : destDoc); - let srcTarg = (protoSrc ? protoSrc : sourceDoc); - linkDoc.Set(KeyStore.LinkedToDocs, dstTarg); - linkDoc.Set(KeyStore.LinkedFromDocs, srcTarg); - dstTarg.GetOrCreateAsync(KeyStore.LinkedFromDocs, ListField, field => { (field as ListField).Data.push(linkDoc) }) - srcTarg.GetOrCreateAsync(KeyStore.LinkedToDocs, ListField, field => { (field as ListField).Data.push(linkDoc) }) - })) - ) - e.stopPropagation(); - } - } + destDoc.GetTAsync(KeyStore.Prototype, Document).then(protoDest => + sourceDoc.GetTAsync(KeyStore.Prototype, Document).then(protoSrc => + runInAction(() => { + linkDoc.Set(KeyStore.Title, new TextField("New Link")); + linkDoc.Set(KeyStore.LinkDescription, new TextField("")); + linkDoc.Set(KeyStore.LinkTags, new TextField("Default")); - onDrop = (e: React.DragEvent) => { - if (e.isDefaultPrevented()) { - return; - } - let text = e.dataTransfer.getData("text/plain"); - if (text && text.startsWith(" { + (field as ListField).Data.push(linkDoc); + } + ); + srcTarg.GetOrCreateAsync( + KeyStore.LinkedToDocs, + ListField, + field => { + (field as ListField).Data.push(linkDoc); + } + ); + }) + ) + ); + e.stopPropagation(); } + }; - @action - onContextMenu = (e: React.MouseEvent): void => { - e.stopPropagation(); - let moved = Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3; - if (moved || e.isDefaultPrevented()) { - e.preventDefault() - return; - } - e.preventDefault() + onDrop = (e: React.DragEvent) => { + if (e.isDefaultPrevented()) { + return; + } + let text = e.dataTransfer.getData("text/plain"); + if (text && text.startsWith(" this.props.focus(this.props.Document) }) - ContextMenu.Instance.addItem({ description: "Open Right", event: () => CollectionDockingView.Instance.AddRightSplit(this.props.Document) }) - ContextMenu.Instance.addItem({ - description: "Copy URL", - event: () => { - Utils.CopyText(ServerUtils.prepend("/doc/" + this.props.Document.Id)); - } - }); - ContextMenu.Instance.addItem({ - description: "Copy ID", - event: () => { - Utils.CopyText(this.props.Document.Id); - } - }); - //ContextMenu.Instance.addItem({ description: "Docking", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Docking) }) - ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) - if (!this.topMost) { - // DocumentViews should stop propagation of this event - e.stopPropagation(); - } + @action + onContextMenu = (e: React.MouseEvent): void => { + e.stopPropagation(); + let moved = + Math.abs(this._downX - e.clientX) > 3 || + Math.abs(this._downY - e.clientY) > 3; + if (moved || e.isDefaultPrevented()) { + e.preventDefault(); + return; + } + e.preventDefault(); - ContextMenu.Instance.addItem({ description: "Delete", event: this.deleteClicked }) - ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) - SelectionManager.SelectDoc(this, e.ctrlKey); + //for testing purposes + ContextMenu.Instance.addItem({ + description: "Minimize", + event: this.minimize + }); + ContextMenu.Instance.addItem({ + description: "Full Screen", + event: this.fullScreenClicked + }); + ContextMenu.Instance.addItem({ + description: "Fields", + event: this.fieldsClicked + }); + ContextMenu.Instance.addItem({ + description: "Center", + event: () => this.props.focus(this.props.Document) + }); + ContextMenu.Instance.addItem({ + description: "Open Right", + event: () => + CollectionDockingView.Instance.AddRightSplit(this.props.Document) + }); + ContextMenu.Instance.addItem({ + description: "Copy URL", + event: () => { + Utils.CopyText(ServerUtils.prepend("/doc/" + this.props.Document.Id)); + } + }); + ContextMenu.Instance.addItem({ + description: "Copy ID", + event: () => { + Utils.CopyText(this.props.Document.Id); + } + }); + //ContextMenu.Instance.addItem({ description: "Docking", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Docking) }) + ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); + if (!this.topMost) { + // DocumentViews should stop propagation of this event + e.stopPropagation(); } + ContextMenu.Instance.addItem({ + description: "Delete", + event: this.deleteClicked + }); + ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); + SelectionManager.SelectDoc(this, e.ctrlKey); + }; - isSelected = () => { - return SelectionManager.IsSelected(this); - } + isMinimized = () => { + return this.minimized; + }; - select = (ctrlPressed: boolean) => { - SelectionManager.SelectDoc(this, ctrlPressed) - } + isSelected = () => { + return SelectionManager.IsSelected(this); + }; - render() { - if (!this.props.Document) { - return (null); - } - var scaling = this.props.ContentScaling(); - var nativeWidth = this.props.Document.GetNumber(KeyStore.NativeWidth, 0); - var nativeHeight = this.props.Document.GetNumber(KeyStore.NativeHeight, 0); - var backgroundcolor = this.props.Document.GetText(KeyStore.BackgroundColor, ""); - return ( -
0 ? nativeWidth.toString() + "px" : "100%", - height: nativeHeight > 0 ? nativeHeight.toString() + "px" : "100%", - transformOrigin: "left top", - transform: `scale(${scaling} , ${scaling})` - }} - onDrop={this.onDrop} - onContextMenu={this.onContextMenu} - onPointerDown={this.onPointerDown} > - -
- ) + select = (ctrlPressed: boolean) => { + SelectionManager.SelectDoc(this, ctrlPressed); + }; + + render() { + if (!this.props.Document) { + return null; } -} \ No newline at end of file + if (this.minimized) { + return ( + // +
+ ); + } else { + var scaling = this.props.ContentScaling(); + var nativeWidth = this.props.Document.GetNumber(KeyStore.NativeWidth, 0); + var nativeHeight = this.props.Document.GetNumber( + KeyStore.NativeHeight, + 0 + ); + var backgroundcolor = this.props.Document.GetText( + KeyStore.BackgroundColor, + "" + ); + return ( +
0 ? nativeWidth.toString() + "px" : "100%", + height: nativeHeight > 0 ? nativeHeight.toString() + "px" : "100%", + transformOrigin: "left top", + transform: `scale(${scaling} , ${scaling})` + }} + onDrop={this.onDrop} + onContextMenu={this.onContextMenu} + onPointerDown={this.onPointerDown} + > + +
+ ); + } + } +} -- cgit v1.2.3-70-g09d2 From 7fdf7396a8bdb2e4f8c3b27ca99a36727d85adae Mon Sep 17 00:00:00 2001 From: Monika Hedman Date: Mon, 1 Apr 2019 23:07:04 -0400 Subject: minimize sorta works??? --- src/client/util/DragManager.ts | 485 +++++++++++++++++------------- src/client/views/DocumentDecorations.scss | 9 +- src/client/views/nodes/DocumentView.scss | 6 +- src/client/views/nodes/DocumentView.tsx | 32 +- src/client/views/nodes/Sticky.tsx | 138 ++++----- 5 files changed, 375 insertions(+), 295 deletions(-) (limited to 'src/client/views/nodes/DocumentView.tsx') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 9ffe964ef..ee0b5333c 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -1,251 +1,312 @@ import { DocumentDecorations } from "../views/DocumentDecorations"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; -import { Document } from "../../fields/Document" +import { Document } from "../../fields/Document"; import { action } from "mobx"; import { ImageField } from "../../fields/ImageField"; import { KeyStore } from "../../fields/KeyStore"; import { CollectionView } from "../views/collections/CollectionView"; import { DocumentView } from "../views/nodes/DocumentView"; -export function setupDrag(_reference: React.RefObject, docFunc: () => Document, removeFunc: (containingCollection: CollectionView) => void = () => { }) { - let onRowMove = action((e: PointerEvent): void => { - e.stopPropagation(); - e.preventDefault(); +export function setupDrag( + _reference: React.RefObject, + docFunc: () => Document, + removeFunc: (containingCollection: CollectionView) => void = () => {} +) { + let onRowMove = action( + (e: PointerEvent): void => { + e.stopPropagation(); + e.preventDefault(); - document.removeEventListener("pointermove", onRowMove); - document.removeEventListener('pointerup', onRowUp); - var dragData = new DragManager.DocumentDragData([docFunc()]); - dragData.removeDocument = removeFunc; - DragManager.StartDocumentDrag([_reference.current!], dragData); - }); - let onRowUp = action((e: PointerEvent): void => { - document.removeEventListener("pointermove", onRowMove); - document.removeEventListener('pointerup', onRowUp); - }); - let onItemDown = (e: React.PointerEvent) => { - // if (this.props.isSelected() || this.props.isTopMost) { - if (e.button == 0) { - e.stopPropagation(); - if (e.shiftKey) { - CollectionDockingView.Instance.StartOtherDrag([docFunc()], e); - } else { - document.addEventListener("pointermove", onRowMove); - document.addEventListener('pointerup', onRowUp); - } - } - //} + document.removeEventListener("pointermove", onRowMove); + document.removeEventListener("pointerup", onRowUp); + var dragData = new DragManager.DocumentDragData([docFunc()]); + dragData.removeDocument = removeFunc; + DragManager.StartDocumentDrag([_reference.current!], dragData); + } + ); + let onRowUp = action( + (e: PointerEvent): void => { + document.removeEventListener("pointermove", onRowMove); + document.removeEventListener("pointerup", onRowUp); + } + ); + let onItemDown = (e: React.PointerEvent) => { + // if (this.props.isSelected() || this.props.isTopMost) { + if (e.button == 0) { + e.stopPropagation(); + if (e.shiftKey) { + CollectionDockingView.Instance.StartOtherDrag([docFunc()], e); + } else { + document.addEventListener("pointermove", onRowMove); + document.addEventListener("pointerup", onRowUp); + } } - return onItemDown; + //} + }; + return onItemDown; } export namespace DragManager { - export function Root() { - const root = document.getElementById("root"); - if (!root) { - throw new Error("No root element found"); - } - return root; + export function Root() { + const root = document.getElementById("root"); + if (!root) { + throw new Error("No root element found"); } + return root; + } - let dragDiv: HTMLDivElement; + let dragDiv: HTMLDivElement; - export enum DragButtons { - Left = 1, Right = 2, Both = Left | Right - } + export enum DragButtons { + Left = 1, + Right = 2, + Both = Left | Right + } - interface DragOptions { - handlers: DragHandlers; + interface DragOptions { + handlers: DragHandlers; - hideSource: boolean | (() => boolean); - } + hideSource: boolean | (() => boolean); + } - export interface DragDropDisposer { - (): void; - } + export interface DragDropDisposer { + (): void; + } - export class DragCompleteEvent { - } + export class DragCompleteEvent {} - export interface DragHandlers { - dragComplete: (e: DragCompleteEvent) => void; - } + export interface DragHandlers { + dragComplete: (e: DragCompleteEvent) => void; + } - export interface DropOptions { - handlers: DropHandlers; - } - export class DropEvent { - constructor(readonly x: number, readonly y: number, readonly data: { [id: string]: any }) { } - } + export interface DropOptions { + handlers: DropHandlers; + } + export class DropEvent { + constructor( + readonly x: number, + readonly y: number, + readonly data: { [id: string]: any } + ) {} + } + export interface DropHandlers { + drop: (e: Event, de: DropEvent) => void; + } + export function MakeDropTarget( + element: HTMLElement, + options: DropOptions + ): DragDropDisposer { + if ("canDrop" in element.dataset) { + throw new Error( + "Element is already droppable, can't make it droppable again" + ); + } + element.dataset["canDrop"] = "true"; + const handler = (e: Event) => { + const ce = e as CustomEvent; + options.handlers.drop(e, ce.detail); + }; + element.addEventListener("dashOnDrop", handler); + return () => { + element.removeEventListener("dashOnDrop", handler); + delete element.dataset["canDrop"]; + }; + } - export interface DropHandlers { - drop: (e: Event, de: DropEvent) => void; + export class DocumentDragData { + constructor(dragDoc: Document[]) { + this.draggedDocuments = dragDoc; + this.droppedDocuments = dragDoc; } + draggedDocuments: Document[]; + droppedDocuments: Document[]; + xOffset?: number; + yOffset?: number; + aliasOnDrop?: boolean; + removeDocument?: (collectionDrop: CollectionView) => void; + [id: string]: any; + } + export function StartDocumentDrag( + eles: HTMLElement[], + dragData: DocumentDragData, + options?: DragOptions + ) { + StartDrag( + eles, + dragData, + options, + (dropData: { [id: string]: any }) => + (dropData.droppedDocuments = dragData.aliasOnDrop + ? dragData.draggedDocuments.map(d => d.CreateAlias()) + : dragData.draggedDocuments) + ); + } - export function MakeDropTarget(element: HTMLElement, options: DropOptions): DragDropDisposer { - if ("canDrop" in element.dataset) { - throw new Error("Element is already droppable, can't make it droppable again"); - } - element.dataset["canDrop"] = "true"; - const handler = (e: Event) => { - const ce = e as CustomEvent; - options.handlers.drop(e, ce.detail); - }; - element.addEventListener("dashOnDrop", handler); - return () => { - element.removeEventListener("dashOnDrop", handler); - delete element.dataset["canDrop"] - }; + export class LinkDragData { + constructor(linkSourceDoc: DocumentView) { + this.linkSourceDocumentView = linkSourceDoc; } - - export class DocumentDragData { - constructor(dragDoc: Document[]) { - this.draggedDocuments = dragDoc; - this.droppedDocuments = dragDoc; - } - draggedDocuments: Document[]; - droppedDocuments: Document[]; - xOffset?: number; - yOffset?: number; - aliasOnDrop?: boolean; - removeDocument?: (collectionDrop: CollectionView) => void; - [id: string]: any; + linkSourceDocumentView: DocumentView; + [id: string]: any; + } + export function StartLinkDrag( + ele: HTMLElement, + dragData: LinkDragData, + options?: DragOptions + ) { + StartDrag([ele], dragData, options); + } + function StartDrag( + eles: HTMLElement[], + dragData: { [id: string]: any }, + options?: DragOptions, + finishDrag?: (dropData: { [id: string]: any }) => void + ) { + if (!dragDiv) { + dragDiv = document.createElement("div"); + dragDiv.className = "dragManager-dragDiv"; + DragManager.Root().appendChild(dragDiv); } - export function StartDocumentDrag(eles: HTMLElement[], dragData: DocumentDragData, options?: DragOptions) { - StartDrag(eles, dragData, options, (dropData: { [id: string]: any }) => dropData.droppedDocuments = dragData.aliasOnDrop ? dragData.draggedDocuments.map(d => d.CreateAlias()) : dragData.draggedDocuments); - } + let scaleXs: number[] = []; + let scaleYs: number[] = []; + let xs: number[] = []; + let ys: number[] = []; - export class LinkDragData { - constructor(linkSourceDoc: DocumentView) { - this.linkSourceDocumentView = linkSourceDoc; - } - linkSourceDocumentView: DocumentView; - [id: string]: any; - } - export function StartLinkDrag(ele: HTMLElement, dragData: LinkDragData, options?: DragOptions) { - StartDrag([ele], dragData, options); - } - function StartDrag(eles: HTMLElement[], dragData: { [id: string]: any }, options?: DragOptions, finishDrag?: (dropData: { [id: string]: any }) => void) { - if (!dragDiv) { - dragDiv = document.createElement("div"); - dragDiv.className = "dragManager-dragDiv" - DragManager.Root().appendChild(dragDiv); + const docs: Document[] = + dragData instanceof DocumentDragData ? dragData.draggedDocuments : []; + let dragElements = eles.map(ele => { + const w = ele.offsetWidth, + h = ele.offsetHeight; + const rect = ele.getBoundingClientRect(); + const scaleX = rect.width / w, + scaleY = rect.height / h; + let x = rect.left, + y = rect.top; + xs.push(x); + ys.push(y); + scaleXs.push(scaleX); + scaleYs.push(scaleY); + let dragElement = ele.cloneNode(true) as HTMLElement; + dragElement.style.opacity = "0.7"; + console.log(dragElement); + dragElement.style.position = "absolute"; + dragElement.style.bottom = ""; + dragElement.style.left = ""; + dragElement.style.transformOrigin = "0 0"; + dragElement.style.zIndex = "1000"; + dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`; + dragElement.style.width = `${rect.width / scaleX}px`; + dragElement.style.height = `${rect.height / scaleY}px`; + + // bcz: PDFs don't show up if you clone them because they contain a canvas. + // however, PDF's have a thumbnail field that contains an image of their canvas. + // So we replace the pdf's canvas with the image thumbnail + if (docs.length) { + var pdfBox = dragElement.getElementsByClassName( + "pdfBox-cont" + )[0] as HTMLElement; + let thumbnail = docs[0].GetT(KeyStore.Thumbnail, ImageField); + if (pdfBox && pdfBox.childElementCount && thumbnail) { + let img = new Image(); + img!.src = thumbnail.toString(); + img!.style.position = "absolute"; + img!.style.width = `${rect.width / scaleX}px`; + img!.style.height = `${rect.height / scaleY}px`; + pdfBox.replaceChild(img!, pdfBox.children[0]); } + } - let scaleXs: number[] = []; - let scaleYs: number[] = []; - let xs: number[] = []; - let ys: number[] = []; - - const docs: Document[] = dragData instanceof DocumentDragData ? dragData.draggedDocuments : []; - let dragElements = eles.map(ele => { - const w = ele.offsetWidth, h = ele.offsetHeight; - const rect = ele.getBoundingClientRect(); - const scaleX = rect.width / w, scaleY = rect.height / h; - let x = rect.left, y = rect.top; - xs.push(x); ys.push(y); - scaleXs.push(scaleX); scaleYs.push(scaleY); - let dragElement = ele.cloneNode(true) as HTMLElement; - dragElement.style.opacity = "0.7"; - dragElement.style.position = "absolute"; - dragElement.style.bottom = ""; - dragElement.style.left = ""; - dragElement.style.transformOrigin = "0 0"; - dragElement.style.zIndex = "1000"; - dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`; - dragElement.style.width = `${rect.width / scaleX}px`; - dragElement.style.height = `${rect.height / scaleY}px`; - - // bcz: PDFs don't show up if you clone them because they contain a canvas. - // however, PDF's have a thumbnail field that contains an image of their canvas. - // So we replace the pdf's canvas with the image thumbnail - if (docs.length) { - var pdfBox = dragElement.getElementsByClassName("pdfBox-cont")[0] as HTMLElement; - let thumbnail = docs[0].GetT(KeyStore.Thumbnail, ImageField); - if (pdfBox && pdfBox.childElementCount && thumbnail) { - let img = new Image(); - img!.src = thumbnail.toString(); - img!.style.position = "absolute"; - img!.style.width = `${rect.width / scaleX}px`; - img!.style.height = `${rect.height / scaleY}px`; - pdfBox.replaceChild(img!, pdfBox.children[0]) - } - } - - dragDiv.appendChild(dragElement); - return dragElement; - }); + dragDiv.appendChild(dragElement); + return dragElement; + }); - let hideSource = false; - if (options) { - if (typeof options.hideSource === "boolean") { - hideSource = options.hideSource; - } else { - hideSource = options.hideSource(); - } - } - eles.map(ele => ele.hidden = hideSource); - - const moveHandler = (e: PointerEvent) => { - e.stopPropagation(); - e.preventDefault(); - if (dragData instanceof DocumentDragData) - dragData.aliasOnDrop = e.ctrlKey || e.altKey; - if (e.shiftKey) { - abortDrag(); - CollectionDockingView.Instance.StartOtherDrag(docs, { pageX: e.pageX, pageY: e.pageY, preventDefault: () => { }, button: 0 }); - } - dragElements.map((dragElement, i) => dragElement.style.transform = `translate(${xs[i] += e.movementX}px, ${ys[i] += e.movementY}px) scale(${scaleXs[i]}, ${scaleYs[i]})`); - }; - - const abortDrag = () => { - document.removeEventListener("pointermove", moveHandler, true); - document.removeEventListener("pointerup", upHandler); - dragElements.map(dragElement => dragDiv.removeChild(dragElement)); - eles.map(ele => ele.hidden = false); - } - const upHandler = (e: PointerEvent) => { - abortDrag(); - FinishDrag(eles, e, dragData, options, finishDrag); - }; - document.addEventListener("pointermove", moveHandler, true); - document.addEventListener("pointerup", upHandler); + let hideSource = false; + if (options) { + if (typeof options.hideSource === "boolean") { + hideSource = options.hideSource; + } else { + hideSource = options.hideSource(); + } } + eles.map(ele => (ele.hidden = hideSource)); - function FinishDrag(dragEles: HTMLElement[], e: PointerEvent, dragData: { [index: string]: any }, options?: DragOptions, finishDrag?: (dragData: { [index: string]: any }) => void) { - let removed = dragEles.map(dragEle => { - let parent = dragEle.parentElement; - if (parent) - parent.removeChild(dragEle); - return [dragEle, parent]; - }); - const target = document.elementFromPoint(e.x, e.y); - removed.map(r => { - let dragEle: HTMLElement = r[0]!; - let parent: HTMLElement | null = r[1]; - if (parent) - parent.appendChild(dragEle); + const moveHandler = (e: PointerEvent) => { + e.stopPropagation(); + e.preventDefault(); + if (dragData instanceof DocumentDragData) + dragData.aliasOnDrop = e.ctrlKey || e.altKey; + if (e.shiftKey) { + abortDrag(); + CollectionDockingView.Instance.StartOtherDrag(docs, { + pageX: e.pageX, + pageY: e.pageY, + preventDefault: () => {}, + button: 0 }); - if (target) { - if (finishDrag) - finishDrag(dragData); - - target.dispatchEvent(new CustomEvent("dashOnDrop", { - bubbles: true, - detail: { - x: e.x, - y: e.y, - data: dragData - } - })); - - if (options) { - options.handlers.dragComplete({}); - } - } - DocumentDecorations.Instance.Hidden = false; + } + dragElements.map( + (dragElement, i) => + (dragElement.style.transform = `translate(${(xs[i] += + e.movementX)}px, ${(ys[i] += e.movementY)}px) scale(${ + scaleXs[i] + }, ${scaleYs[i]})`) + ); + }; + + const abortDrag = () => { + document.removeEventListener("pointermove", moveHandler, true); + document.removeEventListener("pointerup", upHandler); + dragElements.map(dragElement => dragDiv.removeChild(dragElement)); + eles.map(ele => (ele.hidden = false)); + }; + const upHandler = (e: PointerEvent) => { + abortDrag(); + FinishDrag(eles, e, dragData, options, finishDrag); + }; + document.addEventListener("pointermove", moveHandler, true); + document.addEventListener("pointerup", upHandler); + } + + function FinishDrag( + dragEles: HTMLElement[], + e: PointerEvent, + dragData: { [index: string]: any }, + options?: DragOptions, + finishDrag?: (dragData: { [index: string]: any }) => void + ) { + let removed = dragEles.map(dragEle => { + let parent = dragEle.parentElement; + if (parent) parent.removeChild(dragEle); + return [dragEle, parent]; + }); + const target = document.elementFromPoint(e.x, e.y); + removed.map(r => { + let dragEle: HTMLElement = r[0]!; + let parent: HTMLElement | null = r[1]; + if (parent) parent.appendChild(dragEle); + }); + if (target) { + if (finishDrag) finishDrag(dragData); + + target.dispatchEvent( + new CustomEvent("dashOnDrop", { + bubbles: true, + detail: { + x: e.x, + y: e.y, + data: dragData + } + }) + ); + + if (options) { + options.handlers.dragComplete({}); + } } -} \ No newline at end of file + DocumentDecorations.Instance.Hidden = false; + } +} diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss index 7a43f3087..8f5470574 100644 --- a/src/client/views/DocumentDecorations.scss +++ b/src/client/views/DocumentDecorations.scss @@ -1,4 +1,5 @@ @import "global_variables"; + #documentDecorations-container { position: absolute; display: grid; @@ -6,26 +7,32 @@ grid-template-rows: 8px 1fr 8px 30px; grid-template-columns: 8px 1fr 8px; pointer-events: none; + #documentDecorations-centerCont { background: none; } + .documentDecorations-resizer { pointer-events: auto; background: $alt-accent; opacity: 0.8; } + #documentDecorations-topLeftResizer, #documentDecorations-bottomRightResizer { cursor: nwse-resize; } + #documentDecorations-topRightResizer, #documentDecorations-bottomLeftResizer { cursor: nesw-resize; } + #documentDecorations-topResizer, #documentDecorations-bottomResizer { cursor: ns-resize; } + #documentDecorations-leftResizer, #documentDecorations-rightResizer { cursor: ew-resize; @@ -33,7 +40,7 @@ } .documentDecorations-background { - background:lightblue; + background: lightblue; position: absolute; opacity: 0.1; } diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss index 4eda50204..23e072344 100644 --- a/src/client/views/nodes/DocumentView.scss +++ b/src/client/views/nodes/DocumentView.scss @@ -30,10 +30,12 @@ height: 10px; width: 10px; border-radius: 2px; - background: #232323 + background: $dark-color } .minimized-box:hover { - background: #232323 + background: $main-accent; + transform: scale(1.15); + cursor: pointer; } } \ No newline at end of file diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 085307461..713c12975 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -7,7 +7,6 @@ import { observable } from "mobx"; import { library } from "@fortawesome/fontawesome-svg-core"; -import { faSquare } from "@fortawesome/free-solid-svg-icons"; import { observer } from "mobx-react"; import { Document } from "../../../fields/Document"; import { Field, Opt, FieldWaiting } from "../../../fields/Field"; @@ -33,8 +32,6 @@ import React = require("react"); import { ServerUtils } from "../../../server/ServerUtil"; import { DocumentDecorations } from "../DocumentDecorations"; -library.add(faSquare); - export interface DocumentViewProps { ContainingCollectionView: Opt; Document: Document; @@ -438,6 +435,11 @@ export class DocumentView extends React.Component { return this.minimized; }; + @action + expand = () => { + this.minimized = false; + }; + isSelected = () => { return SelectionManager.IsSelected(this); }; @@ -450,18 +452,26 @@ export class DocumentView extends React.Component { if (!this.props.Document) { return null; } + + var scaling = this.props.ContentScaling(); + var nativeWidth = this.props.Document.GetNumber(KeyStore.NativeWidth, 0); + var nativeHeight = this.props.Document.GetNumber(KeyStore.NativeHeight, 0); + if (this.minimized) { return ( - // -
+
); } else { - var scaling = this.props.ContentScaling(); - var nativeWidth = this.props.Document.GetNumber(KeyStore.NativeWidth, 0); - var nativeHeight = this.props.Document.GetNumber( - KeyStore.NativeHeight, - 0 - ); var backgroundcolor = this.props.Document.GetText( KeyStore.BackgroundColor, "" diff --git a/src/client/views/nodes/Sticky.tsx b/src/client/views/nodes/Sticky.tsx index d57dd5c0b..4a4d69e90 100644 --- a/src/client/views/nodes/Sticky.tsx +++ b/src/client/views/nodes/Sticky.tsx @@ -1,83 +1,83 @@ -import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app -import React = require("react") -import { observer } from "mobx-react" -import 'react-pdf/dist/Page/AnnotationLayer.css' +import "react-image-lightbox/style.css"; // This only needs to be imported once in your app +import React = require("react"); +import { observer } from "mobx-react"; +import "react-pdf/dist/Page/AnnotationLayer.css"; interface IProps { - Height: number; - Width: number; - X: number; - Y: number; + Height: number; + Width: number; + X: number; + Y: number; } /** - * Sticky, also known as area highlighting, is used to highlight large selection of the PDF file. - * Improvements that could be made: maybe store line array and store that somewhere for future rerendering. - * - * Written By: Andrew Kim + * Sticky, also known as area highlighting, is used to highlight large selection of the PDF file. + * Improvements that could be made: maybe store line array and store that somewhere for future rerendering. + * + * Written By: Andrew Kim */ @observer export class Sticky extends React.Component { + private initX: number = 0; + private initY: number = 0; - private initX: number = 0; - private initY: number = 0; + private _ref = React.createRef(); + private ctx: any; //context that keeps track of sticky canvas - private _ref = React.createRef(); - private ctx: any; //context that keeps track of sticky canvas - - /** - * drawing. Registers the first point that user clicks when mouse button is pressed down on canvas - */ - drawDown = (e: React.PointerEvent) => { - if (this._ref.current) { - this.ctx = this._ref.current.getContext("2d"); - let mouse = e.nativeEvent; - this.initX = mouse.offsetX; - this.initY = mouse.offsetY; - this.ctx.beginPath(); - this.ctx.lineTo(this.initX, this.initY); - this.ctx.strokeStyle = "black"; - document.addEventListener("pointermove", this.drawMove); - document.addEventListener("pointerup", this.drawUp); - } + /** + * drawing. Registers the first point that user clicks when mouse button is pressed down on canvas + */ + drawDown = (e: React.PointerEvent) => { + if (this._ref.current) { + this.ctx = this._ref.current.getContext("2d"); + let mouse = e.nativeEvent; + this.initX = mouse.offsetX; + this.initY = mouse.offsetY; + this.ctx.beginPath(); + this.ctx.lineTo(this.initX, this.initY); + this.ctx.strokeStyle = "black"; + document.addEventListener("pointermove", this.drawMove); + document.addEventListener("pointerup", this.drawUp); } + }; - //when user drags - drawMove = (e: PointerEvent): void => { - //x and y mouse movement - let x = this.initX += e.movementX, - y = this.initY += e.movementY; - //connects the point - this.ctx.lineTo(x, y); - this.ctx.stroke(); - - } + //when user drags + drawMove = (e: PointerEvent): void => { + //x and y mouse movement + let x = (this.initX += e.movementX), + y = (this.initY += e.movementY); + //connects the point + this.ctx.lineTo(x, y); + this.ctx.stroke(); + }; - /** - * when user lifts the mouse, the drawing ends - */ - drawUp = (e: PointerEvent) => { - this.ctx.closePath(); - console.log(this.ctx); - document.removeEventListener("pointermove", this.drawMove); - } + /** + * when user lifts the mouse, the drawing ends + */ + drawUp = (e: PointerEvent) => { + this.ctx.closePath(); + console.log(this.ctx); + document.removeEventListener("pointermove", this.drawMove); + }; - render() { - return ( -
- - -
- ); - } -} \ No newline at end of file + render() { + return ( +
+ +
+ ); + } +} -- cgit v1.2.3-70-g09d2 From dd9d087b62545a7a57ea2651eace72f851127623 Mon Sep 17 00:00:00 2001 From: Monika Hedman Date: Tue, 2 Apr 2019 16:51:08 -0400 Subject: drag working --- src/client/views/nodes/DocumentView.scss | 22 +++++++++++----------- src/client/views/nodes/DocumentView.tsx | 10 ++++++---- 2 files changed, 17 insertions(+), 15 deletions(-) (limited to 'src/client/views/nodes/DocumentView.tsx') diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss index 23e072344..127a6b535 100644 --- a/src/client/views/nodes/DocumentView.scss +++ b/src/client/views/nodes/DocumentView.scss @@ -25,17 +25,17 @@ overflow-y: scroll; height: calc(100% - 20px); } +} - .minimized-box { - height: 10px; - width: 10px; - border-radius: 2px; - background: $dark-color - } +.minimized-box { + height: 10px; + width: 10px; + border-radius: 2px; + background: $dark-color +} - .minimized-box:hover { - background: $main-accent; - transform: scale(1.15); - cursor: pointer; - } +.minimized-box:hover { + background: $main-accent; + transform: scale(1.15); + cursor: pointer; } \ No newline at end of file diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 713c12975..c4f329357 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -383,10 +383,12 @@ export class DocumentView extends React.Component { e.preventDefault(); //for testing purposes - ContextMenu.Instance.addItem({ - description: "Minimize", - event: this.minimize - }); + if (!this.minimized) { + ContextMenu.Instance.addItem({ + description: "Minimize", + event: this.minimize + }); + } ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked -- cgit v1.2.3-70-g09d2 From 36019dc66ae66bac01118ed05bdb5c6466f9bdc8 Mon Sep 17 00:00:00 2001 From: Monika Hedman Date: Tue, 2 Apr 2019 18:05:56 -0400 Subject: done with minimize to box --- src/client/util/DragManager.ts | 1 - src/client/views/nodes/DocumentView.tsx | 35 +++++-- src/fields/Document.ts | 5 + src/fields/KeyStore.ts | 90 ++++++++--------- src/fields/MinimizedField.tsx | 29 ++++++ src/server/Message.ts | 168 ++++++++++++++++++-------------- src/server/ServerUtil.ts | 151 ++++++++++++++-------------- 7 files changed, 282 insertions(+), 197 deletions(-) create mode 100644 src/fields/MinimizedField.tsx (limited to 'src/client/views/nodes/DocumentView.tsx') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index ee0b5333c..c0f482e18 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -192,7 +192,6 @@ export namespace DragManager { scaleYs.push(scaleY); let dragElement = ele.cloneNode(true) as HTMLElement; dragElement.style.opacity = "0.7"; - console.log(dragElement); dragElement.style.position = "absolute"; dragElement.style.bottom = ""; dragElement.style.left = ""; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index c4f329357..05058e63d 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -31,6 +31,7 @@ import "./DocumentView.scss"; import React = require("react"); import { ServerUtils } from "../../../server/ServerUtil"; import { DocumentDecorations } from "../DocumentDecorations"; +import { MinimizedField } from "../../../fields/MinimizedField"; export interface DocumentViewProps { ContainingCollectionView: Opt; @@ -102,8 +103,15 @@ export class DocumentView extends React.Component { private _downX: number = 0; private _downY: number = 0; + // @observable + // private minimized: boolean = false; + @observable - private minimized: boolean = false; + private _minimized: boolean = this.props.Document.GetData( + KeyStore.Minimized, + MinimizedField, + false as boolean + ); private _reactionDisposer: Opt; @computed get active(): boolean { @@ -310,7 +318,13 @@ export class DocumentView extends React.Component { @action minimize = (e: React.MouseEvent): void => { - this.minimized = true; + //hopefully sets field? + this._minimized = true as boolean; + this.props.Document.SetData( + KeyStore.Minimized, + true as boolean, + MinimizedField + ); SelectionManager.DeselectAll(); }; @@ -383,7 +397,7 @@ export class DocumentView extends React.Component { e.preventDefault(); //for testing purposes - if (!this.minimized) { + if (!this.isMinimized()) { ContextMenu.Instance.addItem({ description: "Minimize", event: this.minimize @@ -434,12 +448,21 @@ export class DocumentView extends React.Component { }; isMinimized = () => { - return this.minimized; + let field = this.props.Document.GetT(KeyStore.Minimized, MinimizedField); + if (field && field !== FieldWaiting) { + return field.Data; + } + //return this.minimized; }; @action expand = () => { - this.minimized = false; + //this._minimized = false; + this.props.Document.SetData( + KeyStore.Minimized, + false as boolean, + MinimizedField + ); }; isSelected = () => { @@ -459,7 +482,7 @@ export class DocumentView extends React.Component { var nativeWidth = this.props.Document.GetNumber(KeyStore.NativeWidth, 0); var nativeHeight = this.props.Document.GetNumber(KeyStore.NativeHeight, 0); - if (this.minimized) { + if (this.isMinimized()) { return (
{ + constructor( + data: boolean = false as boolean, + id?: FieldId, + save: boolean = true as boolean + ) { + super(data, save, id); + } + + ToScriptString(): string { + return `new MinimizedField("${this.Data}")`; + } + + Copy() { + return new MinimizedField(this.Data); + } + + ToJson(): { type: Types; data: boolean; _id: string } { + return { + type: Types.Minimized, + data: this.Data, + _id: this.Id + }; + } +} diff --git a/src/server/Message.ts b/src/server/Message.ts index 05ae0f19a..29df57419 100644 --- a/src/server/Message.ts +++ b/src/server/Message.ts @@ -1,125 +1,145 @@ import { Utils } from "../Utils"; export class Message { - private name: string; - private guid: string; + private name: string; + private guid: string; - get Name(): string { - return this.name; - } + get Name(): string { + return this.name; + } - get Message(): string { - return this.guid - } + get Message(): string { + return this.guid; + } - constructor(name: string) { - this.name = name; - this.guid = Utils.GenerateDeterministicGuid(name) - } + constructor(name: string) { + this.name = name; + this.guid = Utils.GenerateDeterministicGuid(name); + } - GetValue() { - return this.Name; - } + GetValue() { + return this.Name; + } } class TestMessageArgs { - hello: string = ""; + hello: string = ""; } export class SetFieldArgs { - field: string; - value: any; + field: string; + value: any; - constructor(f: string, v: any) { - this.field = f - this.value = v - } + constructor(f: string, v: any) { + this.field = f; + this.value = v; + } } export class GetFieldArgs { - field: string; + field: string; - constructor(f: string) { - this.field = f - } + constructor(f: string) { + this.field = f; + } } export enum Types { - Number, List, Key, Image, Web, Document, Text, RichText, DocumentReference, Html, Video, Audio, Ink, PDF, Tuple, HistogramOp + Number, + List, + Key, + Image, + Web, + Document, + Text, + RichText, + DocumentReference, + Html, + Video, + Audio, + Ink, + PDF, + Tuple, + HistogramOp, + Minimized } export class DocumentTransfer implements Transferable { - readonly type = Types.Document - _id: string - - constructor(readonly obj: { type: Types, data: [string, string][], _id: string }) { - this._id = obj._id - } + readonly type = Types.Document; + _id: string; + + constructor( + readonly obj: { type: Types; data: [string, string][]; _id: string } + ) { + this._id = obj._id; + } } export class ImageTransfer implements Transferable { - readonly type = Types.Image + readonly type = Types.Image; - constructor(readonly _id: string) { } + constructor(readonly _id: string) {} } export class KeyTransfer implements Transferable { - name: string - readonly _id: string - readonly type = Types.Key - - constructor(i: string, n: string) { - this.name = n - this._id = i - } + name: string; + readonly _id: string; + readonly type = Types.Key; + + constructor(i: string, n: string) { + this.name = n; + this._id = i; + } } export class ListTransfer implements Transferable { - type = Types.List; + type = Types.List; - constructor(readonly _id: string) { } + constructor(readonly _id: string) {} } export class NumberTransfer implements Transferable { - readonly type = Types.Number + readonly type = Types.Number; - constructor(readonly value: number, readonly _id: string) { } + constructor(readonly value: number, readonly _id: string) {} } export class TextTransfer implements Transferable { - value: string - readonly _id: string - readonly type = Types.Text - - constructor(t: string, i: string) { - this.value = t - this._id = i - } + value: string; + readonly _id: string; + readonly type = Types.Text; + + constructor(t: string, i: string) { + this.value = t; + this._id = i; + } } export class RichTextTransfer implements Transferable { - value: string - readonly _id: string - readonly type = Types.Text - - constructor(t: string, i: string) { - this.value = t - this._id = i - } + value: string; + readonly _id: string; + readonly type = Types.Text; + + constructor(t: string, i: string) { + this.value = t; + this._id = i; + } } export interface Transferable { - readonly _id: string - readonly type: Types + readonly _id: string; + readonly type: Types; } export namespace MessageStore { - export const Foo = new Message("Foo"); - export const Bar = new Message("Bar"); - export const AddDocument = new Message("Add Document"); - export const SetField = new Message<{ _id: string, data: any, type: Types }>("Set Field") - export const GetField = new Message("Get Field") - export const GetFields = new Message("Get Fields") - export const GetDocument = new Message("Get Document"); - export const DeleteAll = new Message("Delete All"); -} \ No newline at end of file + export const Foo = new Message("Foo"); + export const Bar = new Message("Bar"); + export const AddDocument = new Message("Add Document"); + export const SetField = new Message<{ _id: string; data: any; type: Types }>( + "Set Field" + ); + export const GetField = new Message("Get Field"); + export const GetFields = new Message("Get Fields"); + export const GetDocument = new Message("Get Document"); + export const DeleteAll = new Message("Delete All"); +} diff --git a/src/server/ServerUtil.ts b/src/server/ServerUtil.ts index 98a7a1451..3e24fed3a 100644 --- a/src/server/ServerUtil.ts +++ b/src/server/ServerUtil.ts @@ -1,78 +1,85 @@ - -import { Field } from './../fields/Field'; -import { TextField } from './../fields/TextField'; -import { NumberField } from './../fields/NumberField'; -import { RichTextField } from './../fields/RichTextField'; -import { Key } from './../fields/Key'; -import { ImageField } from './../fields/ImageField'; -import { ListField } from './../fields/ListField'; -import { Document } from './../fields/Document'; -import { Server } from './../client/Server'; -import { Types } from './Message'; -import { Utils } from '../Utils'; -import { HtmlField } from '../fields/HtmlField'; -import { WebField } from '../fields/WebField'; -import { AudioField } from '../fields/AudioField'; -import { VideoField } from '../fields/VideoField'; -import { InkField } from '../fields/InkField'; -import { PDFField } from '../fields/PDFField'; -import { TupleField } from '../fields/TupleField'; -import { HistogramField } from '../client/northstar/dash-fields/HistogramField'; - - +import { Field } from "./../fields/Field"; +import { TextField } from "./../fields/TextField"; +import { NumberField } from "./../fields/NumberField"; +import { RichTextField } from "./../fields/RichTextField"; +import { Key } from "./../fields/Key"; +import { ImageField } from "./../fields/ImageField"; +import { ListField } from "./../fields/ListField"; +import { Document } from "./../fields/Document"; +import { Server } from "./../client/Server"; +import { Types } from "./Message"; +import { Utils } from "../Utils"; +import { HtmlField } from "../fields/HtmlField"; +import { WebField } from "../fields/WebField"; +import { AudioField } from "../fields/AudioField"; +import { VideoField } from "../fields/VideoField"; +import { InkField } from "../fields/InkField"; +import { PDFField } from "../fields/PDFField"; +import { TupleField } from "../fields/TupleField"; +import { MinimizedField } from "../fields/MinimizedField"; +import { HistogramField } from "../client/northstar/dash-fields/HistogramField"; export class ServerUtils { - public static prepend(extension: string): string { return window.location.origin + extension; } + public static prepend(extension: string): string { + return window.location.origin + extension; + } - public static FromJson(json: any): Field { - let obj = json - let data: any = obj.data - let id: string = obj._id - let type: Types = obj.type + public static FromJson(json: any): Field { + let obj = json; + let data: any = obj.data; + let id: string = obj._id; + let type: Types = obj.type; - if (!(data !== undefined && id && type !== undefined)) { - console.log("how did you manage to get an object that doesn't have a data or an id?") - return new TextField("Something to fill the space", Utils.GenerateGuid()); - } + if (!(data !== undefined && id && type !== undefined)) { + console.log( + "how did you manage to get an object that doesn't have a data or an id?" + ); + return new TextField("Something to fill the space", Utils.GenerateGuid()); + } - switch (type) { - case Types.Number: - return new NumberField(data, id, false) - case Types.Text: - return new TextField(data, id, false) - case Types.Html: - return new HtmlField(data, id, false) - case Types.Web: - return new WebField(new URL(data), id, false) - case Types.RichText: - return new RichTextField(data, id, false) - case Types.Key: - return new Key(data, id, false) - case Types.Image: - return new ImageField(new URL(data), id, false) - case Types.HistogramOp: - return HistogramField.FromJson(id, data); - case Types.PDF: - return new PDFField(new URL(data), id, false) - case Types.List: - return ListField.FromJson(id, data) - case Types.Audio: - return new AudioField(new URL(data), id, false) - case Types.Video: - return new VideoField(new URL(data), id, false) - case Types.Tuple: - return new TupleField(data, id, false); - case Types.Ink: - return InkField.FromJson(id, data); - case Types.Document: - let doc: Document = new Document(id, false) - let fields: [string, string][] = data as [string, string][] - fields.forEach(element => { - doc._proxies.set(element[0], element[1]); - }); - return doc - default: - throw Error("Error, unrecognized field type received from server. If you just created a new field type, be sure to add it here"); - } + switch (type) { + case Types.Minimized: + return new MinimizedField(data, id, false); + case Types.Number: + return new NumberField(data, id, false); + case Types.Text: + return new TextField(data, id, false); + case Types.Html: + return new HtmlField(data, id, false); + case Types.Web: + console.log("LOOK HERE! " + data); + return new WebField(new URL(data), id, false); + case Types.RichText: + return new RichTextField(data, id, false); + case Types.Key: + return new Key(data, id, false); + case Types.Image: + return new ImageField(new URL(data), id, false); + case Types.HistogramOp: + return HistogramField.FromJson(id, data); + case Types.PDF: + return new PDFField(new URL(data), id, false); + case Types.List: + return ListField.FromJson(id, data); + case Types.Audio: + return new AudioField(new URL(data), id, false); + case Types.Video: + return new VideoField(new URL(data), id, false); + case Types.Tuple: + return new TupleField(data, id, false); + case Types.Ink: + return InkField.FromJson(id, data); + case Types.Document: + let doc: Document = new Document(id, false); + let fields: [string, string][] = data as [string, string][]; + fields.forEach(element => { + doc._proxies.set(element[0], element[1]); + }); + return doc; + default: + throw Error( + "Error, unrecognized field type received from server. If you just created a new field type, be sure to add it here" + ); } -} \ No newline at end of file + } +} -- cgit v1.2.3-70-g09d2 From fb5a34562b6855f3c9695e556497203577129a6d Mon Sep 17 00:00:00 2001 From: Monika Hedman Date: Tue, 2 Apr 2019 18:10:56 -0400 Subject: clean up 2 --- src/client/views/nodes/DocumentView.tsx | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'src/client/views/nodes/DocumentView.tsx') diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 05058e63d..2b9372e15 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -103,16 +103,6 @@ export class DocumentView extends React.Component { private _downX: number = 0; private _downY: number = 0; - // @observable - // private minimized: boolean = false; - - @observable - private _minimized: boolean = this.props.Document.GetData( - KeyStore.Minimized, - MinimizedField, - false as boolean - ); - private _reactionDisposer: Opt; @computed get active(): boolean { return ( @@ -318,8 +308,6 @@ export class DocumentView extends React.Component { @action minimize = (e: React.MouseEvent): void => { - //hopefully sets field? - this._minimized = true as boolean; this.props.Document.SetData( KeyStore.Minimized, true as boolean, @@ -396,7 +384,6 @@ export class DocumentView extends React.Component { } e.preventDefault(); - //for testing purposes if (!this.isMinimized()) { ContextMenu.Instance.addItem({ description: "Minimize", @@ -452,12 +439,10 @@ export class DocumentView extends React.Component { if (field && field !== FieldWaiting) { return field.Data; } - //return this.minimized; }; @action expand = () => { - //this._minimized = false; this.props.Document.SetData( KeyStore.Minimized, false as boolean, -- cgit v1.2.3-70-g09d2 From 3b456da9c1d90abcfcf33fc6fd762cad1dff7ca7 Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 3 Apr 2019 12:10:31 -0400 Subject: merged with changes to DocumentDecorations so you can minimize/maximize without menu --- src/client/views/DocumentDecorations.scss | 6 +++++- src/client/views/DocumentDecorations.tsx | 25 ++++++++++++++++++++++++- src/client/views/nodes/DocumentView.tsx | 14 +++++++------- 3 files changed, 36 insertions(+), 9 deletions(-) (limited to 'src/client/views/nodes/DocumentView.tsx') diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss index c72623546..befe175b5 100644 --- a/src/client/views/DocumentDecorations.scss +++ b/src/client/views/DocumentDecorations.scss @@ -39,12 +39,16 @@ } .title{ background: lightblue; - grid-column-start:1; + grid-column-start:2; grid-column-end: 4; pointer-events: auto; } } +.documentDecorations-minimizeButton { + background: rgb(250, 57, 9); + pointer-events: all; +} .documentDecorations-background { background: lightblue; position: absolute; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 572c265f3..b74737ec9 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -139,11 +139,33 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> e.preventDefault(); } + onMinimizeDown = (e: React.PointerEvent): void => { + e.stopPropagation(); + if (e.button === 0) { + document.removeEventListener("pointermove", this.onMinimizeMove); + document.addEventListener("pointermove", this.onMinimizeMove); + document.removeEventListener("pointerup", this.onMinimizeUp); + document.addEventListener("pointerup", this.onMinimizeUp); + } + } + onMinimizeMove = (e: PointerEvent): void => { + e.stopPropagation(); + if (e.button === 0) { + } + } + onMinimizeUp = (e: PointerEvent): void => { + e.stopPropagation(); + if (e.button === 0) { + SelectionManager.SelectedDocuments().map(dv => dv.minimize()); + document.removeEventListener("pointermove", this.onMinimizeMove); + document.removeEventListener("pointerup", this.onMinimizeUp); + } + } + onPointerDown = (e: React.PointerEvent): void => { e.stopPropagation(); if (e.button === 0) { this._isPointerDown = true; - console.log("Pointer down"); this._resizer = e.currentTarget.id; document.removeEventListener("pointermove", this.onPointerMove); document.addEventListener("pointermove", this.onPointerMove); @@ -339,6 +361,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> top: bounds.y - this._resizeBorderWidth / 2 - this._titleHeight, opacity: this._opacity }}> +
v
e.preventDefault()}>
e.preventDefault()}>
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 2b9372e15..bc627015c 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -70,18 +70,18 @@ export function FakeJsxArgs(keys: string[], fields: string[] = []): JsxArgs { let Keys: { [name: string]: any } = {}; let Fields: { [name: string]: any } = {}; for (const key of keys) { - let fn = () => {}; + let fn = () => { }; Object.defineProperty(fn, "name", { value: key + "Key" }); Keys[key] = fn; } for (const field of fields) { - let fn = () => {}; + let fn = () => { }; Object.defineProperty(fn, "name", { value: field }); Fields[field] = fn; } let args: JsxArgs = { - Document: function Document() {}, - DocumentView: function DocumentView() {}, + Document: function Document() { }, + DocumentView: function DocumentView() { }, Keys, Fields } as any; @@ -115,7 +115,7 @@ export class DocumentView extends React.Component { return ( !this.props.ContainingCollectionView || this.props.ContainingCollectionView.collectionViewType == - CollectionViewType.Docking + CollectionViewType.Docking ); } @computed get layout(): string { @@ -233,7 +233,7 @@ export class DocumentView extends React.Component { }; DragManager.StartDocumentDrag([this._mainCont.current], dragData, { handlers: { - dragComplete: action(() => {}) + dragComplete: action(() => { }) }, hideSource: !dropAliasOfDraggedDoc }); @@ -307,7 +307,7 @@ export class DocumentView extends React.Component { }; @action - minimize = (e: React.MouseEvent): void => { + public minimize = (): void => { this.props.Document.SetData( KeyStore.Minimized, true as boolean, -- cgit v1.2.3-70-g09d2 From 52dade42e61a1d147bf43ece7f2b1d7b3d7b6b6a Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 3 Apr 2019 16:12:31 -0400 Subject: changed boolean. and editor indentation. --- .vscode/settings.json | 3 +- src/client/views/nodes/DocumentView.tsx | 854 ++++++++++----------- src/fields/BooleanField.ts | 25 + src/fields/MinimizedField.tsx | 29 - src/server/ServerUtil.ts | 116 +-- src/server/database.ts | 10 +- .../upload_a6a70d84ebb65febf7900e29f52cc86d.pdf | Bin 0 -> 1043556 bytes 7 files changed, 509 insertions(+), 528 deletions(-) create mode 100644 src/fields/BooleanField.ts delete mode 100644 src/fields/MinimizedField.tsx create mode 100644 src/server/public/files/upload_a6a70d84ebb65febf7900e29f52cc86d.pdf (limited to 'src/client/views/nodes/DocumentView.tsx') diff --git a/.vscode/settings.json b/.vscode/settings.json index 081b05b38..fc315ffaf 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,6 +7,7 @@ "**/.DS_Store": true, }, "editor.formatOnSave": true, + "editor.detectIndentation": false, "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true -} +} \ No newline at end of file diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index bc627015c..714ab9447 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1,19 +1,13 @@ -import { - action, - computed, - IReactionDisposer, - reaction, - runInAction, - observable -} from "mobx"; -import { library } from "@fortawesome/fontawesome-svg-core"; +import { action, computed, IReactionDisposer, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; import { Document } from "../../../fields/Document"; -import { Field, Opt, FieldWaiting } from "../../../fields/Field"; +import { Field, FieldWaiting, Opt } from "../../../fields/Field"; import { Key } from "../../../fields/Key"; import { KeyStore } from "../../../fields/KeyStore"; import { ListField } from "../../../fields/ListField"; +import { BooleanField } from "../../../fields/BooleanField"; import { TextField } from "../../../fields/TextField"; +import { ServerUtils } from "../../../server/ServerUtil"; import { Utils } from "../../../Utils"; import { Documents } from "../../documents/Documents"; import { DocumentManager } from "../../util/DocumentManager"; @@ -21,34 +15,28 @@ import { DragManager } from "../../util/DragManager"; import { SelectionManager } from "../../util/SelectionManager"; import { Transform } from "../../util/Transform"; import { CollectionDockingView } from "../collections/CollectionDockingView"; -import { - CollectionView, - CollectionViewType -} from "../collections/CollectionView"; +import { CollectionView, CollectionViewType } from "../collections/CollectionView"; import { ContextMenu } from "../ContextMenu"; import { DocumentContentsView } from "./DocumentContentsView"; import "./DocumentView.scss"; import React = require("react"); -import { ServerUtils } from "../../../server/ServerUtil"; -import { DocumentDecorations } from "../DocumentDecorations"; -import { MinimizedField } from "../../../fields/MinimizedField"; export interface DocumentViewProps { - ContainingCollectionView: Opt; - Document: Document; - AddDocument?: (doc: Document, allowDuplicates: boolean) => boolean; - RemoveDocument?: (doc: Document) => boolean; - ScreenToLocalTransform: () => Transform; - isTopMost: boolean; - ContentScaling: () => number; - PanelWidth: () => number; - PanelHeight: () => number; - focus: (doc: Document) => void; - SelectOnLoad: boolean; + ContainingCollectionView: Opt; + Document: Document; + AddDocument?: (doc: Document, allowDuplicates: boolean) => boolean; + RemoveDocument?: (doc: Document) => boolean; + ScreenToLocalTransform: () => Transform; + isTopMost: boolean; + ContentScaling: () => number; + PanelWidth: () => number; + PanelHeight: () => number; + focus: (doc: Document) => void; + SelectOnLoad: boolean; } export interface JsxArgs extends DocumentViewProps { - Keys: { [name: string]: Key }; - Fields: { [name: string]: Field }; + Keys: { [name: string]: Key }; + Fields: { [name: string]: Field }; } /* @@ -67,448 +55,448 @@ Example usage of this function: } */ export function FakeJsxArgs(keys: string[], fields: string[] = []): JsxArgs { - let Keys: { [name: string]: any } = {}; - let Fields: { [name: string]: any } = {}; - for (const key of keys) { - let fn = () => { }; - Object.defineProperty(fn, "name", { value: key + "Key" }); - Keys[key] = fn; - } - for (const field of fields) { - let fn = () => { }; - Object.defineProperty(fn, "name", { value: field }); - Fields[field] = fn; - } - let args: JsxArgs = { - Document: function Document() { }, - DocumentView: function DocumentView() { }, - Keys, - Fields - } as any; - return args; + let Keys: { [name: string]: any } = {}; + let Fields: { [name: string]: any } = {}; + for (const key of keys) { + let fn = () => { }; + Object.defineProperty(fn, "name", { value: key + "Key" }); + Keys[key] = fn; + } + for (const field of fields) { + let fn = () => { }; + Object.defineProperty(fn, "name", { value: field }); + Fields[field] = fn; + } + let args: JsxArgs = { + Document: function Document() { }, + DocumentView: function DocumentView() { }, + Keys, + Fields + } as any; + return args; } export interface JsxBindings { - Document: Document; - isSelected: () => boolean; - select: (isCtrlPressed: boolean) => void; - isTopMost: boolean; - SelectOnLoad: boolean; - [prop: string]: any; + Document: Document; + isSelected: () => boolean; + select: (isCtrlPressed: boolean) => void; + isTopMost: boolean; + SelectOnLoad: boolean; + [prop: string]: any; } @observer export class DocumentView extends React.Component { - private _mainCont = React.createRef(); - private _downX: number = 0; - private _downY: number = 0; + private _mainCont = React.createRef(); + private _downX: number = 0; + private _downY: number = 0; - private _reactionDisposer: Opt; - @computed get active(): boolean { - return ( - SelectionManager.IsSelected(this) || - !this.props.ContainingCollectionView || - this.props.ContainingCollectionView.active() - ); - } - @computed get topMost(): boolean { - return ( - !this.props.ContainingCollectionView || - this.props.ContainingCollectionView.collectionViewType == - CollectionViewType.Docking - ); - } - @computed get layout(): string { - return this.props.Document.GetText( - KeyStore.Layout, - "

Error loading layout data

" - ); - } - @computed get layoutKeys(): Key[] { - return this.props.Document.GetData( - KeyStore.LayoutKeys, - ListField, - new Array() - ); - } - @computed get layoutFields(): Key[] { - return this.props.Document.GetData( - KeyStore.LayoutFields, - ListField, - new Array() - ); - } - screenRect = (): ClientRect | DOMRect => - this._mainCont.current - ? this._mainCont.current.getBoundingClientRect() - : new DOMRect(); - onPointerDown = (e: React.PointerEvent): void => { - this._downX = e.clientX; - this._downY = e.clientY; - if (e.shiftKey && e.buttons === 2) { - if (this.props.isTopMost) { - this.startDragging(e.pageX, e.pageY, e.altKey || e.ctrlKey); - } else - CollectionDockingView.Instance.StartOtherDrag([this.props.Document], e); - e.stopPropagation(); - } else { - if (this.active && !e.isDefaultPrevented()) { - e.stopPropagation(); - document.removeEventListener("pointermove", this.onPointerMove); - document.addEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - document.addEventListener("pointerup", this.onPointerUp); - } + private _reactionDisposer: Opt; + @computed get active(): boolean { + return ( + SelectionManager.IsSelected(this) || + !this.props.ContainingCollectionView || + this.props.ContainingCollectionView.active() + ); + } + @computed get topMost(): boolean { + return ( + !this.props.ContainingCollectionView || + this.props.ContainingCollectionView.collectionViewType == + CollectionViewType.Docking + ); } - }; + @computed get layout(): string { + return this.props.Document.GetText( + KeyStore.Layout, + "

Error loading layout data

" + ); + } + @computed get layoutKeys(): Key[] { + return this.props.Document.GetData( + KeyStore.LayoutKeys, + ListField, + new Array() + ); + } + @computed get layoutFields(): Key[] { + return this.props.Document.GetData( + KeyStore.LayoutFields, + ListField, + new Array() + ); + } + screenRect = (): ClientRect | DOMRect => + this._mainCont.current + ? this._mainCont.current.getBoundingClientRect() + : new DOMRect(); + onPointerDown = (e: React.PointerEvent): void => { + this._downX = e.clientX; + this._downY = e.clientY; + if (e.shiftKey && e.buttons === 2) { + if (this.props.isTopMost) { + this.startDragging(e.pageX, e.pageY, e.altKey || e.ctrlKey); + } else + CollectionDockingView.Instance.StartOtherDrag([this.props.Document], e); + e.stopPropagation(); + } else { + if (this.active && !e.isDefaultPrevented()) { + e.stopPropagation(); + document.removeEventListener("pointermove", this.onPointerMove); + document.addEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); + document.addEventListener("pointerup", this.onPointerUp); + } + } + }; - private dropDisposer?: DragManager.DragDropDisposer; + private dropDisposer?: DragManager.DragDropDisposer; - componentDidMount() { - if (this._mainCont.current) { - this.dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, { - handlers: { drop: this.drop.bind(this) } - }); + componentDidMount() { + if (this._mainCont.current) { + this.dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, { + handlers: { drop: this.drop.bind(this) } + }); + } + runInAction(() => DocumentManager.Instance.DocumentViews.push(this)); + this._reactionDisposer = reaction( + () => + this.props.ContainingCollectionView && + this.props.ContainingCollectionView.SelectedDocs.slice(), + () => { + if ( + this.props.ContainingCollectionView && + this.props.ContainingCollectionView.SelectedDocs.indexOf( + this.props.Document.Id + ) != -1 + ) + SelectionManager.SelectDoc(this, true); + } + ); } - runInAction(() => DocumentManager.Instance.DocumentViews.push(this)); - this._reactionDisposer = reaction( - () => - this.props.ContainingCollectionView && - this.props.ContainingCollectionView.SelectedDocs.slice(), - () => { - if ( - this.props.ContainingCollectionView && - this.props.ContainingCollectionView.SelectedDocs.indexOf( - this.props.Document.Id - ) != -1 - ) - SelectionManager.SelectDoc(this, true); - } - ); - } - componentDidUpdate() { - if (this.dropDisposer) { - this.dropDisposer(); - } - if (this._mainCont.current) { - this.dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, { - handlers: { drop: this.drop.bind(this) } - }); + componentDidUpdate() { + if (this.dropDisposer) { + this.dropDisposer(); + } + if (this._mainCont.current) { + this.dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, { + handlers: { drop: this.drop.bind(this) } + }); + } } - } - componentWillUnmount() { - if (this.dropDisposer) { - this.dropDisposer(); + componentWillUnmount() { + if (this.dropDisposer) { + this.dropDisposer(); + } + runInAction(() => + DocumentManager.Instance.DocumentViews.splice( + DocumentManager.Instance.DocumentViews.indexOf(this), + 1 + ) + ); + if (this._reactionDisposer) { + this._reactionDisposer(); + } } - runInAction(() => - DocumentManager.Instance.DocumentViews.splice( - DocumentManager.Instance.DocumentViews.indexOf(this), - 1 - ) - ); - if (this._reactionDisposer) { - this._reactionDisposer(); + + startDragging(x: number, y: number, dropAliasOfDraggedDoc: boolean) { + if (this._mainCont.current) { + const [left, top] = this.props + .ScreenToLocalTransform() + .inverse() + .transformPoint(0, 0); + let dragData = new DragManager.DocumentDragData([this.props.Document]); + dragData.aliasOnDrop = dropAliasOfDraggedDoc; + dragData.xOffset = x - left; + dragData.yOffset = y - top; + dragData.removeDocument = (dropCollectionView: CollectionView) => { + if ( + this.props.RemoveDocument && + this.props.ContainingCollectionView !== dropCollectionView + ) { + this.props.RemoveDocument(this.props.Document); + } + }; + DragManager.StartDocumentDrag([this._mainCont.current], dragData, { + handlers: { + dragComplete: action(() => { }) + }, + hideSource: !dropAliasOfDraggedDoc + }); + } } - } - startDragging(x: number, y: number, dropAliasOfDraggedDoc: boolean) { - if (this._mainCont.current) { - const [left, top] = this.props - .ScreenToLocalTransform() - .inverse() - .transformPoint(0, 0); - let dragData = new DragManager.DocumentDragData([this.props.Document]); - dragData.aliasOnDrop = dropAliasOfDraggedDoc; - dragData.xOffset = x - left; - dragData.yOffset = y - top; - dragData.removeDocument = (dropCollectionView: CollectionView) => { + onPointerMove = (e: PointerEvent): void => { + if (e.cancelBubble) { + return; + } if ( - this.props.RemoveDocument && - this.props.ContainingCollectionView !== dropCollectionView + Math.abs(this._downX - e.clientX) > 3 || + Math.abs(this._downY - e.clientY) > 3 ) { - this.props.RemoveDocument(this.props.Document); + document.removeEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); + if (!this.topMost || e.buttons == 2 || e.altKey) { + this.startDragging(e.x, e.y, e.ctrlKey || e.altKey); + } } - }; - DragManager.StartDocumentDrag([this._mainCont.current], dragData, { - handlers: { - dragComplete: action(() => { }) - }, - hideSource: !dropAliasOfDraggedDoc - }); - } - } - - onPointerMove = (e: PointerEvent): void => { - if (e.cancelBubble) { - return; - } - if ( - Math.abs(this._downX - e.clientX) > 3 || - Math.abs(this._downY - e.clientY) > 3 - ) { - document.removeEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - if (!this.topMost || e.buttons == 2 || e.altKey) { - this.startDragging(e.x, e.y, e.ctrlKey || e.altKey); - } - } - e.stopPropagation(); - e.preventDefault(); - }; - onPointerUp = (e: PointerEvent): void => { - document.removeEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - e.stopPropagation(); - if ( - Math.abs(e.clientX - this._downX) < 4 && - Math.abs(e.clientY - this._downY) < 4 - ) { - SelectionManager.SelectDoc(this, e.ctrlKey); - } - }; - stopPropogation = (e: React.SyntheticEvent) => { - e.stopPropagation(); - }; + e.stopPropagation(); + e.preventDefault(); + }; + onPointerUp = (e: PointerEvent): void => { + document.removeEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); + e.stopPropagation(); + if ( + Math.abs(e.clientX - this._downX) < 4 && + Math.abs(e.clientY - this._downY) < 4 + ) { + SelectionManager.SelectDoc(this, e.ctrlKey); + } + }; + stopPropogation = (e: React.SyntheticEvent) => { + e.stopPropagation(); + }; - deleteClicked = (): void => { - if (this.props.RemoveDocument) { - this.props.RemoveDocument(this.props.Document); - } - }; + deleteClicked = (): void => { + if (this.props.RemoveDocument) { + this.props.RemoveDocument(this.props.Document); + } + }; - fieldsClicked = (e: React.MouseEvent): void => { - if (this.props.AddDocument) { - this.props.AddDocument( - Documents.KVPDocument(this.props.Document, { width: 300, height: 300 }), - false - ); - } - }; - fullScreenClicked = (e: React.MouseEvent): void => { - CollectionDockingView.Instance.OpenFullScreen(this.props.Document); - ContextMenu.Instance.clearItems(); - ContextMenu.Instance.addItem({ - description: "Close Full Screen", - event: this.closeFullScreenClicked - }); - ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); - }; + fieldsClicked = (e: React.MouseEvent): void => { + if (this.props.AddDocument) { + this.props.AddDocument( + Documents.KVPDocument(this.props.Document, { width: 300, height: 300 }), + false + ); + } + }; + fullScreenClicked = (e: React.MouseEvent): void => { + CollectionDockingView.Instance.OpenFullScreen(this.props.Document); + ContextMenu.Instance.clearItems(); + ContextMenu.Instance.addItem({ + description: "Close Full Screen", + event: this.closeFullScreenClicked + }); + ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); + }; - closeFullScreenClicked = (e: React.MouseEvent): void => { - CollectionDockingView.Instance.CloseFullScreen(); - ContextMenu.Instance.clearItems(); - ContextMenu.Instance.addItem({ - description: "Full Screen", - event: this.fullScreenClicked - }); - ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); - }; + closeFullScreenClicked = (e: React.MouseEvent): void => { + CollectionDockingView.Instance.CloseFullScreen(); + ContextMenu.Instance.clearItems(); + ContextMenu.Instance.addItem({ + description: "Full Screen", + event: this.fullScreenClicked + }); + ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); + }; - @action - public minimize = (): void => { - this.props.Document.SetData( - KeyStore.Minimized, - true as boolean, - MinimizedField - ); - SelectionManager.DeselectAll(); - }; + @action + public minimize = (): void => { + this.props.Document.SetData( + KeyStore.Minimized, + true as boolean, + BooleanField + ); + SelectionManager.DeselectAll(); + }; - @action - drop = (e: Event, de: DragManager.DropEvent) => { - if (de.data instanceof DragManager.LinkDragData) { - let sourceDoc: Document = de.data.linkSourceDocumentView.props.Document; - let destDoc: Document = this.props.Document; - if (this.props.isTopMost) { - return; - } - let linkDoc: Document = new Document(); + @action + drop = (e: Event, de: DragManager.DropEvent) => { + if (de.data instanceof DragManager.LinkDragData) { + let sourceDoc: Document = de.data.linkSourceDocumentView.props.Document; + let destDoc: Document = this.props.Document; + if (this.props.isTopMost) { + return; + } + let linkDoc: Document = new Document(); - destDoc.GetTAsync(KeyStore.Prototype, Document).then(protoDest => - sourceDoc.GetTAsync(KeyStore.Prototype, Document).then(protoSrc => - runInAction(() => { - linkDoc.Set(KeyStore.Title, new TextField("New Link")); - linkDoc.Set(KeyStore.LinkDescription, new TextField("")); - linkDoc.Set(KeyStore.LinkTags, new TextField("Default")); + destDoc.GetTAsync(KeyStore.Prototype, Document).then(protoDest => + sourceDoc.GetTAsync(KeyStore.Prototype, Document).then(protoSrc => + runInAction(() => { + linkDoc.Set(KeyStore.Title, new TextField("New Link")); + linkDoc.Set(KeyStore.LinkDescription, new TextField("")); + linkDoc.Set(KeyStore.LinkTags, new TextField("Default")); - let dstTarg = protoDest ? protoDest : destDoc; - let srcTarg = protoSrc ? protoSrc : sourceDoc; - linkDoc.Set(KeyStore.LinkedToDocs, dstTarg); - linkDoc.Set(KeyStore.LinkedFromDocs, srcTarg); - dstTarg.GetOrCreateAsync( - KeyStore.LinkedFromDocs, - ListField, - field => { - (field as ListField).Data.push(linkDoc); - } - ); - srcTarg.GetOrCreateAsync( - KeyStore.LinkedToDocs, - ListField, - field => { - (field as ListField).Data.push(linkDoc); - } + let dstTarg = protoDest ? protoDest : destDoc; + let srcTarg = protoSrc ? protoSrc : sourceDoc; + linkDoc.Set(KeyStore.LinkedToDocs, dstTarg); + linkDoc.Set(KeyStore.LinkedFromDocs, srcTarg); + dstTarg.GetOrCreateAsync( + KeyStore.LinkedFromDocs, + ListField, + field => { + (field as ListField).Data.push(linkDoc); + } + ); + srcTarg.GetOrCreateAsync( + KeyStore.LinkedToDocs, + ListField, + field => { + (field as ListField).Data.push(linkDoc); + } + ); + }) + ) ); - }) - ) - ); - e.stopPropagation(); - } - }; + e.stopPropagation(); + } + }; - onDrop = (e: React.DragEvent) => { - if (e.isDefaultPrevented()) { - return; - } - let text = e.dataTransfer.getData("text/plain"); - if (text && text.startsWith(" { + if (e.isDefaultPrevented()) { + return; + } + let text = e.dataTransfer.getData("text/plain"); + if (text && text.startsWith(" { - e.stopPropagation(); - let moved = - Math.abs(this._downX - e.clientX) > 3 || - Math.abs(this._downY - e.clientY) > 3; - if (moved || e.isDefaultPrevented()) { - e.preventDefault(); - return; - } - e.preventDefault(); + @action + onContextMenu = (e: React.MouseEvent): void => { + e.stopPropagation(); + let moved = + Math.abs(this._downX - e.clientX) > 3 || + Math.abs(this._downY - e.clientY) > 3; + if (moved || e.isDefaultPrevented()) { + e.preventDefault(); + return; + } + e.preventDefault(); - if (!this.isMinimized()) { - ContextMenu.Instance.addItem({ - description: "Minimize", - event: this.minimize - }); - } - ContextMenu.Instance.addItem({ - description: "Full Screen", - event: this.fullScreenClicked - }); - ContextMenu.Instance.addItem({ - description: "Fields", - event: this.fieldsClicked - }); - ContextMenu.Instance.addItem({ - description: "Center", - event: () => this.props.focus(this.props.Document) - }); - ContextMenu.Instance.addItem({ - description: "Open Right", - event: () => - CollectionDockingView.Instance.AddRightSplit(this.props.Document) - }); - ContextMenu.Instance.addItem({ - description: "Copy URL", - event: () => { - Utils.CopyText(ServerUtils.prepend("/doc/" + this.props.Document.Id)); - } - }); - ContextMenu.Instance.addItem({ - description: "Copy ID", - event: () => { - Utils.CopyText(this.props.Document.Id); - } - }); - //ContextMenu.Instance.addItem({ description: "Docking", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Docking) }) - ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); - if (!this.topMost) { - // DocumentViews should stop propagation of this event - e.stopPropagation(); - } + if (!this.isMinimized()) { + ContextMenu.Instance.addItem({ + description: "Minimize", + event: this.minimize + }); + } + ContextMenu.Instance.addItem({ + description: "Full Screen", + event: this.fullScreenClicked + }); + ContextMenu.Instance.addItem({ + description: "Fields", + event: this.fieldsClicked + }); + ContextMenu.Instance.addItem({ + description: "Center", + event: () => this.props.focus(this.props.Document) + }); + ContextMenu.Instance.addItem({ + description: "Open Right", + event: () => + CollectionDockingView.Instance.AddRightSplit(this.props.Document) + }); + ContextMenu.Instance.addItem({ + description: "Copy URL", + event: () => { + Utils.CopyText(ServerUtils.prepend("/doc/" + this.props.Document.Id)); + } + }); + ContextMenu.Instance.addItem({ + description: "Copy ID", + event: () => { + Utils.CopyText(this.props.Document.Id); + } + }); + //ContextMenu.Instance.addItem({ description: "Docking", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Docking) }) + ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); + if (!this.topMost) { + // DocumentViews should stop propagation of this event + e.stopPropagation(); + } - ContextMenu.Instance.addItem({ - description: "Delete", - event: this.deleteClicked - }); - ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); - SelectionManager.SelectDoc(this, e.ctrlKey); - }; + ContextMenu.Instance.addItem({ + description: "Delete", + event: this.deleteClicked + }); + ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); + SelectionManager.SelectDoc(this, e.ctrlKey); + }; - isMinimized = () => { - let field = this.props.Document.GetT(KeyStore.Minimized, MinimizedField); - if (field && field !== FieldWaiting) { - return field.Data; - } - }; + isMinimized = () => { + let field = this.props.Document.GetT(KeyStore.Minimized, BooleanField); + if (field && field !== FieldWaiting) { + return field.Data; + } + }; - @action - expand = () => { - this.props.Document.SetData( - KeyStore.Minimized, - false as boolean, - MinimizedField - ); - }; + @action + expand = () => { + this.props.Document.SetData( + KeyStore.Minimized, + false as boolean, + BooleanField + ); + }; - isSelected = () => { - return SelectionManager.IsSelected(this); - }; + isSelected = () => { + return SelectionManager.IsSelected(this); + }; - select = (ctrlPressed: boolean) => { - SelectionManager.SelectDoc(this, ctrlPressed); - }; + select = (ctrlPressed: boolean) => { + SelectionManager.SelectDoc(this, ctrlPressed); + }; - render() { - if (!this.props.Document) { - return null; - } + render() { + if (!this.props.Document) { + return null; + } - var scaling = this.props.ContentScaling(); - var nativeWidth = this.props.Document.GetNumber(KeyStore.NativeWidth, 0); - var nativeHeight = this.props.Document.GetNumber(KeyStore.NativeHeight, 0); + var scaling = this.props.ContentScaling(); + var nativeWidth = this.props.Document.GetNumber(KeyStore.NativeWidth, 0); + var nativeHeight = this.props.Document.GetNumber(KeyStore.NativeHeight, 0); - if (this.isMinimized()) { - return ( -
- ); - } else { - var backgroundcolor = this.props.Document.GetText( - KeyStore.BackgroundColor, - "" - ); - return ( -
0 ? nativeWidth.toString() + "px" : "100%", - height: nativeHeight > 0 ? nativeHeight.toString() + "px" : "100%", - transformOrigin: "left top", - transform: `scale(${scaling} , ${scaling})` - }} - onDrop={this.onDrop} - onContextMenu={this.onContextMenu} - onPointerDown={this.onPointerDown} - > - -
- ); + if (this.isMinimized()) { + return ( +
+ ); + } else { + var backgroundcolor = this.props.Document.GetText( + KeyStore.BackgroundColor, + "" + ); + return ( +
0 ? nativeWidth.toString() + "px" : "100%", + height: nativeHeight > 0 ? nativeHeight.toString() + "px" : "100%", + transformOrigin: "left top", + transform: `scale(${scaling} , ${scaling})` + }} + onDrop={this.onDrop} + onContextMenu={this.onContextMenu} + onPointerDown={this.onPointerDown} + > + +
+ ); + } } - } } diff --git a/src/fields/BooleanField.ts b/src/fields/BooleanField.ts new file mode 100644 index 000000000..7378b30a1 --- /dev/null +++ b/src/fields/BooleanField.ts @@ -0,0 +1,25 @@ +import { BasicField } from "./BasicField"; +import { FieldId } from "./Field"; +import { Types } from "../server/Message"; + +export class BooleanField extends BasicField { + constructor(data: boolean = false as boolean, id?: FieldId, save: boolean = true as boolean) { + super(data, save, id); + } + + ToScriptString(): string { + return `new BooleanField("${this.Data}")`; + } + + Copy() { + return new BooleanField(this.Data); + } + + ToJson(): { type: Types; data: boolean; _id: string } { + return { + type: Types.Minimized, + data: this.Data, + _id: this.Id + }; + } +} diff --git a/src/fields/MinimizedField.tsx b/src/fields/MinimizedField.tsx deleted file mode 100644 index 5dfb22e6e..000000000 --- a/src/fields/MinimizedField.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { BasicField } from "./BasicField"; -import { FieldId } from "./Field"; -import { Types } from "../server/Message"; - -export class MinimizedField extends BasicField { - constructor( - data: boolean = false as boolean, - id?: FieldId, - save: boolean = true as boolean - ) { - super(data, save, id); - } - - ToScriptString(): string { - return `new MinimizedField("${this.Data}")`; - } - - Copy() { - return new MinimizedField(this.Data); - } - - ToJson(): { type: Types; data: boolean; _id: string } { - return { - type: Types.Minimized, - data: this.Data, - _id: this.Id - }; - } -} diff --git a/src/server/ServerUtil.ts b/src/server/ServerUtil.ts index f3c5e1d1f..d3409abf4 100644 --- a/src/server/ServerUtil.ts +++ b/src/server/ServerUtil.ts @@ -16,69 +16,69 @@ import { VideoField } from "../fields/VideoField"; import { InkField } from "../fields/InkField"; import { PDFField } from "../fields/PDFField"; import { TupleField } from "../fields/TupleField"; -import { MinimizedField } from "../fields/MinimizedField"; +import { BooleanField } from "../fields/BooleanField"; import { HistogramField } from "../client/northstar/dash-fields/HistogramField"; export class ServerUtils { - public static prepend(extension: string): string { - return window.location.origin + extension; - } + public static prepend(extension: string): string { + return window.location.origin + extension; + } - public static FromJson(json: any): Field { - let obj = json; - let data: any = obj.data; - let id: string = obj._id; - let type: Types = obj.type; + public static FromJson(json: any): Field { + let obj = json; + let data: any = obj.data; + let id: string = obj._id; + let type: Types = obj.type; - if (!(data !== undefined && id && type !== undefined)) { - console.log( - "how did you manage to get an object that doesn't have a data or an id?" - ); - return new TextField("Something to fill the space", Utils.GenerateGuid()); - } + if (!(data !== undefined && id && type !== undefined)) { + console.log( + "how did you manage to get an object that doesn't have a data or an id?" + ); + return new TextField("Something to fill the space", Utils.GenerateGuid()); + } - switch (type) { - case Types.Minimized: - return new MinimizedField(data, id, false); - case Types.Number: - return new NumberField(data, id, false); - case Types.Text: - return new TextField(data, id, false); - case Types.Html: - return new HtmlField(data, id, false); - case Types.Web: - return new WebField(new URL(data), id, false); - case Types.RichText: - return new RichTextField(data, id, false); - case Types.Key: - return new Key(data, id, false); - case Types.Image: - return new ImageField(new URL(data), id, false); - case Types.HistogramOp: - return HistogramField.FromJson(id, data); - case Types.PDF: - return new PDFField(new URL(data), id, false); - case Types.List: - return ListField.FromJson(id, data); - case Types.Audio: - return new AudioField(new URL(data), id, false); - case Types.Video: - return new VideoField(new URL(data), id, false); - case Types.Tuple: - return new TupleField(data, id, false); - case Types.Ink: - return InkField.FromJson(id, data); - case Types.Document: - let doc: Document = new Document(id, false); - let fields: [string, string][] = data as [string, string][]; - fields.forEach(element => { - doc._proxies.set(element[0], element[1]); - }); - return doc; - default: - throw Error( - "Error, unrecognized field type received from server. If you just created a new field type, be sure to add it here" - ); + switch (type) { + case Types.Minimized: + return new BooleanField(data, id, false); + case Types.Number: + return new NumberField(data, id, false); + case Types.Text: + return new TextField(data, id, false); + case Types.Html: + return new HtmlField(data, id, false); + case Types.Web: + return new WebField(new URL(data), id, false); + case Types.RichText: + return new RichTextField(data, id, false); + case Types.Key: + return new Key(data, id, false); + case Types.Image: + return new ImageField(new URL(data), id, false); + case Types.HistogramOp: + return HistogramField.FromJson(id, data); + case Types.PDF: + return new PDFField(new URL(data), id, false); + case Types.List: + return ListField.FromJson(id, data); + case Types.Audio: + return new AudioField(new URL(data), id, false); + case Types.Video: + return new VideoField(new URL(data), id, false); + case Types.Tuple: + return new TupleField(data, id, false); + case Types.Ink: + return InkField.FromJson(id, data); + case Types.Document: + let doc: Document = new Document(id, false); + let fields: [string, string][] = data as [string, string][]; + fields.forEach(element => { + doc._proxies.set(element[0], element[1]); + }); + return doc; + default: + throw Error( + "Error, unrecognized field type received from server. If you just created a new field type, be sure to add it here" + ); + } } - } } diff --git a/src/server/database.ts b/src/server/database.ts index a42d29aac..616251c72 100644 --- a/src/server/database.ts +++ b/src/server/database.ts @@ -1,8 +1,4 @@ -import { action, configure } from 'mobx'; import * as mongodb from 'mongodb'; -import { ObjectID } from 'mongodb'; -import { Transferable } from './Message'; -import { Utils } from '../Utils'; export class Database { public static Instance = new Database() @@ -26,9 +22,9 @@ export class Database { console.log(err.message); console.log(err.errmsg); } - if (res) { - console.log(JSON.stringify(res.result)); - } + // if (res) { + // console.log(JSON.stringify(res.result)); + // } callback() }); } diff --git a/src/server/public/files/upload_a6a70d84ebb65febf7900e29f52cc86d.pdf b/src/server/public/files/upload_a6a70d84ebb65febf7900e29f52cc86d.pdf new file mode 100644 index 000000000..dfd6ab339 Binary files /dev/null and b/src/server/public/files/upload_a6a70d84ebb65febf7900e29f52cc86d.pdf differ -- cgit v1.2.3-70-g09d2 From 4fde212cd00bd2f8fc2fa122309af3bb71bba2fd Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 4 Apr 2019 18:18:45 -0400 Subject: improved pdf bitmaps a bit, but still blurry. --- src/client/documents/Documents.ts | 2 +- src/client/views/collections/CollectionViewBase.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/PDFBox.tsx | 20 +++++++++++--------- 4 files changed, 14 insertions(+), 12 deletions(-) (limited to 'src/client/views/nodes/DocumentView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 0bf275df8..1f0744782 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -136,7 +136,7 @@ export namespace Documents { function GetPdfPrototype(): Document { if (!pdfProto) { pdfProto = setupPrototypeOptions(pdfProtoId, "PDF_PROTO", CollectionPDFView.LayoutString("AnnotationsKey"), - { x: 0, y: 0, nativeWidth: 600, width: 300, layoutKeys: [KeyStore.Data, KeyStore.Annotations] }); + { x: 0, y: 0, nativeWidth: 1200, width: 300, layoutKeys: [KeyStore.Data, KeyStore.Annotations] }); pdfProto.SetNumber(KeyStore.CurPage, 1); pdfProto.SetText(KeyStore.BackgroundLayout, PDFBox.LayoutString()); } diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx index 9eee23a1d..458bae7ab 100644 --- a/src/client/views/collections/CollectionViewBase.tsx +++ b/src/client/views/collections/CollectionViewBase.tsx @@ -128,7 +128,7 @@ export class CollectionViewBase extends React.Component } if (type.indexOf("pdf") !== -1) { ctor = Documents.PdfDocument; - options.nativeWidth = 600; + options.nativeWidth = 1200; } if (type.indexOf("html") !== -1) { if (path.includes('localhost')) { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 714ab9447..b9329f269 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -249,7 +249,7 @@ export class DocumentView extends React.Component { document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); e.stopPropagation(); - if ( + if (!SelectionManager.IsSelected(this) && Math.abs(e.clientX - this._downX) < 4 && Math.abs(e.clientY - this._downY) < 4 ) { diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index c9fed7f66..f9f5bc8f8 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -18,6 +18,7 @@ import "./ImageBox.scss"; import "./PDFBox.scss"; import { Sticky } from './Sticky'; //you should look at sticky and annotation, because they are used here import React = require("react") +import { SelectionManager } from "../../util/SelectionManager"; /** ALSO LOOK AT: Annotation.tsx, Sticky.tsx * This method renders PDF and puts all kinds of functionalities such as annotation, highlighting, @@ -57,6 +58,8 @@ export class PDFBox extends React.Component { private _mainDiv = React.createRef() private _pdf = React.createRef(); + @observable private _renderAsSvg = true; + //very useful for keeping track of X and y position throughout the PDF Canvas private initX: number = 0; private initY: number = 0; @@ -91,9 +94,9 @@ export class PDFBox extends React.Component { componentDidMount() { this._reactionDisposer = reaction( - () => [this.curPage, this.thumbnailPage], + () => [SelectionManager.SelectedDocuments().slice()], () => { - if (this.curPage > 0 && this.thumbnailPage > 0 && this.curPage != this.thumbnailPage) { + if (this.curPage > 0 && this.thumbnailPage > 0 && this.curPage != this.thumbnailPage && !this.props.isSelected()) { this.saveThumbnail(); this._interactive = true; } @@ -375,19 +378,21 @@ export class PDFBox extends React.Component { @action saveThumbnail = () => { + this._renderAsSvg = false; setTimeout(() => { var me = this; let nwidth = me.props.doc.GetNumber(KeyStore.NativeWidth, 0); let nheight = me.props.doc.GetNumber(KeyStore.NativeHeight, 0); htmlToImage.toPng(this._mainDiv.current!, { width: nwidth, height: nheight, quality: 1 }) - .then(function (dataUrl: string) { + .then(action((dataUrl: string) => { me.props.doc.SetData(KeyStore.Thumbnail, new URL(dataUrl), ImageField); me.props.doc.SetNumber(KeyStore.ThumbnailPage, me.props.doc.GetNumber(KeyStore.CurPage, -1)); - }) + me._renderAsSvg = true; + })) .catch(function (error: any) { console.error('oops, something went wrong!', error); }); - }, 1000); + }, 250); } @action @@ -427,9 +432,6 @@ export class PDFBox extends React.Component { this.props.doc.SetNumber(KeyStore.Height, nativeHeight / nativeWidth * this.props.doc.GetNumber(KeyStore.Width, 0)); this.props.doc.SetNumber(KeyStore.NativeHeight, nativeHeight); } - if (!this.props.doc.GetT(KeyStore.Thumbnail, ImageField)) { - this.saveThumbnail(); - } } @computed @@ -439,7 +441,7 @@ export class PDFBox extends React.Component { let pdfUrl = this.props.doc.GetT(this.props.fieldKey, PDFField); let xf = this.props.doc.GetNumber(KeyStore.NativeHeight, 0) / renderHeight; return
- + {({ measureRef }) =>
-- cgit v1.2.3-70-g09d2 From f873d620e9a3804d5a6783d7ea335b27d59b4612 Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 5 Apr 2019 13:03:21 -0400 Subject: fixed dragging misalignment --- src/client/util/DragManager.ts | 53 ++++++++++++---------- src/client/views/DocumentDecorations.tsx | 18 ++++---- .../views/collections/CollectionDockingView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 4 +- 4 files changed, 43 insertions(+), 34 deletions(-) (limited to 'src/client/views/nodes/DocumentView.tsx') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index cc47c57e0..043932de5 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -21,7 +21,7 @@ export function setupDrag( document.removeEventListener("pointerup", onRowUp); var dragData = new DragManager.DocumentDragData([docFunc()]); dragData.removeDocument = removeFunc; - DragManager.StartDocumentDrag([_reference.current!], dragData); + DragManager.StartDocumentDrag([_reference.current!], dragData, e.x, e.y); } ); let onRowUp = action( @@ -132,11 +132,14 @@ export namespace DragManager { export function StartDocumentDrag( eles: HTMLElement[], dragData: DocumentDragData, + downX: number, + downY: number, options?: DragOptions ) { StartDrag( eles, dragData, + downX, downY, options, (dropData: { [id: string]: any }) => (dropData.droppedDocuments = dragData.aliasOnDrop @@ -156,13 +159,15 @@ export namespace DragManager { export function StartLinkDrag( ele: HTMLElement, dragData: LinkDragData, + downX: number, downY: number, options?: DragOptions ) { - StartDrag([ele], dragData, options); + StartDrag([ele], dragData, downX, downY, options); } function StartDrag( eles: HTMLElement[], dragData: { [id: string]: any }, + downX: number, downY: number, options?: DragOptions, finishDrag?: (dropData: { [id: string]: any }) => void ) { @@ -204,23 +209,22 @@ export namespace DragManager { dragElement.style.width = `${rect.width / scaleX}px`; dragElement.style.height = `${rect.height / scaleY}px`; - // bcz: PDFs don't show up if you clone them because they contain a canvas. + // bcz: if PDFs are rendered with svg's, then this code isn't needed + // bcz: PDFs don't show up if you clone them when rendered using a canvas. // however, PDF's have a thumbnail field that contains an image of their canvas. // So we replace the pdf's canvas with the image thumbnail - if (docs.length) { - var pdfBox = dragElement.getElementsByClassName( - "pdfBox-cont" - )[0] as HTMLElement; - let thumbnail = docs[0].GetT(KeyStore.Thumbnail, ImageField); - if (pdfBox && pdfBox.childElementCount && thumbnail) { - let img = new Image(); - img!.src = thumbnail.toString(); - img!.style.position = "absolute"; - img!.style.width = `${rect.width / scaleX}px`; - img!.style.height = `${rect.height / scaleY}px`; - pdfBox.replaceChild(img!, pdfBox.children[0]); - } - } + // if (docs.length) { + // var pdfBox = dragElement.getElementsByClassName("pdfBox-cont")[0] as HTMLElement; + // let thumbnail = docs[0].GetT(KeyStore.Thumbnail, ImageField); + // if (pdfBox && pdfBox.childElementCount && thumbnail) { + // let img = new Image(); + // img!.src = thumbnail.toString(); + // img!.style.position = "absolute"; + // img!.style.width = `${rect.width / scaleX}px`; + // img!.style.height = `${rect.height / scaleY}px`; + // pdfBox.replaceChild(img!, pdfBox.children[0]); + // } + // } dragDiv.appendChild(dragElement); return dragElement; @@ -236,6 +240,8 @@ export namespace DragManager { } eles.map(ele => (ele.hidden = hideSource)); + let lastX = downX; + let lastY = downY; const moveHandler = (e: PointerEvent) => { e.stopPropagation(); e.preventDefault(); @@ -250,12 +256,13 @@ export namespace DragManager { button: 0 }); } - dragElements.map( - (dragElement, i) => - (dragElement.style.transform = `translate(${(xs[i] += - e.movementX)}px, ${(ys[i] += e.movementY)}px) scale(${ - scaleXs[i] - }, ${scaleYs[i]})`) + let moveX = e.pageX - lastX; + let moveY = e.pageY - lastY; + lastX = e.pageX; + lastY = e.pageY; + dragElements.map((dragElement, i) => (dragElement.style.transform = + `translate(${(xs[i] += moveX)}px, ${(ys[i] += moveY)}px) + scale(${scaleXs[i]}, ${scaleYs[i]})`) ); }; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 8bf1a42d1..c7e4a269a 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -126,12 +126,14 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> this._dragging = true; document.removeEventListener("pointermove", this.onBackgroundMove); document.removeEventListener("pointerup", this.onBackgroundUp); - DragManager.StartDocumentDrag(SelectionManager.SelectedDocuments().map(docView => (docView as any)._mainCont!.current!), dragData, { - handlers: { - dragComplete: action(() => this._dragging = false), - }, - hideSource: true - }) + DragManager.StartDocumentDrag(SelectionManager.SelectedDocuments().map(docView => (docView as any)._mainCont!.current!), dragData, + e.x, e.y, + { + handlers: { + dragComplete: action(() => this._dragging = false), + }, + hideSource: true + }) e.stopPropagation(); } @@ -219,7 +221,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> document.removeEventListener("pointermove", this.onLinkerButtonMoved) document.removeEventListener("pointerup", this.onLinkerButtonUp) let dragData = new DragManager.LinkDragData(SelectionManager.SelectedDocuments()[0]); - DragManager.StartLinkDrag(this._linkerButton.current, dragData, { + DragManager.StartLinkDrag(this._linkerButton.current, dragData, e.pageX, e.pageY, { handlers: { dragComplete: action(() => { }), }, @@ -265,7 +267,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> moddrag.push(doc); } let dragData = new DragManager.DocumentDragData(moddrag); - DragManager.StartDocumentDrag([this._linkButton.current], dragData, { + DragManager.StartDocumentDrag([this._linkButton.current], dragData, e.x, e.y, { handlers: { dragComplete: action(() => { }), }, diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 39e0dd989..921ee4591 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -200,7 +200,7 @@ export class CollectionDockingView extends React.Component) => { if (f instanceof Document) - DragManager.StartDocumentDrag([tab], new DragManager.DocumentDragData([f as Document]), + DragManager.StartDocumentDrag([tab], new DragManager.DocumentDragData([f as Document]), e.pageX, e.pageY, { handlers: { dragComplete: action(() => { }), diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index b9329f269..7514e782d 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -219,7 +219,7 @@ export class DocumentView extends React.Component { this.props.RemoveDocument(this.props.Document); } }; - DragManager.StartDocumentDrag([this._mainCont.current], dragData, { + DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { handlers: { dragComplete: action(() => { }) }, @@ -239,7 +239,7 @@ export class DocumentView extends React.Component { document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); if (!this.topMost || e.buttons == 2 || e.altKey) { - this.startDragging(e.x, e.y, e.ctrlKey || e.altKey); + this.startDragging(this._downX, this._downY, e.ctrlKey || e.altKey); } } e.stopPropagation(); -- cgit v1.2.3-70-g09d2