aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTyler Schicke <tyler_schicke@brown.edu>2019-04-04 20:11:09 -0400
committerTyler Schicke <tyler_schicke@brown.edu>2019-04-04 20:11:09 -0400
commit5409aa5e401b1c75c64e36ee141549b0461f1825 (patch)
treedeef278987c5fb8c47638cfebcdb94fec339b6ae /src
parent318dacd846ab06358e26ca49e711e06434287d16 (diff)
parent4fde212cd00bd2f8fc2fa122309af3bb71bba2fd (diff)
Merge branch 'master' of github-tsch-brown:browngraphicslab/Dash-Web into propsRefactor
Diffstat (limited to 'src')
-rw-r--r--src/client/documents/Documents.ts2
-rw-r--r--src/client/northstar/dash-nodes/HistogramBox.scss5
-rw-r--r--src/client/util/DragManager.ts149
-rw-r--r--src/client/util/SelectionManager.ts16
-rw-r--r--src/client/views/DocumentDecorations.scss85
-rw-r--r--src/client/views/DocumentDecorations.tsx256
-rw-r--r--src/client/views/InkingCanvas.scss2
-rw-r--r--src/client/views/InkingCanvas.tsx2
-rw-r--r--src/client/views/Main.scss7
-rw-r--r--src/client/views/collections/CollectionDockingView.scss2
-rw-r--r--src/client/views/collections/CollectionPDFView.scss2
-rw-r--r--src/client/views/collections/CollectionVideoView.scss2
-rw-r--r--src/client/views/collections/CollectionViewBase.tsx22
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx8
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.scss2
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss6
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx44
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.scss2
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx1
-rw-r--r--src/client/views/collections/collectionFreeForm/PreviewCursor.scss4
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx4
-rw-r--r--src/client/views/nodes/DocumentView.scss20
-rw-r--r--src/client/views/nodes/DocumentView.tsx285
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx101
-rw-r--r--src/client/views/nodes/PDFBox.scss4
-rw-r--r--src/client/views/nodes/PDFBox.tsx30
-rw-r--r--src/client/views/nodes/Sticky.tsx138
-rw-r--r--src/client/views/nodes/WebBox.scss2
-rw-r--r--src/fields/BooleanField.ts25
-rw-r--r--src/fields/Document.ts164
-rw-r--r--src/fields/KeyStore.ts90
-rw-r--r--src/server/Message.ts168
-rw-r--r--src/server/ServerUtil.ts94
-rw-r--r--src/server/database.ts10
34 files changed, 1170 insertions, 584 deletions
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()
});
}