From f2d02089b6b749929b7fc3d522ac176b7f6027fd Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 6 Mar 2019 17:59:15 -0500
Subject: fixed render size of pdfs & changed note backrounds contextually.

---
 src/client/views/collections/CollectionView.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'src/client/views/collections/CollectionView.tsx')

diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 31824763d..8d175ee35 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -126,7 +126,7 @@ export class CollectionView extends React.Component<CollectionViewProps> {
                 subView = <div></div>
                 break;
         }
-        return (<div onContextMenu={this.specificContextMenu}>
+        return (<div className="collectionView-cont" onContextMenu={this.specificContextMenu}>
             {subView}
         </div>)
     }
-- 
cgit v1.2.3-70-g09d2


From c4eff83d814b1f9b94b7fc75ca06e8f0474de20d Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
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/views/collections/CollectionView.tsx')

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<InkCanvasProps> {
                 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<InkCanvasProps> {
 
         // parse data from server
         let paths: Array<JSX.Element> = []
+        let curPage = this.props.Document.GetNumber(KeyStore.CurPage, 0)
         Array.from(lines).map(item => {
             let id = item[0];
             let strokeData = item[1];
-            paths.push(<InkingStroke key={id} id={id}
-                line={strokeData.pathData}
-                color={strokeData.color}
-                width={strokeData.width}
-                tool={strokeData.tool}
-                deleteCallback={this.removeLine} />)
+            if (strokeData.page == 0 || strokeData.page == curPage)
+                paths.push(<InkingStroke key={id} id={id}
+                    line={strokeData.pathData}
+                    color={strokeData.color}
+                    width={strokeData.width}
+                    tool={strokeData.tool}
+                    deleteCallback={this.removeLine} />)
         })
 
         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<ListField<Document>>(this.props.fieldKey, ListField);
         if (lvalue && lvalue != FieldWaiting) {
             return lvalue.Data.map(doc => {
-                return (<CollectionFreeFormDocumentView key={doc.Id} Document={doc}
-                    AddDocument={this.props.addDocument}
-                    RemoveDocument={this.props.removeDocument}
-                    ScreenToLocalTransform={this.getTransform}
-                    isTopMost={false}
-                    SelectOnLoad={doc.Id === this._selectOnLoaded}
-                    ContentScaling={this.noScaling}
-                    PanelWidth={doc.Width}
-                    PanelHeight={doc.Height}
-                    ContainingCollectionView={this.props.CollectionView}
-                    focus={this.focusDocument}
-                />);
+                var page = doc.GetNumber(KeyStore.Page, 0);
+                return (page != curPage && page != 0) ? (null) :
+                    (<CollectionFreeFormDocumentView key={doc.Id} Document={doc}
+                        AddDocument={this.props.addDocument}
+                        RemoveDocument={this.props.removeDocument}
+                        ScreenToLocalTransform={this.getTransform}
+                        isTopMost={false}
+                        SelectOnLoad={doc.Id === this._selectOnLoaded}
+                        ContentScaling={this.noScaling}
+                        PanelWidth={doc.Width}
+                        PanelHeight={doc.Height}
+                        ContainingCollectionView={this.props.CollectionView}
+                        focus={this.focusDocument}
+                    />);
             })
         }
         return null;
@@ -248,7 +252,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
     get backgroundView() {
         return !this.backgroundLayout ? (null) :
             (<JsxParser
-                components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox, KeyValueBox, PDFBox }}
+                components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, WebBox, KeyValueBox, PDFBox }}
                 bindings={this.props.bindings}
                 jsx={this.backgroundLayout}
                 showWarnings={true}
@@ -259,7 +263,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
     get overlayView() {
         return !this.overlayLayout ? (null) :
             (<JsxParser
-                components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox, KeyValueBox, PDFBox }}
+                components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, WebBox, KeyValueBox, PDFBox }}
                 bindings={this.props.bindings}
                 jsx={this.overlayLayout}
                 showWarnings={true}
diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx
new file mode 100644
index 000000000..90da43921
--- /dev/null
+++ b/src/client/views/collections/CollectionPDFView.tsx
@@ -0,0 +1,74 @@
+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 { CollectionViewProps } from "./CollectionViewBase";
+import { CollectionTreeView } from "./CollectionTreeView";
+import { Field } from "../../../fields/Field";
+import { CollectionViewType, CollectionView } from "./CollectionView";
+import { JSXElement } from "babel-types";
+
+
+@observer
+export class CollectionPDFView extends React.Component<CollectionViewProps> {
+
+    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 (
+            <div className="pdfBox-buttonTray" key="tray">
+                <button className="pdfButton" onClick={this.onPageBack}>{"<"}</button>
+                <button className="pdfButton" onClick={this.onPageForward}>{">"}</button>
+            </div>);
+    }
+
+    // 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 (<div className="collectionView-cont" onContextMenu={this.specificContextMenu}>
+            {this.subView}
+            {this.props.isSelected() ? this.uIButtons : (null)}
+        </div>)
+    }
+}
\ 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<CollectionViewProps> {
 
     public static LayoutString(fieldKey: string = "DataKey") {
-        return `<CollectionView Document={Document}
+        return `<${CollectionView.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}/>`;
     }
-    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<Document>())
+            const value = props.Document.GetData(props.fieldKey, ListField, new Array<Document>())
             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<Document>())
+        const value = props.Document.GetData(props.fieldKey, ListField, new Array<Document>())
         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<CollectionViewProps> {
         }
     }
 
-    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 = (<CollectionFreeFormView {...this.props}
-                    addDocument={this.addDocument} removeDocument={this.removeDocument} active={this.active}
-                    CollectionView={this} />)
+                subView = (<CollectionFreeFormView {...self.props}
+                    addDocument={self.addDocument} removeDocument={self.removeDocument} active={self.active}
+                    CollectionView={self} />)
                 break;
             case CollectionViewType.Schema:
-                subView = (<CollectionSchemaView {...this.props}
-                    addDocument={this.addDocument} removeDocument={this.removeDocument} active={this.active}
-                    CollectionView={this} />)
+                subView = (<CollectionSchemaView {...self.props}
+                    addDocument={self.addDocument} removeDocument={self.removeDocument} active={self.active}
+                    CollectionView={self} />)
                 break;
             case CollectionViewType.Docking:
-                subView = (<CollectionDockingView {...this.props}
-                    addDocument={this.addDocument} removeDocument={this.removeDocument} active={this.active}
-                    CollectionView={this} />)
+                subView = (<CollectionDockingView {...self.props}
+                    addDocument={self.addDocument} removeDocument={self.removeDocument} active={self.active}
+                    CollectionView={self} />)
                 break;
             case CollectionViewType.Tree:
-                subView = (<CollectionTreeView {...this.props}
-                    addDocument={this.addDocument} removeDocument={this.removeDocument} active={this.active}
-                    CollectionView={this} />)
-                break;
-            default:
-                subView = <div></div>
+                subView = (<CollectionTreeView {...self.props}
+                    addDocument={self.addDocument} removeDocument={self.removeDocument} active={self.active}
+                    CollectionView={self} />)
                 break;
         }
+        return subView;
+    }
+
+    render() {
         return (<div className="collectionView-cont" onContextMenu={this.specificContextMenu}>
-            {subView}
+            {this.subView}
         </div>)
     }
 }
\ 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<DocumentViewProps> {
     }
     @computed get mainContent() {
         return <JsxParser
-            components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox, KeyValueBox, PDFBox }}
+            components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, WebBox, KeyValueBox, PDFBox }}
             bindings={this._documentBindings}
             jsx={this.layout}
             showWarnings={true}
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 5614242b5..fb3e24659 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -1,23 +1,22 @@
-import { action, observable, _interceptReads, computed } from 'mobx';
+import * as htmlToImage from "html-to-image";
+import { action, computed, observable, reaction, IReactionDisposer } from 'mobx';
 import { observer } from "mobx-react";
-import Measure from "react-measure";
 import 'react-image-lightbox/style.css';
+import Measure from "react-measure";
 //@ts-ignore
 import { Document, Page } from "react-pdf";
 import 'react-pdf/dist/Page/AnnotationLayer.css';
+import { FieldWaiting, Opt } from '../../../fields/Field';
+import { ImageField } from '../../../fields/ImageField';
+import { KeyStore } from '../../../fields/KeyStore';
+import { PDFField } from '../../../fields/PDFField';
 import { Utils } from '../../../Utils';
 import { Annotation } from './Annotation';
 import { FieldView, FieldViewProps } from './FieldView';
 import "./ImageBox.scss";
+import "./PDFBox.scss";
 import { Sticky } from './Sticky'; //you should look at sticky and annotation, because they are used here
 import React = require("react")
-import { KeyStore } from '../../../fields/KeyStore';
-import "./PDFBox.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, 
@@ -60,6 +59,7 @@ export class PDFBox extends React.Component<FieldViewProps> {
     //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<FieldViewProps> {
     private _highlightTool = React.createRef<HTMLButtonElement>(); //highlighter button reference
     private _highlightToolOn: boolean = false;
     private _pdfCanvas: any;
+    private _reactionDisposer: Opt<IReactionDisposer>;
 
     @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<FieldViewProps> {
     }
 
 
-
-
     @action
     saveThumbnail = () => {
         setTimeout(() => {
@@ -420,9 +407,11 @@ export class PDFBox extends React.Component<FieldViewProps> {
                 }
             })
         }
-        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<FieldViewProps> {
         }
     }
 
-    @computed
-    get uIButtons() {
-        return (
-            <div className="pdfBox-buttonTray" key="tray">
-                <button className="pdfButton" onClick={this.onPageBack}>{"<"}</button>
-                <button className="pdfButton" onClick={this.onPageForward}>{">"}</button>
-                <button className="pdfButton" onClick={this.selectionTool}>{"Area"}</button>
-                <button className="pdfButton" style={{ color: "white", backgroundColor: "grey" }} onClick={this.onHighlight} ref={this._highlightTool}>Highlight</button>
-                <button className="pdfButton" style={{ color: "white", backgroundColor: "grey" }} ref={this._drawTool} onClick={this.onDraw}>{"Draw"}</button>
-                <button className="pdfButton" ref={this._colorTool} onPointerDown={this.onColorChange}>{"Red"}</button>
-                <button className="pdfButton" ref={this._colorTool} onPointerDown={this.onColorChange}>{"Blue"}</button>
-                <button className="pdfButton" ref={this._colorTool} onPointerDown={this.onColorChange}>{"Green"}</button>
-                <button className="pdfButton" ref={this._colorTool} onPointerDown={this.onColorChange}>{"Black"}</button>
-            </div>);
-    }
-
     @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<FieldViewProps> {
                 <Measure onResize={this.setScaling}>
                     {({ measureRef }) =>
                         <div className="pdfBox-page" ref={measureRef}>
-                            <Page height={renderHeight} pageNumber={this._page} onLoadSuccess={this.onLoaded} />
+                            <Page height={renderHeight} pageNumber={page} onLoadSuccess={this.onLoaded} />
                         </div>
                     }
                 </Measure>
@@ -485,7 +459,6 @@ export class PDFBox extends React.Component<FieldViewProps> {
         return [
             this._pageInfo.area.filter(() => this._pageInfo.area).map((element: any) => element),
             this._currAnno.map((element: any) => element),
-            this.uIButtons,
             <div key="pdfBox-contentShell">
                 {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<string, StrokeData>;
 
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 <bcz@cs.brown.edu>
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/views/collections/CollectionView.tsx')

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<CollectionViewProps> {
             </div>);
     }
 
-    // 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<CollectionViewProps> {
     }
 
     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<CollectionViewProps> {
         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<Document>())
@@ -94,13 +91,8 @@ export class CollectionView extends React.Component<CollectionViewProps> {
         }
     }
 
-    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<CollectionViewProps> {
         }
     }
 
-    @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 = (<CollectionFreeFormView {...self.props}
-                    addDocument={self.addDocument} removeDocument={self.removeDocument} active={self.active}
-                    CollectionView={self} />)
-                break;
-            case CollectionViewType.Schema:
-                subView = (<CollectionSchemaView {...self.props}
-                    addDocument={self.addDocument} removeDocument={self.removeDocument} active={self.active}
-                    CollectionView={self} />)
-                break;
-            case CollectionViewType.Docking:
-                subView = (<CollectionDockingView {...self.props}
-                    addDocument={self.addDocument} removeDocument={self.removeDocument} active={self.active}
-                    CollectionView={self} />)
-                break;
-            case CollectionViewType.Tree:
-                subView = (<CollectionTreeView {...self.props}
-                    addDocument={self.addDocument} removeDocument={self.removeDocument} active={self.active}
-                    CollectionView={self} />)
-                break;
+        let subProps = { ...self.props, addDocument: self.addDocument, removeDocument: self.removeDocument, active: self.active, CollectionView: self }
+        switch (self.collectionViewType) {
+            case CollectionViewType.Freeform: return (<CollectionFreeFormView {...subProps} />)
+            case CollectionViewType.Schema: return (<CollectionSchemaView {...subProps} />)
+            case CollectionViewType.Docking: return (<CollectionDockingView {...subProps} />)
+            case CollectionViewType.Tree: return (<CollectionTreeView {...subProps} />)
         }
-        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<FieldViewProps> {
 
     @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


From b9cfa458a6535e7ee0ff8b81398afa1e123cf458 Mon Sep 17 00:00:00 2001
From: Andrew Kim <andrewdkim@users.noreply.github.com>
Date: Sat, 9 Mar 2019 18:21:06 -0500
Subject: added audio and video nodes

---
 src/client/documents/Documents.ts               | 35 ++++++++++++++++++++
 src/client/views/Main.tsx                       | 11 ++++++-
 src/client/views/collections/CollectionView.tsx |  2 ++
 src/client/views/nodes/AudioBox.scss            |  4 +++
 src/client/views/nodes/AudioBox.tsx             | 44 +++++++++++++++++++++++++
 src/client/views/nodes/DocumentView.tsx         |  4 ++-
 src/client/views/nodes/FieldView.tsx            | 11 +++++++
 src/client/views/nodes/VideoBox.scss            |  4 +++
 src/client/views/nodes/VideoBox.tsx             | 43 ++++++++++++++++++++++++
 src/fields/AudioField.ts                        | 31 +++++++++++++++++
 src/fields/VideoField.ts                        | 30 +++++++++++++++++
 src/server/Message.ts                           |  2 +-
 src/server/ServerUtil.ts                        |  6 ++++
 13 files changed, 224 insertions(+), 3 deletions(-)
 create mode 100644 src/client/views/nodes/AudioBox.scss
 create mode 100644 src/client/views/nodes/AudioBox.tsx
 create mode 100644 src/client/views/nodes/VideoBox.scss
 create mode 100644 src/client/views/nodes/VideoBox.tsx
 create mode 100644 src/fields/AudioField.ts
 create mode 100644 src/fields/VideoField.ts

(limited to 'src/client/views/collections/CollectionView.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 1d24ff7d2..f81ad3188 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -15,6 +15,10 @@ import { Key } from "../../fields/Key"
 import { Field } from "../../fields/Field";
 import { KeyValueBox } from "../views/nodes/KeyValueBox"
 import { KVPField } from "../../fields/KVPField";
+import { VideoField } from "../../fields/VideoField"
+import { VideoBox } from "../views/nodes/VideoBox";
+import { AudioField } from "../../fields/AudioField";
+import { AudioBox } from "../views/nodes/AudioBox";
 
 export interface DocumentOptions {
     x?: number;
@@ -38,11 +42,15 @@ export namespace Documents {
     let webProto: Document;
     let collProto: Document;
     let kvpProto: Document;
+    let videoProto: Document; 
+    let audioProto: Document; 
     const textProtoId = "textProto";
     const imageProtoId = "imageProto";
     const webProtoId = "webProto";
     const collProtoId = "collectionProto";
     const kvpProtoId = "kvpProto";
+    const videoProtoId = "videoProto"
+    const audioProtoId = "audioProto";
 
     export function initProtos(mainDocId: string, callback: (mainDoc?: Document) => void) {
         Server.GetFields([collProtoId, textProtoId, imageProtoId, mainDocId], (fields) => {
@@ -108,6 +116,17 @@ export namespace Documents {
             kvpProto = setupPrototypeOptions(kvpProtoId, "KVP_PROTO", KeyValueBox.LayoutString(),
                 { x: 0, y: 0, width: 300, height: 150, layoutKeys: [KeyStore.Data] })
     }
+    function GetVideoPrototype(): Document {
+        return videoProto ? videoProto :
+            videoProto = setupPrototypeOptions(videoProtoId, "VIDEO_PROTO", VideoBox.LayoutString(),
+                { x: 0, y: 0, width: 300, height: 150, layoutKeys: [KeyStore.Data] })
+    }
+    function GetAudioPrototype(): Document {
+        return audioProto ? audioProto :
+            audioProto = setupPrototypeOptions(audioProtoId, "AUDIO_PROTO", AudioBox.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] },
@@ -117,6 +136,22 @@ export namespace Documents {
         doc.SetText(KeyStore.OverlayLayout, FixedCaption());
         return doc;
     }
+    export function VideoDocument(url: string, options: DocumentOptions = {}){
+        let doc = SetInstanceOptions(GetVideoPrototype(), { ...options, layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] },
+            new URL(url), VideoField);
+        doc.SetText(KeyStore.Caption, "my caption...");
+        doc.SetText(KeyStore.BackgroundLayout, EmbeddedCaption());
+        doc.SetText(KeyStore.OverlayLayout, FixedCaption());
+        return doc;
+    }
+    export function AudioDocument(url: string, options: DocumentOptions = {}){
+        let doc = SetInstanceOptions(GetAudioPrototype(), { ...options, layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] },
+            new URL(url), AudioField);
+        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);
     }
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index d845fa7a3..a52047631 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -52,13 +52,16 @@ Documents.initProtos(mainDocId, (res?: Document) => {
 
     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 audiourl = "http://techslides.com/demos/samples/sample.mp3";
+    let videourl = "http://techslides.com/demos/sample-videos/small.mp4"; 
     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 freeform collection" }));
     let addSchemaNode = action(() => Documents.SchemaDocument([Documents.TextDocument()], { width: 200, height: 200, title: "a schema collection" }));
+    let addVideoNode = action(() => Documents.VideoDocument(videourl, {width: 200, height:200, title: "video node"})); 
     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 addAudioNode = action(() => Documents.AudioDocument(audiourl,{ width: 200, height: 200, title: "audio node" } ))
     let addClick = (creator: () => Document) => action(() =>
         mainfreeform.GetList<Document>(KeyStore.Data, []).push(creator())
     );
@@ -67,6 +70,8 @@ Documents.initProtos(mainDocId, (res?: Document) => {
     let webRef = React.createRef<HTMLDivElement>();
     let textRef = React.createRef<HTMLDivElement>();
     let schemaRef = React.createRef<HTMLDivElement>();
+    let videoRef = React.createRef<HTMLDivElement>(); 
+    let audioRef = React.createRef<HTMLDivElement>(); 
     let colRef = React.createRef<HTMLDivElement>();
 
     ReactDOM.render((
@@ -94,6 +99,10 @@ Documents.initProtos(mainDocId, (res?: Document) => {
                 <button onPointerDown={setupDrag(schemaRef, addSchemaNode)} onClick={addClick(addSchemaNode)}>Add Schema</button></div>
             <div className="main-buttonDiv" style={{ bottom: '125px' }} >
                 <button onClick={clearDatabase}>Clear Database</button></div>
+            <div className="main-buttonDiv" style={{ bottom: '150px' }} ref={videoRef}>
+                <button onPointerDown={setupDrag(videoRef, addVideoNode)} onClick={addClick(addVideoNode)}>Add Video</button></div>
+            <div className="main-buttonDiv" style={{ bottom: '175px' }} ref={audioRef}>
+                <button onPointerDown={setupDrag(audioRef, addAudioNode)} onClick={addClick(addAudioNode)}>Add Audio</button></div>
             <button className="main-undoButtons" style={{ bottom: '25px' }} onClick={() => UndoManager.Undo()}>Undo</button>
             <button className="main-undoButtons" style={{ bottom: '0px' }} onClick={() => UndoManager.Redo()}>Redo</button>
         </div>),
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 31824763d..454d547ef 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -19,6 +19,8 @@ export enum CollectionViewType {
     Freeform,
     Schema,
     Docking,
+    Video, 
+    Audio,
     Tree
 }
 
diff --git a/src/client/views/nodes/AudioBox.scss b/src/client/views/nodes/AudioBox.scss
new file mode 100644
index 000000000..704cdc31c
--- /dev/null
+++ b/src/client/views/nodes/AudioBox.scss
@@ -0,0 +1,4 @@
+.audiobox-cont{
+    height: 100%;
+    width: 100%;
+}
\ No newline at end of file
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
new file mode 100644
index 000000000..f7d89843d
--- /dev/null
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -0,0 +1,44 @@
+import React = require("react")
+import { FieldViewProps, FieldView } from './FieldView';
+import { FieldWaiting } from '../../../fields/Field';
+import { observer } from "mobx-react"
+import { ContextMenu } from "../../views/ContextMenu";
+import { observable, action } from 'mobx';
+import { KeyStore } from '../../../fields/KeyStore';
+import { AudioField } from "../../../fields/AudioField";
+import "./AudioBox.scss"
+import { NumberField } from "../../../fields/NumberField";
+
+@observer
+export class AudioBox extends React.Component<FieldViewProps> {
+
+    public static LayoutString() { return FieldView.LayoutString(AudioBox) }
+
+    constructor(props: FieldViewProps) {
+        super(props);
+    }
+
+   
+
+    componentDidMount() {
+    }
+
+    componentWillUnmount() {
+    }
+
+   
+    render() {
+        let field = this.props.doc.Get(this.props.fieldKey)
+        let path = field == FieldWaiting ? "http://techslides.com/demos/samples/sample.mp3":
+            field instanceof AudioField ? field.Data.href : "http://techslides.com/demos/samples/sample.mp3";
+    
+        return (
+            <div>
+                <audio controls className = "audiobox-cont">
+                    <source src = {path} type="audio/mpeg"/>
+                    Not supported.
+                </audio>
+            </div>
+        )
+    }
+}
\ No newline at end of file
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index e01e1d4cd..b22435f1a 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -15,6 +15,8 @@ import { CollectionView, CollectionViewType } from "../collections/CollectionVie
 import { ContextMenu } from "../ContextMenu";
 import { FormattedTextBox } from "../nodes/FormattedTextBox";
 import { ImageBox } from "../nodes/ImageBox";
+import { VideoBox } from "../nodes/VideoBox"; 
+import { AudioBox } from "../nodes/AudioBox"; 
 import { Documents } from "../../documents/Documents"
 import { KeyValueBox } from "./KeyValueBox"
 import { WebBox } from "../nodes/WebBox";
@@ -194,7 +196,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     }
     @computed get mainContent() {
         return <JsxParser
-            components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox, KeyValueBox }}
+            components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox, KeyValueBox, VideoBox, AudioBox }}
             bindings={this._documentBindings}
             jsx={this.layout}
             showWarnings={true}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 9e63006d1..49f4cefce 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -8,10 +8,15 @@ import { NumberField } from "../../../fields/NumberField";
 import { RichTextField } from "../../../fields/RichTextField";
 import { ImageField } from "../../../fields/ImageField";
 import { WebField } from "../../../fields/WebField";
+import { VideoField } from "../../../fields/VideoField"
 import { Key } from "../../../fields/Key";
 import { FormattedTextBox } from "./FormattedTextBox";
 import { ImageBox } from "./ImageBox";
 import { WebBox } from "./WebBox";
+import { VideoBox } from "./VideoBox";
+import { AudioBox } from "./AudioBox";
+import { AudioField } from "../../../fields/AudioField";
+
 
 //
 // these properties get assigned through the render() method of the DocumentView when it creates this node.
@@ -55,6 +60,12 @@ export class FieldView extends React.Component<FieldViewProps> {
         }
         else if (field instanceof WebField) {
             return <WebBox {...this.props} />
+        } 
+        else if (field instanceof VideoField){ 
+            return <VideoBox {...this.props}/>
+        }
+        else if (field instanceof AudioField){ 
+            return <AudioBox {...this.props}/>
         }
         // bcz: this belongs here, but it doesn't render well so taking it out for now
         // else if (field instanceof HtmlField) {
diff --git a/src/client/views/nodes/VideoBox.scss b/src/client/views/nodes/VideoBox.scss
new file mode 100644
index 000000000..7306450d9
--- /dev/null
+++ b/src/client/views/nodes/VideoBox.scss
@@ -0,0 +1,4 @@
+.videobox-cont{
+    width: 100%; 
+    height: 100%; 
+}
\ No newline at end of file
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
new file mode 100644
index 000000000..22ff5c5ad
--- /dev/null
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -0,0 +1,43 @@
+import React = require("react")
+import { FieldViewProps, FieldView } from './FieldView';
+import { FieldWaiting } from '../../../fields/Field';
+import { observer } from "mobx-react"
+import { VideoField } from '../../../fields/VideoField'; 
+import "./VideoBox.scss"
+import { ContextMenu } from "../../views/ContextMenu";
+import { observable, action } from 'mobx';
+import { KeyStore } from '../../../fields/KeyStore';
+
+@observer
+export class VideoBox extends React.Component<FieldViewProps> {
+
+    public static LayoutString() { return FieldView.LayoutString(VideoBox) }
+
+    constructor(props: FieldViewProps) {
+        super(props);
+    }
+
+   
+
+    componentDidMount() {
+    }
+
+    componentWillUnmount() {
+    }
+
+   
+    render() {
+        let field = this.props.doc.Get(this.props.fieldKey)
+        let path = field == FieldWaiting ? "http://techslides.com/demos/sample-videos/small.mp4":
+            field instanceof VideoField ? field.Data.href : "http://techslides.com/demos/sample-videos/small.mp4";
+    
+        return (
+            <div>
+                <video width = {200} height = {200} controls className = "videobox-cont">
+                    <source src = {path} type = "video/mp4"/>
+                    Not supported.
+                </video>
+            </div>
+        )
+    }
+}
\ No newline at end of file
diff --git a/src/fields/AudioField.ts b/src/fields/AudioField.ts
new file mode 100644
index 000000000..aefcc15c1
--- /dev/null
+++ b/src/fields/AudioField.ts
@@ -0,0 +1,31 @@
+import { BasicField } from "./BasicField";
+import { Field, FieldId } from "./Field";
+import { Types } from "../server/Message";
+
+export class AudioField extends BasicField<URL> {
+    constructor(data: URL | undefined = undefined, id?: FieldId, save: boolean = true) {
+        super(data == undefined ? new URL("http://techslides.com/demos/samples/sample.mp3") : data, save, id);
+    }
+
+    toString(): string {
+        return this.Data.href;
+    }
+    
+    
+    ToScriptString(): string {
+        return `new AudioField("${this.Data}")`;
+    }
+
+    Copy(): Field {
+        return new AudioField(this.Data);
+    }
+
+    ToJson(): { type: Types, data: URL, _id: string } {
+        return {
+            type: Types.Audio,
+            data: this.Data,
+            _id: this.Id
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/src/fields/VideoField.ts b/src/fields/VideoField.ts
new file mode 100644
index 000000000..5f4ae19bf
--- /dev/null
+++ b/src/fields/VideoField.ts
@@ -0,0 +1,30 @@
+import { BasicField } from "./BasicField";
+import { Field, FieldId } from "./Field";
+import { Types } from "../server/Message";
+
+export class VideoField extends BasicField<URL> {
+    constructor(data: URL | undefined = undefined, id?: FieldId, save: boolean = true) {
+        super(data == undefined ? new URL("http://techslides.com/demos/sample-videos/small.mp4") : data, save, id);
+    }
+
+    toString(): string {
+        return this.Data.href;
+    }
+
+    ToScriptString(): string {
+        return `new VideoField("${this.Data}")`;
+    }
+
+    Copy(): Field {
+        return new VideoField(this.Data);
+    }
+
+    ToJson(): { type: Types, data: URL, _id: string } {
+        return {
+            type: Types.Video,
+            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 148e6e723..f85f56dd2 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, Web, Document, Text, RichText, DocumentReference, Html
+    Number, List, Key, Image, Web, Document, Text, RichText, DocumentReference, Html, Video, Audio
 }
 
 export class DocumentTransfer implements Transferable {
diff --git a/src/server/ServerUtil.ts b/src/server/ServerUtil.ts
index a53fb5d2b..2e681fece 100644
--- a/src/server/ServerUtil.ts
+++ b/src/server/ServerUtil.ts
@@ -11,6 +11,8 @@ import { Types } from './Message';
 import { Utils } from '../Utils';
 import { HtmlField } from '../fields/HtmlField';
 import { WebField } from '../fields/WebField';
+import { AudioField } from '../fields/AudioField';
+import { VideoField } from '../fields/VideoField';
 
 export class ServerUtils {
     public static FromJson(json: any): Field {
@@ -41,6 +43,10 @@ export class ServerUtils {
                 return new ImageField(new URL(data), id, false)
             case Types.List:
                 return ListField.FromJson(id, data)
+            case Types.Audio:
+                return new AudioField(new URL(data), id, false)
+            case Types.Video:
+                return new VideoField(new URL(data), id, false)
             case Types.Document:
                 let doc: Document = new Document(id, false)
                 let fields: [string, string][] = data as [string, string][]
-- 
cgit v1.2.3-70-g09d2


From ebe101203788d9fc564671cc38f085c3ef990536 Mon Sep 17 00:00:00 2001
From: tschicke-brown <tyler_schicke@brown.edu>
Date: Sat, 9 Mar 2019 19:09:06 -0500
Subject: Update CollectionView.tsx

---
 src/client/views/collections/CollectionView.tsx | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

(limited to 'src/client/views/collections/CollectionView.tsx')

diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index fca32e615..f154909bb 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -19,8 +19,6 @@ export enum CollectionViewType {
     Freeform,
     Schema,
     Docking,
-    Video, 
-    Audio,
     Tree
 }
 
@@ -118,4 +116,4 @@ export class CollectionView extends React.Component<CollectionViewProps> {
             {this.subView}
         </div>)
     }
-}
\ No newline at end of file
+}
-- 
cgit v1.2.3-70-g09d2

