From 1d667d19f5402dc9f9069e0a57008dac96f6de2a Mon Sep 17 00:00:00 2001 From: madelinegr Date: Tue, 12 Feb 2019 18:55:11 -0500 Subject: set up web box classes --- src/client/documents/Documents.ts | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 72fa608ad..d8db6ee79 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -9,6 +9,8 @@ import { CollectionDockingView } from "../views/collections/CollectionDockingVie import { CollectionSchemaView } from "../views/collections/CollectionSchemaView"; import { ImageField } from "../../fields/ImageField"; import { ImageBox } from "../views/nodes/ImageBox"; +import { WebField } from "../../fields/WebField"; +import { WebBox } from "../views/nodes/WebBox"; import { CollectionFreeFormView } from "../views/collections/CollectionFreeFormView"; import { FieldId } from "../../fields/Field"; @@ -150,6 +152,37 @@ export namespace Documents { return sdoc; } + let webProtoId: FieldId; + function GetWebPrototype(): Document { + if (webProtoId === undefined) { + let webProto = new Document(); + webProtoId = webProto.Id; + webProto.Set(KeyStore.Title, new TextField("WEB PROTO")); + webProto.Set(KeyStore.X, new NumberField(0)); + webProto.Set(KeyStore.Y, new NumberField(0)); + webProto.Set(KeyStore.NativeWidth, new NumberField(300)); + webProto.Set(KeyStore.NativeHeight, new NumberField(300)); + webProto.Set(KeyStore.Width, new NumberField(300)); + webProto.Set(KeyStore.Height, new NumberField(300)); + webProto.Set(KeyStore.Layout, new TextField(CollectionFreeFormView.LayoutString("AnnotationsKey"))); + webProto.Set(KeyStore.BackgroundLayout, new TextField(WebBox.LayoutString())); + webProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data, KeyStore.Annotations])); + Server.AddDocument(webProto); + return webProto; + } + return Server.GetField(webProtoId) as Document; + } + + export function WebDocument(url: string, options: DocumentOptions = {}): Document { + let doc = GetWebPrototype().MakeDelegate(); + setupOptions(doc, options); + doc.Set(KeyStore.Data, new WebField(new URL(url))); + Server.AddDocument(doc); + var sdoc = Server.GetField(doc.Id) as Document; + console.log(sdoc); + return sdoc; + } + let collectionProto: Document; function GetCollectionPrototype(): Document { if (!collectionProto) { -- cgit v1.2.3-70-g09d2 From 837509322d7e556830c57653828e223b06eb38a6 Mon Sep 17 00:00:00 2001 From: madelinegr Date: Tue, 12 Feb 2019 19:25:28 -0500 Subject: fixed bugs with launching --- .DS_Store | Bin 0 -> 6148 bytes package-lock.json | 6 +- src/.DS_Store | Bin 0 -> 6148 bytes src/client/documents/Documents.ts | 4 +- src/client/views/nodes/DocumentView.tsx | 5 +- src/client/views/nodes/WebBox.scss | 4 +- src/documents/Documents.ts | 92 -------------- src/fields/Document 2.ts | 93 -------------- src/fields/DocumentReference 2.ts | 46 ------- src/fields/Field 2.ts | 54 --------- src/fields/FieldUpdatedArgs 2.ts | 27 ----- src/fields/Key 2.ts | 45 ------- src/fields/ListField 2.ts | 21 ---- src/fields/NumberField 2.ts | 13 -- src/fields/TextField 2.ts | 13 -- src/stores/NodeCollectionStore.ts | 25 ---- src/stores/NodeStore.ts | 24 ---- src/stores/RootStore.ts | 16 --- src/stores/StaticTextNodeStore.ts | 16 --- src/stores/VideoNodeStore.ts | 17 --- src/util/TypedEvent.ts | 42 ------- src/viewmodels/DocumentViewModel.ts | 11 -- .../freeformcanvas/CollectionFreeFormView.scss | 15 --- .../freeformcanvas/CollectionFreeFormView.tsx | 98 --------------- src/views/freeformcanvas/FreeFormCanvas.scss | 15 --- src/views/freeformcanvas/FreeFormCanvas.tsx | 86 ------------- src/views/nodes/DocumentView.tsx | 134 --------------------- src/views/nodes/FieldTextBox.tsx | 117 ------------------ src/views/nodes/NodeView.scss | 31 ----- src/views/nodes/RichTextView.tsx | 0 src/views/nodes/TextNodeView.tsx | 28 ----- src/views/nodes/TopBar.tsx | 46 ------- src/views/nodes/VideoNodeView.scss | 5 - src/views/nodes/VideoNodeView.tsx | 29 ----- 34 files changed, 10 insertions(+), 1168 deletions(-) create mode 100644 .DS_Store create mode 100644 src/.DS_Store delete mode 100644 src/documents/Documents.ts delete mode 100644 src/fields/Document 2.ts delete mode 100644 src/fields/DocumentReference 2.ts delete mode 100644 src/fields/Field 2.ts delete mode 100644 src/fields/FieldUpdatedArgs 2.ts delete mode 100644 src/fields/Key 2.ts delete mode 100644 src/fields/ListField 2.ts delete mode 100644 src/fields/NumberField 2.ts delete mode 100644 src/fields/TextField 2.ts delete mode 100644 src/stores/NodeCollectionStore.ts delete mode 100644 src/stores/NodeStore.ts delete mode 100644 src/stores/RootStore.ts delete mode 100644 src/stores/StaticTextNodeStore.ts delete mode 100644 src/stores/VideoNodeStore.ts delete mode 100644 src/util/TypedEvent.ts delete mode 100644 src/viewmodels/DocumentViewModel.ts delete mode 100644 src/views/freeformcanvas/CollectionFreeFormView.scss delete mode 100644 src/views/freeformcanvas/CollectionFreeFormView.tsx delete mode 100644 src/views/freeformcanvas/FreeFormCanvas.scss delete mode 100644 src/views/freeformcanvas/FreeFormCanvas.tsx delete mode 100644 src/views/nodes/DocumentView.tsx delete mode 100644 src/views/nodes/FieldTextBox.tsx delete mode 100644 src/views/nodes/NodeView.scss delete mode 100644 src/views/nodes/RichTextView.tsx delete mode 100644 src/views/nodes/TextNodeView.tsx delete mode 100644 src/views/nodes/TopBar.tsx delete mode 100644 src/views/nodes/VideoNodeView.scss delete mode 100644 src/views/nodes/VideoNodeView.tsx (limited to 'src/client/documents') diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 000000000..8493b4a74 Binary files /dev/null and b/.DS_Store differ diff --git a/package-lock.json b/package-lock.json index a4939f1cb..5b62532c4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9119,7 +9119,7 @@ }, "regjsparser": { "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "resolved": "http://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", "dev": true, "requires": { @@ -9470,7 +9470,7 @@ }, "sha.js": { "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, "requires": { @@ -9962,7 +9962,7 @@ }, "strip-eof": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" }, "strip-indent": { diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 000000000..4d6acb95a Binary files /dev/null and b/src/.DS_Store differ diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index d8db6ee79..605a99bef 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -69,7 +69,7 @@ export namespace Documents { export function TextDocument(options: DocumentOptions = {}): Document { let doc = GetTextPrototype().MakeDelegate(); setupOptions(doc, options); - // doc.SetField(KeyStore.Data, new RichTextField()); + // doc.Set(KeyStore.Data, new RichTextField()); return doc; } @@ -131,7 +131,7 @@ export namespace Documents { imageProto.Set(KeyStore.Height, new NumberField(300)); imageProto.Set(KeyStore.Layout, new TextField(CollectionFreeFormView.LayoutString("AnnotationsKey"))); imageProto.Set(KeyStore.BackgroundLayout, new TextField(ImageBox.LayoutString())); - // imageProto.SetField(KeyStore.Layout, new TextField('
')); + // imageProto.Set(KeyStore.Layout, new TextField('
')); imageProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data, KeyStore.Annotations])); Server.AddDocument(imageProto); return imageProto; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 3a73f2fde..b13d6486b 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -13,6 +13,7 @@ import { CollectionSchemaView } from "../collections/CollectionSchemaView"; import { CollectionViewBase, COLLECTION_BORDER_WIDTH } from "../collections/CollectionViewBase"; import { FormattedTextBox } from "../nodes/FormattedTextBox"; import { ImageBox } from "../nodes/ImageBox"; +import { WebBox } from "../nodes/WebBox"; import "./NodeView.scss"; import React = require("react"); import { Transform } from "../../util/Transform"; @@ -151,7 +152,7 @@ export class DocumentView extends React.Component { bindings.DocumentView = this; // set the DocumentView to this if it hasn't already been set by a sub-class during its render method. } var annotated = { return (
")); - textProto.SetField(KeyStore.LayoutKeys, new ListField([KeyStore.Data])); - } - return textProto; - } - - export function TextDocument(text: string, options:DocumentOptions = {}): Document { - let doc = GetTextPrototype().MakeDelegate(); - setupOptions(doc, options); - // doc.SetField(KeyStore.Data, new TextField(text)); - return doc; - } - - let imageProto:Document; - function GetImagePrototype(): Document { - if(!imageProto) { - imageProto = new Document(); - imageProto.SetField(KeyStore.X, new NumberField(0)); - imageProto.SetField(KeyStore.Y, new NumberField(0)); - imageProto.SetField(KeyStore.Width, new NumberField(300)); - imageProto.SetField(KeyStore.Height, new NumberField(300)); - imageProto.SetField(KeyStore.Layout, new TextField('Image not found')); - imageProto.SetField(KeyStore.LayoutFields, new ListField([KeyStore.Data])); - } - return imageProto; - } - - export function ImageDocument(url: string, options:DocumentOptions = {}): Document { - let doc = GetImagePrototype().MakeDelegate(); - setupOptions(doc, options); - doc.SetField(KeyStore.Data, new TextField(url)); - return doc; - } - - let collectionProto:Document; - function GetCollectionPrototype(): Document { - if(!collectionProto) { - collectionProto = new Document(); - collectionProto.SetField(KeyStore.X, new NumberField(150)); - collectionProto.SetField(KeyStore.Y, new NumberField(0)); - collectionProto.SetField(KeyStore.Width, new NumberField(300)); - collectionProto.SetField(KeyStore.Height, new NumberField(300)); - collectionProto.SetField(KeyStore.Layout, new TextField('')); - collectionProto.SetField(KeyStore.LayoutKeys, new ListField([KeyStore.Data])); - } - return collectionProto; - } - - export function CollectionDocument( documents: Array, options:DocumentOptions = {}): Document { - let doc = GetCollectionPrototype().MakeDelegate(); - setupOptions(doc, options); - doc.SetField(KeyStore.Data, new ListField(documents)); - return doc; - } -} \ No newline at end of file diff --git a/src/fields/Document 2.ts b/src/fields/Document 2.ts deleted file mode 100644 index 0bba9c21e..000000000 --- a/src/fields/Document 2.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { Field, Cast, Opt } from "./Field" -import { Key, KeyStore } from "./Key" -import { ObservableMap } from "mobx"; - -export class Document extends Field { - private fields: ObservableMap = new ObservableMap(); - - GetField(key: Key, ignoreProto: boolean = false): Opt { - let field: Opt; - if (ignoreProto) { - if (this.fields.has(key)) { - field = this.fields.get(key); - } - } else { - let doc: Opt = this; - while (doc && !(doc.fields.has(key))) { - doc = doc.GetPrototype(); - } - - if (doc) { - field = doc.fields.get(key); - } - } - - return field; - } - - GetFieldT(key: Key, ctor: { new(): T }, ignoreProto?: boolean): Opt { - return Cast(this.GetField(key, ignoreProto), ctor); - } - - GetFieldValue(key: Key, ctor: { new(): U }, defaultVal: T): T { - let val = this.GetField(key); - return (val && val instanceof ctor) ? val.Data : defaultVal; - } - - SetField(key: Key, field: Opt): void { - if (field) { - this.fields.set(key, field); - } else { - this.fields.delete(key); - } - } - - SetFieldValue(key: Key, value: any, ctor: { new(): T }): boolean { - let field = this.GetField(key, true); - if (field != null) { - return field.TrySetValue(value); - } else { - field = new ctor(); - if (field.TrySetValue(value)) { - this.SetField(key, field); - return true; - } else { - return false; - } - } - } - - GetPrototype(): Opt { - return this.GetFieldT(KeyStore.Prototype, Document, true); - } - - GetAllPrototypes(): Document[] { - let protos: Document[] = []; - let doc: Opt = this; - while (doc != null) { - protos.push(doc); - doc = doc.GetPrototype(); - } - return protos; - } - - MakeDelegate(): Document { - let delegate = new Document(); - - delegate.SetField(KeyStore.Prototype, this); - - return delegate; - } - - TrySetValue(value: any): boolean { - throw new Error("Method not implemented."); - } - GetValue() { - throw new Error("Method not implemented."); - } - Copy(): Field { - throw new Error("Method not implemented."); - } - - -} \ No newline at end of file diff --git a/src/fields/DocumentReference 2.ts b/src/fields/DocumentReference 2.ts deleted file mode 100644 index 936067bd2..000000000 --- a/src/fields/DocumentReference 2.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Field, Opt } from "./Field"; -import { Document } from "./Document"; -import { Key } from "./Key"; -import { DocumentUpdatedArgs } from "./FieldUpdatedArgs"; - -export class DocumentReference extends Field { - get Key(): Key{ - return this.key; - } - - get Document(): Document { - return this.document; - } - - constructor(private document: Document, private key: Key) { - super(); - } - - private DocFieldUpdated(args: DocumentUpdatedArgs):void{ - // this.FieldUpdated.emit(args.fieldArgs); - } - - Dereference() : Opt { - return this.document.GetField(this.key); - } - - DereferenceToRoot(): Opt { - let field: Opt = this; - while (field instanceof DocumentReference) { - field = field.Dereference(); - } - return field; - } - - TrySetValue(value: any): boolean { - throw new Error("Method not implemented."); - } - GetValue() { - throw new Error("Method not implemented."); - } - Copy(): Field { - throw new Error("Method not implemented."); - } - - -} \ No newline at end of file diff --git a/src/fields/Field 2.ts b/src/fields/Field 2.ts deleted file mode 100644 index 46f92f203..000000000 --- a/src/fields/Field 2.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { TypedEvent } from "../util/TypedEvent"; -import { FieldUpdatedArgs } from "./FieldUpdatedArgs"; -import { DocumentReference } from "./DocumentReference"; -import { Utils } from "../Utils"; - -export function Cast(field: Opt, ctor: { new(): T }): Opt { - if (field) { - if (ctor && field instanceof ctor) { - return field; - } - } - return undefined; -} - -export type Opt = T | undefined; - -export abstract class Field { - //FieldUpdated: TypedEvent> = new TypedEvent>(); - - private id: string; - get Id(): string { - return this.id; - } - - constructor(id: Opt = undefined) { - this.id = id || Utils.GenerateGuid(); - } - - Dereference(): Opt { - return this; - } - DereferenceToRoot(): Opt { - return this; - } - - DereferenceT(ctor: { new(): T }): Opt { - return Cast(this.Dereference(), ctor); - } - - DereferenceToRootT(ctor: { new(): T }): Opt { - return Cast(this.DereferenceToRoot(), ctor); - } - - Equals(other: Field): boolean { - return this.id === other.id; - } - - abstract TrySetValue(value: any): boolean; - - abstract GetValue(): any; - - abstract Copy(): Field; - -} \ No newline at end of file diff --git a/src/fields/FieldUpdatedArgs 2.ts b/src/fields/FieldUpdatedArgs 2.ts deleted file mode 100644 index 23ccf2a5a..000000000 --- a/src/fields/FieldUpdatedArgs 2.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Field, Opt } from "./Field"; -import { Document } from "./Document"; -import { Key } from "./Key"; - -export enum FieldUpdatedAction { - Add, - Remove, - Replace, - Update -} - -export interface FieldUpdatedArgs { - field: Field; - action: FieldUpdatedAction; -} - -export interface DocumentUpdatedArgs { - field: Document; - key: Key; - - oldValue: Opt; - newValue: Opt; - - fieldArgs?: FieldUpdatedArgs; - - action: FieldUpdatedAction; -} diff --git a/src/fields/Key 2.ts b/src/fields/Key 2.ts deleted file mode 100644 index db30f545d..000000000 --- a/src/fields/Key 2.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { Field } from "./Field" -import { Utils } from "../Utils"; -import { observable } from "mobx"; - -export class Key extends Field { - private name:string; - - get Name():string { - return this.name; - } - - constructor(name:string){ - super(Utils.GenerateDeterministicGuid(name)); - - this.name = name; - } - - TrySetValue(value: any): boolean { - throw new Error("Method not implemented."); - } - - GetValue() { - return this.Name; - } - - Copy(): Field { - return this; - } - - -} - -export namespace KeyStore { - export let Prototype = new Key("Prototype"); - export let X = new Key("X"); - export let Y = new Key("Y"); - export let PanX = new Key("PanX"); - export let PanY = new Key("PanY"); - export let Width = new Key("Width"); - export let Height = new Key("Height"); - export let Data = new Key("Data"); - export let Layout = new Key("Layout"); - export let LayoutKeys = new Key("LayoutKeys"); - export let LayoutFields = new Key("LayoutFields"); -} \ No newline at end of file diff --git a/src/fields/ListField 2.ts b/src/fields/ListField 2.ts deleted file mode 100644 index dd96ea8c8..000000000 --- a/src/fields/ListField 2.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Field } from "./Field"; -import { BasicField } from "./BasicField"; - -export class ListField extends BasicField { - constructor(data: T[] = []) { - super(data.slice()); - } - - Get(index:number) : T{ - return this.Data[index]; - } - - Set(index:number, value:T):void { - this.Data[index] = value; - } - - Copy(): Field { - return new ListField(this.Data); - } - -} \ No newline at end of file diff --git a/src/fields/NumberField 2.ts b/src/fields/NumberField 2.ts deleted file mode 100644 index cbe15f987..000000000 --- a/src/fields/NumberField 2.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { BasicField } from "./BasicField" - -export class NumberField extends BasicField { - constructor(data: number = 0) { - super(data); - } - - Copy() { - return new NumberField(this.Data); - } - - -} \ No newline at end of file diff --git a/src/fields/TextField 2.ts b/src/fields/TextField 2.ts deleted file mode 100644 index a7c221788..000000000 --- a/src/fields/TextField 2.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { BasicField } from "./BasicField" - -export class TextField extends BasicField { - constructor(data: string = "") { - super(data); - } - - Copy() { - return new TextField(this.Data); - } - - -} diff --git a/src/stores/NodeCollectionStore.ts b/src/stores/NodeCollectionStore.ts deleted file mode 100644 index ac4f515f1..000000000 --- a/src/stores/NodeCollectionStore.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { computed, observable, action } from "mobx"; -import { NodeStore } from "./NodeStore"; -import { Document } from "../fields/Document"; - -export class NodeCollectionStore extends NodeStore { - - @observable - public Scale: number = 1; - - @observable - public Nodes: NodeStore[] = new Array(); - - @observable - public Docs: Document[] = []; - - @computed - public get Transform(): string { - return "translate(" + this.X + "px," + this.Y + "px) scale(" + this.Scale + "," + this.Scale + ")"; - } - - @action - public AddNodes(stores: NodeStore[]): void { - stores.forEach(store => this.Nodes.push(store)); - } -} \ No newline at end of file diff --git a/src/stores/NodeStore.ts b/src/stores/NodeStore.ts deleted file mode 100644 index 6a734cf44..000000000 --- a/src/stores/NodeStore.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { computed, observable } from "mobx"; -import { Utils } from "../Utils"; - -export class NodeStore { - - public Id: string = Utils.GenerateGuid(); - - @observable - public X: number = 0; - - @observable - public Y: number = 0; - - @observable - public Width: number = 0; - - @observable - public Height: number = 0; - - @computed - public get Transform(): string { - return "translate(" + this.X + "px, " + this.Y + "px)"; - } -} \ No newline at end of file diff --git a/src/stores/RootStore.ts b/src/stores/RootStore.ts deleted file mode 100644 index fa551c1d1..000000000 --- a/src/stores/RootStore.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { action, observable } from "mobx"; -import { NodeStore } from "./NodeStore"; - -// This globally accessible store might come in handy, although you may decide that you don't need it. -export class RootStore { - - private constructor() { - // initialization code - } - - private static _instance: RootStore; - - public static get Instance():RootStore { - return this._instance || (this._instance = new this()); - } -} \ No newline at end of file diff --git a/src/stores/StaticTextNodeStore.ts b/src/stores/StaticTextNodeStore.ts deleted file mode 100644 index 7c342a7a2..000000000 --- a/src/stores/StaticTextNodeStore.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { observable } from "mobx"; -import { NodeStore } from "./NodeStore"; - -export class StaticTextNodeStore extends NodeStore { - - constructor(initializer: Partial) { - super(); - Object.assign(this, initializer); - } - - @observable - public Title: string = ""; - - @observable - public Text: string = ""; -} \ No newline at end of file diff --git a/src/stores/VideoNodeStore.ts b/src/stores/VideoNodeStore.ts deleted file mode 100644 index e5187ab07..000000000 --- a/src/stores/VideoNodeStore.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { observable } from "mobx"; -import { NodeStore } from "./NodeStore"; - -export class VideoNodeStore extends NodeStore { - - constructor(initializer: Partial) { - super(); - Object.assign(this, initializer); - } - - @observable - public Title: string = ""; - - @observable - public Url: string = ""; - -} \ No newline at end of file diff --git a/src/util/TypedEvent.ts b/src/util/TypedEvent.ts deleted file mode 100644 index 0714a7f5c..000000000 --- a/src/util/TypedEvent.ts +++ /dev/null @@ -1,42 +0,0 @@ -export interface Listener { - (event: T): any; -} - -export interface Disposable { - dispose(): void; -} - -/** passes through events as they happen. You will not get events from before you start listening */ -export class TypedEvent { - private listeners: Listener[] = []; - private listenersOncer: Listener[] = []; - - on = (listener: Listener): Disposable => { - this.listeners.push(listener); - return { - dispose: () => this.off(listener) - }; - } - - once = (listener: Listener): void => { - this.listenersOncer.push(listener); - } - - off = (listener: Listener) => { - var callbackIndex = this.listeners.indexOf(listener); - if (callbackIndex > -1) this.listeners.splice(callbackIndex, 1); - } - - emit = (event: T) => { - /** Update any general listeners */ - this.listeners.forEach((listener) => listener(event)); - - /** Clear the `once` queue */ - this.listenersOncer.forEach((listener) => listener(event)); - this.listenersOncer = []; - } - - pipe = (te: TypedEvent): Disposable => { - return this.on((e) => te.emit(e)); - } -} \ No newline at end of file diff --git a/src/viewmodels/DocumentViewModel.ts b/src/viewmodels/DocumentViewModel.ts deleted file mode 100644 index 008275f3c..000000000 --- a/src/viewmodels/DocumentViewModel.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Document } from "../fields/Document"; - -export class DocumentViewModel { - constructor(private doc: Document) { - - } - - get Doc(): Document { - return this.doc; - } -} \ No newline at end of file diff --git a/src/views/freeformcanvas/CollectionFreeFormView.scss b/src/views/freeformcanvas/CollectionFreeFormView.scss deleted file mode 100644 index cb4805eb3..000000000 --- a/src/views/freeformcanvas/CollectionFreeFormView.scss +++ /dev/null @@ -1,15 +0,0 @@ -.collectionfreeformview-container { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - overflow: hidden; - - .collectionfreeformview { - position: absolute; - top: 0; - left: 0; - } -} - diff --git a/src/views/freeformcanvas/CollectionFreeFormView.tsx b/src/views/freeformcanvas/CollectionFreeFormView.tsx deleted file mode 100644 index d5343536d..000000000 --- a/src/views/freeformcanvas/CollectionFreeFormView.tsx +++ /dev/null @@ -1,98 +0,0 @@ -import { observer } from "mobx-react"; -import { Key, KeyStore } from "../../fields/Key"; -import "./FreeFormCanvas.scss"; -import React = require("react"); -import { action } from "mobx"; -import { Document } from "../../fields/Document"; -import { DocumentViewModel } from "../../viewmodels/DocumentViewModel"; -import { DocumentView } from "../nodes/DocumentView"; -import { ListField } from "../../fields/ListField"; -import { NumberField } from "../../fields/NumberField"; -import { SSL_OP_SINGLE_DH_USE } from "constants"; - -interface IProps { - fieldKey: Key; - doc: Document; -} - -@observer -export class CollectionFreeFormView extends React.Component { - - private _isPointerDown: boolean = false; - - constructor(props: IProps) { - super(props); - } - - @action - onPointerDown = (e: React.PointerEvent): void => { - e.stopPropagation(); - if (e.button === 2) { - this._isPointerDown = true; - document.removeEventListener("pointermove", this.onPointerMove); - document.addEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - document.addEventListener("pointerup", this.onPointerUp); - } - } - - @action - onPointerUp = (e: PointerEvent): void => { - e.stopPropagation(); - if (e.button === 2) { - this._isPointerDown = false; - document.removeEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - } - } - - @action - onPointerMove = (e: PointerEvent): void => { - e.preventDefault(); - e.stopPropagation(); - if (!this._isPointerDown) { - return; - } - const { doc } = this.props; - let x = doc.GetFieldValue(KeyStore.PanX, NumberField, Number(0)); - let y = doc.GetFieldValue(KeyStore.PanY, NumberField, Number(0)); - doc.SetFieldValue(KeyStore.PanX, x + e.movementX, NumberField); - doc.SetFieldValue(KeyStore.PanY, y + e.movementY, NumberField); - } - - @action - onPointerWheel = (e: React.WheelEvent): void => { - e.stopPropagation(); - - let scaleAmount = 1 - (e.deltaY / 1000); - //this.props.store.Scale *= scaleAmount; - } - - render() { - const { fieldKey, doc } = this.props; - const value: Document[] = doc.GetFieldValue(fieldKey, ListField, []); - const panx: number = doc.GetFieldValue(KeyStore.PanX, NumberField, Number(0)); - const pany: number = doc.GetFieldValue(KeyStore.PanY, NumberField, Number(0)); - return ( - -
-
e.preventDefault()} style={{ - width: "100%", - height: "calc(100% - 4px)", - overflow: "hidden" - }}> -
-
- {value.map(doc => { - return (); - })} -
-
-
-
- ); - } -} \ No newline at end of file diff --git a/src/views/freeformcanvas/FreeFormCanvas.scss b/src/views/freeformcanvas/FreeFormCanvas.scss deleted file mode 100644 index 884ef90e6..000000000 --- a/src/views/freeformcanvas/FreeFormCanvas.scss +++ /dev/null @@ -1,15 +0,0 @@ -.freeformcanvas-container { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - overflow: hidden; - - .freeformcanvas { - position: absolute; - top: 0; - left: 0; - } -} - diff --git a/src/views/freeformcanvas/FreeFormCanvas.tsx b/src/views/freeformcanvas/FreeFormCanvas.tsx deleted file mode 100644 index 9ef5ab8f7..000000000 --- a/src/views/freeformcanvas/FreeFormCanvas.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import { observer } from "mobx-react"; -import { Key } from "../../fields/Key"; -import { NodeCollectionStore } from "../../stores/NodeCollectionStore"; -import "./FreeFormCanvas.scss"; -import React = require("react"); -import { action } from "mobx"; -import { Document } from "../../fields/Document"; -import {DocumentViewModel} from "../../viewmodels/DocumentViewModel"; -import {DocumentView} from "../nodes/DocumentView"; -import {TextField} from "../../fields/TextField"; -import {ListField} from "../../fields/ListField"; -import {Field} from "../../fields/Field"; - -interface IProps { - store: NodeCollectionStore; -} - -@observer -export class FreeFormCanvas extends React.Component { - - private _isPointerDown: boolean = false; - - constructor(props:IProps) { - super(props); - } - - @action - onPointerDown = (e: React.PointerEvent): void => { - e.stopPropagation(); - if (e.button === 2) { - this._isPointerDown = true; - document.removeEventListener("pointermove", this.onPointerMove); - document.addEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - document.addEventListener("pointerup", this.onPointerUp); - } - } - - @action - onPointerUp = (e: PointerEvent): void => { - e.stopPropagation(); - if (e.button === 2) { - this._isPointerDown = false; - document.removeEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - } - - // let doc = this.props.store.Docs[0]; - // let dataField = doc.GetFieldT(KeyStore.Data, TextField); - // let data = dataField ? dataField.Data : ""; - // this.props.store.Docs[0].SetFieldValue(KeyStore.Data, data + " hello", TextField); - } - - @action - onPointerMove = (e: PointerEvent): void => { - e.stopPropagation(); - if (!this._isPointerDown) { - return; - } - this.props.store.X += e.movementX; - this.props.store.Y += e.movementY; - } - - @action - onPointerWheel = (e: React.WheelEvent): void => { - e.stopPropagation(); - - let scaleAmount = 1 - (e.deltaY / 1000); - this.props.store.Scale *= scaleAmount; - } - - render() { - let store = this.props.store; - return ( -
e.preventDefault()}> -
-
- {this.props.store.Docs.map(doc => { - return (); - })} -
-
-
- ); - } -} \ No newline at end of file diff --git a/src/views/nodes/DocumentView.tsx b/src/views/nodes/DocumentView.tsx deleted file mode 100644 index f955a8c39..000000000 --- a/src/views/nodes/DocumentView.tsx +++ /dev/null @@ -1,134 +0,0 @@ -import { observer } from "mobx-react"; -import React = require("react"); -import { computed } from "mobx"; -import { KeyStore, Key } from "../../fields/Key"; -import { NumberField } from "../../fields/NumberField"; -import { TextField } from "../../fields/TextField"; -import { DocumentViewModel } from "../../viewmodels/DocumentViewModel"; -import { ListField } from "../../fields/ListField"; -import { FieldTextBox } from "../nodes/FieldTextBox" -import { FreeFormCanvas } from "../freeformcanvas/FreeFormCanvas" -import { CollectionFreeFormView } from "../freeformcanvas/CollectionFreeFormView" -import "./NodeView.scss" -const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this? - -interface IProps { - dvm: DocumentViewModel; -} - -@observer -export class DocumentView extends React.Component { - @computed - get x(): number { - return this.props.dvm.Doc.GetFieldValue(KeyStore.X, NumberField, Number(0)); - } - - @computed - get y(): number { - return this.props.dvm.Doc.GetFieldValue(KeyStore.Y, NumberField, Number(0)); - } - - set x(x: number) { - this.props.dvm.Doc.SetFieldValue(KeyStore.X, x, NumberField) - } - - set y(y: number) { - this.props.dvm.Doc.SetFieldValue(KeyStore.Y, y, NumberField) - } - - @computed - get transform(): string { - return `translate(${this.x}px, ${this.y}px)`; - } - - @computed - get width(): number { - return this.props.dvm.Doc.GetFieldValue(KeyStore.Width, NumberField, Number(0)); - } - - @computed - get height(): number { - return this.props.dvm.Doc.GetFieldValue(KeyStore.Height, NumberField, Number(0)); - } - - @computed - get layout(): string { - return this.props.dvm.Doc.GetFieldValue(KeyStore.Layout, TextField, String("

Error loading layout data

")); - } - - @computed - get layoutKeys(): Key[] { - return this.props.dvm.Doc.GetFieldValue(KeyStore.LayoutKeys, ListField, new Array()); - } - - @computed - get layoutFields(): Key[] { - return this.props.dvm.Doc.GetFieldValue(KeyStore.LayoutFields, ListField, new Array()); - } - - private _isPointerDown = false; - - onPointerDown = (e: React.PointerEvent): void => { - e.stopPropagation(); - if (e.button === 2) { - this._isPointerDown = true; - document.removeEventListener("pointermove", this.onPointerMove); - document.addEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - document.addEventListener("pointerup", this.onPointerUp); - } - } - - onPointerUp = (e: PointerEvent): void => { - e.stopPropagation(); - if (e.button === 2) { - e.preventDefault(); - this._isPointerDown = false; - document.removeEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - } - } - - onPointerMove = (e: PointerEvent): void => { - e.stopPropagation(); - e.preventDefault(); - if (!this._isPointerDown) { - return; - } - this.x += e.movementX; - this.y += e.movementY; - } - - render() { - let doc = this.props.dvm.Doc; - let bindings: any = { - doc: doc - }; - for (const key of this.layoutKeys) { - bindings[key.Name + "Key"] = key; - } - for (const key of this.layoutFields) { - let field = doc.GetField(key); - if (field) { - bindings[key.Name] = field.GetValue(); - } - } - return ( -
{ - e.preventDefault() - }}> - -
- ); - } - -} \ No newline at end of file diff --git a/src/views/nodes/FieldTextBox.tsx b/src/views/nodes/FieldTextBox.tsx deleted file mode 100644 index dbac3906a..000000000 --- a/src/views/nodes/FieldTextBox.tsx +++ /dev/null @@ -1,117 +0,0 @@ -import { Key, KeyStore } from "../../fields/Key"; -import { Document } from "../../fields/Document"; -import { observer } from "mobx-react"; -import { TextField } from "../../fields/TextField"; -import React = require("react") -import { action, observable, reaction, IReactionDisposer } from "mobx"; - -import {schema} from "prosemirror-schema-basic"; -import {EditorState, Transaction} from "prosemirror-state" -import {EditorView} from "prosemirror-view" -import {keymap} from "prosemirror-keymap" -import {baseKeymap} from "prosemirror-commands" -import {undo, redo, history} from "prosemirror-history" -import { Opt } from "../../fields/Field"; - -interface IProps { - fieldKey:Key; - doc:Document; -} - -// FieldTextBox: Displays an editable plain text node that maps to a specified Key of a Document -// -// HTML Markup: Key} />"); -// and the node's binding to the specified document KEYNAME as: -// document.SetField(KeyStore.LayoutKeys, new ListField([KeyStore.])); -// The Jsx parser at run time will bind: -// '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 tot his node, -// this will edit the document and assign the new value to that field. -// -@observer -export class FieldTextBox extends React.Component { - private _ref: React.RefObject; - private _editorView: Opt; - private _reactionDisposer: Opt; - - constructor(props:IProps) { - super(props); - - this._ref = React.createRef(); - - this.onChange = this.onChange.bind(this); - } - - dispatchTransaction = (tx: Transaction) => { - if(this._editorView) { - const state = this._editorView.state.apply(tx); - this._editorView.updateState(state); - const {doc, fieldKey} = this.props; - doc.SetFieldValue(fieldKey, JSON.stringify(state.toJSON()), TextField); - } - } - - componentDidMount() { - let state:EditorState; - const {doc, fieldKey} = this.props; - const config = { - schema, - plugins: [ - history(), - keymap({"Mod-z": undo, "Mod-y": redo}), - keymap(baseKeymap) - ] - }; - - let field = doc.GetFieldT(fieldKey, TextField); - if(field) { - state = EditorState.fromJSON(config, JSON.parse(field.Data)); - } else { - state = EditorState.create(config); - } - if(this._ref.current) { - this._editorView = new EditorView(this._ref.current, { - state, - dispatchTransaction: this.dispatchTransaction - }); - } - - this._reactionDisposer = reaction(() => { - const field = this.props.doc.GetFieldT(this.props.fieldKey, TextField); - return field ? field.Data : undefined; - }, (field) => { - if(field && this._editorView) { - this._editorView.updateState(EditorState.fromJSON(config, JSON.parse(field))); - } - }) - } - - componentWillUnmount() { - if(this._editorView) { - this._editorView.destroy(); - } - if(this._reactionDisposer) { - this._reactionDisposer(); - } - } - - shouldComponentUpdate() { - return false; - } - - @action - onChange(e: React.ChangeEvent) { - const {fieldKey, doc} = this.props; - doc.SetFieldValue(fieldKey, e.target.value, TextField); - } - - render() { - return (
) - } -} \ No newline at end of file diff --git a/src/views/nodes/NodeView.scss b/src/views/nodes/NodeView.scss deleted file mode 100644 index a68335f87..000000000 --- a/src/views/nodes/NodeView.scss +++ /dev/null @@ -1,31 +0,0 @@ -.node { - position: absolute; - background: #cdcdcd; - - 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); - } -} - diff --git a/src/views/nodes/RichTextView.tsx b/src/views/nodes/RichTextView.tsx deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/views/nodes/TextNodeView.tsx b/src/views/nodes/TextNodeView.tsx deleted file mode 100644 index 4831e658c..000000000 --- a/src/views/nodes/TextNodeView.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { observer } from "mobx-react"; -import { StaticTextNodeStore } from "../../stores/StaticTextNodeStore"; -import "./NodeView.scss"; -import { TopBar } from "./TopBar"; -import React = require("react"); - -interface IProps { - store: StaticTextNodeStore; -} - -@observer -export class TextNodeView extends React.Component { - - render() { - let store = this.props.store; - return ( -
- -
-
-

{store.Title}

-

{store.Text}

-
-
-
- ); - } -} \ No newline at end of file diff --git a/src/views/nodes/TopBar.tsx b/src/views/nodes/TopBar.tsx deleted file mode 100644 index bb126e8b5..000000000 --- a/src/views/nodes/TopBar.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { observer } from "mobx-react"; -import { NodeStore } from "../../stores/NodeStore"; -import "./NodeView.scss"; -import React = require("react"); - -interface IProps { - store: NodeStore; -} - -@observer -export class TopBar extends React.Component { - - private _isPointerDown = false; - - onPointerDown = (e: React.PointerEvent): void => { - e.stopPropagation(); - e.preventDefault(); - this._isPointerDown = true; - document.removeEventListener("pointermove", this.onPointerMove); - document.addEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - document.addEventListener("pointerup", this.onPointerUp); - } - - onPointerUp = (e: PointerEvent): void => { - e.stopPropagation(); - e.preventDefault(); - this._isPointerDown = false; - document.removeEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - } - - onPointerMove = (e: PointerEvent): void => { - e.stopPropagation(); - e.preventDefault(); - if (!this._isPointerDown) { - return; - } - this.props.store.X += e.movementX; - this.props.store.Y += e.movementY; - } - - render() { - return
- } -} diff --git a/src/views/nodes/VideoNodeView.scss b/src/views/nodes/VideoNodeView.scss deleted file mode 100644 index f412c3519..000000000 --- a/src/views/nodes/VideoNodeView.scss +++ /dev/null @@ -1,5 +0,0 @@ -.node { - video { - width: 100%; - } -} \ No newline at end of file diff --git a/src/views/nodes/VideoNodeView.tsx b/src/views/nodes/VideoNodeView.tsx deleted file mode 100644 index 0a7b3d174..000000000 --- a/src/views/nodes/VideoNodeView.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { observer } from "mobx-react"; -import { VideoNodeStore } from "../../stores/VideoNodeStore"; -import "./NodeView.scss"; -import { TopBar } from "./TopBar"; -import "./VideoNodeView.scss"; -import React = require("react"); - -interface IProps { - store: VideoNodeStore; -} - -@observer -export class VideoNodeView extends React.Component { - - render() { - let store = this.props.store; - return ( -
- -
-
-

{store.Title}

-
-
-
- ); - } -} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From e57c8ed3944bf737afdb2f564d159a53f8a6b1c6 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 25 Feb 2019 01:56:29 -0500 Subject: more css cleanup --- src/client/documents/Documents.ts | 4 +- src/client/views/EditableView.tsx | 2 +- .../views/collections/CollectionDockingView.tsx | 2 +- .../views/collections/CollectionFreeFormView.scss | 6 ++ .../views/collections/CollectionFreeFormView.tsx | 6 -- .../views/collections/CollectionSchemaView.scss | 73 ++++++++++------------ .../views/collections/CollectionSchemaView.tsx | 7 ++- .../views/nodes/CollectionFreeFormDocumentView.tsx | 2 +- src/client/views/nodes/FormattedTextBox.scss | 4 ++ src/client/views/nodes/FormattedTextBox.tsx | 6 +- src/client/views/nodes/ImageBox.scss | 6 +- 11 files changed, 58 insertions(+), 60 deletions(-) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 4c5f26fbd..2dfff6235 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -128,8 +128,8 @@ export namespace Documents { // example of custom display string for an image that shows a caption. function EmbeddedCaption() { - return `
-
` + return `
+
` + ImageBox.LayoutString() + `
` diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 3d1c2ebf4..8d9a47eaa 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -30,7 +30,7 @@ export class EditableView extends React.Component { style={{ width: "100%" }}> } else { return ( -
this.editing = true)} > {this.props.contents} diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 86dc66e39..2230ec14f 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -285,7 +285,7 @@ export class DockedFrameRenderer extends React.Component { if (!this._document) return (null); var content = -
+
.jsx-parser{ + position:absolute; + height: 100%; + } + border-style: solid; box-sizing: border-box; position: relative; diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx index cb6668634..c40da6eaa 100644 --- a/src/client/views/collections/CollectionFreeFormView.tsx +++ b/src/client/views/collections/CollectionFreeFormView.tsx @@ -217,12 +217,6 @@ export class CollectionFreeFormView extends CollectionViewBase { render() { const panx: number = this.props.Document.GetNumber(KeyStore.PanX, 0); const pany: number = this.props.Document.GetNumber(KeyStore.PanY, 0); - var overlay = this.overlayView ? -
- {this.overlayView} -
- : - (null); return (
.jsx-parser{ - position:absolute - } - } - .imageBox-cont { - position:relative; - max-height:100%; - } .ReactTable { position: absolute; // display: inline-block; @@ -32,23 +22,40 @@ height: 100%; background: white; box-sizing: border-box; - } - .ReactTable .rt-table { - overflow-y: auto; - overflow-x: auto; - height: 100%; + .rt-table { + overflow-y: auto; + overflow-x: auto; + height: 100%; - display: -webkit-inline-box; - direction: ltr; - // direction:rtl; - // display:block; - } - .ReactTable .rt-tbody { - //direction: ltr; - direction: rtl; - } - .ReactTable .rt-tr-group { - direction: ltr; + display: -webkit-inline-box; + direction: ltr; + // direction:rtl; + // display:block; + } + .rt-tbody { + //direction: ltr; + direction: rtl; + } + .rt-tr-group { + direction: ltr; + } + .rt-td { + border-width: 1; + border-right-color: #aaa; + .imageBox-cont { + position:relative; + max-height:100%; + } + .imageBox-cont img { + object-fit: contain; + max-width: 100%; + height: 100% + } + } + .rt-tr-group { + border-width: 1; + border-bottom-color: #aaa + } } .ReactTable .rt-thead.-header { background:grey; @@ -61,24 +68,10 @@ border-bottom-style: solid; border-bottom-width: 1; } - .ReactTable .rt-td { - border-width: 1; - border-right-color: #aaa - } - .ReactTable .rt-tr-group { - border-width: 1; - border-bottom-color: #aaa - } - .imageBox-cont img { - object-fit: contain; - height: 100% - } .documentView-node:first-child { background: grey; .imageBox-cont img { object-fit: contain; - max-width: 100%; - height: 100% } } } diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index d2db93120..dc952ef82 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -16,6 +16,8 @@ import "./CollectionSchemaView.scss"; import { COLLECTION_BORDER_WIDTH } from "./CollectionView"; import { CollectionViewBase } from "./CollectionViewBase"; +// bcz: need to add drag and drop of rows and columns. This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657 + @observer export class CollectionSchemaView extends CollectionViewBase { private _mainCont = React.createRef(); @@ -140,7 +142,7 @@ export class CollectionSchemaView extends CollectionViewBase { let content = this._selectedIndex == -1 || !selected ? (null) : ( {({ measureRef }) => -
+
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 17123bf52..d7243421a 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -88,7 +88,7 @@ export class CollectionFreeFormDocumentView extends React.Component { } } render() { + var val = this.props.doc.Get(this.props.fieldKey); return (
) } diff --git a/src/client/views/nodes/ImageBox.scss b/src/client/views/nodes/ImageBox.scss index 5b15b3329..ea459b911 100644 --- a/src/client/views/nodes/ImageBox.scss +++ b/src/client/views/nodes/ImageBox.scss @@ -4,12 +4,14 @@ position: relative; text-align: center; width: 100%; + height: auto; max-width: 100%; max-height: 100% } + .imageBox-cont img { - max-width: 100%; - max-height: 100% + object-fit: contain; + height: 100%; } .imageBox-button { -- cgit v1.2.3-70-g09d2 From c439f11ba9695703697f7abc53a7cc2fd2d5c1a2 Mon Sep 17 00:00:00 2001 From: bob Date: Mon, 25 Feb 2019 12:38:47 -0500 Subject: fixes for dropping documents without a know height. --- src/client/documents/Documents.ts | 6 +--- src/client/views/DocumentDecorations.tsx | 23 ++++++++-------- .../views/collections/CollectionFreeFormView.tsx | 30 ++++++++++++++------ src/client/views/collections/CollectionView.tsx | 11 ++++++-- .../views/collections/CollectionViewBase.tsx | 4 +-- .../views/nodes/CollectionFreeFormDocumentView.tsx | 32 +++++----------------- src/client/views/nodes/DocumentView.tsx | 4 ++- src/client/views/nodes/FormattedTextBox.tsx | 5 +++- src/client/views/nodes/ImageBox.tsx | 13 +++++++-- src/fields/Document.ts | 2 +- src/fields/Field.ts | 3 ++ 11 files changed, 73 insertions(+), 60 deletions(-) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 2dfff6235..15ecfbfe6 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -112,9 +112,7 @@ export namespace Documents { imageProto.Set(KeyStore.X, new NumberField(0)); imageProto.Set(KeyStore.Y, new NumberField(0)); imageProto.Set(KeyStore.NativeWidth, new NumberField(300)); - imageProto.Set(KeyStore.NativeHeight, new NumberField(300)); imageProto.Set(KeyStore.Width, new NumberField(300)); - imageProto.Set(KeyStore.Height, new NumberField(300)); imageProto.Set(KeyStore.Layout, new TextField(CollectionView.LayoutString("AnnotationsKey"))); imageProto.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform) imageProto.Set(KeyStore.BackgroundLayout, new TextField(ImageBox.LayoutString())); @@ -151,9 +149,7 @@ export namespace Documents { doc.Set(KeyStore.BackgroundLayout, new TextField(EmbeddedCaption())); doc.Set(KeyStore.OverlayLayout, new TextField(FixedCaption())); doc.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data, KeyStore.Annotations, KeyStore.Caption])); - - let annotation = Documents.TextDocument({ title: "hello" }); - doc.Set(KeyStore.Annotations, new ListField([annotation])); + console.log("" + doc.GetNumber(KeyStore.Height, 311)); return doc; } diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 2f012913d..975a125f7 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -104,25 +104,26 @@ export class DocumentDecorations extends React.Component { const rect = element.screenRect(); if (rect.width !== 0) { let doc = element.props.Document; - let width = doc.GetOrCreate(KeyStore.Width, NumberField); - let height = doc.GetOrCreate(KeyStore.Height, NumberField); + let width = doc.GetNumber(KeyStore.Width, 0); + let nwidth = doc.GetNumber(KeyStore.NativeWidth, 0); + let nheight = doc.GetNumber(KeyStore.NativeHeight, 0); + let height = doc.GetNumber(KeyStore.Height, nwidth ? nheight / nwidth * width : 0); let x = doc.GetOrCreate(KeyStore.X, NumberField); let y = doc.GetOrCreate(KeyStore.Y, NumberField); - let scale = width.Data / rect.width; - let actualdW = Math.max(width.Data + (dW * scale), 20); - let actualdH = Math.max(height.Data + (dH * scale), 20); - x.Data += dX * (actualdW - width.Data); - y.Data += dY * (actualdH - height.Data); + let scale = width / rect.width; + let actualdW = Math.max(width + (dW * scale), 20); + let actualdH = Math.max(height + (dH * scale), 20); + x.Data += dX * (actualdW - width); + y.Data += dY * (actualdH - height); var nativeWidth = doc.GetNumber(KeyStore.NativeWidth, 0); var nativeHeight = doc.GetNumber(KeyStore.NativeHeight, 0); if (nativeWidth > 0 && nativeHeight > 0) { if (Math.abs(dW) > Math.abs(dH)) actualdH = nativeHeight / nativeWidth * actualdW; - else - actualdW = nativeWidth / nativeHeight * actualdH; + else actualdW = nativeWidth / nativeHeight * actualdH; } - width.Data = actualdW; - height.Data = actualdH; + doc.SetNumber(KeyStore.Width, actualdW); + doc.SetNumber(KeyStore.Height, actualdH); } }) } diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx index c40da6eaa..7cad2cc03 100644 --- a/src/client/views/collections/CollectionFreeFormView.tsx +++ b/src/client/views/collections/CollectionFreeFormView.tsx @@ -102,18 +102,30 @@ export class CollectionFreeFormView extends CollectionViewBase { e.stopPropagation(); e.preventDefault(); let coefficient = 1000; - // if (modes[e.deltaMode] == 'pixels') coefficient = 50; - // else if (modes[e.deltaMode] == 'lines') coefficient = 1000; // This should correspond to line-height?? - let transform = this.getTransform(); - let deltaScale = (1 - (e.deltaY / coefficient)); - let [x, y] = transform.transformPoint(e.clientX, e.clientY); + if (e.ctrlKey) { + var nativeWidth = this.props.Document.GetNumber(KeyStore.NativeWidth, 0); + var nativeHeight = this.props.Document.GetNumber(KeyStore.NativeHeight, 0); + const coefficient = 1000; + let deltaScale = (1 - (e.deltaY / coefficient)); + this.props.Document.SetNumber(KeyStore.NativeWidth, nativeWidth * deltaScale); + this.props.Document.SetNumber(KeyStore.NativeHeight, nativeHeight * deltaScale); + e.stopPropagation(); + e.preventDefault(); + } else { + // if (modes[e.deltaMode] == 'pixels') coefficient = 50; + // else if (modes[e.deltaMode] == 'lines') coefficient = 1000; // This should correspond to line-height?? + let transform = this.getTransform(); - let localTransform = this.getLocalTransform(); - localTransform = localTransform.inverse().scaleAbout(deltaScale, x, y) + let deltaScale = (1 - (e.deltaY / coefficient)); + let [x, y] = transform.transformPoint(e.clientX, e.clientY); - this.props.Document.SetNumber(KeyStore.Scale, localTransform.Scale); - this.SetPan(localTransform.TranslateX, localTransform.TranslateY); + let localTransform = this.getLocalTransform(); + localTransform = localTransform.inverse().scaleAbout(deltaScale, x, y) + + this.props.Document.SetNumber(KeyStore.Scale, localTransform.Scale); + this.SetPan(localTransform.TranslateX, localTransform.TranslateY); + } } @action diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 90080ab43..88c15da07 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -11,6 +11,7 @@ import { CollectionFreeFormView } from "./CollectionFreeFormView"; import { CollectionDockingView } from "./CollectionDockingView"; import { CollectionSchemaView } from "./CollectionSchemaView"; import { CollectionViewProps } from "./CollectionViewBase"; +import { Field } from "../../../fields/Field"; @@ -39,9 +40,13 @@ export class CollectionView extends React.Component { } @action addDocument = (doc: Document): void => { - //TODO This won't create the field if it doesn't already exist - const value = this.props.Document.GetData(this.props.fieldKey, ListField, new Array()) - value.push(doc); + if (this.props.Document.Get(this.props.fieldKey) instanceof Field) { + //TODO This won't create the field if it doesn't already exist + const value = this.props.Document.GetData(this.props.fieldKey, ListField, new Array()) + value.push(doc); + } else { + this.props.Document.SetData(this.props.fieldKey, [doc], ListField); + } } @action diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx index 7e269caf1..f64a48c18 100644 --- a/src/client/views/collections/CollectionViewBase.tsx +++ b/src/client/views/collections/CollectionViewBase.tsx @@ -60,7 +60,7 @@ export class CollectionViewBase extends React.Component let html = e.dataTransfer.getData("text/html"); let text = e.dataTransfer.getData("text/plain"); - if (html) { + if (html && html.indexOf(" if (item.kind === "string" && item.type.indexOf("uri") != -1) { e.dataTransfer.items[i].getAsString(function (s) { action(() => { - var img = Documents.ImageDocument(s, { ...options, nativeWidth: 300, nativeHeight: 300, width: 300, height: 300 }) + var img = Documents.ImageDocument(s, { ...options, nativeWidth: 300, width: 300, }) let docs = that.props.Document.GetT(KeyStore.Data, ListField); if (docs != FieldWaiting) { diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index d7243421a..50dc5a619 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -27,44 +27,26 @@ export class CollectionFreeFormDocumentView extends React.Component 0 && this.nativeHeight > 0) { + if (this.nativeWidth && this.nativeHeight) { this.props.Document.SetNumber(KeyStore.Height, this.nativeHeight / this.nativeWidth * w) } } - @computed - get height(): number { - return this.props.Document.GetNumber(KeyStore.Height, 0); - } - @computed - get nativeHeight(): number { - return this.props.Document.GetNumber(KeyStore.NativeHeight, 0); - } - set height(h: number) { this.props.Document.SetData(KeyStore.Height, h, NumberField); - if (this.nativeWidth > 0 && this.nativeHeight > 0) { + if (this.nativeWidth && this.nativeHeight) { this.props.Document.SetNumber(KeyStore.Width, this.nativeWidth / this.nativeHeight * h) } } - @computed - get zIndex(): number { - return this.props.Document.GetNumber(KeyStore.ZIndex, 0); - } - set zIndex(h: number) { this.props.Document.SetData(KeyStore.ZIndex, h, NumberField) } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index ad1328e5d..212697442 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -196,6 +196,7 @@ export class DocumentView extends React.Component { } @computed get mainContent() { + var val = this.props.Document.Id; return { transform: `scale(${scaling},${scaling})` }} onContextMenu={this.onContextMenu} - onPointerDown={this.onPointerDown} > + onPointerDown={this.onPointerDown} + > {this.mainContent}
) diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 60ee0b5e1..a58e1955f 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -111,10 +111,13 @@ export class FormattedTextBox extends React.Component { e.stopPropagation(); } } + onPointerWheel = (e: React.WheelEvent): void => { + e.stopPropagation(); + } render() { - var val = this.props.doc.Get(this.props.fieldKey); return (
) } } \ No newline at end of file diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index b5ce8b28c..4fe73fb8d 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -9,12 +9,14 @@ import { FieldWaiting } from '../../../fields/Field'; import { observer } from "mobx-react" import { observable, action } from 'mobx'; import { KeyStore } from '../../../fields/KeyStore'; +import { element } from 'prop-types'; @observer export class ImageBox extends React.Component { public static LayoutString() { return FieldView.LayoutString(ImageBox) } private _ref: React.RefObject; + private _imgRef: React.RefObject; private _downX: number = 0; private _downY: number = 0; private _lastTap: number = 0; @@ -25,12 +27,20 @@ export class ImageBox extends React.Component { super(props); this._ref = React.createRef(); + this._imgRef = React.createRef(); this.state = { photoIndex: 0, isOpen: false, }; } + @action + onLoad = (target: any) => { + var h = this._imgRef.current!.naturalHeight; + var w = this._imgRef.current!.naturalWidth; + this.props.doc.SetNumber(KeyStore.NativeHeight, this.props.doc.GetNumber(KeyStore.NativeWidth, 0) * h / w) + } + componentDidMount() { } @@ -84,10 +94,9 @@ export class ImageBox extends React.Component { let path = field == FieldWaiting ? "https://image.flaticon.com/icons/svg/66/66163.svg" : field instanceof ImageField ? field.Data.href : "http://www.cs.brown.edu/~bcz/face.gif"; let nativeWidth = this.props.doc.GetNumber(KeyStore.NativeWidth, 1); - return (
- Image not found + Image not found {this.lightbox(path)}
) } diff --git a/src/fields/Document.ts b/src/fields/Document.ts index 0d7d357a0..4e68b3b4d 100644 --- a/src/fields/Document.ts +++ b/src/fields/Document.ts @@ -31,7 +31,7 @@ export class Document extends Field { } public Width = () => { return this.GetNumber(KeyStore.Width, 0) } - public Height = () => { return this.GetNumber(KeyStore.Height, 0) } + public Height = () => { return 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 = () => { return this.GetNumber(KeyStore.Scale, 1) } @computed diff --git a/src/fields/Field.ts b/src/fields/Field.ts index c7e0232af..d48509a47 100644 --- a/src/fields/Field.ts +++ b/src/fields/Field.ts @@ -1,6 +1,7 @@ import { Utils } from "../Utils"; import { Types } from "../server/Message"; +import { computed } from "mobx"; export function Cast(field: FieldValue, ctor: { new(): T }): Opt { if (field) { @@ -25,6 +26,8 @@ export abstract class Field { } private id: FieldId; + + @computed get Id(): FieldId { return this.id; } -- cgit v1.2.3-70-g09d2 From efe5d9515c88f6e0963ae1c04545b7bbbd8beb55 Mon Sep 17 00:00:00 2001 From: madelinegr Date: Mon, 25 Feb 2019 17:51:40 -0500 Subject: fixed some of bugs caused by pulling from master --- src/client/documents/Documents.ts | 27 --------------------------- src/client/views/nodes/FieldView.tsx | 5 ----- src/client/views/nodes/WebBox.tsx | 8 ++++---- src/fields/WebField.ts | 15 ++++++++++++--- src/server/Message.ts | 2 +- 5 files changed, 17 insertions(+), 40 deletions(-) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 398c6f1a2..5c73c6b87 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -7,17 +7,12 @@ import { ListField } from "../../fields/ListField"; import { FormattedTextBox } from "../views/nodes/FormattedTextBox"; import { ImageField } from "../../fields/ImageField"; import { ImageBox } from "../views/nodes/ImageBox"; -<<<<<<< HEAD import { WebField } from "../../fields/WebField"; import { WebBox } from "../views/nodes/WebBox"; import { CollectionFreeFormView } from "../views/collections/CollectionFreeFormView"; import { FieldId } from "../../fields/Field"; -======= import { CollectionView, CollectionViewType } from "../views/collections/CollectionView"; import { FieldView } from "../views/nodes/FieldView"; -import { HtmlField } from "../../fields/HtmlField"; -import { WebView } from "../views/nodes/WebView"; ->>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87 export interface DocumentOptions { x?: number; @@ -88,28 +83,6 @@ export namespace Documents { return doc; } - let htmlProto: Document; - const htmlProtoId = "htmlProto"; - function GetHtmlPrototype(): Document { - if (!htmlProto) { - htmlProto = new Document(htmlProtoId); - htmlProto.Set(KeyStore.X, new NumberField(0)); - htmlProto.Set(KeyStore.Y, new NumberField(0)); - htmlProto.Set(KeyStore.Width, new NumberField(300)); - htmlProto.Set(KeyStore.Height, new NumberField(150)); - htmlProto.Set(KeyStore.Layout, new TextField(WebView.LayoutString())); - htmlProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data])); - } - return htmlProto; - } - - export function HtmlDocument(html: string, options: DocumentOptions = {}): Document { - let doc = GetHtmlPrototype().MakeDelegate(); - setupOptions(doc, options); - doc.Set(KeyStore.Data, new HtmlField(html)); - return doc; - } - let imageProto: Document; const imageProtoId = "imageProto"; function GetImagePrototype(): Document { diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 368ad049d..978cfe196 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -11,13 +11,10 @@ import { WebField } from "../../../fields/WebField"; import { Key } from "../../../fields/Key"; import { FormattedTextBox } from "./FormattedTextBox"; import { ImageBox } from "./ImageBox"; -<<<<<<< HEAD import { WebBox } from "./WebBox"; import { DocumentView } from "./DocumentView"; -======= import { HtmlField } from "../../../fields/HtmlField"; import { WebView } from "./WebView"; ->>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87 // // these properties get assigned through the render() method of the DocumentView when it creates this node. @@ -61,8 +58,6 @@ export class FieldView extends React.Component { } else if (field instanceof NumberField) { return

{field.Data}

- } else if (field instanceof HtmlField) { - return } else if (field != FieldWaiting) { return

{field.GetValue}

} else diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index b9d0853b9..4f774bae2 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -9,12 +9,12 @@ import { CollectionFreeFormDocumentView } from './CollectionFreeFormDocumentView import { FieldWaiting } from '../../../fields/Field'; import { observer } from "mobx-react" import { observable, action, spy } from 'mobx'; -import { KeyStore } from '../../../fields/Key'; +import { KeyStore } from '../../../fields/KeyStore'; @observer export class WebBox extends React.Component { - public static LayoutString() { return FieldView.LayoutString("WebBox"); } + public static LayoutString() { return FieldView.LayoutString(WebBox); } private _ref: React.RefObject; private _downX: number = 0; private _downY: number = 0; @@ -38,8 +38,7 @@ export class WebBox extends React.Component { onPointerDown = (e: React.PointerEvent): void => { if (Date.now() - this._lastTap < 300) { - if (e.buttons === 1 && this.props.DocumentViewForField instanceof CollectionFreeFormDocumentView && - SelectionManager.IsSelected(this.props.DocumentViewForField)) { + if (e.buttons === 1 && this.props.isSelected()) { e.stopPropagation(); this._downX = e.clientX; this._downY = e.clientY; @@ -50,6 +49,7 @@ export class WebBox extends React.Component { this._lastTap = Date.now(); } } + @action onPointerUp = (e: PointerEvent): void => { document.removeEventListener("pointerup", this.onPointerUp); diff --git a/src/fields/WebField.ts b/src/fields/WebField.ts index cd3519128..8f945d686 100644 --- a/src/fields/WebField.ts +++ b/src/fields/WebField.ts @@ -1,9 +1,10 @@ import { BasicField } from "./BasicField"; -import { Field } from "./Field"; +import { Field, FieldId } from "./Field"; +import { Types } from "../server/Message"; export class WebField extends BasicField { - constructor(data: URL | undefined = undefined) { - super(data == undefined ? new URL("https://crossorigin.me/" + "https://cs.brown.edu/") : data); + constructor(data: URL | undefined = undefined, id?: FieldId, save: boolean = true) { + super(data == undefined ? new URL("https://crossorigin.me/" + "https://cs.brown.edu/") : data, save, id); } toString(): string { @@ -18,4 +19,12 @@ export class WebField extends BasicField { return new WebField(this.Data); } + ToJson(): { type: Types, data: URL, _id: string } { + return { + type: Types.Web, + data: this.Data, + _id: this.Id + } + } + } \ No newline at end of file diff --git a/src/server/Message.ts b/src/server/Message.ts index 80fc9a80d..148e6e723 100644 --- a/src/server/Message.ts +++ b/src/server/Message.ts @@ -45,7 +45,7 @@ export class GetFieldArgs { } export enum Types { - Number, List, Key, Image, Document, Text, RichText, DocumentReference, Html + Number, List, Key, Image, Web, Document, Text, RichText, DocumentReference, Html } export class DocumentTransfer implements Transferable { -- cgit v1.2.3-70-g09d2 From 245904b619675cda216218e8d38d0970b7b6b249 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 25 Feb 2019 22:00:22 -0500 Subject: for mac --- src/client/documents/Documents.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 15ecfbfe6..9770e5cdc 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -130,13 +130,13 @@ export namespace Documents {
` + ImageBox.LayoutString() + `
-
` +
` + FormattedTextBox.LayoutString("CaptionKey") + `
` }; function FixedCaption() { return `
-
` +
` + FormattedTextBox.LayoutString("CaptionKey") + `
` }; -- cgit v1.2.3-70-g09d2 From faccb013ad0265d1507e0b5c59cabb42aedbb88c Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 26 Feb 2019 23:54:07 -0500 Subject: fixed some drag problems. cleaned up Documents.ts --- src/client/documents/Documents.ts | 229 ++++++++++++-------------------- src/client/util/DragManager.ts | 8 +- src/client/views/nodes/DocumentView.tsx | 2 + 3 files changed, 95 insertions(+), 144 deletions(-) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index e5154737e..8b733507b 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -11,6 +11,8 @@ import { WebField } from "../../fields/WebField"; import { WebBox } from "../views/nodes/WebBox"; import { CollectionView, CollectionViewType } from "../views/collections/CollectionView"; import { HtmlField } from "../../fields/HtmlField"; +import { Key } from "../../fields/Key" +import { Field } from "../../fields/Field"; export interface DocumentOptions { x?: number; @@ -20,87 +22,110 @@ export interface DocumentOptions { nativeWidth?: number; nativeHeight?: number; title?: string; + panx?: number; + pany?: number; + scale?: number; + layout?: string; + layoutKeys?: Key[]; + viewType?: number; } export namespace Documents { + let textProto: Document; + let imageProto: Document; + let webProto: Document; + let collProto: Document; + const textProtoId = "textProto"; + const imageProtoId = "imageProto"; + const webProtoId = "webProto"; + const collProtoId = "collectionProto"; + export function initProtos(callback: () => void) { - Server.GetFields([collectionProtoId, textProtoId, imageProtoId], (fields) => { - collectionProto = fields[collectionProtoId] as Document; + Server.GetFields([collProtoId, textProtoId, imageProtoId], (fields) => { + collProto = fields[collProtoId] as Document; imageProto = fields[imageProtoId] as Document; textProto = fields[textProtoId] as Document; + webProto = fields[webProtoId] as Document; callback() }); } - - function setupOptions(doc: Document, options: DocumentOptions): void { - if (options.x !== undefined) { - doc.SetData(KeyStore.X, options.x, NumberField); - } - if (options.y !== undefined) { - doc.SetData(KeyStore.Y, options.y, NumberField); - } - if (options.width !== undefined) { - doc.SetData(KeyStore.Width, options.width, NumberField); - } - if (options.height !== undefined) { - doc.SetData(KeyStore.Height, options.height, NumberField); - } - if (options.nativeWidth !== undefined) { - doc.SetData(KeyStore.NativeWidth, options.nativeWidth, NumberField); - } - if (options.nativeHeight !== undefined) { - doc.SetData(KeyStore.NativeHeight, options.nativeHeight, NumberField); - } - if (options.title !== undefined) { - doc.SetData(KeyStore.Title, options.title, TextField); - } - doc.SetData(KeyStore.Scale, 1, NumberField); - doc.SetData(KeyStore.PanX, 0, NumberField); - doc.SetData(KeyStore.PanY, 0, NumberField); + function assignOptions(doc: Document, options: DocumentOptions): Document { + if (options.x !== undefined) { doc.SetNumber(KeyStore.X, options.x); } + if (options.y !== undefined) { doc.SetNumber(KeyStore.Y, options.y); } + if (options.width !== undefined) { doc.SetNumber(KeyStore.Width, options.width); } + if (options.height !== undefined) { doc.SetNumber(KeyStore.Height, options.height); } + if (options.nativeWidth !== undefined) { doc.SetNumber(KeyStore.NativeWidth, options.nativeWidth); } + if (options.nativeHeight !== undefined) { doc.SetNumber(KeyStore.NativeHeight, options.nativeHeight); } + if (options.title !== undefined) { doc.SetText(KeyStore.Title, options.title); } + if (options.panx !== undefined) { doc.SetNumber(KeyStore.PanX, options.panx); } + if (options.pany !== undefined) { doc.SetNumber(KeyStore.PanY, options.pany); } + if (options.scale !== undefined) { doc.SetNumber(KeyStore.Scale, options.scale); } + if (options.viewType !== undefined) { doc.SetNumber(KeyStore.ViewType, options.viewType); } + if (options.layout !== undefined) { doc.SetText(KeyStore.Layout, options.layout); } + if (options.layoutKeys !== undefined) { doc.Set(KeyStore.LayoutKeys, new ListField(options.layoutKeys)); } + return doc; } - - let textProto: Document; - const textProtoId = "textProto"; - function GetTextPrototype(): Document { - if (!textProto) { - textProto = new Document(textProtoId); - textProto.Set(KeyStore.X, new NumberField(0)); - textProto.Set(KeyStore.Y, new NumberField(0)); - textProto.Set(KeyStore.Width, new NumberField(300)); - textProto.Set(KeyStore.Height, new NumberField(150)); - textProto.Set(KeyStore.Layout, new TextField(FormattedTextBox.LayoutString())); - textProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data])); - } - return textProto; + function setupPrototypeOptions(protoId: string, title: string, layout: string, options: DocumentOptions): Document { + return assignOptions(new Document(protoId), { ...options, title: title, layout: layout }); } - - export function TextDocument(options: DocumentOptions = {}): Document { - let doc = GetTextPrototype().MakeDelegate(); - setupOptions(doc, options); - // doc.Set(KeyStore.Data, new RichTextField()); - return doc; + function SetInstanceOptions(doc: Document, options: DocumentOptions, value: T, ctor: { new(): U }, id?: string) { + var deleg = doc.MakeDelegate(id); + deleg.SetData(KeyStore.Data, value, ctor); + return assignOptions(deleg, options); } - let imageProto: Document; - const imageProtoId = "imageProto"; function GetImagePrototype(): Document { if (!imageProto) { - imageProto = new Document(imageProtoId); - imageProto.Set(KeyStore.Title, new TextField("IMAGE PROTO")); - imageProto.Set(KeyStore.X, new NumberField(0)); - imageProto.Set(KeyStore.Y, new NumberField(0)); - imageProto.Set(KeyStore.NativeWidth, new NumberField(300)); - imageProto.Set(KeyStore.Width, new NumberField(300)); - imageProto.Set(KeyStore.Layout, new TextField(CollectionView.LayoutString("AnnotationsKey"))); - imageProto.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform) - imageProto.Set(KeyStore.BackgroundLayout, new TextField(ImageBox.LayoutString())); - // imageProto.Set(KeyStore.Layout, new TextField('
')); - imageProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data, KeyStore.Annotations])); - return imageProto; + imageProto = setupPrototypeOptions(imageProtoId, "IMAGE_PROTO", CollectionView.LayoutString("AnnotationsKey"), + { x: 0, y: 0, nativeWidth: 300, width: 300, layoutKeys: [KeyStore.Data, KeyStore.Annotations] }); + imageProto.SetText(KeyStore.BackgroundLayout, ImageBox.LayoutString()); } return imageProto; + } + function GetTextPrototype(): Document { + return textProto ? textProto : + textProto = setupPrototypeOptions(textProtoId, "TEXT_PROTO", FormattedTextBox.LayoutString(), + { x: 0, y: 0, width: 300, height: 150, layoutKeys: [KeyStore.Data] }); + } + function GetWebPrototype(): Document { + return webProto ? webProto : + webProto = setupPrototypeOptions(webProtoId, "WEB_PROTO", WebBox.LayoutString(), + { x: 0, y: 0, width: 300, height: 300, layoutKeys: [KeyStore.Data] }); + } + function GetCollectionPrototype(): Document { + return collProto ? collProto : + collProto = setupPrototypeOptions(collProtoId, "COLLECTION_PROTO", CollectionView.LayoutString("DataKey"), + { panx: 0, pany: 0, scale: 1, layoutKeys: [KeyStore.Data] }); + } + export function ImageDocument(url: string, options: DocumentOptions = {}) { + let doc = SetInstanceOptions(GetImagePrototype(), { ...options, layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] }, + new URL(url), ImageField); + doc.SetText(KeyStore.Caption, "my caption..."); + doc.SetText(KeyStore.BackgroundLayout, EmbeddedCaption()); + doc.SetText(KeyStore.OverlayLayout, FixedCaption()); + return doc; + } + export function TextDocument(options: DocumentOptions = {}) { + return SetInstanceOptions(GetTextPrototype(), options, "", TextField); + } + export function WebDocument(url: string, options: DocumentOptions = {}) { + return SetInstanceOptions(GetWebPrototype(), options, new URL(url), WebField); + } + export function HtmlDocument(html: string, options: DocumentOptions = {}) { + return SetInstanceOptions(GetWebPrototype(), options, html, HtmlField); + } + export function FreeformDocument(documents: Array, options: DocumentOptions, id?: string) { + return SetInstanceOptions(GetCollectionPrototype(), { ...options, viewType: CollectionViewType.Freeform }, documents, ListField, id) } + export function SchemaDocument(documents: Array, options: DocumentOptions, id?: string) { + return SetInstanceOptions(GetCollectionPrototype(), { ...options, viewType: CollectionViewType.Schema }, documents, ListField, id) + } + export function DockDocument(config: string, options: DocumentOptions, id?: string) { + return SetInstanceOptions(GetCollectionPrototype(), { ...options, viewType: CollectionViewType.Docking }, config, TextField, id) + } + + // example of custom display string for an image that shows a caption. function EmbeddedCaption() { @@ -118,84 +143,4 @@ export namespace Documents { + FormattedTextBox.LayoutString("CaptionKey") + `
` }; - - export function ImageDocument(url: string, options: DocumentOptions = {}): Document { - let doc = GetImagePrototype().MakeDelegate(); - setupOptions(doc, options); - doc.Set(KeyStore.Data, new ImageField(new URL(url))); - doc.Set(KeyStore.Caption, new TextField("my caption...")); - doc.Set(KeyStore.BackgroundLayout, new TextField(EmbeddedCaption())); - doc.Set(KeyStore.OverlayLayout, new TextField(FixedCaption())); - doc.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data, KeyStore.Annotations, KeyStore.Caption])); - console.log("" + doc.GetNumber(KeyStore.Height, 311)); - return doc; - } - - let webProto: Document; - const webProtoId = "webProto"; - function GetWebPrototype(): Document { - if (!webProto) { - webProto = new Document(webProtoId); - webProto.Set(KeyStore.Title, new TextField("WEB PROTO")); - webProto.Set(KeyStore.X, new NumberField(0)); - webProto.Set(KeyStore.Y, new NumberField(0)); - webProto.Set(KeyStore.Width, new NumberField(300)); - webProto.Set(KeyStore.Height, new NumberField(300)); - //webProto.Set(KeyStore.Layout, new TextField(CollectionView.LayoutString("AnnotationsKey"))); - webProto.Set(KeyStore.Layout, new TextField(WebBox.LayoutString())); - webProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data, KeyStore.Annotations])); - } - return webProto; - } - - export function WebDocument(url: string, options: DocumentOptions = {}): Document { - let doc = GetWebPrototype().MakeDelegate(); - setupOptions(doc, options); - doc.Set(KeyStore.Data, new WebField(new URL(url))); - return doc; - } - export function HtmlDocument(html: string, options: DocumentOptions = {}): Document { - let doc = GetWebPrototype().MakeDelegate(); - setupOptions(doc, options); - doc.Set(KeyStore.Data, new HtmlField(html)); - return doc; - } - - let collectionProto: Document; - const collectionProtoId = "collectionProto"; - function GetCollectionPrototype(): Document { - if (!collectionProto) { - collectionProto = new Document(collectionProtoId); - collectionProto.Set(KeyStore.Scale, new NumberField(1)); - collectionProto.Set(KeyStore.PanX, new NumberField(0)); - collectionProto.Set(KeyStore.PanY, new NumberField(0)); - collectionProto.Set(KeyStore.Layout, new TextField(CollectionView.LayoutString("DataKey"))); - collectionProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data])); - } - return collectionProto; - } - - export function CollectionDocument(data: Array | string, viewType: CollectionViewType, options: DocumentOptions = {}, id?: string): Document { - let doc = GetCollectionPrototype().MakeDelegate(id); - setupOptions(doc, options); - if (typeof data === "string") { - doc.SetText(KeyStore.Data, data); - } else { - doc.SetData(KeyStore.Data, data, ListField); - } - doc.SetNumber(KeyStore.ViewType, viewType); - return doc; - } - - export function FreeformDocument(documents: Array, options: DocumentOptions, id?: string) { - return CollectionDocument(documents, CollectionViewType.Freeform, options, id) - } - - export function SchemaDocument(documents: Array, options: DocumentOptions, id?: string) { - return CollectionDocument(documents, CollectionViewType.Schema, options, id) - } - - export function DockDocument(config: string, options: DocumentOptions, id?: string) { - return CollectionDocument(config, CollectionViewType.Docking, options, id) - } } \ No newline at end of file diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 6b4b8ca57..60910a40b 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -133,7 +133,6 @@ export namespace DragManager { if (hideSource) { ele.hidden = true; } - const moveHandler = (e: PointerEvent) => { e.stopPropagation(); e.preventDefault(); @@ -158,14 +157,19 @@ export namespace DragManager { } const upHandler = (e: PointerEvent) => { abortDrag(); - FinishDrag(dragElement, e, dragData, options); + FinishDrag(ele, e, dragData, options); }; document.addEventListener("pointermove", moveHandler, true); document.addEventListener("pointerup", upHandler); } function FinishDrag(dragEle: HTMLElement, e: PointerEvent, dragData: { [index: string]: any }, options?: DragOptions) { + let parent = dragEle.parentElement; + if (parent) + parent.removeChild(dragEle); const target = document.elementFromPoint(e.x, e.y); + if (parent) + parent.appendChild(dragEle); if (!target) { return; } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 8e5a0d17e..c929f9d54 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -119,6 +119,8 @@ export class DocumentView extends React.Component { return; } if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) { + document.removeEventListener("pointermove", this.onPointerMove) + document.removeEventListener("pointerup", this.onPointerUp) this._contextMenuCanOpen = false; if (this._mainCont.current != null && !this.topMost) { this._contextMenuCanOpen = false; -- cgit v1.2.3-70-g09d2 From 7d7d9349a9c2c7136eccf8d08af506d00f2bd2fd Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 27 Feb 2019 00:24:46 -0500 Subject: cleaned up main a tiny bit --- src/client/documents/Documents.ts | 6 +- src/client/views/Main.tsx | 156 ++++++++++++++++---------------------- 2 files changed, 70 insertions(+), 92 deletions(-) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 8b733507b..ba13cc31b 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -40,13 +40,13 @@ export namespace Documents { const webProtoId = "webProto"; const collProtoId = "collectionProto"; - export function initProtos(callback: () => void) { - Server.GetFields([collProtoId, textProtoId, imageProtoId], (fields) => { + export function initProtos(mainDocId: string, callback: (mainDoc?: Document) => void) { + Server.GetFields([collProtoId, textProtoId, imageProtoId, mainDocId], (fields) => { collProto = fields[collProtoId] as Document; imageProto = fields[imageProtoId] as Document; textProto = fields[textProtoId] as Document; webProto = fields[webProtoId] as Document; - callback() + callback(fields[mainDocId] as Document) }); } function assignOptions(doc: Document, options: DocumentOptions): Document { diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 578aecd1e..305627c19 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -53,98 +53,76 @@ document.addEventListener("pointerdown", action(function (e: PointerEvent) { // const doc7 = Documents.SchemaDocument(schemaDocs) const mainDocId = "mainDoc"; -Documents.initProtos(() => { - Utils.EmitCallback(Server.Socket, MessageStore.GetField, mainDocId, (res: any) => { - console.log("HELLO WORLD") - console.log("RESPONSE: " + res) - let mainContainer: Document; - let mainfreeform: Document; - if (res) { - mainContainer = ServerUtils.FromJson(res) as Document; - mainContainer.GetAsync(KeyStore.ActiveFrame, field => mainfreeform = field as Document); - } - else { - mainContainer = Documents.DockDocument(JSON.stringify({ content: [{ type: 'row', content: [] }] }), { title: "main container" }, mainDocId); - Utils.Emit(Server.Socket, MessageStore.AddDocument, new DocumentTransfer(mainContainer.ToJson())) +Documents.initProtos(mainDocId, (res?: Document) => { + console.log("HELLO WORLD") + console.log("RESPONSE: " + res) + let mainContainer: Document; + let mainfreeform: Document; + if (res) { + mainContainer = res as Document; + mainContainer.GetAsync(KeyStore.ActiveFrame, field => mainfreeform = field as Document); + } + else { + mainContainer = Documents.DockDocument(JSON.stringify({ content: [{ type: 'row', content: [] }] }), { title: "main container" }, mainDocId); + Utils.Emit(Server.Socket, MessageStore.AddDocument, new DocumentTransfer(mainContainer.ToJson())) - setTimeout(() => { - mainfreeform = Documents.FreeformDocument([], { x: 0, y: 400, title: "mini collection" }); - Utils.Emit(Server.Socket, MessageStore.AddDocument, new DocumentTransfer(mainfreeform.ToJson())); + // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container) + setTimeout(() => { + mainfreeform = Documents.FreeformDocument([], { x: 0, y: 400, title: "mini collection" }); + Utils.Emit(Server.Socket, MessageStore.AddDocument, new DocumentTransfer(mainfreeform.ToJson())); - var docs = [mainfreeform].map(doc => CollectionDockingView.makeDocumentConfig(doc)); - mainContainer.SetText(KeyStore.Data, JSON.stringify({ content: [{ type: 'row', content: docs }] })); - mainContainer.Set(KeyStore.ActiveFrame, mainfreeform); - }, 0); - } + var docs = [mainfreeform].map(doc => CollectionDockingView.makeDocumentConfig(doc)); + mainContainer.SetText(KeyStore.Data, JSON.stringify({ content: [{ type: 'row', content: docs }] })); + mainContainer.Set(KeyStore.ActiveFrame, mainfreeform); + }, 0); + } - let clearDatabase = action(() => Utils.Emit(Server.Socket, MessageStore.DeleteAll, {})) - let addTextNode = action(() => Documents.TextDocument({ width: 200, height: 200, title: "a text note" })) - let addColNode = action(() => Documents.FreeformDocument([], { width: 200, height: 200, title: "a feeform collection" })); - let addSchemaNode = action(() => Documents.SchemaDocument([Documents.TextDocument()], { width: 200, height: 200, title: "a schema collection" })); - let addImageNode = action(() => Documents.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { - width: 200, height: 200, title: "an image of a cat" - })); - let addWebNode = action(() => Documents.WebDocument("https://cs.brown.edu/courses/cs166/", { - width: 200, height: 200, title: "a sample web page" - })); + let imgurl = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg"; + let weburl = "https://cs.brown.edu/courses/cs166/"; + let clearDatabase = action(() => Utils.Emit(Server.Socket, MessageStore.DeleteAll, {})) + let addTextNode = action(() => Documents.TextDocument({ width: 200, height: 200, title: "a text note" })) + let addColNode = action(() => Documents.FreeformDocument([], { width: 200, height: 200, title: "a feeform collection" })); + let addSchemaNode = action(() => Documents.SchemaDocument([Documents.TextDocument()], { width: 200, height: 200, title: "a schema collection" })); + let addImageNode = action(() => Documents.ImageDocument(imgurl, { width: 200, height: 200, title: "an image of a cat" })); + let addWebNode = action(() => Documents.WebDocument(weburl, { width: 200, height: 200, title: "a sample web page" })); - let addClick = (creator: any) => action(() => { - var img = creator(); - img.SetNumber(KeyStore.X, 0); - img.SetNumber(KeyStore.Y, 0); - mainfreeform.GetList(KeyStore.Data, []).push(img); - }); + let addClick = (creator: any) => action(() => { + var img = creator(); + img.SetNumber(KeyStore.X, 0); + img.SetNumber(KeyStore.Y, 0); + mainfreeform.GetList(KeyStore.Data, []).push(img); + }); - let imgRef = React.createRef(); - let webRef = React.createRef(); - let textRef = React.createRef(); - let schemaRef = React.createRef(); - let colRef = React.createRef(); + let imgRef = React.createRef(); + let webRef = React.createRef(); + let textRef = React.createRef(); + let schemaRef = React.createRef(); + let colRef = React.createRef(); - ReactDOM.render(( -
- Transform.Identity} - ContentScaling={() => 1} - PanelWidth={() => 0} - PanelHeight={() => 0} - isTopMost={true} - ContainingCollectionView={undefined} /> - - -
-
-
-
-
-
-
-
-
-
- - - -
), - document.getElementById('root')); - }) -}); -// let doc5 = Documents.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { -// x: 650, y: 500, width: 600, height: 600, title: "cat 2" -// }); -// let docset2 = new Array(doc4);//, doc1, doc3); -// let doc6 = Documents.CollectionDocument(docset2, { -// x: 350, y: 100, width: 600, height: 600, title: "docking collection" -// }); -// let mainNodes = mainContainer.GetOrCreate(KeyStore.Data, ListField); -// mainNodes.Data.push(doc6); -// mainNodes.Data.push(doc2); -// mainNodes.Data.push(doc4); -// mainNodes.Data.push(doc3); -// mainNodes.Data.push(doc5); -// mainNodes.Data.push(doc1); -//mainNodes.Data.push(doc2); -//mainNodes.Data.push(doc6); -// mainContainer.Set(KeyStore.Data, mainNodes); -//} -//); + ReactDOM.render(( +
+ Transform.Identity} + ContentScaling={() => 1} + PanelWidth={() => 0} + PanelHeight={() => 0} + isTopMost={true} + ContainingCollectionView={undefined} /> + + +
+
+
+
+
+
+
+
+
+
+ + + +
), + document.getElementById('root')); +}) -- cgit v1.2.3-70-g09d2 From 23387df535e9ab87a08196aab19de6f937ae9bba Mon Sep 17 00:00:00 2001 From: madelinegr Date: Thu, 28 Feb 2019 00:20:14 -0500 Subject: finished kvp --- package-lock.json | 21 +-- package.json | 2 +- src/client/documents/Documents.ts | 16 ++ .../views/collections/CollectionFreeFormView.tsx | 7 - src/client/views/nodes/DocumentView.tsx | 14 +- src/client/views/nodes/FieldView.tsx | 2 + src/client/views/nodes/KeyValuePair.tsx | 68 ++++++++ src/client/views/nodes/KeyValuePane.tsx | 176 +++++++++------------ src/fields/KVPField | 0 src/fields/KVPField.ts | 30 ++++ 10 files changed, 198 insertions(+), 138 deletions(-) create mode 100644 src/client/views/nodes/KeyValuePair.tsx create mode 100644 src/fields/KVPField create mode 100644 src/fields/KVPField.ts (limited to 'src/client/documents') diff --git a/package-lock.json b/package-lock.json index d03e78a2d..75e6cae17 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3285,11 +3285,6 @@ } } }, - "font-awesome": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz", - "integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM=" - }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -3399,13 +3394,11 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true, - "optional": true + "bundled": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3422,8 +3415,7 @@ }, "concat-map": { "version": "0.0.1", - "bundled": true, - "optional": true + "bundled": true }, "console-control-strings": { "version": "1.1.0", @@ -3552,7 +3544,6 @@ "minimatch": { "version": "3.0.4", "bundled": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -10434,14 +10425,6 @@ "scheduler": "^0.12.0" } }, - "react-fontawesome": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/react-fontawesome/-/react-fontawesome-1.6.1.tgz", - "integrity": "sha1-7dzhfn3HMaoJ/UoYZoimF5OhbFw=", - "requires": { - "prop-types": "^15.5.6" - } - }, "react-golden-layout": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/react-golden-layout/-/react-golden-layout-1.0.6.tgz", diff --git a/package.json b/package.json index 8568a7bef..ae7a7b25c 100644 --- a/package.json +++ b/package.json @@ -116,4 +116,4 @@ "url-loader": "^1.1.2", "uuid": "^3.3.2" } -} \ No newline at end of file +} diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index ba13cc31b..41f1c9b3f 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -13,6 +13,8 @@ import { CollectionView, CollectionViewType } from "../views/collections/Collect import { HtmlField } from "../../fields/HtmlField"; import { Key } from "../../fields/Key" import { Field } from "../../fields/Field"; +import { KeyValuePane } from "../views/nodes/KeyValuePane" +import { KVPField } from "../../fields/KVPField"; export interface DocumentOptions { x?: number; @@ -35,10 +37,12 @@ export namespace Documents { let imageProto: Document; let webProto: Document; let collProto: Document; + let kvpProto: Document; const textProtoId = "textProto"; const imageProtoId = "imageProto"; const webProtoId = "webProto"; const collProtoId = "collectionProto"; + const kvpProtoId = "kvpProto"; export function initProtos(mainDocId: string, callback: (mainDoc?: Document) => void) { Server.GetFields([collProtoId, textProtoId, imageProtoId, mainDocId], (fields) => { @@ -46,6 +50,7 @@ export namespace Documents { imageProto = fields[imageProtoId] as Document; textProto = fields[textProtoId] as Document; webProto = fields[webProtoId] as Document; + kvpProto = fields[kvpProtoId] as Document; callback(fields[mainDocId] as Document) }); } @@ -98,6 +103,12 @@ export namespace Documents { { panx: 0, pany: 0, scale: 1, layoutKeys: [KeyStore.Data] }); } + function GetKVPPrototype(): Document { + return kvpProto ? kvpProto : + kvpProto = setupPrototypeOptions(kvpProtoId, "KVP_PROTO", KeyValuePane.LayoutString(), + { x: 0, y: 0, width: 300, height: 150, layoutKeys: [KeyStore.Data] }) + } + export function ImageDocument(url: string, options: DocumentOptions = {}) { let doc = SetInstanceOptions(GetImagePrototype(), { ...options, layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] }, new URL(url), ImageField); @@ -124,6 +135,11 @@ export namespace Documents { export function DockDocument(config: string, options: DocumentOptions, id?: string) { return SetInstanceOptions(GetCollectionPrototype(), { ...options, viewType: CollectionViewType.Docking }, config, TextField, id) } + export function KVPDocument(document: Document, options: DocumentOptions = {}, id?: string) { + var deleg = GetKVPPrototype().MakeDelegate(id); + deleg.Set(KeyStore.Data, document); + return assignOptions(deleg, options); + } diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx index 29d254e56..137bcf706 100644 --- a/src/client/views/collections/CollectionFreeFormView.tsx +++ b/src/client/views/collections/CollectionFreeFormView.tsx @@ -194,12 +194,6 @@ export class CollectionFreeFormView extends CollectionViewBase { }); } - @action - addKVP(doc: Document) { - let fields = doc.fields; - //TODO: return kvpg - } - @computed get backgroundLayout(): string | undefined { let field = this.props.Document.GetT(KeyStore.BackgroundLayout, TextField); if (field && field !== "") { @@ -266,7 +260,6 @@ export class CollectionFreeFormView extends CollectionViewBase { } render() { - //TODO: put KVP stuff in this function //determines whether preview text cursor should be visible (ie when user taps this collection it should) let cursor = null; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index d1706c80c..23cfa6df3 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -20,13 +20,9 @@ import { KeyValuePane } from "../nodes/KeyValuePane" import { WebBox } from "../nodes/WebBox"; import "./DocumentView.scss"; import React = require("react"); +import { CollectionViewProps } from "../collections/CollectionViewBase"; const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this? -/* - if containingcollectionview is CollectionFreeformView: - (ContainingCollectionView as CollectionFreeformView)?.addKVP -*/ - export interface DocumentViewProps { ContainingCollectionView: Opt; @@ -161,8 +157,8 @@ export class DocumentView extends React.Component { } fieldsClicked = (e: React.MouseEvent): void => { - if (this.props.ContainingCollectionView) { - (this.props.ContainingCollectionView as unknown as CollectionFreeFormView).addKVP(this.props.Document); + if (this.props.AddDocument) { + this.props.AddDocument(Documents.KVPDocument(this.props.Document)); } } fullScreenClicked = (e: React.MouseEvent): void => { @@ -190,7 +186,7 @@ export class DocumentView extends React.Component { e.preventDefault() ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked }) - ContextMenu.Instance.addItem({ description: "Fields", event: () => this.fieldsClicked }) + ContextMenu.Instance.addItem({ description: "Fields", event: this.fieldsClicked }) ContextMenu.Instance.addItem({ description: "Open Right", event: () => CollectionDockingView.Instance.AddRightSplit(this.props.Document) }) ContextMenu.Instance.addItem({ description: "Freeform", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform) }) ContextMenu.Instance.addItem({ description: "Schema", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Schema) }) @@ -209,7 +205,7 @@ export class DocumentView extends React.Component { @computed get mainContent() { return { + + @observable + private key: Opt + + constructor(props: KeyValuePairProps) { + super(props); + Server.GetField(this.props.fieldId, + action((field: Opt) => { + if (field) { + this.key = field as Key; + } + })); + + } + + + + render() { + if (!this.key) { + return error + + } + let props: FieldViewProps = { + doc: this.props.doc, + fieldKey: this.key, + isSelected: () => false, + select: () => { }, + isTopMost: false, + bindings: {}, + selectOnLoad: false, + } + return ( + {this.key.Name} + ) + } +} \ No newline at end of file diff --git a/src/client/views/nodes/KeyValuePane.tsx b/src/client/views/nodes/KeyValuePane.tsx index 26d5ed9fd..90f5b653c 100644 --- a/src/client/views/nodes/KeyValuePane.tsx +++ b/src/client/views/nodes/KeyValuePane.tsx @@ -4,121 +4,93 @@ import 'react-image-lightbox/style.css'; // This only needs to be imported once import "./KeyValuePane.scss"; import React = require("react") import { FieldViewProps, FieldView } from './FieldView'; -import { FieldWaiting } from '../../../fields/Field'; +import { FieldWaiting, Opt, Field } from '../../../fields/Field'; import { observer } from "mobx-react" -import { observable, action } from 'mobx'; +import { observable, action, IReactionDisposer, reaction, ObservableMap } from 'mobx'; import { KeyStore } from '../../../fields/KeyStore'; +import { RichTextField } from "../../../fields/RichTextField"; import { element } from 'prop-types'; import { props } from 'bluebird'; +import { EditorView } from 'prosemirror-view'; +import { Transaction, EditorState } from 'prosemirror-state'; +import { schema } from 'prosemirror-schema-basic'; +import { keymap } from 'prosemirror-keymap'; +import { undo, redo } from 'prosemirror-history'; +import { baseKeymap } from 'prosemirror-commands'; +import { KVPField } from '../../../fields/KVPField'; +import { Document } from '../../../fields/Document'; +import { Key } from '../../../fields/Key'; +import { JSXElement } from 'babel-types'; +import { KeyValuePair } from "./KeyValuePair" @observer -export class KeyValuePane extends React.Component/**/ { +export class KeyValuePane extends React.Component { - public static LayoutString() { return FieldView.LayoutString(KeyValuePane) } - //private _ref: React.RefObject; - // private _downX: number = 0; - // private _downY: number = 0; - // private _lastTap: number = 0; - // @observable private _photoIndex: number = 0; - // @observable private _isOpen: boolean = false; + public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(KeyValuePane, fieldStr) } + private _ref: React.RefObject; + private _editorView: Opt; + private _reactionDisposer: Opt; - constructor() { + + constructor(props: FieldViewProps) { super(props); + + this._ref = React.createRef(); + } + + + + shouldComponentUpdate() { + return false; + } + + + onPointerDown = (e: React.PointerEvent): void => { + if (e.buttons === 1 && this.props.isSelected()) { + e.stopPropagation(); + } + } + onPointerWheel = (e: React.WheelEvent): void => { + e.stopPropagation(); + } + + createTable = () => { + let table: Array = [] + let ret = "waiting" + let doc = this.props.doc.GetT(KeyStore.Data, Document); + if (!doc || doc == "") { + return Loading... + } + let realDoc = doc; + + let ids: { [key: string]: string } = {}; + let protos = doc.GetAllPrototypes(); + for (const proto of protos) { + proto._proxies.forEach((val, key) => { + if (!(key in ids)) { + ids[key] = key; + } + }) + } + + let rows: JSX.Element[] = []; + for (let key in ids) { + rows.push() + } + return rows; } - // constructor(props: FieldViewProps) { - // super(props); - - // // this._ref = React.createRef(); - // // this._imgRef = React.createRef(); - // // this.state = { - // // photoIndex: 0, - // // isOpen: false, - // // }; - // } - - // @action - // onLoad = (target: any) => { - // var h = this._imgRef.current!.naturalHeight; - // var w = this._imgRef.current!.naturalWidth; - // this.props.doc.SetNumber(KeyStore.NativeHeight, this.props.doc.GetNumber(KeyStore.NativeWidth, 0) * h / w) - // } - - // componentDidMount() { - // } - - // componentWillUnmount() { - // } - - // onPointerDown = (e: React.PointerEvent): void => { - // if (Date.now() - this._lastTap < 300) { - // if (e.buttons === 1 && this.props.isSelected()) { - // e.stopPropagation(); - // this._downX = e.clientX; - // this._downY = e.clientY; - // document.removeEventListener("pointerup", this.onPointerUp); - // document.addEventListener("pointerup", this.onPointerUp); - // } - // } else { - // this._lastTap = Date.now(); - // } - // } - // @action - // onPointerUp = (e: PointerEvent): void => { - // document.removeEventListener("pointerup", this.onPointerUp); - // if (Math.abs(e.clientX - this._downX) < 2 && Math.abs(e.clientY - this._downY) < 2) { - // this._isOpen = true; - // } - // e.stopPropagation(); - // } - - // lightbox = (path: string) => { - // const images = [path, "http://www.cs.brown.edu/~bcz/face.gif"]; - // if (this._isOpen && this.props.isSelected()) { - // return ( - // this._isOpen = false - // )} - // onMovePrevRequest={action(() => - // this._photoIndex = (this._photoIndex + images.length - 1) % images.length - // )} - // onMoveNextRequest={action(() => - // this._photoIndex = (this._photoIndex + 1) % images.length - // )} - // />) - // } - // } + render() { - // let field = this.props.doc.Get(this.props.fieldKey); - // let path = field == FieldWaiting ? "https://image.flaticon.com/icons/svg/66/66163.svg" : - // field instanceof ImageField ? field.Data.href : "http://www.cs.brown.edu/~bcz/face.gif"; - // let nativeWidth = this.props.doc.GetNumber(KeyStore.NativeWidth, 1); - // return ( - //
- // Image not found - // {this.lightbox(path)} - //
) - console.log("bleh"); + return ( - - - - - - - - - - - - - - - - + + + + + + {this.createTable()} +
KeyFields
JillSmith
EveJackson
JohnDoe
KeyFields
) } } \ No newline at end of file diff --git a/src/fields/KVPField b/src/fields/KVPField new file mode 100644 index 000000000..e69de29bb diff --git a/src/fields/KVPField.ts b/src/fields/KVPField.ts new file mode 100644 index 000000000..a7ecc0768 --- /dev/null +++ b/src/fields/KVPField.ts @@ -0,0 +1,30 @@ +import { BasicField } from "./BasicField" +import { FieldId } from "./Field"; +import { Types } from "../server/Message"; +import { Document } from "./Document" + +export class KVPField extends BasicField { + constructor(data: Document | undefined = undefined, id?: FieldId, save: boolean = true) { + super(data == undefined ? new Document() : data, save, id); + } + + toString(): string { + return this.Data.Title; + } + + ToScriptString(): string { + return `new KVPField("${this.Data}")`; + } + + Copy() { + return new KVPField(this.Data); + } + + ToJson(): { type: Types, data: Document, _id: string } { + return { + type: Types.Text, + data: this.Data, + _id: this.Id + } + } +} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 4a42946b5c8ec86e66a89fec2e66971a242e3dbb Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 28 Feb 2019 09:19:53 -0500 Subject: added css --- .vscode/launch.json | 4 - src/client/documents/Documents.ts | 4 +- .../views/collections/CollectionFreeFormView.tsx | 5 +- src/client/views/nodes/DocumentView.tsx | 4 +- src/client/views/nodes/FieldView.tsx | 2 - src/client/views/nodes/KeyValueBox.scss | 24 ++++++ src/client/views/nodes/KeyValueBox.tsx | 89 ++++++++++++++++++++ src/client/views/nodes/KeyValuePair.tsx | 6 +- src/client/views/nodes/KeyValuePane.scss | 0 src/client/views/nodes/KeyValuePane.tsx | 96 ---------------------- tsconfig.json | 6 +- 11 files changed, 124 insertions(+), 116 deletions(-) create mode 100644 src/client/views/nodes/KeyValueBox.scss create mode 100644 src/client/views/nodes/KeyValueBox.tsx delete mode 100644 src/client/views/nodes/KeyValuePane.scss delete mode 100644 src/client/views/nodes/KeyValuePane.tsx (limited to 'src/client/documents') diff --git a/.vscode/launch.json b/.vscode/launch.json index 8aa197fa5..074f9ddf0 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -12,10 +12,6 @@ "breakOnLoad": true, "url": "http://localhost:1050", "webRoot": "${workspaceFolder}", - "skipFiles": [ - "${workspaceRoot}/node_modules/**/*.js", - "${workspaceRoot}/node_modules/**/*.ts", - ] }, { "type": "node", diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 41f1c9b3f..1d24ff7d2 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -13,7 +13,7 @@ import { CollectionView, CollectionViewType } from "../views/collections/Collect import { HtmlField } from "../../fields/HtmlField"; import { Key } from "../../fields/Key" import { Field } from "../../fields/Field"; -import { KeyValuePane } from "../views/nodes/KeyValuePane" +import { KeyValueBox } from "../views/nodes/KeyValueBox" import { KVPField } from "../../fields/KVPField"; export interface DocumentOptions { @@ -105,7 +105,7 @@ export namespace Documents { function GetKVPPrototype(): Document { return kvpProto ? kvpProto : - kvpProto = setupPrototypeOptions(kvpProtoId, "KVP_PROTO", KeyValuePane.LayoutString(), + kvpProto = setupPrototypeOptions(kvpProtoId, "KVP_PROTO", KeyValueBox.LayoutString(), { x: 0, y: 0, width: 300, height: 150, layoutKeys: [KeyStore.Data] }) } diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx index 137bcf706..96b6d1477 100644 --- a/src/client/views/collections/CollectionFreeFormView.tsx +++ b/src/client/views/collections/CollectionFreeFormView.tsx @@ -16,6 +16,7 @@ import { DocumentView } from "../nodes/DocumentView"; import { FormattedTextBox } from "../nodes/FormattedTextBox"; import { ImageBox } from "../nodes/ImageBox"; import { WebBox } from "../nodes/WebBox"; +import { KeyValueBox } from "../nodes/KeyValueBox" import "./CollectionFreeFormView.scss"; import { COLLECTION_BORDER_WIDTH } from "./CollectionView"; import { CollectionViewBase } from "./CollectionViewBase"; @@ -230,7 +231,7 @@ export class CollectionFreeFormView extends CollectionViewBase { get backgroundView() { return !this.backgroundLayout ? (null) : ( { @computed get mainContent() { return { + + public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(KeyValueBox, fieldStr) } + private _ref: React.RefObject; + private _editorView: Opt; + private _reactionDisposer: Opt; + + + constructor(props: FieldViewProps) { + super(props); + + this._ref = React.createRef(); + } + + + + shouldComponentUpdate() { + return false; + } + + + onPointerDown = (e: React.PointerEvent): void => { + if (e.buttons === 1 && this.props.isSelected()) { + e.stopPropagation(); + } + } + onPointerWheel = (e: React.WheelEvent): void => { + e.stopPropagation(); + } + + createTable = () => { + let table: Array = [] + let ret = "waiting" + let doc = this.props.doc.GetT(KeyStore.Data, Document); + if (!doc || doc == "") { + return Loading... + } + let realDoc = doc; + + let ids: { [key: string]: string } = {}; + let protos = doc.GetAllPrototypes(); + for (const proto of protos) { + proto._proxies.forEach((val, key) => { + if (!(key in ids)) { + ids[key] = key; + } + }) + } + + let rows: JSX.Element[] = []; + let i = 0; + for (let key in ids) { + if (i++ % 2 == 0) + rows.push() + else rows.push() + } + return rows; + } + + + render() { + + return (
+ + + + + + + {this.createTable()} + +
KeyFields
+
) + } +} \ No newline at end of file diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index b8a0cca48..ecdd47a1e 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -1,5 +1,5 @@ import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app -import "./KeyValuePane.scss"; +import "./KeyValueBox.scss"; import React = require("react") import { FieldViewProps, FieldView } from './FieldView'; import { Opt, Field } from '../../../fields/Field'; @@ -12,6 +12,7 @@ import { Server } from "../../Server" // Represents one row in a key value plane export interface KeyValuePairProps { + rowStyle: string; fieldId: string; doc: Document; } @@ -33,7 +34,6 @@ export class KeyValuePair extends React.Component { } - render() { if (!this.key) { return error @@ -49,7 +49,7 @@ export class KeyValuePair extends React.Component { selectOnLoad: false, } return ( - {this.key.Name} + {this.key.Name} ) } } \ No newline at end of file diff --git a/src/client/views/nodes/KeyValuePane.scss b/src/client/views/nodes/KeyValuePane.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/client/views/nodes/KeyValuePane.tsx b/src/client/views/nodes/KeyValuePane.tsx deleted file mode 100644 index 90f5b653c..000000000 --- a/src/client/views/nodes/KeyValuePane.tsx +++ /dev/null @@ -1,96 +0,0 @@ - -import Lightbox from 'react-image-lightbox'; -import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app -import "./KeyValuePane.scss"; -import React = require("react") -import { FieldViewProps, FieldView } from './FieldView'; -import { FieldWaiting, Opt, Field } from '../../../fields/Field'; -import { observer } from "mobx-react" -import { observable, action, IReactionDisposer, reaction, ObservableMap } from 'mobx'; -import { KeyStore } from '../../../fields/KeyStore'; -import { RichTextField } from "../../../fields/RichTextField"; -import { element } from 'prop-types'; -import { props } from 'bluebird'; -import { EditorView } from 'prosemirror-view'; -import { Transaction, EditorState } from 'prosemirror-state'; -import { schema } from 'prosemirror-schema-basic'; -import { keymap } from 'prosemirror-keymap'; -import { undo, redo } from 'prosemirror-history'; -import { baseKeymap } from 'prosemirror-commands'; -import { KVPField } from '../../../fields/KVPField'; -import { Document } from '../../../fields/Document'; -import { Key } from '../../../fields/Key'; -import { JSXElement } from 'babel-types'; -import { KeyValuePair } from "./KeyValuePair" - -@observer -export class KeyValuePane extends React.Component { - - public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(KeyValuePane, fieldStr) } - private _ref: React.RefObject; - private _editorView: Opt; - private _reactionDisposer: Opt; - - - constructor(props: FieldViewProps) { - super(props); - - this._ref = React.createRef(); - } - - - - shouldComponentUpdate() { - return false; - } - - - onPointerDown = (e: React.PointerEvent): void => { - if (e.buttons === 1 && this.props.isSelected()) { - e.stopPropagation(); - } - } - onPointerWheel = (e: React.WheelEvent): void => { - e.stopPropagation(); - } - - createTable = () => { - let table: Array = [] - let ret = "waiting" - let doc = this.props.doc.GetT(KeyStore.Data, Document); - if (!doc || doc == "") { - return Loading... - } - let realDoc = doc; - - let ids: { [key: string]: string } = {}; - let protos = doc.GetAllPrototypes(); - for (const proto of protos) { - proto._proxies.forEach((val, key) => { - if (!(key in ids)) { - ids[key] = key; - } - }) - } - - let rows: JSX.Element[] = []; - for (let key in ids) { - rows.push() - } - return rows; - } - - - render() { - - return ( - - - - - - {this.createTable()} - -
KeyFields
) - } -} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 823fc2732..e2538bc39 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,9 +11,5 @@ "dom", "es2015" ] - }, - "exclude": [ - "node_modules", - "static" - ] + } } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 7c6de7a2875fb8967231d1f6857a1f1e4b49d412 Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 6 Mar 2019 12:30:28 -0500 Subject: fixed to work analogous to images --- src/client/documents/Documents.ts | 12 ++-- src/client/views/Main.tsx | 4 +- .../views/collections/CollectionFreeFormView.tsx | 5 +- src/client/views/nodes/ImageBox.tsx | 14 ++-- src/client/views/nodes/PDFNode.tsx | 79 ++++++++++++---------- 5 files changed, 65 insertions(+), 49 deletions(-) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 94e1cb8dd..d2183c90f 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -40,8 +40,9 @@ export namespace Documents { let webProto: Document; let collProto: Document; let kvpProto: Document; + let pdfProto: Document; const textProtoId = "textProto"; - const pdfProtoId = "textProto"; + const pdfProtoId = "pdfProto"; const imageProtoId = "imageProto"; const webProtoId = "webProto"; const collProtoId = "collectionProto"; @@ -96,9 +97,12 @@ export namespace Documents { { x: 0, y: 0, width: 300, height: 150, layoutKeys: [KeyStore.Data] }); } function GetPdfPrototype(): Document { - return textProto ? textProto : - textProto = setupPrototypeOptions(pdfProtoId, "PDF_PROTO", PDFNode.LayoutString(), - { x: 0, y: 0, width: 300, height: 150, layoutKeys: [KeyStore.Data] }); + if (!pdfProto) { + pdfProto = setupPrototypeOptions(pdfProtoId, "PDF_PROTO", CollectionView.LayoutString("AnnotationsKey"), + { x: 0, y: 0, nativeWidth: 300, nativeHeight: 300, width: 300, layoutKeys: [KeyStore.Data, KeyStore.Annotations] }); + pdfProto.SetText(KeyStore.BackgroundLayout, PDFNode.LayoutString()); + } + return pdfProto; } function GetWebPrototype(): Document { return webProto ? webProto : diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index bbf315052..abacb258e 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -51,7 +51,7 @@ Documents.initProtos(mainDocId, (res?: Document) => { } let imgurl = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg"; - let pdfurl = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg" + let pdfurl = "http://www.adobe.com/support/products/enterprise/knowledgecenter/media/c4611_sample_explain.pdf" let weburl = "https://cs.brown.edu/courses/cs166/"; let clearDatabase = action(() => Utils.Emit(Server.Socket, MessageStore.DeleteAll, {})) let addTextNode = action(() => Documents.TextDocument({ width: 200, height: 200, title: "a text note" })) @@ -66,7 +66,7 @@ Documents.initProtos(mainDocId, (res?: Document) => { ); let imgRef = React.createRef(); - let pdfRef = React.createRef(); + let pdfRef = React.createRef(); let webRef = React.createRef(); let textRef = React.createRef(); let schemaRef = React.createRef(); diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx index 1a7349201..285d515cd 100644 --- a/src/client/views/collections/CollectionFreeFormView.tsx +++ b/src/client/views/collections/CollectionFreeFormView.tsx @@ -15,6 +15,7 @@ import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocum import { DocumentView } from "../nodes/DocumentView"; import { FormattedTextBox } from "../nodes/FormattedTextBox"; import { ImageBox } from "../nodes/ImageBox"; +import { PDFNode } from "../nodes/PDFNode"; import { WebBox } from "../nodes/WebBox"; import { KeyValueBox } from "../nodes/KeyValueBox" import "./CollectionFreeFormView.scss"; @@ -246,7 +247,7 @@ export class CollectionFreeFormView extends CollectionViewBase { get backgroundView() { return !this.backgroundLayout ? (null) : ( { diff --git a/src/client/views/nodes/PDFNode.tsx b/src/client/views/nodes/PDFNode.tsx index 8f29e8b4d..4749ed101 100644 --- a/src/client/views/nodes/PDFNode.tsx +++ b/src/client/views/nodes/PDFNode.tsx @@ -1,17 +1,17 @@ +import { action, observable } from 'mobx'; +import { observer } from "mobx-react"; +import Measure from "react-measure"; import 'react-image-lightbox/style.css'; -import "./ImageBox.scss"; -import React = require("react") -import { observer } from "mobx-react" -import { observable, action } from 'mobx'; -import 'react-pdf/dist/Page/AnnotationLayer.css' //@ts-ignore -import { Document, Page, PDFPageProxy, PageAnnotation } from "react-pdf"; +import { Document, Page } from "react-pdf"; +import 'react-pdf/dist/Page/AnnotationLayer.css'; import { Utils } from '../../../Utils'; -import { Sticky } from './Sticky'; //you should look at sticky and annotation, because they are used here import { Annotation } from './Annotation'; -import { ObjectPositionProperty } from 'csstype'; -import { keydownHandler } from 'prosemirror-keymap'; -import { FieldViewProps, FieldView } from './FieldView'; +import { FieldView, FieldViewProps } from './FieldView'; +import "./ImageBox.scss"; +import { Sticky } from './Sticky'; //you should look at sticky and annotation, because they are used here +import React = require("react") +import { KeyStore } from '../../../fields/KeyStore'; /** ALSO LOOK AT: Annotation.tsx, Sticky.tsx * This method renders PDF and puts all kinds of functionalities such as annotation, highlighting, @@ -390,6 +390,11 @@ export class PDFNode extends React.Component { } + @action + setScaling = (r: any) => { + this.props.doc.SetNumber(KeyStore.NativeWidth, r.entry.width); + this.props.doc.SetNumber(KeyStore.NativeHeight, r.entry.height); + } render() { return (
{ - { - if (this._mainDiv.current) { - this._mainDiv.current.childNodes.forEach((element) => { - if (element.nodeName == "DIV") { - element.childNodes[0].childNodes.forEach((e) => { - - if (e instanceof HTMLCanvasElement) { - this._pdfCanvas = e; - this._pdfContext = e.getContext("2d") - - } - - }) + + {({ measureRef }) => +
+ { + if (this._mainDiv.current) { + this._mainDiv.current.childNodes.forEach((element) => { + if (element.nodeName == "DIV") { + element.childNodes[0].childNodes.forEach((e) => { + + if (e instanceof HTMLCanvasElement) { + this._pdfCanvas = e; + this._pdfContext = e.getContext("2d") + + } + + }) + } + }) + } + this.numPage = page.transport.numPages + if (this.perPage.length == 0) { //Makes sure it only runs once + this.perPage = [...Array(this.numPage)] + } } - }) - } - this.numPage = page.transport.numPages - if (this.perPage.length == 0) { //Makes sure it only runs once - this.perPage = [...Array(this.numPage)] - } - } + } + /> +
} - /> +
); -- cgit v1.2.3-70-g09d2 From f2d02089b6b749929b7fc3d522ac176b7f6027fd Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 6 Mar 2019 17:59:15 -0500 Subject: fixed render size of pdfs & changed note backrounds contextually. --- src/client/documents/Documents.ts | 2 +- .../views/collections/CollectionFreeFormView.scss | 28 +++++- .../views/collections/CollectionFreeFormView.tsx | 6 +- src/client/views/collections/CollectionView.tsx | 2 +- src/client/views/nodes/FormattedTextBox.scss | 8 +- src/client/views/nodes/PDFNode.scss | 9 ++ src/client/views/nodes/PDFNode.tsx | 109 ++++++++++++--------- 7 files changed, 111 insertions(+), 53 deletions(-) create mode 100644 src/client/views/nodes/PDFNode.scss (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index d2183c90f..47b8ea844 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -99,7 +99,7 @@ export namespace Documents { function GetPdfPrototype(): Document { if (!pdfProto) { pdfProto = setupPrototypeOptions(pdfProtoId, "PDF_PROTO", CollectionView.LayoutString("AnnotationsKey"), - { x: 0, y: 0, nativeWidth: 300, nativeHeight: 300, width: 300, layoutKeys: [KeyStore.Data, KeyStore.Annotations] }); + { x: 0, y: 0, nativeWidth: 600, width: 300, layoutKeys: [KeyStore.Data, KeyStore.Annotations] }); pdfProto.SetText(KeyStore.BackgroundLayout, PDFNode.LayoutString()); } return pdfProto; diff --git a/src/client/views/collections/CollectionFreeFormView.scss b/src/client/views/collections/CollectionFreeFormView.scss index f432e8cc3..fb9394d59 100644 --- a/src/client/views/collections/CollectionFreeFormView.scss +++ b/src/client/views/collections/CollectionFreeFormView.scss @@ -1,9 +1,35 @@ .collectionfreeformview-container { + .collectionfreeformview > .jsx-parser{ + position:absolute; + height: 100%; + } + + border-style: solid; + box-sizing: border-box; + position: relative; + top: 0; + left: 0; + width: 100%; + height: 100%; + overflow: hidden; + .collectionfreeformview { + position: absolute; + top: 0; + left: 0; + width:100%; + height: 100%; + } +} +.collectionfreeformview-overlay { + .collectionfreeformview > .jsx-parser{ position:absolute; height: 100%; } + .formattedTextBox-cont { + background:yellow; + } border-style: solid; box-sizing: border-box; @@ -18,7 +44,7 @@ top: 0; left: 0; width:100%; - height: 100% + height: 100%; } } diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx index 285d515cd..be5784b32 100644 --- a/src/client/views/collections/CollectionFreeFormView.tsx +++ b/src/client/views/collections/CollectionFreeFormView.tsx @@ -67,8 +67,8 @@ export class CollectionFreeFormView extends CollectionViewBase { @action onPointerDown = (e: React.PointerEvent): void => { - if ((e.button === 2 && this.props.active()) || - !e.defaultPrevented) { + if (((e.button === 2 && this.props.active()) || + !e.defaultPrevented) && (!this.isAnnotationOverlay || this.zoomScaling != 1 || e.button == 0)) { document.removeEventListener("pointermove", this.onPointerMove); document.addEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); @@ -292,7 +292,7 @@ export class CollectionFreeFormView extends CollectionViewBase { const pany: number = -this.props.Document.GetNumber(KeyStore.PanY, 0); return ( -
{ subView =
break; } - return (
+ return (
{subView}
) } diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss index 21bd43b6e..3e21f34de 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -11,8 +11,12 @@ .formattedTextBox-cont { background: white; padding: 1; - border: black; - border-width: 10; + border-width: 1px; + border-radius: 2px; + border-color:black; + box-sizing: border-box; + background: white; + border-style:solid; overflow-y: scroll; overflow-x: hidden; color: initial; diff --git a/src/client/views/nodes/PDFNode.scss b/src/client/views/nodes/PDFNode.scss new file mode 100644 index 000000000..f4935cba9 --- /dev/null +++ b/src/client/views/nodes/PDFNode.scss @@ -0,0 +1,9 @@ +.react-pdf__Page { + transform-origin: left top; + //transform: scale(0.2, 0.2); + position: absolute; +} +.pdfButton-Tray { + position:absolute; + z-index: 25; +} \ No newline at end of file diff --git a/src/client/views/nodes/PDFNode.tsx b/src/client/views/nodes/PDFNode.tsx index 16afdccd8..b80283065 100644 --- a/src/client/views/nodes/PDFNode.tsx +++ b/src/client/views/nodes/PDFNode.tsx @@ -12,6 +12,9 @@ import "./ImageBox.scss"; import { Sticky } from './Sticky'; //you should look at sticky and annotation, because they are used here import React = require("react") import { KeyStore } from '../../../fields/KeyStore'; +import "./PDFNode.scss"; +import { PDFField } from '../../../fields/PDFField'; +import { FieldWaiting } from '../../../fields/Field'; /** ALSO LOOK AT: Annotation.tsx, Sticky.tsx * This method renders PDF and puts all kinds of functionalities such as annotation, highlighting, @@ -392,10 +395,21 @@ export class PDFNode extends React.Component { @action setScaling = (r: any) => { - this.props.doc.SetNumber(KeyStore.NativeWidth, r.entry.width); - this.props.doc.SetNumber(KeyStore.NativeHeight, r.entry.height); + // bcz: the nativeHeight should really be set when the document is imported. + // also, the native dimensions could be different for different pages of the PDF + // so this design is flawed. + var nativeWidth = this.props.doc.GetNumber(KeyStore.NativeWidth, 0); + if (!this.props.doc.GetNumber(KeyStore.NativeHeight, 0)) { + this.props.doc.SetNumber(KeyStore.NativeHeight, nativeWidth * r.entry.height / r.entry.width); + } } render() { + const renderHeight = 2400; + let xf = this.props.doc.GetNumber(KeyStore.NativeHeight, 0) / renderHeight; + var pdfUrl = this.props.doc.GetT(this.props.fieldKey, PDFField); + if (!pdfUrl || pdfUrl == FieldWaiting) { + return (null); + } return (
{ return element })} - - - - - - - - - - - - - {({ measureRef }) => -
- { - if (this._mainDiv.current) { - this._mainDiv.current.childNodes.forEach((element) => { - if (element.nodeName == "DIV") { - element.childNodes[0].childNodes.forEach((e) => { - - if (e instanceof HTMLCanvasElement) { - this._pdfCanvas = e; - this._pdfContext = e.getContext("2d") - - } - - }) - } - }) - } - this.numPage = page.transport.numPages - if (this.perPage.length == 0) { //Makes sure it only runs once - this.perPage = [...Array(this.numPage)] +
+ + + + + + + + + +
+ +
+ + + {({ measureRef }) => +
+ { + if (this._mainDiv.current) { + this._mainDiv.current.childNodes.forEach((element) => { + if (element.nodeName == "DIV") { + element.childNodes[0].childNodes.forEach((e) => { + + if (e instanceof HTMLCanvasElement) { + this._pdfCanvas = e; + this._pdfContext = e.getContext("2d") + + } + + }) + } + }) + } + this.numPage = page.transport.numPages + if (this.perPage.length == 0) { //Makes sure it only runs once + this.perPage = [...Array(this.numPage)] + } } } - } - /> -
- } -
-
-
+ /> +
+ } +
+
+
+
); } -- cgit v1.2.3-70-g09d2 From 4796d17b089824df4455788c564414526c08eaa4 Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 8 Mar 2019 09:21:18 -0500 Subject: merged with master --- src/client/documents/Documents.ts | 5 +- src/client/util/DragManager.ts | 6 +- .../views/collections/CollectionFreeFormView.tsx | 16 +- src/client/views/nodes/DocumentView.tsx | 4 +- src/client/views/nodes/PDFBox.scss | 15 + src/client/views/nodes/PDFBox.tsx | 515 +++++++++++++++++++++ src/client/views/nodes/PDFNode.scss | 15 - src/client/views/nodes/PDFNode.tsx | 515 --------------------- 8 files changed, 544 insertions(+), 547 deletions(-) create mode 100644 src/client/views/nodes/PDFBox.scss create mode 100644 src/client/views/nodes/PDFBox.tsx delete mode 100644 src/client/views/nodes/PDFNode.scss delete mode 100644 src/client/views/nodes/PDFNode.tsx (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 47b8ea844..f73823603 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -14,9 +14,8 @@ import { HtmlField } from "../../fields/HtmlField"; import { Key } from "../../fields/Key" import { Field } from "../../fields/Field"; import { KeyValueBox } from "../views/nodes/KeyValueBox" -import { KVPField } from "../../fields/KVPField"; import { PDFField } from "../../fields/PDFField"; -import { PDFNode } from "../views/nodes/PDFNode"; +import { PDFBox } from "../views/nodes/PDFBox"; export interface DocumentOptions { x?: number; @@ -100,7 +99,7 @@ export namespace Documents { if (!pdfProto) { pdfProto = setupPrototypeOptions(pdfProtoId, "PDF_PROTO", CollectionView.LayoutString("AnnotationsKey"), { x: 0, y: 0, nativeWidth: 600, width: 300, layoutKeys: [KeyStore.Data, KeyStore.Annotations] }); - pdfProto.SetText(KeyStore.BackgroundLayout, PDFNode.LayoutString()); + pdfProto.SetText(KeyStore.BackgroundLayout, PDFBox.LayoutString()); } return pdfProto; } diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index a7af399e2..513a6ac9e 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -124,15 +124,15 @@ export namespace DragManager { // So we replace the pdf's canvas with the image thumbnail const docView: DocumentView = dragData["documentView"]; const doc: Document = docView ? docView.props.Document : dragData["document"]; - var pdfNode = dragElement.getElementsByClassName("pdfNode-cont")[0] as HTMLElement; + var pdfBox = dragElement.getElementsByClassName("pdfBox-cont")[0] as HTMLElement; let thumbnail = doc.GetT(KeyStore.Thumbnail, ImageField); - if (pdfNode && pdfNode.childElementCount && thumbnail) { + if (pdfBox && pdfBox.childElementCount && thumbnail) { let img = new Image(); img!.src = thumbnail.toString(); img!.style.position = "absolute"; img!.style.width = `${rect.width / scaleX}px`; img!.style.height = `${rect.height / scaleY}px`; - pdfNode.replaceChild(img!, pdfNode.children[0]) + pdfBox.replaceChild(img!, pdfBox.children[0]) } dragDiv.appendChild(dragElement); diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx index 86d9a10e3..74e70ef33 100644 --- a/src/client/views/collections/CollectionFreeFormView.tsx +++ b/src/client/views/collections/CollectionFreeFormView.tsx @@ -1,30 +1,28 @@ -import { observable, action, computed } from "mobx"; +import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; import { Document } from "../../../fields/Document"; import { FieldWaiting } from "../../../fields/Field"; import { KeyStore } from "../../../fields/KeyStore"; import { ListField } from "../../../fields/ListField"; import { TextField } from "../../../fields/TextField"; +import { Documents } from "../../documents/Documents"; import { DragManager } from "../../util/DragManager"; import { Transform } from "../../util/Transform"; import { undoBatch } from "../../util/UndoManager"; import { CollectionDockingView } from "../collections/CollectionDockingView"; import { CollectionSchemaView } from "../collections/CollectionSchemaView"; import { CollectionView } from "../collections/CollectionView"; +import { InkingCanvas } from "../InkingCanvas"; import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView"; import { DocumentView } from "../nodes/DocumentView"; import { FormattedTextBox } from "../nodes/FormattedTextBox"; import { ImageBox } from "../nodes/ImageBox"; -import { PDFNode } from "../nodes/PDFNode"; +import { KeyValueBox } from "../nodes/KeyValueBox"; +import { PDFBox } from "../nodes/PDFBox"; import { WebBox } from "../nodes/WebBox"; -import { KeyValueBox } from "../nodes/KeyValueBox" import "./CollectionFreeFormView.scss"; import { COLLECTION_BORDER_WIDTH } from "./CollectionView"; import { CollectionViewBase } from "./CollectionViewBase"; -import { Documents } from "../../documents/Documents"; -import { InkingCanvas } from "../InkingCanvas"; -import { InkingControl } from "../InkingControl"; -import { InkTool } from "../../../fields/InkField"; import React = require("react"); const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this? @@ -250,7 +248,7 @@ export class CollectionFreeFormView extends CollectionViewBase { get backgroundView() { return !this.backgroundLayout ? (null) : ( { } @computed get mainContent() { return { + public static LayoutString() { return FieldView.LayoutString(PDFBox); } + + private _mainDiv = React.createRef() + private _pdf = React.createRef(); + + //very useful for keeping track of X and y position throughout the PDF Canvas + private initX: number = 0; + private initY: number = 0; + + //checks if tool is on + private _toolOn: boolean = false; //checks if tool is on + private _pdfContext: any = null; //gets pdf context + private bool: Boolean = false; //general boolean debounce + private currSpan: any;//keeps track of current span (for highlighting) + + private _currTool: any; //keeps track of current tool button reference + private _drawToolOn: boolean = false; //boolean that keeps track of the drawing tool + private _drawTool = React.createRef()//drawing tool button reference + + private _colorTool = React.createRef(); //color button reference + private _currColor: string = "black"; //current color that user selected (for ink/pen) + + private _highlightTool = React.createRef(); //highlighter button reference + private _highlightToolOn: boolean = false; + private _pdfCanvas: any; + + @observable private _perPageInfo: Object[] = []; //stores pageInfo + @observable private _pageInfo: any = { area: [], divs: [], anno: [] }; //divs is array of objects linked to anno + + @observable private _currAnno: any = [] + @observable private _page: number = 1; //default is the first page. + @observable private _numPages: number = 1; //default number of pages + @observable private _interactive: boolean = false; + @observable private _loaded: boolean = false; + + /** + * for pagination backwards + */ + @action + onPageBack = () => { + if (this._page > 1) { + this._page -= 1; + this._currAnno = []; + this._perPageInfo[this._page] = this._pageInfo + this._pageInfo = { area: [], divs: [], anno: [] }; //resets the object to default + if (this._perPageInfo[this._page - 1]) { + this._pageInfo = this._perPageInfo[this._page - 1]; + } + this.saveThumbnail(); + } + } + + /** + * for pagination forwards + */ + @action + onPageForward = () => { + if (this._page < this._numPages) { + this._page += 1; + this._currAnno = []; + this._perPageInfo[this._page - 2] = this._pageInfo; + this._pageInfo = { area: [], divs: [], anno: [] }; //resets the object to default + if (this._perPageInfo[this._page - 1]) { + this._pageInfo = this._perPageInfo[this._page - 1]; + } + this.saveThumbnail(); + } + } + + /** + * selection tool used for area highlighting (stickies). Kinda temporary + */ + selectionTool = () => { + this._toolOn = true; + } + /** + * when user draws on the canvas. When mouse pointer is down + */ + drawDown = (e: PointerEvent) => { + this.initX = e.offsetX; + this.initY = e.offsetY; + this._pdfContext.beginPath(); + this._pdfContext.lineTo(this.initX, this.initY); + this._pdfContext.strokeStyle = this._currColor; + this._pdfCanvas.addEventListener("pointermove", this.drawMove); + this._pdfCanvas.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._pdfContext.lineTo(x, y); + this._pdfContext.stroke(); + } + + drawUp = (e: PointerEvent) => { + this._pdfContext.closePath(); + this._pdfCanvas.removeEventListener("pointermove", this.drawMove); + this._pdfCanvas.removeEventListener("pointerdown", this.drawDown); + this._pdfCanvas.addEventListener("pointerdown", this.drawDown); + } + + + /** + * highlighting helper function + */ + makeEditableAndHighlight = (colour: string) => { + var range, sel = window.getSelection(); + if (sel.rangeCount && sel.getRangeAt) { + range = sel.getRangeAt(0); + } + document.designMode = "on"; + if (!document.execCommand("HiliteColor", false, colour)) { + document.execCommand("HiliteColor", false, colour); + } + + if (range) { + sel.removeAllRanges(); + sel.addRange(range); + + let obj: Object = { parentDivs: [], spans: [] }; + //@ts-ignore + if (range.commonAncestorContainer.className == 'react-pdf__Page__textContent') { //multiline highlighting case + obj = this.highlightNodes(range.commonAncestorContainer.childNodes) + } else { //single line highlighting case + let parentDiv = range.commonAncestorContainer.parentElement + if (parentDiv) { + if (parentDiv.className == 'react-pdf__Page__textContent') { //when highlight is overwritten + obj = this.highlightNodes(parentDiv.childNodes) + } else { + parentDiv.childNodes.forEach((child) => { + if (child.nodeName == 'SPAN') { + //@ts-ignore + obj.parentDivs.push(parentDiv) + //@ts-ignore + child.id = "highlighted" + //@ts-ignore + obj.spans.push(child) + child.addEventListener("mouseover", this.onEnter); //adds mouseover annotation handler + } + }) + } + } + } + this._pageInfo.divs.push(obj); + + } + document.designMode = "off"; + } + + highlightNodes = (nodes: NodeListOf) => { + let temp = { parentDivs: [], spans: [] } + nodes.forEach((div) => { + div.childNodes.forEach((child) => { + if (child.nodeName == 'SPAN') { + //@ts-ignore + temp.parentDivs.push(div) + //@ts-ignore + child.id = "highlighted" + //@ts-ignore + temp.spans.push(child) + child.addEventListener("mouseover", this.onEnter); //adds mouseover annotation handler + } + }) + + }) + return temp; + } + + /** + * when the cursor enters the highlight, it pops out annotation. ONLY WORKS FOR SINGLE DIV LINES + */ + @action + onEnter = (e: any) => { + let span: HTMLSpanElement = e.toElement; + let index: any; + this._pageInfo.divs.forEach((obj: any) => { + obj.spans.forEach((element: any) => { + if (element == span) { + if (!index) { + index = this._pageInfo.divs.indexOf(obj); + } + } + }) + }) + + if (this._pageInfo.anno.length >= index + 1) { + if (this._currAnno.length == 0) { + this._currAnno.push(this._pageInfo.anno[index]); + } + } else { + if (this._currAnno.length == 0) { //if there are no current annotation + let div = span.offsetParent; + //@ts-ignore + let divX = div.style.left + //@ts-ignore + let divY = div.style.top + //slicing "px" from the end + divX = divX.slice(0, divX.length - 2); //gets X of the DIV element (parent of Span) + divY = divY.slice(0, divY.length - 2); //gets Y of the DIV element (parent of Span) + let annotation = + this._pageInfo.anno.push(annotation); + this._currAnno.push(annotation); + } + } + + } + + /** + * highlight function for highlighting actual text. This works fine. + */ + highlight = (color: string) => { + if (window.getSelection()) { + try { + if (!document.execCommand("hiliteColor", false, color)) { + this.makeEditableAndHighlight(color); + } + } catch (ex) { + this.makeEditableAndHighlight(color) + } + } + } + + /** + * controls the area highlighting (stickies) Kinda temporary + */ + onPointerDown = (e: React.PointerEvent) => { + if (this._toolOn) { + let mouse = e.nativeEvent; + this.initX = mouse.offsetX; + this.initY = mouse.offsetY; + + } + } + + /** + * controls area highlighting and partially highlighting. Kinda temporary + */ + @action + onPointerUp = (e: React.PointerEvent) => { + if (this._highlightToolOn) { + this.highlight("rgba(76, 175, 80, 0.3)"); //highlights to this default color. + this._highlightToolOn = false; + } + if (this._toolOn) { + let mouse = e.nativeEvent; + let finalX = mouse.offsetX; + let finalY = mouse.offsetY; + let width = Math.abs(finalX - this.initX); //width + let height = Math.abs(finalY - this.initY); //height + + //these two if statements are bidirectional dragging. You can drag from any point to another point and generate sticky + if (finalX < this.initX) { + this.initX = finalX; + } + if (finalY < this.initY) { + this.initY = finalY; + } + + if (this._mainDiv.current) { + let sticky = + this._pageInfo.area.push(sticky); + } + this._toolOn = false; + } + this._interactive = true; + } + + /** + * starts drawing the line when user presses down. + */ + onDraw = () => { + if (this._currTool != null) { + this._currTool.style.backgroundColor = "grey"; + } + + if (this._drawTool.current) { + this._currTool = this._drawTool.current; + if (this._drawToolOn) { + this._drawToolOn = false; + this._pdfCanvas.removeEventListener("pointerdown", this.drawDown); + this._pdfCanvas.removeEventListener("pointerup", this.drawUp); + this._pdfCanvas.removeEventListener("pointermove", this.drawMove); + this._drawTool.current.style.backgroundColor = "grey"; + } else { + this._drawToolOn = true; + this._pdfCanvas.addEventListener("pointerdown", this.drawDown); + this._drawTool.current.style.backgroundColor = "cyan"; + } + } + } + + + /** + * for changing color (for ink/pen) + */ + onColorChange = (e: React.PointerEvent) => { + if (e.currentTarget.innerHTML == "Red") { + this._currColor = "red"; + } else if (e.currentTarget.innerHTML == "Blue") { + this._currColor = "blue"; + } else if (e.currentTarget.innerHTML == "Green") { + this._currColor = "green"; + } else if (e.currentTarget.innerHTML == "Black") { + this._currColor = "black"; + } + + } + + + /** + * For highlighting (text drag highlighting) + */ + onHighlight = () => { + this._drawToolOn = false; + if (this._currTool != null) { + this._currTool.style.backgroundColor = "grey"; + } + if (this._highlightTool.current) { + this._currTool = this._drawTool.current; + if (this._highlightToolOn) { + this._highlightToolOn = false; + this._highlightTool.current.style.backgroundColor = "grey"; + } else { + this._highlightToolOn = true; + this._highlightTool.current.style.backgroundColor = "orange"; + } + } + } + + + + + @action + saveThumbnail = () => { + setTimeout(() => { + var me = this; + htmlToImage.toPng(this._mainDiv.current!, + { width: me.props.doc.GetNumber(KeyStore.NativeWidth, 0), height: me.props.doc.GetNumber(KeyStore.NativeHeight, 0), quality: 0.5 }) + .then(function (dataUrl: string) { + me.props.doc.SetData(KeyStore.Thumbnail, new URL(dataUrl), ImageField); + }) + .catch(function (error: any) { + console.error('oops, something went wrong!', error); + }); + }, 1000); + } + + @action + onLoaded = (page: any) => { + if (this._mainDiv.current) { + this._mainDiv.current.childNodes.forEach((element) => { + if (element.nodeName == "DIV") { + element.childNodes[0].childNodes.forEach((e) => { + + if (e instanceof HTMLCanvasElement) { + this._pdfCanvas = e; + this._pdfContext = e.getContext("2d") + + } + + }) + } + }) + } + this._numPages = page._transport.numPages; + if (this._perPageInfo.length == 0) { //Makes sure it only runs once + this._perPageInfo = [...Array(this._numPages)] + } + this._loaded = true; + } + + @action + setScaling = (r: any) => { + // bcz: the nativeHeight should really be set when the document is imported. + // also, the native dimensions could be different for different pages of the PDF + // so this design is flawed. + var nativeWidth = this.props.doc.GetNumber(KeyStore.NativeWidth, 0); + if (!this.props.doc.GetNumber(KeyStore.NativeHeight, 0)) { + this.props.doc.SetNumber(KeyStore.NativeHeight, nativeWidth * r.entry.height / r.entry.width); + } + if (!this.props.doc.GetT(KeyStore.Thumbnail, ImageField)) { + this.saveThumbnail(); + } + } + + @computed + get uIButtons() { + return ( +
+ + + + + + + + + +
); + } + + @computed + get pdfContent() { + const renderHeight = 2400; + let pdfUrl = this.props.doc.GetT(this.props.fieldKey, PDFField); + let xf = this.props.doc.GetNumber(KeyStore.NativeHeight, 0) / renderHeight; + return
+ + + {({ measureRef }) => +
+ +
+ } +
+
+
; + } + + @computed + get pdfRenderer() { + let proxy = this._loaded ? (null) : this.imageProxyRenderer; + let pdfUrl = this.props.doc.GetT(this.props.fieldKey, PDFField); + if ((!this._interactive && proxy) || !pdfUrl || pdfUrl == FieldWaiting) { + return proxy; + } + return [ + this._pageInfo.area.filter(() => this._pageInfo.area).map((element: any) => element), + this._currAnno.map((element: any) => element), + this.uIButtons, +
+ {this.pdfContent} + {proxy} +
+ ]; + } + + @computed + get imageProxyRenderer() { + let field = this.props.doc.Get(KeyStore.Thumbnail); + if (field) { + let path = field == FieldWaiting ? "https://image.flaticon.com/icons/svg/66/66163.svg" : + field instanceof ImageField ? field.Data.href : "http://cs.brown.edu/people/bcz/prairie.jpg"; + return ; + } + return (null); + } + + render() { + return ( +
+ {this.pdfRenderer} +
+ ); + } + +} \ No newline at end of file diff --git a/src/client/views/nodes/PDFNode.scss b/src/client/views/nodes/PDFNode.scss deleted file mode 100644 index 18ebca952..000000000 --- a/src/client/views/nodes/PDFNode.scss +++ /dev/null @@ -1,15 +0,0 @@ -.react-pdf__Page { - transform-origin: left top; - position: absolute; -} -.react-pdf__Document { - position: absolute; -} -.pdfNode-buttonTray { - position:absolute; - z-index: 25; -} -.pdfNode-contentContainer { - position: absolute; - transform-origin: "left top"; -} \ No newline at end of file diff --git a/src/client/views/nodes/PDFNode.tsx b/src/client/views/nodes/PDFNode.tsx deleted file mode 100644 index 648bd3e62..000000000 --- a/src/client/views/nodes/PDFNode.tsx +++ /dev/null @@ -1,515 +0,0 @@ -import { action, observable, _interceptReads, computed } from 'mobx'; -import { observer } from "mobx-react"; -import Measure from "react-measure"; -import 'react-image-lightbox/style.css'; -//@ts-ignore -import { Document, Page } from "react-pdf"; -import 'react-pdf/dist/Page/AnnotationLayer.css'; -import { Utils } from '../../../Utils'; -import { Annotation } from './Annotation'; -import { FieldView, FieldViewProps } from './FieldView'; -import "./ImageBox.scss"; -import { Sticky } from './Sticky'; //you should look at sticky and annotation, because they are used here -import React = require("react") -import { KeyStore } from '../../../fields/KeyStore'; -import "./PDFNode.scss"; -import { PDFField } from '../../../fields/PDFField'; -import { FieldWaiting } from '../../../fields/Field'; -import { ImageField } from '../../../fields/ImageField'; -import * as htmlToImage from "html-to-image"; -import { url } from 'inspector'; - -/** ALSO LOOK AT: Annotation.tsx, Sticky.tsx - * This method renders PDF and puts all kinds of functionalities such as annotation, highlighting, - * area selection (I call it stickies), embedded ink node for directly annotating using a pen or - * mouse, and pagination. - * - * - * HOW TO USE: - * AREA selection: - * 1) Click on Area button. - * 2) click on any part of the PDF, and drag to get desired sized area shape - * 3) You can write on the area (hence the reason why it's called sticky) - * 4) to make another area, you need to click on area button AGAIN. - * - * HIGHLIGHT: (Buggy. No multiline/multidiv text highlighting for now...) - * 1) just click and drag on a text - * 2) click highlight - * 3) for annotation, just pull your cursor over to that text - * 4) another method: click on highlight first and then drag on your desired text - * 5) To make another highlight, you need to reclick on the button - * - * Draw: - * 1) click draw and select color. then just draw like there's no tomorrow. - * 2) once you finish drawing your masterpiece, just reclick on the draw button to end your drawing session. - * - * Pagination: - * 1) click on arrows. You'll notice that stickies will stay in those page. But... highlights won't. - * 2) to test this out, make few area/stickies and then click on next page then come back. You'll see that they are all saved. - * - * - * written by: Andrew Kim - */ -@observer -export class PDFNode extends React.Component { - public static LayoutString() { return FieldView.LayoutString(PDFNode); } - - private _mainDiv = React.createRef() - private _pdf = React.createRef(); - - //very useful for keeping track of X and y position throughout the PDF Canvas - private initX: number = 0; - private initY: number = 0; - - //checks if tool is on - private _toolOn: boolean = false; //checks if tool is on - private _pdfContext: any = null; //gets pdf context - private bool: Boolean = false; //general boolean debounce - private currSpan: any;//keeps track of current span (for highlighting) - - private _currTool: any; //keeps track of current tool button reference - private _drawToolOn: boolean = false; //boolean that keeps track of the drawing tool - private _drawTool = React.createRef()//drawing tool button reference - - private _colorTool = React.createRef(); //color button reference - private _currColor: string = "black"; //current color that user selected (for ink/pen) - - private _highlightTool = React.createRef(); //highlighter button reference - private _highlightToolOn: boolean = false; - private _pdfCanvas: any; - - @observable private _perPageInfo: Object[] = []; //stores pageInfo - @observable private _pageInfo: any = { area: [], divs: [], anno: [] }; //divs is array of objects linked to anno - - @observable private _currAnno: any = [] - @observable private _page: number = 1; //default is the first page. - @observable private _numPages: number = 1; //default number of pages - @observable private _interactive: boolean = false; - @observable private _loaded: boolean = false; - - /** - * for pagination backwards - */ - @action - onPageBack = () => { - if (this._page > 1) { - this._page -= 1; - this._currAnno = []; - this._perPageInfo[this._page] = this._pageInfo - this._pageInfo = { area: [], divs: [], anno: [] }; //resets the object to default - if (this._perPageInfo[this._page - 1]) { - this._pageInfo = this._perPageInfo[this._page - 1]; - } - this.saveThumbnail(); - } - } - - /** - * for pagination forwards - */ - @action - onPageForward = () => { - if (this._page < this._numPages) { - this._page += 1; - this._currAnno = []; - this._perPageInfo[this._page - 2] = this._pageInfo; - this._pageInfo = { area: [], divs: [], anno: [] }; //resets the object to default - if (this._perPageInfo[this._page - 1]) { - this._pageInfo = this._perPageInfo[this._page - 1]; - } - this.saveThumbnail(); - } - } - - /** - * selection tool used for area highlighting (stickies). Kinda temporary - */ - selectionTool = () => { - this._toolOn = true; - } - /** - * when user draws on the canvas. When mouse pointer is down - */ - drawDown = (e: PointerEvent) => { - this.initX = e.offsetX; - this.initY = e.offsetY; - this._pdfContext.beginPath(); - this._pdfContext.lineTo(this.initX, this.initY); - this._pdfContext.strokeStyle = this._currColor; - this._pdfCanvas.addEventListener("pointermove", this.drawMove); - this._pdfCanvas.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._pdfContext.lineTo(x, y); - this._pdfContext.stroke(); - } - - drawUp = (e: PointerEvent) => { - this._pdfContext.closePath(); - this._pdfCanvas.removeEventListener("pointermove", this.drawMove); - this._pdfCanvas.removeEventListener("pointerdown", this.drawDown); - this._pdfCanvas.addEventListener("pointerdown", this.drawDown); - } - - - /** - * highlighting helper function - */ - makeEditableAndHighlight = (colour: string) => { - var range, sel = window.getSelection(); - if (sel.rangeCount && sel.getRangeAt) { - range = sel.getRangeAt(0); - } - document.designMode = "on"; - if (!document.execCommand("HiliteColor", false, colour)) { - document.execCommand("HiliteColor", false, colour); - } - - if (range) { - sel.removeAllRanges(); - sel.addRange(range); - - let obj: Object = { parentDivs: [], spans: [] }; - //@ts-ignore - if (range.commonAncestorContainer.className == 'react-pdf__Page__textContent') { //multiline highlighting case - obj = this.highlightNodes(range.commonAncestorContainer.childNodes) - } else { //single line highlighting case - let parentDiv = range.commonAncestorContainer.parentElement - if (parentDiv) { - if (parentDiv.className == 'react-pdf__Page__textContent') { //when highlight is overwritten - obj = this.highlightNodes(parentDiv.childNodes) - } else { - parentDiv.childNodes.forEach((child) => { - if (child.nodeName == 'SPAN') { - //@ts-ignore - obj.parentDivs.push(parentDiv) - //@ts-ignore - child.id = "highlighted" - //@ts-ignore - obj.spans.push(child) - child.addEventListener("mouseover", this.onEnter); //adds mouseover annotation handler - } - }) - } - } - } - this._pageInfo.divs.push(obj); - - } - document.designMode = "off"; - } - - highlightNodes = (nodes: NodeListOf) => { - let temp = { parentDivs: [], spans: [] } - nodes.forEach((div) => { - div.childNodes.forEach((child) => { - if (child.nodeName == 'SPAN') { - //@ts-ignore - temp.parentDivs.push(div) - //@ts-ignore - child.id = "highlighted" - //@ts-ignore - temp.spans.push(child) - child.addEventListener("mouseover", this.onEnter); //adds mouseover annotation handler - } - }) - - }) - return temp; - } - - /** - * when the cursor enters the highlight, it pops out annotation. ONLY WORKS FOR SINGLE DIV LINES - */ - @action - onEnter = (e: any) => { - let span: HTMLSpanElement = e.toElement; - let index: any; - this._pageInfo.divs.forEach((obj: any) => { - obj.spans.forEach((element: any) => { - if (element == span) { - if (!index) { - index = this._pageInfo.divs.indexOf(obj); - } - } - }) - }) - - if (this._pageInfo.anno.length >= index + 1) { - if (this._currAnno.length == 0) { - this._currAnno.push(this._pageInfo.anno[index]); - } - } else { - if (this._currAnno.length == 0) { //if there are no current annotation - let div = span.offsetParent; - //@ts-ignore - let divX = div.style.left - //@ts-ignore - let divY = div.style.top - //slicing "px" from the end - divX = divX.slice(0, divX.length - 2); //gets X of the DIV element (parent of Span) - divY = divY.slice(0, divY.length - 2); //gets Y of the DIV element (parent of Span) - let annotation = - this._pageInfo.anno.push(annotation); - this._currAnno.push(annotation); - } - } - - } - - /** - * highlight function for highlighting actual text. This works fine. - */ - highlight = (color: string) => { - if (window.getSelection()) { - try { - if (!document.execCommand("hiliteColor", false, color)) { - this.makeEditableAndHighlight(color); - } - } catch (ex) { - this.makeEditableAndHighlight(color) - } - } - } - - /** - * controls the area highlighting (stickies) Kinda temporary - */ - onPointerDown = (e: React.PointerEvent) => { - if (this._toolOn) { - let mouse = e.nativeEvent; - this.initX = mouse.offsetX; - this.initY = mouse.offsetY; - - } - } - - /** - * controls area highlighting and partially highlighting. Kinda temporary - */ - @action - onPointerUp = (e: React.PointerEvent) => { - if (this._highlightToolOn) { - this.highlight("rgba(76, 175, 80, 0.3)"); //highlights to this default color. - this._highlightToolOn = false; - } - if (this._toolOn) { - let mouse = e.nativeEvent; - let finalX = mouse.offsetX; - let finalY = mouse.offsetY; - let width = Math.abs(finalX - this.initX); //width - let height = Math.abs(finalY - this.initY); //height - - //these two if statements are bidirectional dragging. You can drag from any point to another point and generate sticky - if (finalX < this.initX) { - this.initX = finalX; - } - if (finalY < this.initY) { - this.initY = finalY; - } - - if (this._mainDiv.current) { - let sticky = - this._pageInfo.area.push(sticky); - } - this._toolOn = false; - } - this._interactive = true; - } - - /** - * starts drawing the line when user presses down. - */ - onDraw = () => { - if (this._currTool != null) { - this._currTool.style.backgroundColor = "grey"; - } - - if (this._drawTool.current) { - this._currTool = this._drawTool.current; - if (this._drawToolOn) { - this._drawToolOn = false; - this._pdfCanvas.removeEventListener("pointerdown", this.drawDown); - this._pdfCanvas.removeEventListener("pointerup", this.drawUp); - this._pdfCanvas.removeEventListener("pointermove", this.drawMove); - this._drawTool.current.style.backgroundColor = "grey"; - } else { - this._drawToolOn = true; - this._pdfCanvas.addEventListener("pointerdown", this.drawDown); - this._drawTool.current.style.backgroundColor = "cyan"; - } - } - } - - - /** - * for changing color (for ink/pen) - */ - onColorChange = (e: React.PointerEvent) => { - if (e.currentTarget.innerHTML == "Red") { - this._currColor = "red"; - } else if (e.currentTarget.innerHTML == "Blue") { - this._currColor = "blue"; - } else if (e.currentTarget.innerHTML == "Green") { - this._currColor = "green"; - } else if (e.currentTarget.innerHTML == "Black") { - this._currColor = "black"; - } - - } - - - /** - * For highlighting (text drag highlighting) - */ - onHighlight = () => { - this._drawToolOn = false; - if (this._currTool != null) { - this._currTool.style.backgroundColor = "grey"; - } - if (this._highlightTool.current) { - this._currTool = this._drawTool.current; - if (this._highlightToolOn) { - this._highlightToolOn = false; - this._highlightTool.current.style.backgroundColor = "grey"; - } else { - this._highlightToolOn = true; - this._highlightTool.current.style.backgroundColor = "orange"; - } - } - } - - - - - @action - saveThumbnail = () => { - setTimeout(() => { - var me = this; - htmlToImage.toPng(this._mainDiv.current!, - { width: me.props.doc.GetNumber(KeyStore.NativeWidth, 0), height: me.props.doc.GetNumber(KeyStore.NativeHeight, 0), quality: 0.5 }) - .then(function (dataUrl: string) { - me.props.doc.SetData(KeyStore.Thumbnail, new URL(dataUrl), ImageField); - }) - .catch(function (error: any) { - console.error('oops, something went wrong!', error); - }); - }, 1000); - } - - @action - onLoaded = (page: any) => { - if (this._mainDiv.current) { - this._mainDiv.current.childNodes.forEach((element) => { - if (element.nodeName == "DIV") { - element.childNodes[0].childNodes.forEach((e) => { - - if (e instanceof HTMLCanvasElement) { - this._pdfCanvas = e; - this._pdfContext = e.getContext("2d") - - } - - }) - } - }) - } - this._numPages = page.transport.numPages - if (this._perPageInfo.length == 0) { //Makes sure it only runs once - this._perPageInfo = [...Array(this._numPages)] - } - this._loaded = true; - } - - @action - setScaling = (r: any) => { - // bcz: the nativeHeight should really be set when the document is imported. - // also, the native dimensions could be different for different pages of the PDF - // so this design is flawed. - var nativeWidth = this.props.doc.GetNumber(KeyStore.NativeWidth, 0); - if (!this.props.doc.GetNumber(KeyStore.NativeHeight, 0)) { - this.props.doc.SetNumber(KeyStore.NativeHeight, nativeWidth * r.entry.height / r.entry.width); - } - if (!this.props.doc.GetT(KeyStore.Thumbnail, ImageField)) { - this.saveThumbnail(); - } - } - - @computed - get uIButtons() { - return ( -
- - - - - - - - - -
); - } - - @computed - get pdfContent() { - const renderHeight = 2400; - let pdfUrl = this.props.doc.GetT(this.props.fieldKey, PDFField); - let xf = this.props.doc.GetNumber(KeyStore.NativeHeight, 0) / renderHeight; - return
- - - {({ measureRef }) => -
- -
- } -
-
-
; - } - - @computed - get pdfRenderer() { - let proxy = this._loaded ? (null) : this.imageProxyRenderer; - let pdfUrl = this.props.doc.GetT(this.props.fieldKey, PDFField); - if ((!this._interactive && proxy) || !pdfUrl || pdfUrl == FieldWaiting) { - return proxy; - } - return [ - this._pageInfo.area.filter(() => this._pageInfo.area).map((element: any) => element), - this._currAnno.map((element: any) => element), - this.uIButtons, -
- {this.pdfContent} - {proxy} -
- ]; - } - - @computed - get imageProxyRenderer() { - let field = this.props.doc.Get(KeyStore.Thumbnail); - if (field) { - let path = field == FieldWaiting ? "https://image.flaticon.com/icons/svg/66/66163.svg" : - field instanceof ImageField ? field.Data.href : "http://cs.brown.edu/people/bcz/prairie.jpg"; - return ; - } - return (null); - } - - render() { - return ( -
- {this.pdfRenderer} -
- ); - } - -} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From c4eff83d814b1f9b94b7fc75ca06e8f0474de20d Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 8 Mar 2019 11:44:28 -0500 Subject: working version of pdfs with annotations. --- src/client/documents/Documents.ts | 4 +- src/client/views/InkingCanvas.tsx | 17 ++-- .../views/collections/CollectionFreeFormView.scss | 2 +- .../views/collections/CollectionFreeFormView.tsx | 32 +++---- src/client/views/collections/CollectionPDFView.tsx | 74 +++++++++++++++++ src/client/views/collections/CollectionView.tsx | 78 ++++++++++------- src/client/views/nodes/DocumentView.tsx | 3 +- src/client/views/nodes/PDFBox.tsx | 97 ++++++++-------------- src/fields/InkField.ts | 1 + src/fields/KeyStore.ts | 3 + 10 files changed, 193 insertions(+), 118 deletions(-) create mode 100644 src/client/views/collections/CollectionPDFView.tsx (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index f73823603..fb1c3d867 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -16,6 +16,7 @@ import { Field } from "../../fields/Field"; import { KeyValueBox } from "../views/nodes/KeyValueBox" import { PDFField } from "../../fields/PDFField"; import { PDFBox } from "../views/nodes/PDFBox"; +import { CollectionPDFView } from "../views/collections/CollectionPDFView"; export interface DocumentOptions { x?: number; @@ -97,8 +98,9 @@ export namespace Documents { } function GetPdfPrototype(): Document { if (!pdfProto) { - pdfProto = setupPrototypeOptions(pdfProtoId, "PDF_PROTO", CollectionView.LayoutString("AnnotationsKey"), + pdfProto = setupPrototypeOptions(pdfProtoId, "PDF_PROTO", CollectionPDFView.LayoutString("AnnotationsKey"), { x: 0, y: 0, nativeWidth: 600, width: 300, layoutKeys: [KeyStore.Data, KeyStore.Annotations] }); + pdfProto.SetNumber(KeyStore.Page, 1); pdfProto.SetText(KeyStore.BackgroundLayout, PDFBox.LayoutString()); } return pdfProto; diff --git a/src/client/views/InkingCanvas.tsx b/src/client/views/InkingCanvas.tsx index baf1567b7..14a779837 100644 --- a/src/client/views/InkingCanvas.tsx +++ b/src/client/views/InkingCanvas.tsx @@ -66,7 +66,8 @@ export class InkingCanvas extends React.Component { pathData: [point], color: InkingControl.Instance.selectedColor, width: InkingControl.Instance.selectedWidth, - tool: InkingControl.Instance.selectedTool + tool: InkingControl.Instance.selectedTool, + page: this.props.Document.GetNumber(KeyStore.CurPage, 0) }); this.inkData = data; this._isDrawing = true; @@ -137,15 +138,17 @@ export class InkingCanvas extends React.Component { // parse data from server let paths: Array = [] + let curPage = this.props.Document.GetNumber(KeyStore.CurPage, 0) Array.from(lines).map(item => { let id = item[0]; let strokeData = item[1]; - paths.push() + if (strokeData.page == 0 || strokeData.page == curPage) + paths.push() }) return ( diff --git a/src/client/views/collections/CollectionFreeFormView.scss b/src/client/views/collections/CollectionFreeFormView.scss index f496517f5..b059163ed 100644 --- a/src/client/views/collections/CollectionFreeFormView.scss +++ b/src/client/views/collections/CollectionFreeFormView.scss @@ -34,7 +34,7 @@ border-style: solid; box-sizing: border-box; - position: relative; + position: absolute; top: 0; left: 0; width: 100%; diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx index 74e70ef33..782313e55 100644 --- a/src/client/views/collections/CollectionFreeFormView.tsx +++ b/src/client/views/collections/CollectionFreeFormView.tsx @@ -12,6 +12,7 @@ import { undoBatch } from "../../util/UndoManager"; import { CollectionDockingView } from "../collections/CollectionDockingView"; import { CollectionSchemaView } from "../collections/CollectionSchemaView"; import { CollectionView } from "../collections/CollectionView"; +import { CollectionPDFView } from "../collections/CollectionPDFView"; import { InkingCanvas } from "../InkingCanvas"; import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView"; import { DocumentView } from "../nodes/DocumentView"; @@ -224,21 +225,24 @@ export class CollectionFreeFormView extends CollectionViewBase { @computed get views() { + var curPage = this.props.Document.GetNumber(KeyStore.CurPage, 1); const lvalue = this.props.Document.GetT>(this.props.fieldKey, ListField); if (lvalue && lvalue != FieldWaiting) { return lvalue.Data.map(doc => { - return (); + var page = doc.GetNumber(KeyStore.Page, 0); + return (page != curPage && page != 0) ? (null) : + (); }) } return null; @@ -248,7 +252,7 @@ export class CollectionFreeFormView extends CollectionViewBase { get backgroundView() { return !this.backgroundLayout ? (null) : ( { + + public static LayoutString(fieldKey: string = "DataKey") { + return `<${CollectionPDFView.name} Document={Document} + ScreenToLocalTransform={ScreenToLocalTransform} fieldKey={${fieldKey}} panelWidth={PanelWidth} panelHeight={PanelHeight} isSelected={isSelected} select={select} bindings={bindings} + isTopMost={isTopMost} SelectOnLoad={selectOnLoad} BackgroundView={BackgroundView} focus={focus}/>`; + } + + @action onPageBack = () => this.curPage > 1 ? this.props.Document.SetNumber(KeyStore.CurPage, this.curPage - 1) : 0; + @action onPageForward = () => this.curPage < this.numPages ? this.props.Document.SetNumber(KeyStore.CurPage, this.curPage + 1) : 0; + + @computed private get curPage() { return this.props.Document.GetNumber(KeyStore.CurPage, 0); } + @computed private get numPages() { return this.props.Document.GetNumber(KeyStore.NumPages, 0); } + @computed private get uIButtons() { + return ( +
+ + +
); + } + + // CollectionView API starts here... + + public active: () => boolean = () => CollectionView.Active(this); + + @action + addDocument = (doc: Document): void => { + doc.SetNumber(KeyStore.Page, this.curPage); + CollectionView.AddDocument(this.props, doc); + } + + @action removeDocument = (doc: Document): boolean => { + return CollectionView.RemoveDocument(this.props, doc); + } + + specificContextMenu = (e: React.MouseEvent): void => { + if (!e.isPropagationStopped) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 + ContextMenu.Instance.addItem({ description: "PDFOptions", event: () => { } }) + } + } + + get collectionViewType(): CollectionViewType { return CollectionViewType.Freeform; } + + + @computed + get subView(): any { return CollectionView.SubView(this); } + + render() { + return (
+ {this.subView} + {this.props.isSelected() ? this.uIButtons : (null)} +
) + } +} \ No newline at end of file diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 8d175ee35..504538e85 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -1,4 +1,4 @@ -import { action } from "mobx"; +import { action, computed } from "mobx"; import { observer } from "mobx-react"; import { Document } from "../../../fields/Document"; import { ListField } from "../../../fields/ListField"; @@ -28,32 +28,42 @@ export const COLLECTION_BORDER_WIDTH = 2; export class CollectionView extends React.Component { public static LayoutString(fieldKey: string = "DataKey") { - return ``; } - public active = () => { - var isSelected = this.props.isSelected(); - var childSelected = SelectionManager.SelectedDocuments().some(view => view.props.ContainingCollectionView == this); - var topMost = this.props.isTopMost; + + public active: () => boolean = () => CollectionView.Active(this); + + public static Active(self: CollectionView): boolean { + var isSelected = self.props.isSelected(); + var childSelected = SelectionManager.SelectedDocuments().some(view => view.props.ContainingCollectionView == self); + var topMost = self.props.isTopMost; return isSelected || childSelected || topMost; } - @action + addDocument = (doc: Document): void => { - if (this.props.Document.Get(this.props.fieldKey) instanceof Field) { + CollectionView.AddDocument(this.props, doc); + } + removeDocument = (doc: Document): boolean => { + return CollectionView.RemoveDocument(this.props, doc); + } + + @action + public static AddDocument(props: CollectionViewProps, doc: Document) { + if (props.Document.Get(props.fieldKey) instanceof Field) { //TODO This won't create the field if it doesn't already exist - const value = this.props.Document.GetData(this.props.fieldKey, ListField, new Array()) + const value = props.Document.GetData(props.fieldKey, ListField, new Array()) value.push(doc); } else { - this.props.Document.SetData(this.props.fieldKey, [doc], ListField); + props.Document.SetData(props.fieldKey, [doc], ListField); } } - @action - removeDocument = (doc: Document): boolean => { + public static RemoveDocument(props: CollectionViewProps, doc: Document): boolean { //TODO This won't create the field if it doesn't already exist - const value = this.props.Document.GetData(this.props.fieldKey, ListField, new Array()) + const value = props.Document.GetData(props.fieldKey, ListField, new Array()) let index = -1; for (let i = 0; i < value.length; i++) { if (value[i].Id == doc.Id) { @@ -98,36 +108,40 @@ export class CollectionView extends React.Component { } } - render() { - let viewType = this.collectionViewType; - let subView: JSX.Element; + @computed + get subView() { return CollectionView.SubView(this); } + + public static SubView(self: CollectionView) { + let viewType = self.collectionViewType; + let subView = (null); switch (viewType) { case CollectionViewType.Freeform: - subView = () + subView = () break; case CollectionViewType.Schema: - subView = () + subView = () break; case CollectionViewType.Docking: - subView = () + subView = () break; case CollectionViewType.Tree: - subView = () - break; - default: - subView =
+ subView = () break; } + return subView; + } + + render() { return (
- {subView} + {this.subView}
) } } \ No newline at end of file diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 20526c256..41e93df35 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -12,6 +12,7 @@ import { CollectionDockingView } from "../collections/CollectionDockingView"; import { CollectionFreeFormView } from "../collections/CollectionFreeFormView"; import { CollectionSchemaView } from "../collections/CollectionSchemaView"; import { CollectionView, CollectionViewType } from "../collections/CollectionView"; +import { CollectionPDFView } from "../collections/CollectionPDFView"; import { ContextMenu } from "../ContextMenu"; import { FormattedTextBox } from "../nodes/FormattedTextBox"; import { ImageBox } from "../nodes/ImageBox"; @@ -195,7 +196,7 @@ export class DocumentView extends React.Component { } @computed get mainContent() { return { //very useful for keeping track of X and y position throughout the PDF Canvas private initX: number = 0; private initY: number = 0; + private initPage: boolean = false; //checks if tool is on private _toolOn: boolean = false; //checks if tool is on @@ -77,47 +77,36 @@ export class PDFBox extends React.Component { private _highlightTool = React.createRef(); //highlighter button reference private _highlightToolOn: boolean = false; private _pdfCanvas: any; + private _reactionDisposer: Opt; @observable private _perPageInfo: Object[] = []; //stores pageInfo @observable private _pageInfo: any = { area: [], divs: [], anno: [] }; //divs is array of objects linked to anno @observable private _currAnno: any = [] - @observable private _page: number = 1; //default is the first page. - @observable private _numPages: number = 1; //default number of pages @observable private _interactive: boolean = false; @observable private _loaded: boolean = false; - /** - * for pagination backwards - */ - @action - onPageBack = () => { - if (this._page > 1) { - this._page -= 1; - this._currAnno = []; - this._perPageInfo[this._page] = this._pageInfo - this._pageInfo = { area: [], divs: [], anno: [] }; //resets the object to default - if (this._perPageInfo[this._page - 1]) { - this._pageInfo = this._perPageInfo[this._page - 1]; - } - this.saveThumbnail(); - } + @computed private get curPage() { return this.props.doc.GetNumber(KeyStore.CurPage, 0); } + + componentDidMount() { + this._reactionDisposer = reaction( + () => this.curPage, + () => { + if (this.curPage && this.initPage) { + this.saveThumbnail(); + this._interactive = true; + } else { + if (this.curPage) + this.initPage = true; + } + }, + { fireImmediately: true }); + } - /** - * for pagination forwards - */ - @action - onPageForward = () => { - if (this._page < this._numPages) { - this._page += 1; - this._currAnno = []; - this._perPageInfo[this._page - 2] = this._pageInfo; - this._pageInfo = { area: [], divs: [], anno: [] }; //resets the object to default - if (this._perPageInfo[this._page - 1]) { - this._pageInfo = this._perPageInfo[this._page - 1]; - } - this.saveThumbnail(); + componentWillUnmount() { + if (this._reactionDisposer) { + this._reactionDisposer(); } } @@ -386,8 +375,6 @@ export class PDFBox extends React.Component { } - - @action saveThumbnail = () => { setTimeout(() => { @@ -420,9 +407,11 @@ export class PDFBox extends React.Component { } }) } - this._numPages = page._transport.numPages; + + // bcz: the number of pages should really be set when the document is imported. + this.props.doc.SetNumber(KeyStore.NumPages, page._transport.numPages); if (this._perPageInfo.length == 0) { //Makes sure it only runs once - this._perPageInfo = [...Array(this._numPages)] + this._perPageInfo = [...Array(page._transport.numPages)] } this._loaded = true; } @@ -441,24 +430,9 @@ export class PDFBox extends React.Component { } } - @computed - get uIButtons() { - return ( -
- - - - - - - - - -
); - } - @computed get pdfContent() { + const page = this.curPage; const renderHeight = 2400; let pdfUrl = this.props.doc.GetT(this.props.fieldKey, PDFField); let xf = this.props.doc.GetNumber(KeyStore.NativeHeight, 0) / renderHeight; @@ -467,7 +441,7 @@ export class PDFBox extends React.Component { {({ measureRef }) =>
- +
}
@@ -485,7 +459,6 @@ export class PDFBox extends React.Component { return [ this._pageInfo.area.filter(() => this._pageInfo.area).map((element: any) => element), this._currAnno.map((element: any) => element), - this.uIButtons,
{this.pdfContent} {proxy} diff --git a/src/fields/InkField.ts b/src/fields/InkField.ts index a475e2aae..1108a04a5 100644 --- a/src/fields/InkField.ts +++ b/src/fields/InkField.ts @@ -13,6 +13,7 @@ export interface StrokeData { color: string; width: string; tool: InkTool; + page: number; } export type StrokeMap = Map; diff --git a/src/fields/KeyStore.ts b/src/fields/KeyStore.ts index 259d1acaf..f67257093 100644 --- a/src/fields/KeyStore.ts +++ b/src/fields/KeyStore.ts @@ -4,6 +4,7 @@ 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"); @@ -27,5 +28,7 @@ export namespace KeyStore { export const ActiveFrame = new Key("ActiveFrame"); export const DocumentText = new Key("DocumentText"); export const Thumbnail = new Key("Thumbnail"); + export const CurPage = new Key("CurPage"); + export const NumPages = new Key("NumPages"); export const Ink = new Key("Ink"); } -- cgit v1.2.3-70-g09d2 From d3e66a67406447682c59045a0130d884fe1045a6 Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 8 Mar 2019 13:03:57 -0500 Subject: bug fixes and hack to make context menu appear again --- src/client/documents/Documents.ts | 2 +- src/client/views/collections/CollectionPDFView.tsx | 35 ++++----------- src/client/views/collections/CollectionView.tsx | 52 +++++----------------- src/client/views/nodes/PDFBox.tsx | 4 +- 4 files changed, 24 insertions(+), 69 deletions(-) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index fb1c3d867..fc210e9a2 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -100,7 +100,7 @@ export namespace Documents { if (!pdfProto) { pdfProto = setupPrototypeOptions(pdfProtoId, "PDF_PROTO", CollectionPDFView.LayoutString("AnnotationsKey"), { x: 0, y: 0, nativeWidth: 600, width: 300, layoutKeys: [KeyStore.Data, KeyStore.Annotations] }); - pdfProto.SetNumber(KeyStore.Page, 1); + pdfProto.SetNumber(KeyStore.CurPage, 1); pdfProto.SetText(KeyStore.BackgroundLayout, PDFBox.LayoutString()); } return pdfProto; diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx index 90da43921..7fd9f0f11 100644 --- a/src/client/views/collections/CollectionPDFView.tsx +++ b/src/client/views/collections/CollectionPDFView.tsx @@ -1,20 +1,11 @@ import { action, computed } from "mobx"; import { observer } from "mobx-react"; import { Document } from "../../../fields/Document"; -import { ListField } from "../../../fields/ListField"; -import { SelectionManager } from "../../util/SelectionManager"; -import { ContextMenu } from "../ContextMenu"; -import React = require("react"); import { KeyStore } from "../../../fields/KeyStore"; -import { NumberField } from "../../../fields/NumberField"; -import { CollectionFreeFormView } from "./CollectionFreeFormView"; -import { CollectionDockingView } from "./CollectionDockingView"; -import { CollectionSchemaView } from "./CollectionSchemaView"; +import { ContextMenu } from "../ContextMenu"; +import { CollectionView, CollectionViewType } from "./CollectionView"; import { CollectionViewProps } from "./CollectionViewBase"; -import { CollectionTreeView } from "./CollectionTreeView"; -import { Field } from "../../../fields/Field"; -import { CollectionViewType, CollectionView } from "./CollectionView"; -import { JSXElement } from "babel-types"; +import React = require("react"); @observer @@ -39,30 +30,20 @@ export class CollectionPDFView extends React.Component {
); } - // CollectionView API starts here... + // "inherited" CollectionView API starts here... public active: () => boolean = () => CollectionView.Active(this); - @action - addDocument = (doc: Document): void => { - doc.SetNumber(KeyStore.Page, this.curPage); - CollectionView.AddDocument(this.props, doc); - } - - @action removeDocument = (doc: Document): boolean => { - return CollectionView.RemoveDocument(this.props, doc); - } + addDocument = (doc: Document): void => { CollectionView.AddDocument(this.props, doc); } + removeDocument = (doc: Document): boolean => { return CollectionView.RemoveDocument(this.props, doc); } specificContextMenu = (e: React.MouseEvent): void => { - if (!e.isPropagationStopped) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 - ContextMenu.Instance.addItem({ description: "PDFOptions", event: () => { } }) + if (!e.isPropagationStopped() && this.props.Document.Id != "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 + ContextMenu.Instance.addItem({ description: "PDFOptions", event: () => { } }); } } get collectionViewType(): CollectionViewType { return CollectionViewType.Freeform; } - - - @computed get subView(): any { return CollectionView.SubView(this); } render() { diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 504538e85..49df04163 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -34,6 +34,9 @@ export class CollectionView extends React.Component { } public active: () => boolean = () => CollectionView.Active(this); + addDocument = (doc: Document): void => { CollectionView.AddDocument(this.props, doc); } + removeDocument = (doc: Document): boolean => { return CollectionView.RemoveDocument(this.props, doc); } + get subView() { return CollectionView.SubView(this); } public static Active(self: CollectionView): boolean { var isSelected = self.props.isSelected(); @@ -42,15 +45,9 @@ export class CollectionView extends React.Component { return isSelected || childSelected || topMost; } - addDocument = (doc: Document): void => { - CollectionView.AddDocument(this.props, doc); - } - removeDocument = (doc: Document): boolean => { - return CollectionView.RemoveDocument(this.props, doc); - } - @action public static AddDocument(props: CollectionViewProps, doc: Document) { + doc.SetNumber(KeyStore.Page, props.Document.GetNumber(KeyStore.CurPage, 0)); if (props.Document.Get(props.fieldKey) instanceof Field) { //TODO This won't create the field if it doesn't already exist const value = props.Document.GetData(props.fieldKey, ListField, new Array()) @@ -94,13 +91,8 @@ export class CollectionView extends React.Component { } } - set collectionViewType(type: CollectionViewType) { - let Document = this.props.Document; - Document.SetData(KeyStore.ViewType, type, NumberField); - } - specificContextMenu = (e: React.MouseEvent): void => { - if (!e.isPropagationStopped) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 + if (!e.isPropagationStopped() && this.props.Document.Id != "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 ContextMenu.Instance.addItem({ description: "Freeform", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform) }) ContextMenu.Instance.addItem({ description: "Schema", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Schema) }) ContextMenu.Instance.addItem({ description: "Treeview", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Tree) }) @@ -108,35 +100,15 @@ export class CollectionView extends React.Component { } } - @computed - get subView() { return CollectionView.SubView(this); } - public static SubView(self: CollectionView) { - let viewType = self.collectionViewType; - let subView = (null); - switch (viewType) { - case CollectionViewType.Freeform: - subView = () - break; - case CollectionViewType.Schema: - subView = () - break; - case CollectionViewType.Docking: - subView = () - break; - case CollectionViewType.Tree: - subView = () - break; + let subProps = { ...self.props, addDocument: self.addDocument, removeDocument: self.removeDocument, active: self.active, CollectionView: self } + switch (self.collectionViewType) { + case CollectionViewType.Freeform: return () + case CollectionViewType.Schema: return () + case CollectionViewType.Docking: return () + case CollectionViewType.Tree: return () } - return subView; + return (null); } render() { diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index fb3e24659..70a70c7c8 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -432,7 +432,9 @@ export class PDFBox extends React.Component { @computed get pdfContent() { - const page = this.curPage; + let page = this.curPage; + if (page == 0) + page = 1; const renderHeight = 2400; let pdfUrl = this.props.doc.GetT(this.props.fieldKey, PDFField); let xf = this.props.doc.GetNumber(KeyStore.NativeHeight, 0) / renderHeight; -- cgit v1.2.3-70-g09d2