diff options
37 files changed, 1174 insertions, 586 deletions
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/package.json b/package.json index 4fc253834..bdfd32389 100644 --- a/package.json +++ b/package.json @@ -107,6 +107,7 @@ "express-validator": "^5.3.1", "expressjs": "^1.0.1", "flexlayout-react": "^0.3.3", + "font-awesome": "^4.7.0", "formidable": "^1.2.1", "golden-layout": "^1.5.9", "html-to-image": "^0.1.0", diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 15f980895..1b1485c12 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -137,7 +137,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/northstar/dash-nodes/HistogramBox.scss b/src/client/northstar/dash-nodes/HistogramBox.scss index b11840a65..94da36e29 100644 --- a/src/client/northstar/dash-nodes/HistogramBox.scss +++ b/src/client/northstar/dash-nodes/HistogramBox.scss @@ -1,6 +1,8 @@ .histogrambox-container { padding: 0vw; position: absolute; + top: 0; + left:0; text-align: center; width: 100%; height: 100%; @@ -8,6 +10,7 @@ } .histogrambox-xaxislabel { position:absolute; + left:0; width:100%; text-align: center; bottom:0; @@ -19,11 +22,13 @@ position:absolute; height:100%; width: 25px; + left:0; bottom:0; background: lightgray; } .histogrambox-yaxislabel-text { position:absolute; + left:0; transform-origin: left; transform: rotate(-90deg); text-align: center; diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index d8e70a8b4..02e0a18df 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -1,6 +1,6 @@ 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"; @@ -31,11 +31,11 @@ export function setupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc: CollectionDockingView.Instance.StartOtherDrag([docFunc()], e); } else { document.addEventListener("pointermove", onRowMove); - document.addEventListener('pointerup', onRowUp); + document.addEventListener("pointerup", onRowUp); } } //} - } + }; return onItemDown; } @@ -51,7 +51,9 @@ export namespace DragManager { let dragDiv: HTMLDivElement; export enum DragButtons { - Left = 1, Right = 2, Both = Left | Right + Left = 1, + Right = 2, + Both = Left | Right } interface DragOptions { @@ -64,8 +66,7 @@ export namespace DragManager { (): void; } - export class DragCompleteEvent { - } + export class DragCompleteEvent { } export interface DragHandlers { dragComplete: (e: DragCompleteEvent) => void; @@ -75,19 +76,25 @@ export namespace DragManager { handlers: DropHandlers; } export class DropEvent { - constructor(readonly x: number, readonly y: number, readonly data: { [id: string]: any }) { } + 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 { + 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"); + throw new Error( + "Element is already droppable, can't make it droppable again" + ); } element.dataset.canDrop = "true"; const handler = (e: Event) => { @@ -116,24 +123,46 @@ export namespace DragManager { [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 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 class LinkDragData { constructor(linkSourceDoc: DocumentView) { this.linkSourceDocumentView = linkSourceDoc; } + droppedDocuments: Document[] = []; linkSourceDocumentView: DocumentView; [id: string]: any; } - export function StartLinkDrag(ele: HTMLElement, dragData: LinkDragData, options?: DragOptions) { + 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) { + 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" + dragDiv.className = "dragManager-dragDiv"; DragManager.Root().appendChild(dragDiv); } @@ -142,19 +171,27 @@ export namespace DragManager { let xs: number[] = []; let ys: number[] = []; - const docs: Document[] = dragData instanceof DocumentDragData ? dragData.draggedDocuments : []; + const docs: Document[] = + dragData instanceof DocumentDragData ? dragData.draggedDocuments : []; let dragElements = eles.map(ele => { - const w = ele.offsetWidth, h = ele.offsetHeight; + 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); + 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.margin = "0"; + dragElement.style.top = "0"; dragElement.style.bottom = ""; - dragElement.style.left = ""; + dragElement.style.left = "0"; dragElement.style.transformOrigin = "0 0"; dragElement.style.zIndex = "1000"; dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`; @@ -165,7 +202,9 @@ export namespace DragManager { // 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; + 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(); @@ -189,7 +228,7 @@ export namespace DragManager { hideSource = options.hideSource(); } } - eles.map(ele => ele.hidden = hideSource); + eles.map(ele => (ele.hidden = hideSource)); const moveHandler = (e: PointerEvent) => { e.stopPropagation(); @@ -198,17 +237,28 @@ export namespace DragManager { dragData.aliasOnDrop = e.ctrlKey || e.altKey; if (e.shiftKey) { abortDrag(); - CollectionDockingView.Instance.StartOtherDrag(docs, { pageX: e.pageX, pageY: e.pageY, preventDefault: () => { }, button: 0 }); + 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]})`); + 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); - } + eles.map(ele => (ele.hidden = false)); + }; const upHandler = (e: PointerEvent) => { abortDrag(); FinishDrag(eles, e, dragData, options, finishDrag); @@ -217,32 +267,37 @@ export namespace DragManager { document.addEventListener("pointerup", upHandler); } - function FinishDrag(dragEles: HTMLElement[], e: PointerEvent, dragData: { [index: string]: any }, options?: DragOptions, finishDrag?: (dragData: { [index: string]: any }) => void) { + 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); + if (parent) parent.removeChild(dragEle); return [dragEle, parent]; }); const target = document.elementFromPoint(e.x, e.y); removed.map(r => { let dragEle = r[0]; let parent = r[1]; - if (parent && dragEle) - parent.appendChild(dragEle); + if (parent && dragEle) parent.appendChild(dragEle); }); if (target) { - if (finishDrag) - finishDrag(dragData); - - target.dispatchEvent(new CustomEvent<DropEvent>("dashOnDrop", { - bubbles: true, - detail: { - x: e.x, - y: e.y, - data: dragData - } - })); + if (finishDrag) finishDrag(dragData); + + target.dispatchEvent( + new CustomEvent<DropEvent>("dashOnDrop", { + bubbles: true, + detail: { + x: e.x, + y: e.y, + data: dragData + } + }) + ); if (options) { options.handlers.dragComplete({}); @@ -250,4 +305,4 @@ export namespace DragManager { } DocumentDecorations.Instance.Hidden = false; } -}
\ No newline at end of file +} diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 494420f0b..5e1fa9576 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -1,6 +1,6 @@ import { observable, action } from "mobx"; import { DocumentView } from "../views/nodes/DocumentView"; -import { Document } from "../../fields/Document" +import { Document } from "../../fields/Document"; export namespace SelectionManager { class Manager { @@ -15,7 +15,7 @@ export namespace SelectionManager { } if (manager.SelectedDocuments.indexOf(doc) === -1) { - manager.SelectedDocuments.push(doc) + manager.SelectedDocuments.push(doc); doc.props.onActiveChanged(true); } } @@ -27,10 +27,10 @@ export namespace SelectionManager { } } - const manager = new Manager; + const manager = new Manager(); export function SelectDoc(doc: DocumentView, ctrlPressed: boolean): void { - manager.SelectDoc(doc, ctrlPressed) + manager.SelectDoc(doc, ctrlPressed); } export function IsSelected(doc: DocumentView): boolean { @@ -41,17 +41,15 @@ export namespace SelectionManager { let found: DocumentView | undefined = undefined; if (except) { for (const view of manager.SelectedDocuments) { - if (view.props.Document === except) - found = view; + if (view.props.Document === except) found = view; } } manager.DeselectAll() - if (found) - manager.SelectDoc(found, false); + if (found) manager.SelectDoc(found, false); } export function SelectedDocuments(): Array<DocumentView> { return manager.SelectedDocuments; } -}
\ No newline at end of file +} diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss index 7a43f3087..d7137d7a2 100644 --- a/src/client/views/DocumentDecorations.scss +++ b/src/client/views/DocumentDecorations.scss @@ -1,39 +1,90 @@ @import "global_variables"; + #documentDecorations-container { position: absolute; + top: 0; + left:0; display: grid; z-index: 1000; - grid-template-rows: 8px 1fr 8px 30px; - grid-template-columns: 8px 1fr 8px; + grid-template-rows: 20px 8px 1fr 8px; + grid-template-columns: 8px 8px 1fr 8px 8px; pointer-events: none; + #documentDecorations-centerCont { + grid-column:3; background: none; } + .documentDecorations-resizer { pointer-events: auto; background: $alt-accent; opacity: 0.8; } + + #documentDecorations-topLeftResizer, + #documentDecorations-leftResizer, + #documentDecorations-bottomLeftResizer { + grid-column: 1 + } + + #documentDecorations-topResizer, + #documentDecorations-bottomResizer { + grid-column-start: 2; + grid-column-end: 5; + } + + #documentDecorations-bottomRightResizer, + #documentDecorations-topRightResizer, + #documentDecorations-rightResizer { + grid-column-start:5; + grid-column-end:7; + } + #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; } + .title{ + background: lightblue; + grid-column-start:3; + grid-column-end: 4; + pointer-events: auto; + } } +.documentDecorations-closeButton { + background:$alt-accent; + opacity: 0.8; + grid-column-start: 4; + grid-column-end: 6; + pointer-events: all; + text-align: center; +} +.documentDecorations-minimizeButton { + background:$alt-accent; + opacity: 0.8; + grid-column-start: 1; + grid-column-end: 3; + pointer-events: all; + text-align: center; +} .documentDecorations-background { - background:lightblue; + background: lightblue; position: absolute; opacity: 0.1; } @@ -70,7 +121,8 @@ // } // } .linkFlyout { - grid-column: 1/4 + grid-column: 1/4; + margin-left: 25px; } .linkButton-empty:hover { @@ -85,6 +137,31 @@ cursor: pointer; } +.linkButton-linker { + position:absolute; + bottom:0px; + left: 0px; + height: 20px; + width: 20px; + margin-top: 10px; + margin-right: 5px; + border-radius: 50%; + opacity: 0.9; + pointer-events: auto; + color: $dark-color; + border: $dark-color 1px solid; + text-transform: uppercase; + letter-spacing: 2px; + font-size: 75%; + transition: transform 0.2s; + text-align: center; + display: flex; + justify-content: center; + align-items: center; +} +.linkButton-tray { + grid-column: 1/4; +} .linkButton-empty { height: 20px; width: 20px; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index a6117dfa0..99588480d 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -1,37 +1,84 @@ -import { action, computed, observable, trace } from "mobx"; +import { action, computed, observable, trace, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { KeyStore } from '../../fields/KeyStore'; +import { Key } from "../../fields/Key"; +//import ContentEditable from 'react-contenteditable' +import { KeyStore } from "../../fields/KeyStore"; import { ListField } from "../../fields/ListField"; import { NumberField } from "../../fields/NumberField"; +import { Document } from "../../fields/Document"; +import { TextField } from "../../fields/TextField"; import { DragManager } from "../util/DragManager"; import { SelectionManager } from "../util/SelectionManager"; import { CollectionView } from "./collections/CollectionView"; import './DocumentDecorations.scss'; +import { DocumentView } from "./nodes/DocumentView"; import { LinkMenu } from "./nodes/LinkMenu"; import React = require("react"); +import { FieldWaiting } from "../../fields/Field"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @observer -export class DocumentDecorations extends React.Component { +export class DocumentDecorations extends React.Component<{}, { value: string }> { static Instance: DocumentDecorations private _resizer = "" private _isPointerDown = false; - + private keyinput: React.RefObject<HTMLInputElement>; + private _documents: DocumentView[] = SelectionManager.SelectedDocuments(); private _resizeBorderWidth = 16; + private _linkBoxHeight = 30; + private _titleHeight = 20; private _linkButton = React.createRef<HTMLDivElement>(); + private _linkerButton = React.createRef<HTMLDivElement>(); + //@observable private _title: string = this._documents[0].props.Document.Title; + @observable private _title: string = this._documents.length > 0 ? this._documents[0].props.Document.Title : ""; + @observable private _fieldKey: Key = KeyStore.Title; @observable private _hidden = false; + @observable private _opacity = 1; @observable private _dragging = false; + constructor(props: Readonly<{}>) { super(props) - DocumentDecorations.Instance = this + this.handleChange = this.handleChange.bind(this); + this.keyinput = React.createRef(); + } + + @action + handleChange = (event: any) => { + this._title = event.target.value; + }; + + @action + enterPressed = (e: any) => { + var key = e.keyCode || e.which; + // enter pressed + if (key == 13) { + var text = e.target.value; + if (text[0] == '#') { + let command = text.slice(1, text.length); + this._fieldKey = new Key(command) + // if (command == "Title" || command == "title") { + // this._fieldKey = KeyStore.Title; + // } + // else if (command == "Width" || command == "width") { + // this._fieldKey = KeyStore.Width; + // } + this._title = "changed" + // TODO: Change field with switch statement + } + else { + this._title = "changed"; + } + e.target.blur(); + } } @computed get Bounds(): { x: number, y: number, b: number, r: number } { + this._documents = SelectionManager.SelectedDocuments(); return SelectionManager.SelectedDocuments().reduce((bounds, documentView) => { if (documentView.props.isTopMost) { return bounds; @@ -91,6 +138,53 @@ export class DocumentDecorations extends React.Component { e.preventDefault(); } + onCloseDown = (e: React.PointerEvent): void => { + e.stopPropagation(); + if (e.button === 0) { + document.removeEventListener("pointermove", this.onCloseMove); + document.addEventListener("pointermove", this.onCloseMove); + document.removeEventListener("pointerup", this.onCloseUp); + document.addEventListener("pointerup", this.onCloseUp); + } + } + onCloseMove = (e: PointerEvent): void => { + e.stopPropagation(); + if (e.button === 0) { + } + } + @action + onCloseUp = (e: PointerEvent): void => { + e.stopPropagation(); + if (e.button === 0) { + SelectionManager.SelectedDocuments().map(dv => dv.props.RemoveDocument && dv.props.RemoveDocument(dv.props.Document)); + SelectionManager.DeselectAll(); + document.removeEventListener("pointermove", this.onCloseMove); + document.removeEventListener("pointerup", this.onCloseUp); + } + } + 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) { @@ -103,18 +197,40 @@ export class DocumentDecorations extends React.Component { } } - onLinkButtonDown = (e: React.PointerEvent): void => { - // if () - // let linkMenu = new LinkMenu(SelectionManager.SelectedDocuments()[0]); - // linkMenu.Hidden = false; - console.log("down"); + onLinkerButtonDown = (e: React.PointerEvent): void => { + e.stopPropagation(); + document.removeEventListener("pointermove", this.onLinkerButtonMoved) + document.addEventListener("pointermove", this.onLinkerButtonMoved); + document.removeEventListener("pointerup", this.onLinkerButtonUp) + document.addEventListener("pointerup", this.onLinkerButtonUp); + } + onLinkerButtonUp = (e: PointerEvent): void => { + document.removeEventListener("pointermove", this.onLinkerButtonMoved) + document.removeEventListener("pointerup", this.onLinkerButtonUp) + e.stopPropagation(); + } + + onLinkerButtonMoved = (e: PointerEvent): void => { + if (this._linkerButton.current != null) { + document.removeEventListener("pointermove", this.onLinkerButtonMoved) + document.removeEventListener("pointerup", this.onLinkerButtonUp) + let dragData = new DragManager.LinkDragData(SelectionManager.SelectedDocuments()[0]); + DragManager.StartLinkDrag(this._linkerButton.current, dragData, { + handlers: { + dragComplete: action(() => { }), + }, + hideSource: false + }) + } + e.stopPropagation(); + } + onLinkButtonDown = (e: React.PointerEvent): void => { e.stopPropagation(); document.removeEventListener("pointermove", this.onLinkButtonMoved) document.addEventListener("pointermove", this.onLinkButtonMoved); document.removeEventListener("pointerup", this.onLinkButtonUp) document.addEventListener("pointerup", this.onLinkButtonUp); - } onLinkButtonUp = (e: PointerEvent): void => { @@ -123,18 +239,35 @@ export class DocumentDecorations extends React.Component { e.stopPropagation(); } - - onLinkButtonMoved = (e: PointerEvent): void => { + onLinkButtonMoved = async (e: PointerEvent) => { if (this._linkButton.current != null) { document.removeEventListener("pointermove", this.onLinkButtonMoved) - document.removeEventListener("pointerup", this.onLinkButtonUp) - let dragData = new DragManager.LinkDragData(SelectionManager.SelectedDocuments()[0]); - DragManager.StartLinkDrag(this._linkButton.current, dragData, { - handlers: { - dragComplete: action(() => { }), - }, - hideSource: false - }) + document.removeEventListener("pointerup", this.onLinkButtonUp); + + let sourceDoc = SelectionManager.SelectedDocuments()[0].props.Document; + let srcTarg = sourceDoc.GetT(KeyStore.Prototype, Document) + let draggedDocs = (srcTarg && srcTarg != FieldWaiting) ? + srcTarg.GetList(KeyStore.LinkedToDocs, [] as Document[]).map(linkDoc => + (linkDoc.GetT(KeyStore.LinkedToDocs, Document)) as Document) : []; + let draggedFromDocs = (srcTarg && srcTarg != FieldWaiting) ? + srcTarg.GetList(KeyStore.LinkedFromDocs, [] as Document[]).map(linkDoc => + (linkDoc.GetT(KeyStore.LinkedFromDocs, Document)) as Document) : []; + draggedDocs.push(...draggedFromDocs); + if (draggedDocs.length) { + let moddrag = [] as Document[]; + for (let i = 0; i < draggedDocs.length; i++) { + let doc = await draggedDocs[i].GetTAsync(KeyStore.AnnotationOn, Document); + if (doc) + moddrag.push(doc); + } + let dragData = new DragManager.DocumentDragData(moddrag); + DragManager.StartDocumentDrag([this._linkButton.current], dragData, { + handlers: { + dragComplete: action(() => { }), + }, + hideSource: false + }) + } } e.stopPropagation(); } @@ -226,6 +359,19 @@ export class DocumentDecorations extends React.Component { } } + getValue = (): string => { + if (this._title === "changed" && this._documents.length > 0) { + let field = this._documents[0].props.Document.Get(this._fieldKey); + if (field instanceof TextField) { + return (field as TextField).GetValue(); + } + else if (field instanceof NumberField) { + return (field as NumberField).GetValue().toString(); + } + } + return this._title; + } + changeFlyoutContent = (): void => { } @@ -234,6 +380,8 @@ export class DocumentDecorations extends React.Component { // } render() { var bounds = this.Bounds; + // console.log(this._documents.length) + // let test = this._documents[0].props.Document.Title; if (this.Hidden) { return (null); } @@ -251,43 +399,45 @@ export class DocumentDecorations extends React.Component { linkButton = (<Flyout anchorPoint={anchorPoints.RIGHT_TOP} content={ - <LinkMenu docView={selFirst} changeFlyout={this.changeFlyoutContent}> - </LinkMenu> + <LinkMenu docView={selFirst} changeFlyout={this.changeFlyoutContent} /> }> <div className={"linkButton-" + (selFirst.props.Document.GetData(KeyStore.LinkedToDocs, ListField, []).length ? "nonempty" : "empty")} onPointerDown={this.onLinkButtonDown} >{linkCount}</div> </Flyout>); } - return ( - <div className="documentDecorations"> - <div className="documentDecorations-background" style={{ - width: (bounds.r - bounds.x + this._resizeBorderWidth) + "px", - height: (bounds.b - bounds.y + this._resizeBorderWidth) + "px", - left: bounds.x - this._resizeBorderWidth / 2, - top: bounds.y - this._resizeBorderWidth / 2, - pointerEvents: this._dragging ? "none" : "all", - zIndex: SelectionManager.SelectedDocuments().length > 1 ? 1000 : 0, - }} onPointerDown={this.onBackgroundDown} onContextMenu={(e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation() }} > - </div> - <div id="documentDecorations-container" style={{ - width: (bounds.r - bounds.x + this._resizeBorderWidth) + "px", - height: (bounds.b - bounds.y + this._resizeBorderWidth + 30) + "px", - left: bounds.x - this._resizeBorderWidth / 2, - top: bounds.y - this._resizeBorderWidth / 2, - }}> - <div id="documentDecorations-topLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div> - <div id="documentDecorations-topResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div> - <div id="documentDecorations-topRightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div> - <div id="documentDecorations-leftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div> - <div id="documentDecorations-centerCont"></div> - <div id="documentDecorations-rightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div> - <div id="documentDecorations-bottomLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div> - <div id="documentDecorations-bottomResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div> - <div id="documentDecorations-bottomRightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div> - - <div title="View Links" className="linkFlyout" ref={this._linkButton}>{linkButton}</div> - - </div > + return (<div className="documentDecorations"> + <div className="documentDecorations-background" style={{ + width: (bounds.r - bounds.x + this._resizeBorderWidth) + "px", + height: (bounds.b - bounds.y + this._resizeBorderWidth) + "px", + left: bounds.x - this._resizeBorderWidth / 2, + top: bounds.y - this._resizeBorderWidth / 2, + pointerEvents: this._dragging ? "none" : "all", + zIndex: SelectionManager.SelectedDocuments().length > 1 ? 1000 : 0, + }} onPointerDown={this.onBackgroundDown} onContextMenu={(e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation() }} > </div> + <div id="documentDecorations-container" style={{ + width: (bounds.r - bounds.x + this._resizeBorderWidth) + "px", + height: (bounds.b - bounds.y + this._resizeBorderWidth + this._linkBoxHeight + this._titleHeight) + "px", + left: bounds.x - this._resizeBorderWidth / 2, + top: bounds.y - this._resizeBorderWidth / 2 - this._titleHeight, + opacity: this._opacity + }}> + <div className="documentDecorations-minimizeButton" onPointerDown={this.onMinimizeDown}>...</div> + <input ref={this.keyinput} className="title" type="text" name="dynbox" value={this.getValue()} onChange={this.handleChange} onPointerDown={this.onPointerDown} onKeyPress={this.enterPressed} /> + <div className="documentDecorations-closeButton" onPointerDown={this.onCloseDown}>X</div> + <div id="documentDecorations-topLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div> + <div id="documentDecorations-topResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div> + <div id="documentDecorations-topRightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div> + <div id="documentDecorations-leftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div> + <div id="documentDecorations-centerCont"></div> + <div id="documentDecorations-rightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div> + <div id="documentDecorations-bottomLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div> + <div id="documentDecorations-bottomResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div> + <div id="documentDecorations-bottomRightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div> + + <div title="View Links" className="linkFlyout" ref={this._linkButton}> {linkButton} </div> + <div className="linkButton-linker" ref={this._linkerButton} onPointerDown={this.onLinkerButtonDown}>∞</div> + </div > + </div> ) } }
\ No newline at end of file diff --git a/src/client/views/InkingCanvas.scss b/src/client/views/InkingCanvas.scss index 35c8ee942..c5a2a50cb 100644 --- a/src/client/views/InkingCanvas.scss +++ b/src/client/views/InkingCanvas.scss @@ -2,6 +2,8 @@ .inkingCanvas-paths-ink, .inkingCanvas-paths-markers, .inkingCanvas-noSelect, .inkingCanvas-canSelect { position: absolute; + top: 0; + left:0; width: 8192px; height: 8192px; cursor:"crosshair"; diff --git a/src/client/views/InkingCanvas.tsx b/src/client/views/InkingCanvas.tsx index a2956f1b6..4b3ea48c5 100644 --- a/src/client/views/InkingCanvas.tsx +++ b/src/client/views/InkingCanvas.tsx @@ -134,7 +134,7 @@ export class InkingCanvas extends React.Component<InkCanvasProps> { {paths.filter(path => path.props.tool === InkTool.Highlighter)} </svg>, <svg className={`inkingCanvas-paths-ink`} key="Pens" - style={{ left: `-${this.inkMidX - this.maxCanvasDim}px`, top: `-${this.inkMidY - this.maxCanvasDim}px` }}> + style={{ left: `${this.inkMidX - this.maxCanvasDim}px`, top: `${this.inkMidY - this.maxCanvasDim}px` }}> {paths.filter(path => path.props.tool !== InkTool.Highlighter)} </svg>]; } diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss index 698a9c617..594803aab 100644 --- a/src/client/views/Main.scss +++ b/src/client/views/Main.scss @@ -7,6 +7,9 @@ body { overflow: hidden; font-family: $sans-serif; margin: 0; + position:absolute; + top: 0; + left:0; } #dash-title { @@ -158,11 +161,15 @@ button:hover { width:100%; height:100%; position:absolute; + top: 0; + left:0; } #mainContent-div { width:100%; height:100%; position:absolute; + top: 0; + left:0; } #add-options-content { display: table; diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss index 2706c3272..583d50c5b 100644 --- a/src/client/views/collections/CollectionDockingView.scss +++ b/src/client/views/collections/CollectionDockingView.scss @@ -3,7 +3,7 @@ } .collectiondockingview-container { - position: relative; + position: absolute; top: 0; left: 0; overflow: hidden; diff --git a/src/client/views/collections/CollectionPDFView.scss b/src/client/views/collections/CollectionPDFView.scss index 0144625c1..0eca3f1cd 100644 --- a/src/client/views/collections/CollectionPDFView.scss +++ b/src/client/views/collections/CollectionPDFView.scss @@ -9,6 +9,8 @@ width: 100%; height: 100%; position: absolute; + top: 0; + left:0; } .collectionPdfView-backward { diff --git a/src/client/views/collections/CollectionVideoView.scss b/src/client/views/collections/CollectionVideoView.scss index cbb981b13..ed56ad268 100644 --- a/src/client/views/collections/CollectionVideoView.scss +++ b/src/client/views/collections/CollectionVideoView.scss @@ -3,6 +3,8 @@ width: 100%; height: 100%; position: absolute; + top: 0; + left:0; } .collectionVideoView-time{ diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx index 147e5fd6b..b4784ae9c 100644 --- a/src/client/views/collections/CollectionViewBase.tsx +++ b/src/client/views/collections/CollectionViewBase.tsx @@ -72,7 +72,8 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps> if (de.data instanceof DragManager.DocumentDragData) { if (de.data.aliasOnDrop) { [KeyStore.Width, KeyStore.Height, KeyStore.CurPage].map(key => - de.data.draggedDocuments.GetTAsync(key, NumberField, (f: Opt<NumberField>) => f ? de.data.droppedDocument.SetNumber(key, f.Data) : null)); + de.data.draggedDocuments.map((draggedDocument: Document, i: number) => + draggedDocument.GetTAsync(key, NumberField, (f: Opt<NumberField>) => f ? de.data.droppedDocuments[i].SetNumber(key, f.Data) : null))); } let added = false; if (de.data.aliasOnDrop) { @@ -86,6 +87,24 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps> e.stopPropagation(); return added; } + if (de.data instanceof DragManager.LinkDragData) { + let sourceDoc: Document = de.data.linkSourceDocumentView.props.Document; + if (sourceDoc) runInAction(() => { + let srcTarg = sourceDoc.GetT(KeyStore.Prototype, Document) + if (srcTarg && srcTarg != FieldWaiting) { + let linkDocs = srcTarg.GetList(KeyStore.LinkedToDocs, [] as Document[]); + linkDocs.map(linkDoc => { + let targDoc = linkDoc.GetT(KeyStore.LinkedToDocs, Document); + if (targDoc && targDoc != FieldWaiting) { + let dropdoc = targDoc.MakeDelegate(); + de.data.droppedDocuments.push(dropdoc); + this.props.addDocument(dropdoc, false); + } + }) + } + }) + return true; + } return false; } @@ -102,6 +121,7 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps> } if (type.indexOf("pdf") !== -1) { ctor = Documents.PdfDocument; + options.nativeWidth = 1200; } if (type.indexOf("html") !== -1) { if (path.includes('localhost')) { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index e84f0c5ad..3dfd74ec8 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -23,10 +23,10 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo let l = this.props.LinkDocs; let a = this.props.A; let b = this.props.B; - let x1 = a.GetNumber(KeyStore.X, 0) + a.GetNumber(KeyStore.Width, 0) / 2; - let y1 = a.GetNumber(KeyStore.Y, 0) + a.GetNumber(KeyStore.Height, 0) / 2; - let x2 = b.GetNumber(KeyStore.X, 0) + b.GetNumber(KeyStore.Width, 0) / 2; - let y2 = b.GetNumber(KeyStore.Y, 0) + b.GetNumber(KeyStore.Height, 0) / 2; + let x1 = a.GetNumber(KeyStore.X, 0) + (a.GetBoolean(KeyStore.Minimized, false) ? 5 : a.GetNumber(KeyStore.Width, 0) / 2); + let y1 = a.GetNumber(KeyStore.Y, 0) + (a.GetBoolean(KeyStore.Minimized, false) ? 5 : a.GetNumber(KeyStore.Height, 0) / 2); + let x2 = b.GetNumber(KeyStore.X, 0) + (b.GetBoolean(KeyStore.Minimized, false) ? 5 : b.GetNumber(KeyStore.Width, 0) / 2); + let y2 = b.GetNumber(KeyStore.Y, 0) + (b.GetBoolean(KeyStore.Minimized, false) ? 5 : b.GetNumber(KeyStore.Height, 0) / 2); return ( <line key={Utils.GenerateGuid()} className="collectionfreeformlinkview-linkLine" onPointerDown={this.onPointerDown} style={{ strokeWidth: `${l.length * 5}` }} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.scss index 4341c82f7..30e158603 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.scss @@ -1,6 +1,8 @@ .collectionfreeformlinksview-svgCanvas{ transform: translate(-10000px,-10000px); position: absolute; + top: 0; + left: 0; width: 20000px; height: 20000px; pointer-events: none; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss index 81d21d89a..79d520069 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss @@ -26,7 +26,7 @@ border: 0px solid $light-color-secondary; border-radius: $border-radius; box-sizing: border-box; - position: relative; + position: absolute; overflow: hidden; top: 0; left: 0; @@ -41,12 +41,12 @@ .formattedTextBox-cont { background: $light-color-secondary; } - + opacity: 0.99; border: 0px solid transparent; border-radius: $border-radius; box-sizing: border-box; - position:relative; + position:absolute; overflow: hidden; top: 0; left: 0; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 4aad06607..19227f5e0 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -22,6 +22,7 @@ import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCurso import { PreviewCursor } from "./PreviewCursor"; import { DocumentManager } from "../../../util/DocumentManager"; import { SelectionManager } from "../../../util/SelectionManager"; +import { NumberField } from "../../../../fields/NumberField"; @observer export class CollectionFreeFormView extends CollectionViewBase { @@ -83,23 +84,32 @@ export class CollectionFreeFormView extends CollectionViewBase { drop = (e: Event, de: DragManager.DropEvent) => { if (super.drop(e, de)) { if (de.data instanceof DragManager.DocumentDragData) { - let screenX = de.x - (de.data.xOffset || 0); - let screenY = de.y - (de.data.yOffset || 0); - const [x, y] = this.getTransform().transformPoint(screenX, screenY); - let dragDoc = de.data.draggedDocuments[0]; - let dragX = dragDoc.GetNumber(KeyStore.X, 0); - let dragY = dragDoc.GetNumber(KeyStore.Y, 0); - de.data.draggedDocuments.map(d => { - let docX = d.GetNumber(KeyStore.X, 0); - let docY = d.GetNumber(KeyStore.Y, 0); - d.SetNumber(KeyStore.X, x + (docX - dragX)); - d.SetNumber(KeyStore.Y, y + (docY - dragY)); - if (!d.GetNumber(KeyStore.Width, 0)) { - d.SetNumber(KeyStore.Width, 300); - d.SetNumber(KeyStore.Height, 300); - } - this.bringToFront(d); - }) + let droppedDocs = de.data.droppedDocuments; + let xoff = de.data.xOffset as number || 0; + let yoff = de.data.yOffset as number || 0; + if (droppedDocs.length) { + let screenX = de.x - xoff; + let screenY = de.y - yoff; + const [x, y] = this.getTransform().transformPoint(screenX, screenY); + let dragDoc = droppedDocs[0]; + let dragX = dragDoc.GetNumber(KeyStore.X, 0); + let dragY = dragDoc.GetNumber(KeyStore.Y, 0); + droppedDocs.map(async d => { + let docX = d.GetNumber(KeyStore.X, 0); + let docY = d.GetNumber(KeyStore.Y, 0); + d.SetNumber(KeyStore.X, x + (docX - dragX)); + d.SetNumber(KeyStore.Y, y + (docY - dragY)); + let docW = await d.GetTAsync(KeyStore.Width, NumberField); + let docH = await d.GetTAsync(KeyStore.Height, NumberField); + if (!docW) { + d.SetNumber(KeyStore.Width, 300); + } + if (!docH) { + d.SetNumber(KeyStore.Height, 300); + } + this.bringToFront(d); + }) + } } return true; } diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.scss b/src/client/views/collections/collectionFreeForm/MarqueeView.scss index 1ee3b244b..0b406e722 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.scss +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.scss @@ -1,6 +1,8 @@ .marqueeView { position: absolute; + top:0; + left:0; width:100%; height:100%; } diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index b068d49d0..7022fd972 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -135,6 +135,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps> this.marqueeInkDelete(inkData); // }, 100); this.cleanupInteractions(); + SelectionManager.DeselectAll(); } } @action diff --git a/src/client/views/collections/collectionFreeForm/PreviewCursor.scss b/src/client/views/collections/collectionFreeForm/PreviewCursor.scss index 21210be2b..7a67c29bf 100644 --- a/src/client/views/collections/collectionFreeForm/PreviewCursor.scss +++ b/src/client/views/collections/collectionFreeForm/PreviewCursor.scss @@ -3,9 +3,13 @@ color: black; position: absolute; transform-origin: left top; + top: 0; + left:0; pointer-events: none; } .previewCursorView { + top: 0; + left:0; position: absolute; width:100%; height:100%; diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index ce453b4af..dcf82ccd4 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -64,8 +64,12 @@ export class CollectionFreeFormDocumentView extends React.Component<DocumentView return <DocumentView {...this.props} ContentScaling={this.contentScaling} ScreenToLocalTransform={this.getTransform} + PanelWidth={this.panelWidth} + PanelHeight={this.panelHeight} /> } + panelWidth = () => this.props.Document.GetBoolean(KeyStore.Minimized, false) ? 10 : this.props.PanelWidth(); + panelHeight = () => this.props.Document.GetBoolean(KeyStore.Minimized, false) ? 10 : this.props.PanelHeight(); render() { return ( diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss index 85a115f1c..5126e69f9 100644 --- a/src/client/views/nodes/DocumentView.scss +++ b/src/client/views/nodes/DocumentView.scss @@ -1,23 +1,43 @@ @import "../global_variables"; + .documentView-node { position: absolute; + top: 0; + left:0; background: $light-color; //overflow: hidden; + &.minimized { width: 30px; height: 30px; } + .top { background: #232323; height: 20px; cursor: pointer; } + .content { padding: 20px 20px; height: auto; box-sizing: border-box; } + .scroll-box { overflow-y: scroll; height: calc(100% - 20px); } } + +.minimized-box { + height: 10px; + width: 10px; + border-radius: 2px; + background: $dark-color +} + +.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 2a9b3b9ac..31adec0d7 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1,11 +1,13 @@ 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"; @@ -18,8 +20,6 @@ import { ContextMenu } from "../ContextMenu"; import { DocumentContentsView } from "./DocumentContentsView"; import "./DocumentView.scss"; import React = require("react"); -import { ServerUtils } from "../../../server/ServerUtil"; -import { CollectionViewType } from "../collections/CollectionBaseView"; export interface DocumentViewProps { @@ -39,8 +39,8 @@ export interface DocumentViewProps { onActiveChanged: (isActive: boolean) => void; } export interface JsxArgs extends DocumentViewProps { - Keys: { [name: string]: Key } - Fields: { [name: string]: Field } + Keys: { [name: string]: Key }; + Fields: { [name: string]: Field }; } /* @@ -59,16 +59,16 @@ Example usage of this function: } */ export function FakeJsxArgs(keys: string[], fields: string[] = []): JsxArgs { - let Keys: { [name: string]: any } = {} - let Fields: { [name: string]: any } = {} + let Keys: { [name: string]: any } = {}; + let Fields: { [name: string]: any } = {}; for (const key of keys) { - let fn = () => { } - Object.defineProperty(fn, "name", { value: key + "Key" }) + 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 }) + let fn = () => { }; + Object.defineProperty(fn, "name", { value: field }); Fields[field] = fn; } let args: JsxArgs = { @@ -80,8 +80,6 @@ export function FakeJsxArgs(keys: string[], fields: string[] = []): JsxArgs { return args; } - - @observer export class DocumentView extends React.Component<DocumentViewProps> { private _mainCont = React.createRef<HTMLDivElement>(); @@ -102,27 +100,29 @@ export class DocumentView extends React.Component<DocumentViewProps> { 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); + } else + CollectionDockingView.Instance.StartOtherDrag([this.props.Document], e); e.stopPropagation(); } else { if (this.active && !e.isDefaultPrevented()) { e.stopPropagation(); - document.removeEventListener("pointermove", this.onPointerMove) + document.removeEventListener("pointermove", this.onPointerMove); document.addEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp) + document.removeEventListener("pointerup", this.onPointerUp); document.addEventListener("pointerup", this.onPointerUp); } } - } + }; private dropDisposer?: DragManager.DragDropDisposer; componentDidMount() { if (this._mainCont.current) { - this.dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, { handlers: { drop: this.drop.bind(this) } }); + this.dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, { + handlers: { drop: this.drop.bind(this) } + }); } - runInAction(() => DocumentManager.Instance.DocumentViews.push(this)) + runInAction(() => DocumentManager.Instance.DocumentViews.push(this)); } componentDidUpdate() { @@ -130,7 +130,9 @@ export class DocumentView extends React.Component<DocumentViewProps> { this.dropDisposer(); } if (this._mainCont.current) { - this.dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, { handlers: { drop: this.drop.bind(this) } }); + this.dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, { + handlers: { drop: this.drop.bind(this) } + }); } } @@ -138,12 +140,15 @@ export class DocumentView extends React.Component<DocumentViewProps> { if (this.dropDisposer) { this.dropDisposer(); } - runInAction(() => DocumentManager.Instance.DocumentViews.splice(DocumentManager.Instance.DocumentViews.indexOf(this), 1)) + runInAction(() => DocumentManager.Instance.DocumentViews.splice(DocumentManager.Instance.DocumentViews.indexOf(this), 1)); } startDragging(x: number, y: number, dropAliasOfDraggedDoc: boolean) { if (this._mainCont.current) { - const [left, top] = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0); + 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; @@ -151,10 +156,10 @@ export class DocumentView extends React.Component<DocumentViewProps> { dragData.moveDocument = this.props.moveDocument; DragManager.StartDocumentDrag([this._mainCont.current], dragData, { handlers: { - dragComplete: action(() => { }), + dragComplete: action(() => { }) }, hideSource: !dropAliasOfDraggedDoc - }) + }); } } @@ -162,52 +167,74 @@ export class DocumentView extends React.Component<DocumentViewProps> { if (e.cancelBubble) { return; } - if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) { - document.removeEventListener("pointermove", this.onPointerMove) + 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) { + 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) + 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) { + if (!SelectionManager.IsSelected(this) && + 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); } - } + }; 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) - } + 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) - } + 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, + BooleanField + ); + SelectionManager.DeselectAll(); + }; @action drop = (e: Event, de: DragManager.DropEvent) => { @@ -219,23 +246,37 @@ export class DocumentView extends React.Component<DocumentViewProps> { } 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<Document>).Data.push(linkDoc) }) - srcTarg.GetOrCreateAsync(KeyStore.LinkedToDocs, ListField, field => { (field as ListField<Document>).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<Document>).Data.push(linkDoc); + } + ); + srcTarg.GetOrCreateAsync( + KeyStore.LinkedToDocs, + ListField, + field => { + (field as ListField<Document>).Data.push(linkDoc); + } + ); + }) + ) + ); e.stopPropagation(); } - } + }; onDrop = (e: React.DragEvent) => { if (e.isDefaultPrevented()) { @@ -249,22 +290,43 @@ export class DocumentView extends React.Component<DocumentViewProps> { e.stopPropagation(); 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; + let moved = + Math.abs(this._downX - e.clientX) > 3 || + Math.abs(this._downY - e.clientY) > 3; if (moved || e.isDefaultPrevented()) { - e.preventDefault() + e.preventDefault(); return; } - e.preventDefault() + e.preventDefault(); - 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) }) + 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: () => { @@ -278,46 +340,93 @@ export class DocumentView extends React.Component<DocumentViewProps> { } }); //ContextMenu.Instance.addItem({ description: "Docking", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Docking) }) - ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) + 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) + 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, BooleanField); + if (field && field !== FieldWaiting) { + return field.Data; + } + }; + @action + expand = () => { + this.props.Document.SetData( + KeyStore.Minimized, + false as boolean, + BooleanField + ); + }; isSelected = () => SelectionManager.IsSelected(this) select = (ctrlPressed: boolean) => { - SelectionManager.SelectDoc(this, ctrlPressed) - } + SelectionManager.SelectDoc(this, ctrlPressed); + }; render() { if (!this.props.Document) { - return (null); + 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 ( - <div className="documentView-node" ref={this._mainCont} - style={{ - background: backgroundcolor, - width: nativeWidth > 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} > - <DocumentContentsView {...this.props} isSelected={this.isSelected} select={this.select} layoutKey={KeyStore.Layout} /> - </div > - ) + + if (this.isMinimized()) { + return ( + <div + className="minimized-box" + ref={this._mainCont} + style={{ + transformOrigin: "left top", + transform: `scale(${scaling} , ${scaling})` + }} + onClick={this.expand} + onDrop={this.onDrop} + onPointerDown={this.onPointerDown} + /> + ); + } else { + var backgroundcolor = this.props.Document.GetText( + KeyStore.BackgroundColor, + "" + ); + return ( + <div + className="documentView-node" + ref={this._mainCont} + style={{ + background: backgroundcolor, + width: nativeWidth > 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} + > + <DocumentContentsView + {...this.props} + isSelected={this.isSelected} + select={this.select} + layoutKey={KeyStore.Layout} + /> + </div> + ); + } } -}
\ No newline at end of file +} diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 99ba9addc..263343da0 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -3,28 +3,25 @@ import { baseKeymap } from "prosemirror-commands"; import { history, redo, undo } from "prosemirror-history"; import { keymap } from "prosemirror-keymap"; import { schema } from "../../util/RichTextSchema"; -import { EditorState, Transaction, } from "prosemirror-state"; +import { EditorState, Transaction } from "prosemirror-state"; import { EditorView } from "prosemirror-view"; import { Opt, FieldWaiting } from "../../../fields/Field"; import "./FormattedTextBox.scss"; -import React = require("react") +import React = require("react"); import { RichTextField } from "../../../fields/RichTextField"; import { FieldViewProps, FieldView } from "./FieldView"; -import { Plugin } from 'prosemirror-state' -import { Decoration, DecorationSet } from 'prosemirror-view' -import { TooltipTextMenu } from "../../util/TooltipTextMenu" +import { Plugin } from "prosemirror-state"; +import { Decoration, DecorationSet } from "prosemirror-view"; +import { TooltipTextMenu } from "../../util/TooltipTextMenu"; import { ContextMenu } from "../../views/ContextMenu"; import { inpRules } from "../../util/RichTextRules"; const { buildMenuItems } = require("prosemirror-example-setup"); const { menuBar } = require("prosemirror-menu"); - - - // FormattedTextBox: Displays an editable plain text node that maps to a specified Key of a Document // // HTML Markup: <FormattedTextBox Doc={Document's ID} FieldKey={Key's name + "Key"} -// +// // In Code, the node's HTML is specified in the document's parameterized structure as: // document.SetField(KeyStore.Layout, "<FormattedTextBox doc={doc} fieldKey={<KEYNAME>Key} />"); // and the node's binding to the specified document KEYNAME as: @@ -33,13 +30,14 @@ const { menuBar } = require("prosemirror-menu"); // 'fieldKey' property to the Key stored in LayoutKeys // and 'doc' property to the document that is being rendered // -// When rendered() by React, this extracts the TextController from the Document stored at the -// specified Key and assigns it to an HTML input node. When changes are made to this node, +// When rendered() by React, this extracts the TextController from the Document stored at the +// specified Key and assigns it to an HTML input node. When changes are made to this node, // this will edit the document and assign the new value to that field. //] export class FormattedTextBox extends React.Component<FieldViewProps> { - - public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(FormattedTextBox, fieldStr) } + public static LayoutString(fieldStr: string = "DataKey") { + return FieldView.LayoutString(FormattedTextBox, fieldStr); + } private _ref: React.RefObject<HTMLDivElement>; private _editorView: Opt<EditorView>; private _reactionDisposer: Opt<IReactionDisposer>; @@ -55,11 +53,15 @@ export class FormattedTextBox extends React.Component<FieldViewProps> { if (this._editorView) { const state = this._editorView.state.apply(tx); this._editorView.updateState(state); - const { Document: doc, fieldKey } = this.props; - doc.SetDataOnPrototype(fieldKey, JSON.stringify(state.toJSON()), RichTextField); + const { Document, fieldKey } = this.props; + Document.SetDataOnPrototype( + fieldKey, + JSON.stringify(state.toJSON()), + RichTextField + ); // doc.SetData(fieldKey, JSON.stringify(state.toJSON()), RichTextField); } - } + }; componentDidMount() { let state: EditorState; @@ -75,7 +77,7 @@ export class FormattedTextBox extends React.Component<FieldViewProps> { }; let field = this.props.Document.GetT(this.props.fieldKey, RichTextField); - if (field && field != FieldWaiting && field.Data) { + if (field && field !== FieldWaiting && field.Data) { state = EditorState.fromJSON(config, JSON.parse(field.Data)); } else { state = EditorState.create(config); @@ -87,14 +89,19 @@ export class FormattedTextBox extends React.Component<FieldViewProps> { }); } - this._reactionDisposer = reaction(() => { - const field = this.props.Document.GetT(this.props.fieldKey, RichTextField); - return field && field != FieldWaiting ? field.Data : undefined; - }, (field) => { - if (field && this._editorView) { - this._editorView.updateState(EditorState.fromJSON(config, JSON.parse(field))); + this._reactionDisposer = reaction( + () => { + const field = this.props.Document.GetT(this.props.fieldKey, RichTextField); + return field && field !== FieldWaiting ? field.Data : undefined; + }, + field => { + if (field && this._editorView) { + this._editorView.updateState( + EditorState.fromJSON(config, JSON.parse(field)) + ); + } } - }) + ); if (this.props.selectOnLoad) { this.props.select(false); this._editorView!.focus(); @@ -116,22 +123,25 @@ export class FormattedTextBox extends React.Component<FieldViewProps> { @action onChange(e: React.ChangeEvent<HTMLInputElement>) { - const { fieldKey, Document: doc } = this.props; - doc.SetOnPrototype(fieldKey, new RichTextField(e.target.value)) + const { fieldKey, Document } = this.props; + Document.SetOnPrototype(fieldKey, new RichTextField(e.target.value)); // doc.SetData(fieldKey, e.target.value, RichTextField); } onPointerDown = (e: React.PointerEvent): void => { if (e.buttons === 1 && this.props.isSelected() && !e.altKey) { e.stopPropagation(); } - } + }; //REPLACE THIS WITH CAPABILITIES SPECIFIC TO THIS TYPE OF NODE - textCapability = (e: React.MouseEvent): void => { - } + textCapability = (e: React.MouseEvent): void => { }; specificContextMenu = (e: React.MouseEvent): void => { - ContextMenu.Instance.addItem({ description: "Text Capability", event: this.textCapability }); + ContextMenu.Instance.addItem({ + description: "Text Capability", + event: this.textCapability + }); + // ContextMenu.Instance.addItem({ // description: "Submenu", // items: [ @@ -144,19 +154,18 @@ export class FormattedTextBox extends React.Component<FieldViewProps> { // ] // }) // e.stopPropagation() - - } + }; onPointerWheel = (e: React.WheelEvent): void => { e.stopPropagation(); - } + }; tooltipMenuPlugin() { return new Plugin({ view(_editorView) { - return new TooltipTextMenu(_editorView) + return new TooltipTextMenu(_editorView); } - }) + }); } onKeyPress(e: React.KeyboardEvent) { e.stopPropagation(); @@ -165,13 +174,17 @@ export class FormattedTextBox extends React.Component<FieldViewProps> { // (e.nativeEvent as any).DASHFormattedTextBoxHandled = true; } render() { - return (<div className="formattedTextBox-cont" - onKeyDown={this.onKeyPress} - onKeyPress={this.onKeyPress} - onPointerDown={this.onPointerDown} - onContextMenu={this.specificContextMenu} - // tfs: do we need this event handler - onWheel={this.onPointerWheel} - ref={this._ref} />) + return ( + <div + className="formattedTextBox-cont" + onKeyDown={this.onKeyPress} + onKeyPress={this.onKeyPress} + onPointerDown={this.onPointerDown} + onContextMenu={this.specificContextMenu} + // tfs: do we need this event handler + onWheel={this.onPointerWheel} + ref={this._ref} + /> + ); } -}
\ No newline at end of file +} diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss index ad947afd5..830dfe6c6 100644 --- a/src/client/views/nodes/PDFBox.scss +++ b/src/client/views/nodes/PDFBox.scss @@ -1,12 +1,16 @@ .react-pdf__Page { transform-origin: left top; position: absolute; + top: 0; + left:0; } .react-pdf__Document { position: absolute; } .pdfBox-buttonTray { position:absolute; + top: 0; + left:0; z-index: 25; } .pdfBox-contentContainer { diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 66c9f477e..d1fb06153 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -1,5 +1,5 @@ import * as htmlToImage from "html-to-image"; -import { action, computed, observable, reaction, IReactionDisposer, trace, keys } from 'mobx'; +import { action, computed, IReactionDisposer, observable, reaction } from 'mobx'; import { observer } from "mobx-react"; import 'react-image-lightbox/style.css'; import Measure from "react-measure"; @@ -10,6 +10,7 @@ import { FieldWaiting, Opt } from '../../../fields/Field'; import { ImageField } from '../../../fields/ImageField'; import { KeyStore } from '../../../fields/KeyStore'; import { PDFField } from '../../../fields/PDFField'; +import { RouteStore } from "../../../server/RouteStore"; import { Utils } from '../../../Utils'; import { Annotation } from './Annotation'; import { FieldView, FieldViewProps } from './FieldView'; @@ -17,8 +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 { RouteStore } from "../../../server/RouteStore"; -import { NumberField } from "../../../fields/NumberField"; +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, @@ -58,6 +58,8 @@ export class PDFBox extends React.Component<FieldViewProps> { private _mainDiv = React.createRef<HTMLDivElement>() private _pdf = React.createRef<HTMLCanvasElement>(); + @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; @@ -92,9 +94,9 @@ export class PDFBox extends React.Component<FieldViewProps> { 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; } @@ -376,18 +378,21 @@ export class PDFBox extends React.Component<FieldViewProps> { @action saveThumbnail = () => { + this._renderAsSvg = false; setTimeout(() => { var me = this; - htmlToImage.toPng(this._mainDiv.current!, - { width: me.props.Document.GetNumber(KeyStore.NativeWidth, 0), height: me.props.Document.GetNumber(KeyStore.NativeHeight, 0), quality: 0.5 }) - .then(function (dataUrl: string) { + let nwidth = me.props.Document.GetNumber(KeyStore.NativeWidth, 0); + let nheight = me.props.Document.GetNumber(KeyStore.NativeHeight, 0); + htmlToImage.toPng(this._mainDiv.current!, { width: nwidth, height: nheight, quality: 1 }) + .then(action((dataUrl: string) => { me.props.Document.SetData(KeyStore.Thumbnail, new URL(dataUrl), ImageField); me.props.Document.SetNumber(KeyStore.ThumbnailPage, me.props.Document.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<FieldViewProps> { this.props.Document.SetNumber(KeyStore.Height, nativeHeight / nativeWidth * this.props.Document.GetNumber(KeyStore.Width, 0)); this.props.Document.SetNumber(KeyStore.NativeHeight, nativeHeight); } - if (!this.props.Document.GetT(KeyStore.Thumbnail, ImageField)) { - this.saveThumbnail(); - } } @computed @@ -439,7 +441,7 @@ export class PDFBox extends React.Component<FieldViewProps> { let pdfUrl = this.props.Document.GetT(this.props.fieldKey, PDFField); let xf = this.props.Document.GetNumber(KeyStore.NativeHeight, 0) / renderHeight; return <div className="pdfBox-contentContainer" key="container" style={{ transform: `scale(${xf}, ${xf})` }}> - <Document file={window.origin + RouteStore.corsProxy + `/${pdfUrl}`}> + <Document file={window.origin + RouteStore.corsProxy + `/${pdfUrl}`} renderMode={this._renderAsSvg ? "svg" : ""}> <Measure onResize={this.setScaling}> {({ measureRef }) => <div className="pdfBox-page" ref={measureRef}> 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<IProps> { + private initX: number = 0; + private initY: number = 0; - private initX: number = 0; - private initY: number = 0; + private _ref = React.createRef<HTMLCanvasElement>(); + private ctx: any; //context that keeps track of sticky canvas - private _ref = React.createRef<HTMLCanvasElement>(); - 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 ( - <div onPointerDown={this.drawDown}> - <canvas ref={this._ref} height={this.props.Height} width={this.props.Width} - style={{ - position: "absolute", - top: "20px", - left: "0px", - zIndex: 1, - background: "yellow", - transform: `translate(${this.props.X}px, ${this.props.Y}px)`, - opacity: 0.4 - }} - /> - - </div> - ); - } -}
\ No newline at end of file + render() { + return ( + <div onPointerDown={this.drawDown}> + <canvas + ref={this._ref} + height={this.props.Height} + width={this.props.Width} + style={{ + position: "absolute", + top: "20px", + left: "0px", + zIndex: 1, + background: "yellow", + transform: `translate(${this.props.X}px, ${this.props.Y}px)`, + opacity: 0.4 + }} + /> + </div> + ); + } +} diff --git a/src/client/views/nodes/WebBox.scss b/src/client/views/nodes/WebBox.scss index a535b2638..c73bc0c47 100644 --- a/src/client/views/nodes/WebBox.scss +++ b/src/client/views/nodes/WebBox.scss @@ -2,6 +2,8 @@ .webBox-cont { padding: 0vw; position: absolute; + top: 0; + left:0; width: 100%; height: 100%; overflow: scroll; 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<boolean> { + 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/Document.ts b/src/fields/Document.ts index 6d13c96b8..8eca5e30c 100644 --- a/src/fields/Document.ts +++ b/src/fields/Document.ts @@ -1,6 +1,6 @@ -import { Key } from "./Key" +import { Key } from "./Key"; import { KeyStore } from "./KeyStore"; -import { Field, Cast, FieldWaiting, FieldValue, FieldId, Opt } from "./Field" +import { Field, Cast, FieldWaiting, FieldValue, FieldId, Opt } from "./Field"; import { NumberField } from "./NumberField"; import { ObservableMap, computed, action, runInAction } from "mobx"; import { TextField } from "./TextField"; @@ -9,17 +9,21 @@ import { Server } from "../client/Server"; import { Types } from "../server/Message"; import { UndoManager } from "../client/util/UndoManager"; import { HtmlField } from "./HtmlField"; +import { BooleanField } from "./BooleanField"; export class Document extends Field { //TODO tfs: We should probably store FieldWaiting in fields when we request it from the server so that we don't set up multiple server gets for the same document and field - public fields: ObservableMap<string, { key: Key, field: Field }> = new ObservableMap(); + public fields: ObservableMap< + string, + { key: Key; field: Field } + > = new ObservableMap(); public _proxies: ObservableMap<string, FieldId> = new ObservableMap(); constructor(id?: string, save: boolean = true) { - super(id) + super(id); if (save) { - Server.UpdateField(this) + Server.UpdateField(this); } } @@ -31,20 +35,19 @@ export class Document extends Field { } public Width = () => this.GetNumber(KeyStore.Width, 0) - public Height = () => this.GetNumber(KeyStore.Height, this.GetNumber(KeyStore.NativeWidth, 0) ? this.GetNumber(KeyStore.NativeHeight, 0) / this.GetNumber(KeyStore.NativeWidth, 0) * this.GetNumber(KeyStore.Width, 0) : 0) + public Height = () => this.GetNumber(KeyStore.Height, this.GetNumber(KeyStore.NativeWidth, 0) ? (this.GetNumber(KeyStore.NativeHeight, 0) / this.GetNumber(KeyStore.NativeWidth, 0)) * this.GetNumber(KeyStore.Width, 0) : 0); public Scale = () => this.GetNumber(KeyStore.Scale, 1) @computed public get Title(): string { let title = this.Get(KeyStore.Title, true); if (title) - if (title != FieldWaiting && title instanceof TextField) + if (title !== FieldWaiting && title instanceof TextField) return title.Data; else return "-waiting-"; let parTitle = this.GetT(KeyStore.Title, TextField); if (parTitle) - if (parTitle != FieldWaiting) - return parTitle.Data + ".alias"; + if (parTitle !== FieldWaiting) return parTitle.Data + ".alias"; else return "-waiting-.alias"; return "-untitled-"; } @@ -57,7 +60,7 @@ export class Document extends Field { /** * Get the field in the document associated with the given key. If the * associated field has not yet been filled in from the server, a request - * to the server will automatically be sent, the value will be filled in + * to the server will automatically be sent, the value will be filled in * when the request is completed, and {@link Field.ts#FieldWaiting} will be returned. * @param key - The key of the value to get * @param ignoreProto - If true, ignore any prototype this document @@ -65,7 +68,7 @@ export class Document extends Field { * If false (default), search up the prototype chain, starting at this document, * for a document that has a field associated with the given key, and return the first * one found. - * + * * @returns If the document does not have a field associated with the given key, returns `undefined`. * If the document does have an associated field, but the field has not been fetched from the server, returns {@link Field.ts#FieldWaiting}. * If the document does have an associated field, and the field has not been fetched from the server, returns the associated field. @@ -78,10 +81,10 @@ export class Document extends Field { } else if (this._proxies.has(key.Id)) { Server.GetDocumentField(this, key); /* - The field might have been instantly filled from the cache - Maybe we want to just switch back to returning the value - from Server.GetDocumentField if it's in the cache - */ + The field might have been instantly filled from the cache + Maybe we want to just switch back to returning the value + from Server.GetDocumentField if it's in the cache + */ if (this.fields.has(key.Id)) { field = this.fields.get(key.Id)!.field; } else { @@ -97,10 +100,10 @@ export class Document extends Field { if (curProxy) { Server.GetDocumentField(doc, key); /* - The field might have been instantly filled from the cache - Maybe we want to just switch back to returning the value - from Server.GetDocumentField if it's in the cache - */ + The field might have been instantly filled from the cache + Maybe we want to just switch back to returning the value + from Server.GetDocumentField if it's in the cache + */ if (this.fields.has(key.Id)) { field = this.fields.get(key.Id)!.field; } else { @@ -108,7 +111,10 @@ export class Document extends Field { } break; } - if ((doc.fields.has(KeyStore.Prototype.Id) || doc._proxies.has(KeyStore.Prototype.Id))) { + if ( + doc.fields.has(KeyStore.Prototype.Id) || + doc._proxies.has(KeyStore.Prototype.Id) + ) { doc = doc.GetPrototype(); } else { break; @@ -118,8 +124,7 @@ export class Document extends Field { break; } } - if (doc === FieldWaiting) - field = FieldWaiting; + if (doc === FieldWaiting) field = FieldWaiting; } return field; @@ -148,20 +153,28 @@ export class Document extends Field { } else { callback(undefined); } - }) + }); } else { callback(undefined); } } GetTAsync<T extends Field>(key: Key, ctor: { new(): T }): Promise<Opt<T>>; - GetTAsync<T extends Field>(key: Key, ctor: { new(): T }, callback: (field: Opt<T>) => void): void; - GetTAsync<T extends Field>(key: Key, ctor: { new(): T }, callback?: (field: Opt<T>) => void): Promise<Opt<T>> | void { + GetTAsync<T extends Field>( + key: Key, + ctor: { new(): T }, + callback: (field: Opt<T>) => void + ): void; + GetTAsync<T extends Field>( + key: Key, + ctor: { new(): T }, + callback?: (field: Opt<T>) => void + ): Promise<Opt<T>> | void { let fn = (cb: (field: Opt<T>) => void) => { - return this.GetAsync(key, (field) => { + return this.GetAsync(key, field => { cb(Cast(field, ctor)); }); - } + }; if (callback) { fn(callback); } else { @@ -175,10 +188,14 @@ export class Document extends Field { * or the field associated with the given key is not of the given type. * @param ctor - Constructor of the field type to get. E.g., TextField, ImageField, etc. */ - GetOrCreateAsync<T extends Field>(key: Key, ctor: { new(): T }, callback: (field: T) => void): void { + GetOrCreateAsync<T extends Field>( + key: Key, + ctor: { new(): T }, + callback: (field: T) => void + ): void { //This currently doesn't deal with prototypes if (this._proxies.has(key.Id)) { - Server.GetDocumentField(this, key, (field) => { + Server.GetDocumentField(this, key, field => { if (field && field instanceof ctor) { callback(field); } else { @@ -201,17 +218,25 @@ export class Document extends Field { * @returns Same as {@link Document#Get}, except will return `undefined` * if there is an associated field but it is of the wrong type. */ - GetT<T extends Field = Field>(key: Key, ctor: { new(...args: any[]): T }, ignoreProto: boolean = false): FieldValue<T> { + GetT<T extends Field = Field>( + key: Key, + ctor: { new(...args: any[]): T }, + ignoreProto: boolean = false + ): FieldValue<T> { var getfield = this.Get(key, ignoreProto); - if (getfield != FieldWaiting) { + if (getfield !== FieldWaiting) { return Cast(getfield, ctor); } return FieldWaiting; } - GetOrCreate<T extends Field>(key: Key, ctor: { new(): T }, ignoreProto: boolean = false): T { + GetOrCreate<T extends Field>( + key: Key, + ctor: { new(): T }, + ignoreProto: boolean = false + ): T { const field = this.GetT(key, ctor, ignoreProto); - if (field && field != FieldWaiting) { + if (field && field !== FieldWaiting) { return field; } const newField = new ctor(); @@ -219,9 +244,13 @@ export class Document extends Field { return newField; } - GetData<T, U extends Field & { Data: T }>(key: Key, ctor: { new(): U }, defaultVal: T): T { + GetData<T, U extends Field & { Data: T }>( + key: Key, + ctor: { new(): U }, + defaultVal: T + ): T { let val = this.Get(key); - let vval = (val && val instanceof ctor) ? val.Data : defaultVal; + let vval = val && val instanceof ctor ? val.Data : defaultVal; return vval; } @@ -229,6 +258,10 @@ export class Document extends Field { return this.GetData(key, HtmlField, defaultVal); } + GetBoolean(key: Key, defaultVal: boolean): boolean { + return this.GetData(key, BooleanField, defaultVal); + } + GetNumber(key: Key, defaultVal: number): number { return this.GetData(key, NumberField, defaultVal); } @@ -238,7 +271,7 @@ export class Document extends Field { } GetList<T extends Field>(key: Key, defaultVal: T[]): T[] { - return this.GetData<T[], ListField<T>>(key, ListField, defaultVal) + return this.GetData<T[], ListField<T>>(key, ListField, defaultVal); } @action @@ -246,16 +279,15 @@ export class Document extends Field { let old = this.fields.get(key.Id); let oldField = old ? old.field : undefined; if (setOnPrototype) { - this.SetOnPrototype(key, field) - } - else { + this.SetOnPrototype(key, field); + } else { if (field) { this.fields.set(key.Id, { key, field }); - this._proxies.set(key.Id, field.Id) + this._proxies.set(key.Id, field.Id); // Server.AddDocumentField(this, key, field); } else { this.fields.delete(key.Id); - this._proxies.delete(key.Id) + this._proxies.delete(key.Id); // Server.DeleteDocumentField(this, key); } Server.UpdateField(this); @@ -264,26 +296,36 @@ export class Document extends Field { UndoManager.AddEvent({ undo: () => this.Set(key, oldField, setOnPrototype), redo: () => this.Set(key, field, setOnPrototype) - }) + }); } } @action SetOnPrototype(key: Key, field: Field | undefined): void { this.GetTAsync(KeyStore.Prototype, Document, (f: Opt<Document>) => { - f && f.Set(key, field) - }) + f && f.Set(key, field); + }); } @action - SetDataOnPrototype<T, U extends Field & { Data: T }>(key: Key, value: T, ctor: { new(): U }, replaceWrongType = true) { + SetDataOnPrototype<T, U extends Field & { Data: T }>( + key: Key, + value: T, + ctor: { new(): U }, + replaceWrongType = true + ) { this.GetTAsync(KeyStore.Prototype, Document, (f: Opt<Document>) => { - f && f.SetData(key, value, ctor) - }) + f && f.SetData(key, value, ctor); + }); } @action - SetData<T, U extends Field & { Data: T }>(key: Key, value: T, ctor: { new(data: T): U }, replaceWrongType = true) { + SetData<T, U extends Field & { Data: T }>( + key: Key, + value: T, + ctor: { new(data: T): U }, + replaceWrongType = true + ) { let field = this.Get(key, true); if (field instanceof ctor) { field.Data = value; @@ -311,7 +353,7 @@ export class Document extends Field { GetAllPrototypes(): Document[] { let protos: Document[] = []; let doc: FieldValue<Document> = this; - while (doc && doc != FieldWaiting) { + while (doc && doc !== FieldWaiting) { protos.push(doc); doc = doc.GetPrototype(); } @@ -319,12 +361,12 @@ export class Document extends Field { } CreateAlias(id?: string): Document { - let alias = new Document(id) + let alias = new Document(id); this.GetTAsync(KeyStore.Prototype, Document, (f: Opt<Document>) => { - f && alias.Set(KeyStore.Prototype, f) - }) + f && alias.Set(KeyStore.Prototype, f); + }); - return alias + return alias; } MakeDelegate(id?: string): Document { @@ -344,7 +386,11 @@ export class Document extends Field { } GetValue() { return this.Title; - var title = (this._proxies.has(KeyStore.Title.Id) ? "???" : this.Title) + "(" + this.Id + ")"; + var title = + (this._proxies.has(KeyStore.Title.Id) ? "???" : this.Title) + + "(" + + this.Id + + ")"; return title; //throw new Error("Method not implemented."); } @@ -352,11 +398,11 @@ export class Document extends Field { throw new Error("Method not implemented."); } - ToJson(): { type: Types, data: [string, string][], _id: string } { - let fields: [string, string][] = [] + ToJson(): { type: Types; data: [string, string][]; _id: string } { + let fields: [string, string][] = []; this._proxies.forEach((field, key) => { if (field) { - fields.push([key, field]) + fields.push([key, field]); } }); @@ -364,6 +410,6 @@ export class Document extends Field { type: Types.Document, data: fields, _id: this.Id - } + }; } -}
\ No newline at end of file +} diff --git a/src/fields/KeyStore.ts b/src/fields/KeyStore.ts index 1f039e592..6ed3b1604 100644 --- a/src/fields/KeyStore.ts +++ b/src/fields/KeyStore.ts @@ -1,48 +1,50 @@ import { Key } from "./Key"; +import { KeyTransfer } from "../server/Message"; export namespace KeyStore { - export const Prototype = new Key("Prototype"); - export const X = new Key("X"); - export const Y = new Key("Y"); - export const Page = new Key("Page"); - export const Title = new Key("Title"); - export const Author = new Key("Author"); - export const PanX = new Key("PanX"); - export const PanY = new Key("PanY"); - export const Scale = new Key("Scale"); - export const NativeWidth = new Key("NativeWidth"); - export const NativeHeight = new Key("NativeHeight"); - export const Width = new Key("Width"); - export const Height = new Key("Height"); - export const ZIndex = new Key("ZIndex"); - export const Data = new Key("Data"); - export const Annotations = new Key("Annotations"); - export const ViewType = new Key("ViewType"); - export const Layout = new Key("Layout"); - export const BackgroundColor = new Key("BackgroundColor"); - export const BackgroundLayout = new Key("BackgroundLayout"); - export const OverlayLayout = new Key("OverlayLayout"); - export const LayoutKeys = new Key("LayoutKeys"); - export const LayoutFields = new Key("LayoutFields"); - export const ColumnsKey = new Key("SchemaColumns"); - export const SchemaSplitPercentage = new Key("SchemaSplitPercentage"); - export const Caption = new Key("Caption"); - export const ActiveWorkspace = new Key("ActiveWorkspace"); - export const DocumentText = new Key("DocumentText"); - export const BrushingDocs = new Key("BrushingDocs"); - export const LinkedToDocs = new Key("LinkedToDocs"); - export const LinkedFromDocs = new Key("LinkedFromDocs"); - export const LinkDescription = new Key("LinkDescription"); - export const LinkTags = new Key("LinkTag"); - export const Thumbnail = new Key("Thumbnail"); - export const ThumbnailPage = new Key("ThumbnailPage"); - export const CurPage = new Key("CurPage"); - export const AnnotationOn = new Key("AnnotationOn"); - export const NumPages = new Key("NumPages"); - export const Ink = new Key("Ink"); - export const Cursors = new Key("Cursors"); - export const OptionalRightCollection = new Key("OptionalRightCollection"); - export const Archives = new Key("Archives"); - export const Updated = new Key("Updated"); - export const Workspaces = new Key("Workspaces"); + export const Prototype = new Key("Prototype"); + export const X = new Key("X"); + export const Y = new Key("Y"); + export const Page = new Key("Page"); + export const Title = new Key("Title"); + export const Author = new Key("Author"); + export const PanX = new Key("PanX"); + export const PanY = new Key("PanY"); + export const Scale = new Key("Scale"); + export const NativeWidth = new Key("NativeWidth"); + export const NativeHeight = new Key("NativeHeight"); + export const Width = new Key("Width"); + export const Height = new Key("Height"); + export const ZIndex = new Key("ZIndex"); + export const Data = new Key("Data"); + export const Annotations = new Key("Annotations"); + export const ViewType = new Key("ViewType"); + export const Layout = new Key("Layout"); + export const BackgroundColor = new Key("BackgroundColor"); + export const BackgroundLayout = new Key("BackgroundLayout"); + export const OverlayLayout = new Key("OverlayLayout"); + export const LayoutKeys = new Key("LayoutKeys"); + export const LayoutFields = new Key("LayoutFields"); + export const ColumnsKey = new Key("SchemaColumns"); + export const SchemaSplitPercentage = new Key("SchemaSplitPercentage"); + export const Caption = new Key("Caption"); + export const ActiveWorkspace = new Key("ActiveWorkspace"); + export const DocumentText = new Key("DocumentText"); + export const BrushingDocs = new Key("BrushingDocs"); + export const LinkedToDocs = new Key("LinkedToDocs"); + export const LinkedFromDocs = new Key("LinkedFromDocs"); + export const LinkDescription = new Key("LinkDescription"); + export const LinkTags = new Key("LinkTag"); + export const Thumbnail = new Key("Thumbnail"); + export const ThumbnailPage = new Key("ThumbnailPage"); + export const CurPage = new Key("CurPage"); + export const AnnotationOn = new Key("AnnotationOn"); + export const NumPages = new Key("NumPages"); + export const Ink = new Key("Ink"); + export const Cursors = new Key("Cursors"); + export const OptionalRightCollection = new Key("OptionalRightCollection"); + export const Archives = new Key("Archives"); + export const Updated = new Key("Updated"); + export const Workspaces = new Key("Workspaces"); + export const Minimized = new Key("Minimized"); } 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<T> { - 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<string>("Foo"); - export const Bar = new Message<string>("Bar"); - export const AddDocument = new Message<DocumentTransfer>("Add Document"); - export const SetField = new Message<{ _id: string, data: any, type: Types }>("Set Field") - export const GetField = new Message<string>("Get Field") - export const GetFields = new Message<string[]>("Get Fields") - export const GetDocument = new Message<string>("Get Document"); - export const DeleteAll = new Message<any>("Delete All"); -}
\ No newline at end of file + export const Foo = new Message<string>("Foo"); + export const Bar = new Message<string>("Bar"); + export const AddDocument = new Message<DocumentTransfer>("Add Document"); + export const SetField = new Message<{ _id: string; data: any; type: Types }>( + "Set Field" + ); + export const GetField = new Message<string>("Get Field"); + export const GetFields = new Message<string[]>("Get Fields"); + export const GetDocument = new Message<string>("Get Document"); + export const DeleteAll = new Message<any>("Delete All"); +} diff --git a/src/server/ServerUtil.ts b/src/server/ServerUtil.ts index 98a7a1451..d3409abf4 100644 --- a/src/server/ServerUtil.ts +++ b/src/server/ServerUtil.ts @@ -1,78 +1,84 @@ - -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 { 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 + 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?") + 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 BooleanField(data, id, false); case Types.Number: - return new NumberField(data, id, false) + return new NumberField(data, id, false); case Types.Text: - return new TextField(data, id, false) + return new TextField(data, id, false); case Types.Html: - return new HtmlField(data, id, false) + return new HtmlField(data, id, false); case Types.Web: - return new WebField(new URL(data), id, false) + return new WebField(new URL(data), id, false); case Types.RichText: - return new RichTextField(data, id, false) + return new RichTextField(data, id, false); case Types.Key: - return new Key(data, id, false) + return new Key(data, id, false); case Types.Image: - return new ImageField(new URL(data), id, false) + 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) + return new PDFField(new URL(data), id, false); case Types.List: - return ListField.FromJson(id, data) + return ListField.FromJson(id, data); case Types.Audio: - return new AudioField(new URL(data), id, false) + return new AudioField(new URL(data), id, false); case Types.Video: - return new VideoField(new URL(data), id, false) + 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][] + 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 + 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"); + 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 +} diff --git a/src/server/database.ts b/src/server/database.ts index 87a0b3c70..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/tsconfig.json b/tsconfig.json index 2b2c69fe1..41db1d0a7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,7 +10,7 @@ "lib": [ "dom", "es2015" - ] + ], }, // "exclude": [ // "node_modules", |