From d2c9550f23c4e5654822ac01b973bb965e3f6dec Mon Sep 17 00:00:00 2001
From: Sam Wilkins <samuel_wilkins@brown.edu>
Date: Fri, 14 Jun 2019 20:49:12 -0400
Subject: cleaned up Docs namespace and thoroughly documented
 DocServer.GetRefFields

---
 .../collections/collectionFreeForm/MarqueeView.tsx     | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

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

diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 29734fa19..cd386abfa 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -79,7 +79,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                 }
                 ns.map(line => {
                     let indent = line.search(/\S|$/);
-                    let newBox = Docs.TextDocument({ width: 200, height: 35, x: x + indent / 3 * 10, y: y, documentText: "@@@" + line, title: line });
+                    let newBox = Docs.Create.TextDocument({ width: 200, height: 35, x: x + indent / 3 * 10, y: y, documentText: "@@@" + line, title: line });
                     this.props.addDocument(newBox, false);
                     y += 40 * this.props.getTransform().Scale;
                 });
@@ -89,13 +89,13 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             navigator.clipboard.readText().then(text => {
                 let ns = text.split("\n").filter(t => t.trim() !== "\r" && t.trim() !== "");
                 if (ns.length === 1 && text.startsWith("http")) {
-                    this.props.addDocument(Docs.ImageDocument(text, { nativeWidth: 300, width: 300, x: x, y: y }), false);// paste an image from its URL in the paste buffer
+                    this.props.addDocument(Docs.Create.ImageDocument(text, { nativeWidth: 300, width: 300, x: x, y: y }), false);// paste an image from its URL in the paste buffer
                 } else {
                     this.pasteTable(ns, x, y);
                 }
             });
         } else {
-            let newBox = Docs.TextDocument({ width: 200, height: 100, x: x, y: y, title: "-typed text-" });
+            let newBox = Docs.Create.TextDocument({ width: 200, height: 100, x: x, y: y, title: "-typed text-" });
             this.props.addLiveTextDocument(newBox);
         }
         e.stopPropagation();
@@ -136,7 +136,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                 doc.width = 200;
                 docList.push(doc);
             }
-            let newCol = Docs.SchemaDocument([...(groupAttr ? ["_group"] : []), ...columns.filter(c => c)], docList, { x: x, y: y, title: "droppedTable", width: 300, height: 100 });
+            let newCol = Docs.Create.SchemaDocument([...(groupAttr ? ["_group"] : []), ...columns.filter(c => c)], docList, { x: x, y: y, title: "droppedTable", width: 300, height: 100 });
 
             this.props.addDocument(newCol, false);
         }
@@ -259,7 +259,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             let ink = Cast(this.props.container.props.Document.ink, InkField);
             let inkData = ink ? ink.inkData : undefined;
             let zoomBasis = NumCast(this.props.container.props.Document.scale, 1);
-            let newCollection = Docs.FreeformDocument(selected, {
+            let newCollection = Docs.Create.FreeformDocument(selected, {
                 x: bounds.left,
                 y: bounds.top,
                 panX: 0,
@@ -283,14 +283,14 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                     d.page = -1;
                     return d;
                 });
-                let summary = Docs.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" });
+                let summary = Docs.Create.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" });
                 newCollection.proto!.summaryDoc = summary;
                 selected = [newCollection];
                 newCollection.x = bounds.left + bounds.width;
                 summary.proto!.subBulletDocs = new List<Doc>(selected);
                 //summary.proto!.maximizeLocation = "inTab";  // or "inPlace", or "onRight"
                 summary.templates = new List<string>([Templates.Bullet.Layout]);
-                let container = Docs.FreeformDocument([summary, newCollection], { x: bounds.left, y: bounds.top, width: 300, height: 200, title: "-summary-" });
+                let container = Docs.Create.FreeformDocument([summary, newCollection], { x: bounds.left, y: bounds.top, width: 300, height: 200, title: "-summary-" });
                 container.viewType = CollectionViewType.Stacking;
                 this.props.addLiveTextDocument(container);
                 // });
@@ -303,11 +303,11 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                         d.page = -1;
                         return d;
                     });
-                    let summary = Docs.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" });
+                    let summary = Docs.Create.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" });
                     SearchBox.convertDataUri(dataUrl, "icon" + summary[Id] + "_image").then((returnedFilename) => {
                         if (returnedFilename) {
                             let url = DocServer.prepend(returnedFilename);
-                            let imageSummary = Docs.ImageDocument(url, {
+                            let imageSummary = Docs.Create.ImageDocument(url, {
                                 x: bounds.left, y: bounds.top + 100 / zoomBasis,
                                 width: 150, height: bounds.height / bounds.width * 150, title: "-summary image-"
                             });
-- 
cgit v1.2.3-70-g09d2


From de0304b2966ebdede9d9db8c510e19020046115c Mon Sep 17 00:00:00 2001
From: Sam Wilkins <samuel_wilkins@brown.edu>
Date: Mon, 17 Jun 2019 13:38:15 -0400
Subject: peripheral renaming fixes

---
 src/client/documents/Documents.ts                              |  4 ++--
 src/client/util/History.ts                                     |  6 +++---
 src/client/util/SearchUtil.ts                                  |  4 ++--
 src/client/util/TooltipTextMenu.tsx                            |  8 ++++----
 src/client/views/MainView.tsx                                  | 10 +++++-----
 src/client/views/SearchBox.tsx                                 |  6 +++---
 src/client/views/collections/CollectionDockingView.tsx         | 10 +++++-----
 src/client/views/collections/CollectionSubView.tsx             |  8 ++++----
 src/client/views/collections/CollectionVideoView.tsx           |  2 +-
 src/client/views/collections/DockedFrameRenderer.tsx           |  2 +-
 .../collections/collectionFreeForm/CollectionFreeFormView.tsx  |  4 ++--
 .../views/collections/collectionFreeForm/MarqueeView.tsx       |  2 +-
 src/client/views/nodes/DocumentView.tsx                        |  2 +-
 src/client/views/nodes/FormattedTextBox.tsx                    |  6 +++---
 src/client/views/nodes/PDFBox.tsx                              |  2 +-
 src/client/views/nodes/VideoBox.tsx                            |  2 +-
 src/debug/Viewer.tsx                                           |  2 +-
 src/mobile/ImageUpload.tsx                                     |  4 ++--
 src/new_fields/Proxy.ts                                        |  2 +-
 src/server/authentication/models/current_user_utils.ts         |  6 +++---
 20 files changed, 46 insertions(+), 46 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index b10954636..758291b9b 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -98,7 +98,7 @@ export namespace Docs {
             // non-guid string ids for each document prototype
             let protoIds = [textProtoId, histoProtoId, collProtoId, imageProtoId, webProtoId, kvpProtoId, videoProtoId, audioProtoId, pdfProtoId, iconProtoId]
             // fetch the actual prototype documents from the server
-            let actualProtos = await DocServer.GetRefFields(protoIds);
+            let actualProtos = await DocServer.getRefFields(protoIds);
 
             // initialize prototype documents
             textProto = actualProtos[textProtoId] as Doc || CreateTextProto();
@@ -363,7 +363,7 @@ export namespace Docs {
                 CurrentUserUtils.AddNorthstarSchema(schema, schemaDoc);
                 const docs = schemaDocuments;
                 CurrentUserUtils.GetAllNorthstarColumnAttributes(schema).map(attr => {
-                    DocServer.GetRefField(attr.displayName! + ".alias").then(action((field: Opt<Field>) => {
+                    DocServer.getRefField(attr.displayName! + ".alias").then(action((field: Opt<Field>) => {
                         if (field instanceof Doc) {
                             docs.push(field);
                         } else {
diff --git a/src/client/util/History.ts b/src/client/util/History.ts
index 545ea8629..94bfcbe09 100644
--- a/src/client/util/History.ts
+++ b/src/client/util/History.ts
@@ -88,7 +88,7 @@ export namespace HistoryUtil {
     }
 
     export function createUrl(params: ParsedUrl): string {
-        let baseUrl = DocServer.prepend(`/${params.type}`);
+        let baseUrl = DocServer.Util.prepend(`/${params.type}`);
         switch (params.type) {
             case "doc":
                 const initializers = encodeURIComponent(JSON.stringify(params.initializers));
@@ -103,7 +103,7 @@ export namespace HistoryUtil {
     }
 
     export async function initDoc(id: string, initializer: DocInitializerList) {
-        const doc = await DocServer.GetRefField(id);
+        const doc = await DocServer.getRefField(id);
         if (!(doc instanceof Doc)) {
             return;
         }
@@ -111,7 +111,7 @@ export namespace HistoryUtil {
     }
 
     async function onDocUrl(url: DocUrl) {
-        const field = await DocServer.GetRefField(url.docId);
+        const field = await DocServer.getRefField(url.docId);
         await Promise.all(Object.keys(url.initializers).map(id => initDoc(id, url.initializers[id])));
         if (field instanceof Doc) {
             MainView.Instance.openWorkspace(field, true);
diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts
index 28ec8ca14..9dd9acbb7 100644
--- a/src/client/util/SearchUtil.ts
+++ b/src/client/util/SearchUtil.ts
@@ -7,13 +7,13 @@ export namespace SearchUtil {
     export function Search(query: string, returnDocs: true): Promise<Doc[]>;
     export function Search(query: string, returnDocs: false): Promise<string[]>;
     export async function Search(query: string, returnDocs: boolean) {
-        const ids = JSON.parse(await rp.get(DocServer.prepend("/search"), {
+        const ids = JSON.parse(await rp.get(DocServer.Util.prepend("/search"), {
             qs: { query }
         }));
         if (!returnDocs) {
             return ids;
         }
-        const docMap = await DocServer.GetRefFields(ids);
+        const docMap = await DocServer.getRefFields(ids);
         return ids.map((id: string) => docMap[id]).filter((doc: any) => doc instanceof Doc);
     }
 
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index fa2483db5..36219a99e 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -187,9 +187,9 @@ export class TooltipTextMenu {
                 let link = node && node.marks.find(m => m.type.name === "link");
                 if (link) {
                     let href: string = link.attrs.href;
-                    if (href.indexOf(DocServer.prepend("/doc/")) === 0) {
-                        let docid = href.replace(DocServer.prepend("/doc/"), "");
-                        DocServer.GetRefField(docid).then(action((f: Opt<Field>) => {
+                    if (href.indexOf(DocServer.Util.prepend("/doc/")) === 0) {
+                        let docid = href.replace(DocServer.Util.prepend("/doc/"), "");
+                        DocServer.getRefField(docid).then(action((f: Opt<Field>) => {
                             if (f instanceof Doc) {
                                 if (DocumentManager.Instance.getDocumentView(f)) {
                                     DocumentManager.Instance.getDocumentView(f)!.props.focus(f);
@@ -218,7 +218,7 @@ export class TooltipTextMenu {
                         handlers: {
                             dragComplete: action(() => {
                                 let m = dragData.droppedDocuments;
-                                this.makeLink(DocServer.prepend("/doc/" + m[0][Id]));
+                                this.makeLink(DocServer.Util.prepend("/doc/" + m[0][Id]));
                             }),
                         },
                         hideSource: false
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 984db0426..734961b56 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -76,11 +76,11 @@ export class MainView extends React.Component {
         // causes errors to be generated when modifying an observable outside of an action
         configure({ enforceActions: "observed" });
         if (window.location.search.includes("readonly")) {
-            DocServer.makeReadOnly();
+            DocServer.Util.makeReadOnly();
         }
         if (window.location.search.includes("safe")) {
             if (!window.location.search.includes("nro")) {
-                DocServer.makeReadOnly();
+                DocServer.Util.makeReadOnly();
             }
             CollectionBaseView.SetSafeMode(true);
         }
@@ -141,7 +141,7 @@ export class MainView extends React.Component {
                 this.createNewWorkspace();
             }
         } else {
-            DocServer.GetRefField(CurrentUserUtils.MainDocId).then(field =>
+            DocServer.getRefField(CurrentUserUtils.MainDocId).then(field =>
                 field instanceof Doc ? this.openWorkspace(field) :
                     this.createNewWorkspace(CurrentUserUtils.MainDocId));
         }
@@ -294,7 +294,7 @@ export class MainView extends React.Component {
         let logoutRef = React.createRef<HTMLDivElement>();
 
         return [
-            <button className="clear-db-button" key="clear-db" onClick={e => e.shiftKey && e.altKey && DocServer.DeleteDatabase()}>Clear Database</button>,
+            <button className="clear-db-button" key="clear-db" onClick={e => e.shiftKey && e.altKey && DocServer.Util.deleteDatabase()}>Clear Database</button>,
             <div id="toolbar" key="toolbar">
                 <div ref={notifsRef}>
                     <button className="toolbar-button round-button" title="Notifs"
@@ -312,7 +312,7 @@ export class MainView extends React.Component {
             </div >,
             this.isSearchVisible ? <div className="main-searchDiv" key="search" style={{ top: '34px', right: '1px', position: 'absolute' }} > <SearchBox /> </div> : null,
             <div className="main-buttonDiv" key="logout" style={{ bottom: '0px', right: '1px', position: 'absolute' }} ref={logoutRef}>
-                <button onClick={() => request.get(DocServer.prepend(RouteStore.logout), emptyFunction)}>Log Out</button></div>
+                <button onClick={() => request.get(DocServer.Util.prepend(RouteStore.logout), emptyFunction)}>Log Out</button></div>
         ];
 
     }
diff --git a/src/client/views/SearchBox.tsx b/src/client/views/SearchBox.tsx
index 7164d98a4..973715876 100644
--- a/src/client/views/SearchBox.tsx
+++ b/src/client/views/SearchBox.tsx
@@ -56,13 +56,13 @@ export class SearchBox extends React.Component {
 
     @action
     getResults = async (query: string) => {
-        let response = await rp.get(DocServer.prepend('/search'), {
+        let response = await rp.get(DocServer.Util.prepend('/search'), {
             qs: {
                 query
             }
         });
         let res: string[] = JSON.parse(response);
-        const fields = await DocServer.GetRefFields(res);
+        const fields = await DocServer.getRefFields(res);
         const docs: Doc[] = [];
         for (const id of res) {
             const field = fields[id];
@@ -74,7 +74,7 @@ export class SearchBox extends React.Component {
     }
     public static async convertDataUri(imageUri: string, returnedFilename: string) {
         try {
-            let posting = DocServer.prepend(RouteStore.dataUriToImage);
+            let posting = DocServer.Util.prepend(RouteStore.dataUriToImage);
             const returnedUri = await rp.post(posting, {
                 body: {
                     uri: imageUri,
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index e2bcb10ec..4f5837590 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -306,7 +306,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
             let y = e.clientY;
             let docid = (e.target as any).DashDocId;
             let tab = (e.target as any).parentElement as HTMLElement;
-            DocServer.GetRefField(docid).then(action(async (sourceDoc: Opt<Field>) =>
+            DocServer.getRefField(docid).then(action(async (sourceDoc: Opt<Field>) =>
                 (sourceDoc instanceof Doc) && DragLinksAsDocuments(tab, x, y, sourceDoc)));
         } else
             if ((className === "lm_title" || className === "lm_tab lm_active") && !e.shiftKey) {
@@ -320,7 +320,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
                 if (glTab && glTab.contentItem && glTab.contentItem.parent) {
                     glTab.contentItem.parent.setActiveContentItem(glTab.contentItem);
                 }
-                DocServer.GetRefField(docid).then(action((f: Opt<Field>) => {
+                DocServer.getRefField(docid).then(action((f: Opt<Field>) => {
                     if (f instanceof Doc) {
                         DragManager.StartDocumentDrag([tab], new DragManager.DocumentDragData([f]), x, y,
                             {
@@ -372,7 +372,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
             if (tab.contentItem.config.fixed) {
                 tab.contentItem.parent.config.fixed = true;
             }
-            DocServer.GetRefField(tab.contentItem.config.props.documentId).then(async doc => {
+            DocServer.getRefField(tab.contentItem.config.props.documentId).then(async doc => {
                 if (doc instanceof Doc) {
                     let counter: any = this.htmlToElement(`<span class="messageCounter">0</div>`);
                     tab.element.append(counter);
@@ -409,7 +409,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
                 if (tab.reactionDisposer) {
                     tab.reactionDisposer();
                 }
-                let doc = await DocServer.GetRefField(tab.contentItem.config.props.documentId);
+                let doc = await DocServer.getRefField(tab.contentItem.config.props.documentId);
                 if (doc instanceof Doc) {
                     let theDoc = doc;
                     CollectionDockingView.TopLevel._removedDocs.push(theDoc);
@@ -434,7 +434,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
                 //if (confirm('really close this?')) {
                 stack.remove();
                 stack.contentItems.map(async (contentItem: any) => {
-                    let doc = await DocServer.GetRefField(contentItem.config.props.documentId);
+                    let doc = await DocServer.getRefField(contentItem.config.props.documentId);
                     if (doc instanceof Doc) {
                         let theDoc = doc;
                         CollectionDockingView.TopLevel._removedDocs.push(theDoc);
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 440a2410b..36e276d13 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -133,7 +133,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
                 if (path.includes(window.location.hostname)) {
                     let s = path.split('/');
                     let id = s[s.length - 1];
-                    DocServer.GetRefField(id).then(field => {
+                    DocServer.getRefField(id).then(field => {
                         if (field instanceof Doc) {
                             let alias = Doc.MakeAlias(field);
                             alias.x = options.x || 0;
@@ -170,8 +170,8 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
             if (html && html.indexOf(document.location.origin)) { // prosemirror text containing link to dash document
                 let start = html.indexOf(window.location.origin);
                 let path = html.substr(start, html.length - start);
-                let docid = path.substr(0, path.indexOf("\">")).replace(DocServer.prepend("/doc/"), "").split("?")[0];
-                DocServer.GetRefField(docid).then(f => (f instanceof Doc) && this.props.addDocument(f, false));
+                let docid = path.substr(0, path.indexOf("\">")).replace(DocServer.Util.prepend("/doc/"), "").split("?")[0];
+                DocServer.getRefField(docid).then(f => (f instanceof Doc) && this.props.addDocument(f, false));
                 return;
             }
             if (html && html.indexOf("<img") !== 0 && !html.startsWith("<a")) {
@@ -194,7 +194,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
                 if (item.kind === "string" && item.type.indexOf("uri") !== -1) {
                     let str: string;
                     let prom = new Promise<string>(resolve => e.dataTransfer.items[i].getAsString(resolve))
-                        .then(action((s: string) => rp.head(DocServer.prepend(RouteStore.corsProxy + "/" + (str = s)))))
+                        .then(action((s: string) => rp.head(DocServer.Util.prepend(RouteStore.corsProxy + "/" + (str = s)))))
                         .then(result => {
                             let type = result["content-type"];
                             if (type) {
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index bd5cd5450..ccbac9915 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -97,7 +97,7 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
                 let filename = encodeURIComponent("snapshot" + this.props.Document.title + "_" + this.props.Document.curPage).replace(/\./g, "");
                 SearchBox.convertDataUri(dataUrl, filename).then((returnedFilename) => {
                     if (returnedFilename) {
-                        let url = DocServer.prepend(returnedFilename);
+                        let url = DocServer.Util.prepend(returnedFilename);
                         let imageSummary = Docs.Create.ImageDocument(url, {
                             x: NumCast(this.props.Document.x) + width, y: NumCast(this.props.Document.y),
                             width: 150, height: height / width * 150, title: "--snapshot" + NumCast(this.props.Document.curPage) + " image-"
diff --git a/src/client/views/collections/DockedFrameRenderer.tsx b/src/client/views/collections/DockedFrameRenderer.tsx
index 25d4b2a49..1e7c5661b 100644
--- a/src/client/views/collections/DockedFrameRenderer.tsx
+++ b/src/client/views/collections/DockedFrameRenderer.tsx
@@ -42,7 +42,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
     }
     constructor(props: any) {
         super(props);
-        DocServer.GetRefField(this.props.documentId).then(action((f: Opt<Field>) => this._document = f as Doc));
+        DocServer.getRefField(this.props.documentId).then(action((f: Opt<Field>) => this._document = f as Doc));
     }
 
     nativeWidth = () => NumCast(this._document!.nativeWidth, this._panelWidth);
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 9d19df540..cd613e6ab 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -235,8 +235,8 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             e.preventDefault();
             let start = html.indexOf(window.location.origin);
             let path = html.substr(start, html.length - start);
-            let docid = path.substr(0, path.indexOf("\">")).replace(DocServer.prepend("/doc/"), "").split("?")[0];
-            DocServer.GetRefField(docid).then(f => {
+            let docid = path.substr(0, path.indexOf("\">")).replace(DocServer.Util.prepend("/doc/"), "").split("?")[0];
+            DocServer.getRefField(docid).then(f => {
                 if (f instanceof Doc) {
                     f.x = pt[0];
                     f.y = pt[1];
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index cd386abfa..07a58ed64 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -306,7 +306,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                     let summary = Docs.Create.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" });
                     SearchBox.convertDataUri(dataUrl, "icon" + summary[Id] + "_image").then((returnedFilename) => {
                         if (returnedFilename) {
-                            let url = DocServer.prepend(returnedFilename);
+                            let url = DocServer.Util.prepend(returnedFilename);
                             let imageSummary = Docs.Create.ImageDocument(url, {
                                 x: bounds.left, y: bounds.top + 100 / zoomBasis,
                                 width: 150, height: bounds.height / bounds.width * 150, title: "-summary image-"
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 16e40000d..fdcb20e9a 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -422,7 +422,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             }, icon: "search"
         });
         cm.addItem({ description: "Center View", event: () => this.props.focus(this.props.Document), icon: "crosshairs" });
-        cm.addItem({ description: "Copy URL", event: () => Utils.CopyText(DocServer.prepend("/doc/" + this.props.Document[Id])), icon: "link" });
+        cm.addItem({ description: "Copy URL", event: () => Utils.CopyText(DocServer.Util.prepend("/doc/" + this.props.Document[Id])), icon: "link" });
         cm.addItem({ description: "Copy ID", event: () => Utils.CopyText(this.props.Document[Id]), icon: "fingerprint" });
         cm.addItem({ description: "Delete", event: this.deleteClicked, icon: "trash" });
         if (!this.topMost) {
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index d00a4b928..6a14a04f7 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -237,9 +237,9 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
                 href = parent.childNodes[0].href;
             }
             if (href) {
-                if (href.indexOf(DocServer.prepend("/doc/")) === 0) {
-                    let docid = href.replace(DocServer.prepend("/doc/"), "").split("?")[0];
-                    DocServer.GetRefField(docid).then(f => {
+                if (href.indexOf(DocServer.Util.prepend("/doc/")) === 0) {
+                    let docid = href.replace(DocServer.Util.prepend("/doc/"), "").split("?")[0];
+                    DocServer.getRefField(docid).then(f => {
                         (f instanceof Doc) && DocumentManager.Instance.jumpToDocument(f, ctrlKey, document => this.props.addDocTab(document, "inTab"))
                     });
                 }
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index aa29a7170..df9e49b64 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -257,7 +257,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
                 .then(action((dataUrl: string) => {
                     SearchBox.convertDataUri(dataUrl, "icon" + this.Document[Id] + "_" + this.curPage).then((returnedFilename) => {
                         if (returnedFilename) {
-                            let url = DocServer.prepend(returnedFilename);
+                            let url = DocServer.Util.prepend(returnedFilename);
                             this.props.Document.thumbnail = new ImageField(new URL(url));
                         }
                         runInAction(() => this._renderAsSvg = true);
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 35ecf12f6..9ab607e91 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -97,7 +97,7 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
             };
             try {
                 let responseSchema: any = {};
-                const videoInfoResponse = await rp.get(DocServer.prepend(RouteStore.corsProxy + "/" + `https://www.youtube.com/watch?v=${videoId}`), videoInfoRequestConfig);
+                const videoInfoResponse = await rp.get(DocServer.Util.prepend(RouteStore.corsProxy + "/" + `https://www.youtube.com/watch?v=${videoId}`), videoInfoRequestConfig);
                 const dataHtml = videoInfoResponse;
                 const start = dataHtml.indexOf('ytplayer.config = ') + 18;
                 const end = dataHtml.indexOf(';ytplayer.load');
diff --git a/src/debug/Viewer.tsx b/src/debug/Viewer.tsx
index b22300d0b..753149756 100644
--- a/src/debug/Viewer.tsx
+++ b/src/debug/Viewer.tsx
@@ -146,7 +146,7 @@ class Viewer extends React.Component {
     @action
     onKeyPress = (e: React.KeyboardEvent<HTMLDivElement>) => {
         if (e.key === "Enter") {
-            DocServer.GetRefField(this.idToAdd).then(action((field: any) => {
+            DocServer.getRefField(this.idToAdd).then(action((field: any) => {
                 if (field !== undefined) {
                     this.fields.push(field);
                 }
diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx
index a8f94b746..df597e0a9 100644
--- a/src/mobile/ImageUpload.tsx
+++ b/src/mobile/ImageUpload.tsx
@@ -57,11 +57,11 @@ class Uploader extends React.Component {
 
                         this.status = "getting user document";
 
-                        const res = await rp.get(DocServer.prepend(RouteStore.getUserDocumentId));
+                        const res = await rp.get(DocServer.Util.prepend(RouteStore.getUserDocumentId));
                         if (!res) {
                             throw new Error("No user id returned");
                         }
-                        const field = await DocServer.GetRefField(res);
+                        const field = await DocServer.getRefField(res);
                         let pending: Opt<Doc>;
                         if (field instanceof Doc) {
                             pending = await Cast(field.optionalRightCollection, Doc);
diff --git a/src/new_fields/Proxy.ts b/src/new_fields/Proxy.ts
index 130ec066e..230e4ab8b 100644
--- a/src/new_fields/Proxy.ts
+++ b/src/new_fields/Proxy.ts
@@ -57,7 +57,7 @@ export class ProxyField<T extends RefField> extends ObjectField {
             return undefined;
         }
         if (!this.promise) {
-            this.promise = DocServer.GetRefField(this.fieldId).then(action((field: any) => {
+            this.promise = DocServer.getRefField(this.fieldId).then(action((field: any) => {
                 this.promise = undefined;
                 this.cache = field;
                 if (field === undefined) this.failed = true;
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index 169be3b99..95c20d2db 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -40,7 +40,7 @@ export class CurrentUserUtils {
     }
 
     public static async loadCurrentUser(): Promise<any> {
-        let userPromise = rp.get(DocServer.prepend(RouteStore.getCurrUser)).then(response => {
+        let userPromise = rp.get(DocServer.Util.prepend(RouteStore.getCurrUser)).then(response => {
             if (response) {
                 let obj = JSON.parse(response);
                 CurrentUserUtils.curr_id = obj.id as string;
@@ -49,9 +49,9 @@ export class CurrentUserUtils {
                 throw new Error("There should be a user! Why does Dash think there isn't one?");
             }
         });
-        let userDocPromise = await rp.get(DocServer.prepend(RouteStore.getUserDocumentId)).then(id => {
+        let userDocPromise = await rp.get(DocServer.Util.prepend(RouteStore.getUserDocumentId)).then(id => {
             if (id) {
-                return DocServer.GetRefField(id).then(field =>
+                return DocServer.getRefField(id).then(field =>
                     runInAction(() => this.user_document = field instanceof Doc ? field : this.createUserDocument(id)));
             } else {
                 throw new Error("There should be a user id! Why does Dash think there isn't one?");
-- 
cgit v1.2.3-70-g09d2


From b99e6418eb2c39f91befb002477267699d545683 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 3 Jul 2019 23:54:53 -0400
Subject: fixed minor things with marquees

---
 .../views/collections/CollectionTreeView.tsx       | 66 ++++++++++++++--------
 .../collectionFreeForm/MarqueeView.scss            |  2 +-
 .../collections/collectionFreeForm/MarqueeView.tsx |  4 +-
 src/client/views/nodes/DocumentView.tsx            |  4 +-
 4 files changed, 47 insertions(+), 29 deletions(-)

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

diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 0cc31f031..622ba37d1 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -1,7 +1,7 @@
 import { library } from '@fortawesome/fontawesome-svg-core';
-import { faAngleRight, faBell, faCaretDown, faCaretRight, faCaretSquareDown, faCaretSquareRight, faTrashAlt } from '@fortawesome/free-solid-svg-icons';
+import { faAngleRight, faCamera, faExpand, faBell, faCaretDown, faCaretRight, faCaretSquareDown, faCaretSquareRight, faTrashAlt } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, observable } from "mobx";
+import { action, computed, observable, trace } from "mobx";
 import { observer } from "mobx-react";
 import { Doc, DocListCast, HeightSym, WidthSym, Opt } from '../../../new_fields/Doc';
 import { Id } from '../../../new_fields/FieldSymbols';
@@ -9,7 +9,7 @@ import { List } from '../../../new_fields/List';
 import { Document, listSpec } from '../../../new_fields/Schema';
 import { BoolCast, Cast, NumCast, StrCast } from '../../../new_fields/Types';
 import { emptyFunction, Utils } from '../../../Utils';
-import { Docs, DocUtils } from '../../documents/Documents';
+import { Docs, DocUtils, DocTypes } from '../../documents/Documents';
 import { DocumentManager } from '../../util/DocumentManager';
 import { DragManager, dropActionType, SetupDrag } from "../../util/DragManager";
 import { SelectionManager } from '../../util/SelectionManager';
@@ -51,6 +51,8 @@ export interface TreeViewProps {
 library.add(faTrashAlt);
 library.add(faAngleRight);
 library.add(faBell);
+library.add(faCamera);
+library.add(faExpand);
 library.add(faCaretDown);
 library.add(faCaretRight);
 library.add(faCaretSquareDown);
@@ -66,6 +68,7 @@ class TreeView extends React.Component<TreeViewProps> {
     private _dref = React.createRef<HTMLDivElement>();
     @observable __chosenKey: string = "";
     @computed get _chosenKey() { return this.__chosenKey ? this.__chosenKey : this.fieldKey; }
+    @computed get MAX_EMBED_HEIGHT() { return NumCast(this.props.document.maxEmbedHeight, 300); }
     @observable _collapsed: boolean = true;
 
     @computed get fieldKey() {
@@ -153,20 +156,12 @@ class TreeView extends React.Component<TreeViewProps> {
         </div>;
     }
 
-    titleClicked = (e: React.MouseEvent) => {
-        if (this._collapsed) return false;
-        else {
-            this.props.document.embed = !BoolCast(this.props.document.embed);
-            return true;
-        }
-    }
     static loadId = "";
     editableView = (key: string, style?: string) => (<EditableView
         oneLine={true}
         display={"inline"}
         editing={this.resolvedDataDoc[Id] === TreeView.loadId}
         contents={StrCast(this.props.document[key])}
-        onClick={this.titleClicked}
         height={36}
         fontStyle={style}
         GetValue={() => StrCast(this.props.document[key])}
@@ -236,18 +231,19 @@ class TreeView extends React.Component<TreeViewProps> {
 
     onWorkspaceContextMenu = (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: "Open Fields", event: () => { let kvp = Docs.KVPDocument(this.props.document, { width: 300, height: 300 }); this.props.addDocTab(kvp, this.props.dataDoc ? this.props.dataDoc : kvp, "onRight"); }, icon: "layer-group" });
+            ContextMenu.Instance.addItem({ description: (BoolCast(this.props.document.embed) ? "Collapse" : "Expand") + " inline", event: () => this.props.document.embed = !BoolCast(this.props.document.embed), icon: "expand" });
             if (NumCast(this.props.document.viewType) !== CollectionViewType.Docking) {
                 ContextMenu.Instance.addItem({ description: "Open Tab", event: () => this.props.addDocTab(this.props.document, this.resolvedDataDoc, "inTab"), icon: "folder" });
                 ContextMenu.Instance.addItem({ description: "Open Right", event: () => this.props.addDocTab(this.props.document, this.resolvedDataDoc, "onRight"), icon: "caret-square-right" });
                 if (DocumentManager.Instance.getDocumentViews(this.resolvedDataDoc).length) {
-                    ContextMenu.Instance.addItem({ description: "Focus", event: () => DocumentManager.Instance.getDocumentViews(this.resolvedDataDoc).map(view => view.props.focus(this.props.document, true)) });
+                    ContextMenu.Instance.addItem({ description: "Focus", event: () => DocumentManager.Instance.getDocumentViews(this.resolvedDataDoc).map(view => view.props.focus(this.props.document, true)), icon: "camera" });
                 }
-                ContextMenu.Instance.addItem({ description: "Delete Item", event: undoBatch(() => this.props.deleteDoc(this.props.document)) });
+                ContextMenu.Instance.addItem({ description: "Delete Item", event: undoBatch(() => this.props.deleteDoc(this.props.document)), icon: "trash-alt" });
             } else {
-                ContextMenu.Instance.addItem({ description: "Open as Workspace", event: undoBatch(() => MainView.Instance.openWorkspace(this.resolvedDataDoc)) });
-                ContextMenu.Instance.addItem({ description: "Delete Workspace", event: undoBatch(() => this.props.deleteDoc(this.props.document)) });
+                ContextMenu.Instance.addItem({ description: "Open as Workspace", event: undoBatch(() => MainView.Instance.openWorkspace(this.resolvedDataDoc)), icon: "caret-square-right" });
+                ContextMenu.Instance.addItem({ description: "Delete Workspace", event: undoBatch(() => this.props.deleteDoc(this.props.document)), icon: "trash-alt" });
             }
+            ContextMenu.Instance.addItem({ description: "Open Fields", event: () => { let kvp = Docs.KVPDocument(this.props.document, { width: 300, height: 300 }); this.props.addDocTab(kvp, this.props.dataDoc ? this.props.dataDoc : kvp, "onRight"); }, icon: "layer-group" });
             ContextMenu.Instance.displayMenu(e.pageX > 156 ? e.pageX - 156 : 0, e.pageY - 15);
             e.stopPropagation();
             e.preventDefault();
@@ -268,6 +264,8 @@ class TreeView extends React.Component<TreeViewProps> {
             e.stopPropagation();
         }
         if (de.data instanceof DragManager.DocumentDragData) {
+            e.stopPropagation();
+            if (de.data.draggedDocuments[0] === this.props.document) return true;
             let addDoc = (doc: Doc) => this.props.addDocument(doc, this.resolvedDataDoc, before);
             if (inside) {
                 let docList = Cast(this.resolvedDataDoc.data, listSpec(Doc));
@@ -275,7 +273,6 @@ class TreeView extends React.Component<TreeViewProps> {
                     addDoc = (doc: Doc) => { docList && docList.push(doc); return true; };
                 }
             }
-            e.stopPropagation();
             let movedDocs = (de.data.options === this.props.treeViewId ? de.data.draggedDocuments : de.data.droppedDocuments);
             return (de.data.dropAction || de.data.userDropAction) ?
                 de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d, this.resolvedDataDoc, before) || added, false)
@@ -314,18 +311,37 @@ class TreeView extends React.Component<TreeViewProps> {
         return ele;
     }
 
-    fitToBox = () => {
+    @computed get docBounds() {
+        if (StrCast(this.props.document.type).indexOf(DocTypes.COL) === -1) return undefined;
         let layoutDoc = Doc.expandTemplateLayout(this.props.document, this.props.dataDoc);
-        let bounds = Doc.ComputeContentBounds(layoutDoc);
-        return [(bounds.x + bounds.r) / 2, (bounds.y + bounds.b) / 2, Math.min(this.props.panelHeight() / (bounds.b - bounds.y), this.props.panelWidth() / (bounds.r - bounds.x))];
+        return Doc.ComputeContentBounds(layoutDoc);
+    }
+    docWidth = () => {
+        let aspect = NumCast(this.props.document.nativeHeight) / NumCast(this.props.document.nativeWidth);
+        if (aspect) return Math.min(this.props.document[WidthSym](), Math.min(this.MAX_EMBED_HEIGHT / aspect, this.props.panelWidth() - 5));
+        return NumCast(this.props.document.nativeWidth) ? Math.min(this.props.document[WidthSym](), this.props.panelWidth() - 5) : this.props.panelWidth() - 5;
     }
+    docHeight = () => {
+        let bounds = this.docBounds;
+        return Math.min(this.MAX_EMBED_HEIGHT, (() => {
+            let aspect = NumCast(this.props.document.nativeHeight) / NumCast(this.props.document.nativeWidth);
+            if (aspect) return this.docWidth() * aspect;
+            if (bounds) return this.docWidth() * (bounds.b - bounds.y) / (bounds.r - bounds.x);
+            return NumCast(this.props.document.height) ? NumCast(this.props.document.height) : 50;
+        })());
+    }
+    fitToBox = () => {
+        let bounds = this.docBounds!;
+        return [(bounds.x + bounds.r) / 2, (bounds.y + bounds.b) / 2, Math.min(this.docHeight() / (bounds.b - bounds.y), this.docWidth() / (bounds.r - bounds.x))];
+    }
+
     render() {
         let contentElement: (JSX.Element | null) = null;
         let docList = Cast(this.resolvedDataDoc[this._chosenKey], listSpec(Doc));
         let remDoc = (doc: Doc) => this.remove(doc, this._chosenKey);
         let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.resolvedDataDoc, this._chosenKey, doc, addBefore, before);
         let doc = Cast(this.resolvedDataDoc[this._chosenKey], Doc);
-        let docWidth = () => NumCast(this.props.document.nativeWidth) ? Math.min(this.props.document[WidthSym](), this.props.panelWidth() - 5) : this.props.panelWidth() - 5;
+
         if (!this._collapsed) {
             if (!this.props.document.embed) {
                 contentElement = <ul key={this._chosenKey + "more"}>
@@ -335,14 +351,14 @@ class TreeView extends React.Component<TreeViewProps> {
                 </ul >;
             } else {
                 let layoutDoc = Doc.expandTemplateLayout(this.props.document, this.props.dataDoc);
-                contentElement = <div ref={this._dref} style={{ display: "inline-block", height: layoutDoc[HeightSym]() }} key={this.props.document[Id]}>
+                contentElement = <div ref={this._dref} style={{ display: "inline-block", height: this.docHeight() }} key={this.props.document[Id]}>
                     <CollectionSchemaPreview
                         Document={layoutDoc}
                         DataDocument={this.resolvedDataDoc}
                         renderDepth={this.props.renderDepth}
-                        fitToBox={this.fitToBox}
-                        width={docWidth}
-                        height={layoutDoc[HeightSym]}
+                        fitToBox={this.docBounds && !NumCast(this.props.document.nativeWidth) ? this.fitToBox : undefined}
+                        width={this.docWidth}
+                        height={this.docHeight}
                         getTransform={this.docTransform}
                         CollectionView={undefined}
                         addDocument={emptyFunction as any}
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.scss b/src/client/views/collections/collectionFreeForm/MarqueeView.scss
index 6e8ec8662..9fc2e44fb 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.scss
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.scss
@@ -21,6 +21,6 @@
         white-space:nowrap;
     }
     .marquee-legend::after {
-        content: "Press: c (collection), s (summary), r (replace) or Delete"
+        content: "Press: c (collection), s (summary), or Delete"
     }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 2a78cda2f..31c0fe499 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -248,7 +248,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             this.cleanupInteractions(false);
             e.stopPropagation();
         }
-        if (e.key === "c" || e.key === "s" || e.key === "S" || e.key === "e" || e.key === "p") {
+        if (e.key === "c" || e.key === "s" || e.key === "S" || e.key === "e") {
             this._commandExecuted = true;
             e.stopPropagation();
             e.preventDefault();
@@ -277,7 +277,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                 width: bounds.width,
                 height: bounds.height,
                 ink: inkData ? new InkField(this.marqueeInkSelect(inkData)) : undefined,
-                title: e.key === "s" || e.key === "S" ? "-summary-" : e.key === "p" ? "-summary-" : "a nested collection",
+                title: e.key === "s" || e.key === "S" ? "-summary-" : "a nested collection",
             });
             this.marqueeInkDelete(inkData);
 
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 8b75d0d25..69dc31fec 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -589,8 +589,10 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 style={{
                     outlineColor: "maroon",
                     outlineStyle: "dashed",
-                    outlineWidth: BoolCast(this.props.Document.libraryBrush) || BoolCast(this.props.Document.protoBrush) ?
+                    outlineWidth: (BoolCast(this.props.Document.libraryBrush) || BoolCast(this.props.Document.protoBrush)) && !NumCast(this.props.Document.borderRounding) ?
                         `${this.props.ScreenToLocalTransform().Scale}px` : "0px",
+                    border: (BoolCast(this.props.Document.libraryBrush) || BoolCast(this.props.Document.protoBrush)) && NumCast(this.props.Document.borderRounding) ?
+                        `dashed maroon ${this.props.ScreenToLocalTransform().Scale}px` : undefined,
                     borderRadius: "inherit",
                     background: backgroundColor,
                     width: nativeWidth,
-- 
cgit v1.2.3-70-g09d2


From d479f5e6bcdb7d1a0edb2f8cf366549abe2a910b Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Thu, 4 Jul 2019 14:08:00 -0400
Subject: added text font color setting.   adding interactive border radius.
 moved main toolbar.

---
 src/client/documents/Documents.ts                  |  4 +--
 src/client/util/DragManager.ts                     |  1 +
 src/client/util/RichTextSchema.tsx                 | 11 ++++++++
 src/client/util/TooltipTextMenu.tsx                |  3 +-
 src/client/views/DocumentDecorations.scss          | 22 +++++++++++++++
 src/client/views/DocumentDecorations.tsx           | 32 ++++++++++++++++++++++
 src/client/views/InkingControl.tsx                 |  3 ++
 src/client/views/Main.scss                         |  2 +-
 src/client/views/MainOverlayTextBox.tsx            |  5 ++++
 src/client/views/MainView.tsx                      |  2 +-
 .../collections/collectionFreeForm/MarqueeView.tsx | 16 ++++-------
 .../views/nodes/CollectionFreeFormDocumentView.tsx | 15 ++++++----
 src/client/views/nodes/DocumentView.tsx            |  4 +--
 src/client/views/nodes/FormattedTextBox.tsx        | 11 +++++++-
 14 files changed, 106 insertions(+), 25 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 7a976e7d7..2bddf053a 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -77,7 +77,7 @@ export interface DocumentOptions {
     backgroundLayout?: string;
     curPage?: number;
     documentText?: string;
-    borderRounding?: number;
+    borderRounding?: string;
     schemaColumns?: List<string>;
     dockingConfig?: string;
     dbDoc?: Doc;
@@ -93,7 +93,7 @@ export namespace DocUtils {
         if (target === CurrentUserUtils.UserDocument) return;
 
         UndoManager.RunInBatch(() => {
-            let linkDoc = Docs.TextDocument({ width: 100, height: 30, borderRounding: -1 });
+            let linkDoc = Docs.TextDocument({ width: 100, height: 30, borderRounding: "100%" });
             linkDoc.type = DocTypes.LINK;
             let linkDocProto = Doc.GetProto(linkDoc);
 
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 7dc48fb78..d4b1bc8f4 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -315,6 +315,7 @@ export namespace DragManager {
             scaleYs.push(scaleY);
             let dragElement = ele.cloneNode(true) as HTMLElement;
             dragElement.style.opacity = "0.7";
+            dragElement.style.borderRadius = getComputedStyle(ele).borderRadius;
             dragElement.style.position = "absolute";
             dragElement.style.margin = "0";
             dragElement.style.top = "0";
diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx
index 63c879d67..2a57180d3 100644
--- a/src/client/util/RichTextSchema.tsx
+++ b/src/client/util/RichTextSchema.tsx
@@ -348,6 +348,17 @@ export const marks: { [index: string]: MarkSpec } = {
         }]
     },
 
+    pFontColor: {
+        attrs: {
+            color: { default: "yellow" }
+        },
+        parseDOM: [{ style: 'background: #d9dbdd' }],
+        toDOM: (node) => {
+            return ['span', {
+                style: `color: ${node.attrs.color}`
+            }];
+        }
+    },
 
     /** FONT SIZES */
     pFontSize: {
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 9f8d0b2f6..e3e26d1f4 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -111,7 +111,8 @@ export class TooltipTextMenu {
         this.fontSizeToNum.set(schema.marks.p32, 32);
         this.fontSizeToNum.set(schema.marks.p48, 48);
         this.fontSizeToNum.set(schema.marks.p72, 72);
-        //this.fontSizeToNum.set(schema.marks.pFontSize,schema.marks.pFontSize.)
+        this.fontSizeToNum.set(schema.marks.pFontSize, 10);
+        this.fontSizeToNum.set(schema.marks.pFontSize, 10);
         this.fontSizes = Array.from(this.fontSizeToNum.keys());
 
         //list types
diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index ba9f32d7d..2d430512b 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -26,6 +26,14 @@ $linkGap : 3px;
         opacity: 0.8;
     }
 
+    .documentDecorations-radius {
+        pointer-events: auto;
+        background: black;
+        opacity: 0.8;
+        transform: translate(10px, 10px);
+        grid-row: 4;
+    }
+
     #documentDecorations-topLeftResizer,
     #documentDecorations-leftResizer,
     #documentDecorations-bottomLeftResizer {
@@ -44,11 +52,25 @@ $linkGap : 3px;
         grid-column-start: 5;
         grid-column-end: 7;
     }
+    
+    #documentDecorations-borderRadius{
+        grid-column-start: 5;
+        grid-column-end: 7;
+        border-radius: 100%;
+        .borderRadiusTooltip{
+            width:10px;
+            height:10px;
+            position:absolute;
+        }
+    }
 
     #documentDecorations-topLeftResizer,
     #documentDecorations-bottomRightResizer {
         cursor: nwse-resize;
     }
+    #documentDecorations-bottomRightResizer {
+        grid-row:4;
+    }
 
     #documentDecorations-topRightResizer,
     #documentDecorations-bottomLeftResizer {
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 3df520428..c7990647a 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -341,6 +341,37 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         iconDoc.y = where[1] + NumCast(selView.props.Document.y);
     }
 
+    _radiusDown = [0, 0];
+    @action
+    onRadiusDown = (e: React.PointerEvent): void => {
+        e.stopPropagation();
+        if (e.button === 0) {
+            this._radiusDown = [e.clientX, e.clientY];
+            this._isPointerDown = true;
+            this._resizeUndo = UndoManager.StartBatch("DocDecs set radius");
+            document.removeEventListener("pointermove", this.onRadiusMove);
+            document.removeEventListener("pointerup", this.onRadiusUp);
+            document.addEventListener("pointermove", this.onRadiusMove);
+            document.addEventListener("pointerup", this.onRadiusUp);
+        }
+    }
+
+    onRadiusMove = (e: PointerEvent): void => {
+        let dist = Math.sqrt((e.clientX - this._radiusDown[0]) * (e.clientX - this._radiusDown[0]) + (e.clientY - this._radiusDown[1]) * (e.clientY - this._radiusDown[1]));
+        SelectionManager.SelectedDocuments().map(dv => Doc.GetProto(dv.props.Document).borderRounding = `${Math.min(100, dist)}%`);
+        e.stopPropagation();
+        e.preventDefault();
+    }
+
+    onRadiusUp = (e: PointerEvent): void => {
+        e.stopPropagation();
+        e.preventDefault();
+        this._isPointerDown = false;
+        this._resizeUndo && this._resizeUndo.end();
+        document.removeEventListener("pointermove", this.onRadiusMove);
+        document.removeEventListener("pointerup", this.onRadiusUp);
+    }
+
     @action
     onPointerDown = (e: React.PointerEvent): void => {
         e.stopPropagation();
@@ -705,6 +736,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 <div id="documentDecorations-bottomLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                 <div id="documentDecorations-bottomResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                 <div id="documentDecorations-bottomRightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
+                <div id="documentDecorations-borderRadius" className="documentDecorations-radius" onPointerDown={this.onRadiusDown} onContextMenu={(e) => e.preventDefault()}><span className="borderRadiusTooltip" title="Drag Corner Radius"></span></div>
                 <div className="link-button-container">
                     <div className="linkButtonWrapper">
                         <div title="View Links" className="linkFlyout" ref={this._linkButton}> {linkButton}  </div>
diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx
index 0461d7299..c7f7bdb66 100644
--- a/src/client/views/InkingControl.tsx
+++ b/src/client/views/InkingControl.tsx
@@ -10,6 +10,8 @@ import { InkTool } from "../../new_fields/InkField";
 import { Doc } from "../../new_fields/Doc";
 import { undoBatch, UndoManager } from "../util/UndoManager";
 import { StrCast } from "../../new_fields/Types";
+import { FormattedTextBox } from "./nodes/FormattedTextBox";
+import { MainOverlayTextBox } from "./MainOverlayTextBox";
 
 library.add(faPen, faHighlighter, faEraser, faBan);
 
@@ -42,6 +44,7 @@ export class InkingControl extends React.Component {
     switchColor = action((color: ColorResult): void => {
         this._selectedColor = color.hex + (color.rgb.a !== undefined ? this.decimalToHexString(Math.round(color.rgb.a * 255)) : "ff");
         if (InkingControl.Instance.selectedTool === InkTool.None) {
+            if (MainOverlayTextBox.Instance.SetColor(color.hex)) return;
             let selected = SelectionManager.SelectedDocuments();
             let oldColors = selected.map(view => {
                 let targetDoc = view.props.Document.isTemplate ? view.props.Document : Doc.GetProto(view.props.Document);
diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss
index 44c1cb9fc..b85a8040a 100644
--- a/src/client/views/Main.scss
+++ b/src/client/views/Main.scss
@@ -144,7 +144,7 @@ button:hover {
 #add-nodes-menu {
     position: absolute;
     bottom: 22px;
-    left: 24px;
+    left: 250px;
 
     > label {
         background: $dark-color;
diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx
index 7d15702a2..d8aaea259 100644
--- a/src/client/views/MainOverlayTextBox.tsx
+++ b/src/client/views/MainOverlayTextBox.tsx
@@ -36,6 +36,11 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
         this._outerdiv && this._tooltip && !this._outerdiv.contains(this._tooltip) && this._outerdiv.appendChild(this._tooltip);
     }
 
+    public SetColor(color: string) {
+        return this._textBox && this._textBox.setFontColor(color);
+    }
+
+
     constructor(props: MainOverlayTextBoxProps) {
         super(props);
         this._textProxyDiv = React.createRef();
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 1542fedef..61ccf4c1d 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -354,7 +354,7 @@ export class MainView extends React.Component {
             [React.createRef<HTMLDivElement>(), "tree", "Add Tree", addTreeNode],
         ];
 
-        return < div id="add-nodes-menu" >
+        return < div id="add-nodes-menu" style={{ left: this.flyoutWidth + 5 }} >
             <input type="checkbox" id="add-menu-toggle" ref={this.addMenuToggle} />
             <label htmlFor="add-menu-toggle" title="Add Node"><p>+</p></label>
 
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 31c0fe499..4850c6218 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -44,14 +44,12 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
     _commandExecuted = false;
 
     @action
-    cleanupInteractions = (all: boolean = false, rem_keydown: boolean = true) => {
+    cleanupInteractions = (all: boolean = false) => {
         if (all) {
             document.removeEventListener("pointerup", this.onPointerUp, true);
             document.removeEventListener("pointermove", this.onPointerMove, true);
         }
-        if (rem_keydown) {
-            document.removeEventListener("keydown", this.marqueeCommand, true);
-        }
+        document.removeEventListener("keydown", this.marqueeCommand, true);
         this._visible = false;
     }
 
@@ -191,12 +189,9 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                 SelectionManager.DeselectAll(mselect.length ? undefined : this.props.container.props.Document);
             }
             this.props.selectDocuments(mselect.length ? mselect : [this.props.container.props.Document]);
-            mselect.length ? this.cleanupInteractions(true, false) : this.cleanupInteractions(true);
-        }
-        else {
-            //console.log("invisible");
-            this.cleanupInteractions(true);
         }
+        //console.log("invisible");
+        this.cleanupInteractions(true);
 
         if (e.altKey) {
             e.preventDefault();
@@ -266,13 +261,12 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             }
             let ink = Cast(this.props.container.props.Document.ink, InkField);
             let inkData = ink ? ink.inkData : undefined;
-            let zoomBasis = NumCast(this.props.container.props.Document.scale, 1);
             let newCollection = Docs.FreeformDocument(selected, {
                 x: bounds.left,
                 y: bounds.top,
                 panX: 0,
                 panY: 0,
-                borderRounding: e.key === "e" ? -1 : undefined,
+                borderRounding: e.key === "e" ? "100%" : undefined,
                 backgroundColor: this.props.container.isAnnotationOverlay ? undefined : "white",
                 width: bounds.width,
                 height: bounds.height,
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 30cf74f3e..1c00687ed 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -70,11 +70,14 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
     }
 
     borderRounding = () => {
-        let br = NumCast(this.props.Document.borderRounding);
-        return br >= 0 ? br :
-            NumCast(this.props.Document.nativeWidth) === 0 ?
-                Math.min(this.props.PanelWidth(), this.props.PanelHeight())
-                : Math.min(this.Document.nativeWidth || 0, this.Document.nativeHeight || 0);
+        let br = StrCast(this.props.Document.borderRounding);
+        if (br.endsWith("%")) {
+            let percent = Number(br.substr(0, br.length - 1)) / 100;
+            let nativeDim = Math.min(NumCast(this.props.Document.nativeWidth), NumCast(this.props.Document.nativeHeight));
+            let minDim = percent * (nativeDim ? nativeDim : Math.min(this.props.PanelWidth(), this.props.PanelHeight()));
+            return minDim;
+        }
+        return undefined;
     }
 
     render() {
@@ -84,7 +87,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
                     transformOrigin: "left top",
                     position: "absolute",
                     backgroundColor: "transparent",
-                    borderRadius: `${this.borderRounding()}px`,
+                    borderRadius: this.borderRounding(),
                     transform: this.transform,
                     transition: StrCast(this.props.Document.transition),
                     width: this.width,
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index f751a45fe..a84cac37f 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -589,9 +589,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 style={{
                     outlineColor: "maroon",
                     outlineStyle: "dashed",
-                    outlineWidth: BoolCast(this.props.Document.libraryBrush) && !NumCast(this.props.Document.borderRounding) ?
+                    outlineWidth: BoolCast(this.props.Document.libraryBrush) && !StrCast(this.props.Document.borderRounding) ?
                         `${this.props.ScreenToLocalTransform().Scale}px` : "0px",
-                    border: BoolCast(this.props.Document.libraryBrush) && NumCast(this.props.Document.borderRounding) ?
+                    border: BoolCast(this.props.Document.libraryBrush) && StrCast(this.props.Document.borderRounding) ?
                         `dashed maroon ${this.props.ScreenToLocalTransform().Scale}px` : undefined,
                     borderRadius: "inherit",
                     background: backgroundColor,
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 1eeb04755..bf6f4c764 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -97,6 +97,15 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
         return "";
     }
 
+    @undoBatch
+    public setFontColor(color: string) {
+        if (this._editorView!.state.selection.from === this._editorView!.state.selection.to) return false;
+        let colorMark = this._editorView!.state.schema.mark(this._editorView!.state.schema.marks.pFontColor, { color: color });
+        this._editorView!.dispatch(this._editorView!.state.tr.addMark(this._editorView!.state.selection.from,
+            this._editorView!.state.selection.to, colorMark));
+        return true;
+    }
+
     constructor(props: FieldViewProps) {
         super(props);
         if (this.props.outer_div) {
@@ -418,7 +427,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
     }
     render() {
         let style = this.props.isOverlay ? "scroll" : "hidden";
-        let rounded = NumCast(this.props.Document.borderRounding) < 0 ? "-rounded" : "";
+        let rounded = StrCast(this.props.Document.borderRounding) === "100%" ? "-rounded" : "";
         let interactive = InkingControl.Instance.selectedTool ? "" : "interactive";
         return (
             <div className={`formattedTextBox-cont-${style}`} ref={this._ref}
-- 
cgit v1.2.3-70-g09d2


From 5348a12503ccfd8d0f67085b189f8ab0037a1edd Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Mon, 8 Jul 2019 13:54:25 -0400
Subject: added a MakePortal menu item for docs.  made lock pos affect scroll
 and zoom of free form views.

---
 .../collectionFreeForm/CollectionFreeFormView.tsx          |  3 ++-
 .../views/collections/collectionFreeForm/MarqueeView.tsx   |  3 +--
 src/client/views/nodes/DocumentView.tsx                    | 14 +++++++++++++-
 3 files changed, 16 insertions(+), 4 deletions(-)

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

diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 7a22b7ec3..cb55a0d5d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -198,6 +198,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
 
     @action
     onPointerWheel = (e: React.WheelEvent): void => {
+        if (BoolCast(this.props.Document.lockedPosition)) return;
         // if (!this.props.active()) {
         //     return;
         // }
@@ -244,7 +245,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
 
     @action
     setPan(panX: number, panY: number) {
-
+        if (BoolCast(this.props.Document.lockedPosition)) return;
         this.props.Document.panTransformType = "None";
         var scale = this.getLocalTransform().inverse().Scale;
         const newPanX = Math.min((1 - 1 / scale) * this.nativeWidth, Math.max(0, panX));
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 4850c6218..c83e1e3f5 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -243,7 +243,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             this.cleanupInteractions(false);
             e.stopPropagation();
         }
-        if (e.key === "c" || e.key === "s" || e.key === "S" || e.key === "e") {
+        if (e.key === "c" || e.key === "s" || e.key === "S") {
             this._commandExecuted = true;
             e.stopPropagation();
             e.preventDefault();
@@ -266,7 +266,6 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                 y: bounds.top,
                 panX: 0,
                 panY: 0,
-                borderRounding: e.key === "e" ? "100%" : undefined,
                 backgroundColor: this.props.container.isAnnotationOverlay ? undefined : "white",
                 width: bounds.width,
                 height: bounds.height,
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index ef397a824..80520c685 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -24,7 +24,7 @@ import { CollectionView } from "../collections/CollectionView";
 import { ContextMenu } from "../ContextMenu";
 import { DocComponent } from "../DocComponent";
 import { PresentationView } from "../presentationview/PresentationView";
-import { Template } from "./../Templates";
+import { Template, Templates } from "./../Templates";
 import { DocumentContentsView } from "./DocumentContentsView";
 import * as rp from "request-promise";
 import "./DocumentView.scss";
@@ -46,6 +46,7 @@ library.add(fa.faAlignCenter);
 library.add(fa.faCaretSquareRight);
 library.add(fa.faSquare);
 library.add(fa.faConciergeBell);
+library.add(fa.faWindowRestore);
 library.add(fa.faFolder);
 library.add(fa.faMapPin);
 library.add(fa.faLink);
@@ -521,6 +522,17 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         cm.addItem({ description: "Pin to Pres", event: () => PresentationView.Instance.PinDoc(this.props.Document), icon: "map-pin" });
         cm.addItem({ description: BoolCast(this.props.Document.lockedPosition) ? "Unlock Pos" : "Lock Pos", event: this.toggleLockPosition, icon: BoolCast(this.props.Document.lockedPosition) ? "unlock" : "lock" });
         cm.addItem({ description: this.props.Document.isButton ? "Remove Button" : "Make Button", event: this.makeBtnClicked, icon: "concierge-bell" });
+        cm.addItem({
+            description: "Make Portal", event: () => {
+                let portal = Docs.FreeformDocument([], { width: this.props.Document[WidthSym]() + 10, height: this.props.Document[HeightSym](), title: this.props.Document.title + ".portal" });
+                Doc.GetProto(this.props.Document).subBulletDocs = new List<Doc>([portal]);
+                //summary.proto!.maximizeLocation = "inTab";  // or "inPlace", or "onRight"
+                Doc.GetProto(this.props.Document).templates = new List<string>([Templates.Bullet.Layout]);
+                let coll = Docs.StackingDocument([this.props.Document, portal], { x: NumCast(this.props.Document.x), y: NumCast(this.props.Document.y), width: this.props.Document[WidthSym]() + 10, height: this.props.Document[HeightSym](), title: this.props.Document.title + ".cont" });
+                this.props.addDocument && this.props.addDocument(coll);
+                this.props.removeDocument && this.props.removeDocument(this.props.Document);
+            }, icon: "window-restore"
+        })
         cm.addItem({
             description: "Find aliases", event: async () => {
                 const aliases = await SearchUtil.GetAliasesOfDocument(this.props.Document);
-- 
cgit v1.2.3-70-g09d2


From 1d00e2e05acabe938ee496b6bf4bea55e82056e7 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 9 Jul 2019 14:18:12 -0400
Subject: fixed ink marqueeing.  fixed link following on clicks.  commented out
 link displays.

---
 src/client/documents/Documents.ts                  |  1 -
 .../collections/collectionFreeForm/MarqueeView.tsx | 26 +++++++++++-----
 src/client/views/nodes/DocumentView.tsx            | 36 ++++++++--------------
 src/new_fields/Doc.ts                              |  2 +-
 4 files changed, 31 insertions(+), 34 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 2bddf053a..109afeeb0 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -59,7 +59,6 @@ export interface DocumentOptions {
     x?: number;
     y?: number;
     type?: string;
-    ink?: InkField;
     width?: number;
     height?: number;
     nativeWidth?: number;
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index c83e1e3f5..8a619bfae 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -1,7 +1,7 @@
 import * as htmlToImage from "html-to-image";
 import { action, computed, observable } from "mobx";
 import { observer } from "mobx-react";
-import { Doc } from "../../../../new_fields/Doc";
+import { Doc, FieldResult } from "../../../../new_fields/Doc";
 import { Id } from "../../../../new_fields/FieldSymbols";
 import { InkField, StrokeData } from "../../../../new_fields/InkField";
 import { List } from "../../../../new_fields/List";
@@ -224,6 +224,18 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
         return { left: topLeft[0], top: topLeft[1], width: Math.abs(size[0]), height: Math.abs(size[1]) };
     }
 
+    get ink() {
+        let container = this.props.container.Document;
+        let containerKey = this.props.container.props.fieldKey;
+        return Cast(container[containerKey + "_ink"], InkField);
+    }
+
+    set ink(value: InkField | undefined) {
+        let container = Doc.GetProto(this.props.container.Document);
+        let containerKey = this.props.container.props.fieldKey;
+        container[containerKey + "_ink"] = value;
+    }
+
     @undoBatch
     @action
     marqueeCommand = async (e: KeyboardEvent) => {
@@ -235,9 +247,8 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             e.stopPropagation();
             (e as any).propagationIsStopped = true;
             this.marqueeSelect().map(d => this.props.removeDocument(d));
-            let ink = Cast(this.props.container.props.Document.ink, InkField);
-            if (ink) {
-                this.marqueeInkDelete(ink.inkData);
+            if (this.ink) {
+                this.marqueeInkDelete(this.ink.inkData);
             }
             SelectionManager.DeselectAll();
             this.cleanupInteractions(false);
@@ -259,8 +270,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                     return d;
                 });
             }
-            let ink = Cast(this.props.container.props.Document.ink, InkField);
-            let inkData = ink ? ink.inkData : undefined;
+            let inkData = this.ink ? this.ink.inkData : undefined;
             let newCollection = Docs.FreeformDocument(selected, {
                 x: bounds.left,
                 y: bounds.top,
@@ -269,9 +279,9 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                 backgroundColor: this.props.container.isAnnotationOverlay ? undefined : "white",
                 width: bounds.width,
                 height: bounds.height,
-                ink: inkData ? new InkField(this.marqueeInkSelect(inkData)) : undefined,
                 title: e.key === "s" || e.key === "S" ? "-summary-" : "a nested collection",
             });
+            newCollection.data_ink = inkData ? new InkField(this.marqueeInkSelect(inkData)) : undefined;
             this.marqueeInkDelete(inkData);
 
             if (e.key === "s") {
@@ -348,7 +358,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             let idata = new Map();
             ink.forEach((value: StrokeData, key: string, map: any) =>
                 !InkingCanvas.IntersectStrokeRect(value, this.Bounds) && idata.set(key, value));
-            Doc.SetOnPrototype(this.props.container.props.Document, "ink", new InkField(idata));
+            this.ink = new InkField(idata);
         }
     }
 
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 47ec3b5a1..430409ee3 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -339,30 +339,18 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                     }
                 }
                 else if (linkedDocs.length) {
-                    let linkedDoc = linkedDocs.length ? linkedDocs[0] : expandedDocs[0];
-                    let linkedPages = [linkedDocs.length ? NumCast(linkedDocs[0].anchor1Page, undefined) : NumCast(linkedDocs[0].anchor2Page, undefined),
-                    linkedDocs.length ? NumCast(linkedDocs[0].anchor2Page, undefined) : NumCast(linkedDocs[0].anchor1Page, undefined)];
-                    let maxLocation = StrCast(linkedDoc.maximizeLocation, "inTab");
-                    DocumentManager.Instance.jumpToDocument(linkedDoc, ctrlKey, false, document => this.props.addDocTab(document, undefined, maxLocation), linkedPages[altKey ? 1 : 0]);
-
-                    // else if (linkedToDocs.length || linkedFromDocs.length) {
-                    //     let linkedFwdDocs = [
-                    //         linkedToDocs.length ? linkedToDocs[0].linkedTo as Doc : linkedFromDocs.length ? linkedFromDocs[0].linkedFrom as Doc : expandedDocs[0],
-                    //         linkedFromDocs.length ? linkedFromDocs[0].linkedFrom as Doc : linkedToDocs.length ? linkedToDocs[0].linkedTo as Doc : expandedDocs[0]];
-
-                    //     let linkedFwdContextDocs = [
-                    //         linkedToDocs.length ? await (linkedToDocs[0].linkedToContext) as Doc : linkedFromDocs.length ? await PromiseValue(linkedFromDocs[0].linkedFromContext) as Doc : undefined,
-                    //         linkedFromDocs.length ? await (linkedFromDocs[0].linkedFromContext) as Doc : linkedToDocs.length ? await PromiseValue(linkedToDocs[0].linkedToContext) as Doc : undefined];
-
-                    //     let linkedFwdPage = [
-                    //         linkedToDocs.length ? NumCast(linkedToDocs[0].linkedToPage, undefined) : linkedFromDocs.length ? NumCast(linkedFromDocs[0].linkedFromPage, undefined) : undefined,
-                    //         linkedFromDocs.length ? NumCast(linkedFromDocs[0].linkedFromPage, undefined) : linkedToDocs.length ? NumCast(linkedToDocs[0].linkedToPage, undefined) : undefined];
-
-                    //     if (!linkedFwdDocs.some(l => l instanceof Promise)) {
-                    //         let maxLocation = StrCast(linkedFwdDocs[altKey ? 1 : 0].maximizeLocation, "inTab");
-                    //         let targetContext = !Doc.AreProtosEqual(linkedFwdContextDocs[altKey ? 1 : 0], this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document) ? linkedFwdContextDocs[altKey ? 1 : 0] : undefined;
-                    //         DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0], ctrlKey, false, document => this.props.addDocTab(document, undefined, maxLocation), linkedFwdPage[altKey ? 1 : 0], targetContext);
-                    //     }
+                    let first = linkedDocs.filter(d => Doc.AreProtosEqual(d.anchor1 as Doc, this.props.Document));
+                    let linkedFwdDocs = first.length ? [first[0].anchor2 as Doc, first[0].anchor1 as Doc] : [expandedDocs[0], expandedDocs[0]];
+
+                    let linkedFwdContextDocs = [first.length ? await (first[0].context) as Doc : undefined, undefined];
+
+                    let linkedFwdPage = [first.length ? NumCast(first[0].linkedToPage, undefined) : undefined, undefined];
+
+                    if (!linkedFwdDocs.some(l => l instanceof Promise)) {
+                        let maxLocation = StrCast(linkedFwdDocs[0].maximizeLocation, "inTab");
+                        let targetContext = !Doc.AreProtosEqual(linkedFwdContextDocs[altKey ? 1 : 0], this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document) ? linkedFwdContextDocs[altKey ? 1 : 0] : undefined;
+                        DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0], ctrlKey, false, document => this.props.addDocTab(document, undefined, maxLocation), linkedFwdPage[altKey ? 1 : 0], targetContext);
+                    }
                 }
             }
         }
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index aa13b1d7a..a07f56ca4 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -277,7 +277,7 @@ export namespace Doc {
     }
 
     //
-    // Resolves a reference to a field by returning 'doc' if o field extension is specified,
+    // Resolves a reference to a field by returning 'doc' if field extension is specified,
     // otherwise, it returns the extension document stored in doc.<fieldKey>_ext.
     // This mechanism allows any fields to be extended with an extension document that can
     // be used to capture field-specific metadata.  For example, an image field can be extended
-- 
cgit v1.2.3-70-g09d2


From bbfc935958b88c7ecaeb9a1e06a255cac958ec4c Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 16 Jul 2019 11:58:16 -0400
Subject: added extendsDoc to extension doc's  fixed folllowing links to video
 locations.  fixed aspects of youtube integration.

---
 .../views/collections/CollectionVideoView.tsx      |  4 +--
 .../collections/collectionFreeForm/MarqueeView.tsx |  2 +-
 src/client/views/nodes/LinkMenuItem.tsx            |  5 +--
 src/client/views/nodes/VideoBox.tsx                | 42 +++++++++-------------
 src/new_fields/Doc.ts                              |  6 +++-
 5 files changed, 27 insertions(+), 32 deletions(-)

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

diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index f731c4cef..faf507496 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -88,14 +88,14 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
                 canvas.width = 640;
                 canvas.height = 640 * NumCast(this.props.Document.nativeHeight) / NumCast(this.props.Document.nativeWidth);
                 var ctx = canvas.getContext('2d');//draw image to canvas. scale to target dimensions
-                ctx && ctx.drawImage(this._videoBox!.player!, 0, 0, canvas.width, canvas.height);
+                this._videoBox!.player && ctx && ctx.drawImage(this._videoBox!.player!, 0, 0, canvas.width, canvas.height);
 
                 //convert to desired file format
                 var dataUrl = canvas.toDataURL('image/png'); // can also use 'image/png'
                 // if you want to preview the captured image,
 
                 let filename = encodeURIComponent("snapshot" + this.props.Document.title + "_" + this.props.Document.curPage).replace(/\./g, "");
-                SearchBox.convertDataUri(dataUrl, filename).then((returnedFilename) => {
+                SearchBox.convertDataUri(dataUrl, filename).then(returnedFilename => {
                     if (returnedFilename) {
                         let url = DocServer.prepend(returnedFilename);
                         let imageSummary = Docs.Create.ImageDocument(url, {
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index a4a6881f8..b765517a2 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -147,7 +147,6 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
         PreviewCursor.Visible = false;
         this.cleanupInteractions(true);
         if (e.button === 2 || (e.button === 0 && e.altKey)) {
-            if (!this.props.container.props.active()) this.props.selectDocuments([this.props.container.props.Document]);
             document.addEventListener("pointermove", this.onPointerMove, true);
             document.addEventListener("pointerup", this.onPointerUp, true);
             document.addEventListener("keydown", this.marqueeCommand, true);
@@ -181,6 +180,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
 
     @action
     onPointerUp = (e: PointerEvent): void => {
+        if (!this.props.container.props.active()) this.props.selectDocuments([this.props.container.props.Document]);
         // console.log("pointer up!");
         if (this._visible) {
             // console.log("visible");
diff --git a/src/client/views/nodes/LinkMenuItem.tsx b/src/client/views/nodes/LinkMenuItem.tsx
index 9728671c0..6a18a4e7b 100644
--- a/src/client/views/nodes/LinkMenuItem.tsx
+++ b/src/client/views/nodes/LinkMenuItem.tsx
@@ -7,7 +7,7 @@ import { undoBatch } from "../../util/UndoManager";
 import './LinkMenu.scss';
 import React = require("react");
 import { Doc } from '../../../new_fields/Doc';
-import { StrCast, Cast, BoolCast, FieldValue } from '../../../new_fields/Types';
+import { StrCast, Cast, BoolCast, FieldValue, NumCast } from '../../../new_fields/Types';
 import { observable, action } from 'mobx';
 import { LinkManager } from '../../util/LinkManager';
 import { DragLinkAsDocument } from '../../util/DragManager';
@@ -38,7 +38,8 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
             jumpToDoc = pdfDoc;
         }
         if (DocumentManager.Instance.getDocumentView(jumpToDoc)) {
-            DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey);
+            let self = this;
+            DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, undefined, undefined, NumCast((this.props.destinationDoc === self.props.linkDoc.anchor2 ? self.props.linkDoc.anchor2Page : self.props.linkDoc.anchor1Page)));
         } else {
             CollectionDockingView.Instance.AddRightSplit(jumpToDoc, undefined);
         }
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 85e56ca7b..3ade3396e 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -1,5 +1,5 @@
 import React = require("react");
-import { action, IReactionDisposer, observable, reaction, trace, computed, runInAction } from "mobx";
+import { action, IReactionDisposer, observable, reaction, trace, computed, runInAction, untracked } from "mobx";
 import { observer } from "mobx-react";
 import { makeInterface } from "../../../new_fields/Schema";
 import { Cast, FieldValue, NumCast } from "../../../new_fields/Types";
@@ -14,7 +14,6 @@ import { pageSchema } from "./ImageBox";
 import "./VideoBox.scss";
 import { InkTool } from "../../../new_fields/InkField";
 import { DocumentDecorations } from "../DocumentDecorations";
-import { addHiddenFinalProp } from "mobx/lib/internal";
 
 type VideoDocument = makeInterface<[typeof positionSchema, typeof pageSchema]>;
 const VideoDocument = makeInterface(positionSchema, pageSchema);
@@ -53,18 +52,21 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
     @action public Play = (update: boolean = true) => {
         this.Playing = true;
         update && this.player && this.player.play();
+        console.log("PLAYING = " + update);
         update && this._youtubePlayer && this._youtubePlayer.playVideo();
         !this._playTimer && (this._playTimer = setInterval(this.updateTimecode, 500));
         this.updateTimecode();
     }
 
     @action public Seek(time: number) {
+        console.log("Seeking " + time);
         //if (this._youtubePlayer && this._youtubePlayer.getPlayerState() === 5) return;
-        this._youtubePlayer && !this.Playing && this._youtubePlayer.seekTo(time);
+        this._youtubePlayer && this._youtubePlayer.seekTo(Math.round(time), true);
     }
 
     @action public Pause = (update: boolean = true) => {
         this.Playing = false;
+        console.log("PAUSING = " + update);
         update && this.player && this.player.pause();
         update && this._youtubePlayer && this._youtubePlayer.pauseVideo();
         this._playTimer && clearInterval(this._playTimer);
@@ -122,6 +124,8 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
         if (field) {
             let subitems: ContextMenuProps[] = [];
             subitems.push({ description: "Toggle Show Controls", event: action(() => VideoBox._showControls = !VideoBox._showControls), icon: "expand-arrows-alt" });
+            subitems.push({ description: "GOTO 3", event: action(() => this.Seek(3)), icon: "expand-arrows-alt" });
+            subitems.push({ description: "PLAY", event: action(() => this.Play()), icon: "expand-arrows-alt" });
             ContextMenu.Instance.addItem({ description: "Video Funcs...", subitems: subitems });
         }
     }
@@ -151,38 +155,22 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
         else this._youtubeContentCreated = false;
 
         let iframe = e.target;
-        let startupTimecode = NumCast(this.Document.curPage);
         let onYoutubePlayerStateChange = (event: any) => runInAction(() => {
-            if (event.data !== YT.PlayerState.UNSTARTED && event.data !== YT.PlayerState.BUFFERING) {
-                // if (startupTimecode !== -1) {
-                //     startupTimecode = -1;
-                //     if (event.data === YT.PlayerState.PLAYING) this.Pause();
-                // }
-                if (event.data == YT.PlayerState.PLAYING && !this.Playing) this.Play(false);
-                if (event.data == YT.PlayerState.PAUSED && this.Playing) this.Pause(false);
-            }
+            console.log("Event  " + event.data);
+            if (event.data == YT.PlayerState.PLAYING && !this.Playing) this.Play(false);
+            if (event.data == YT.PlayerState.PAUSED && this.Playing) this.Pause(false);
         });
         let onYoutubePlayerReady = (event: any) => {
+            console.log("READY!");
             this._reactionDisposer && this._reactionDisposer();
             this._youtubeReactionDisposer && this._youtubeReactionDisposer();
-            this._reactionDisposer = reaction(() => this.props.Document.curPage, () => this.Seek(this.Document.curPage || 0));
+            this._reactionDisposer = reaction(() => this.props.Document.curPage, () => !this.Playing && this.Seek(this.Document.curPage || 0));
             this._youtubeReactionDisposer = reaction(() => [this.props.isSelected(), DocumentDecorations.Instance.Interacting, InkingControl.Instance.selectedTool], () => {
                 let interactive = InkingControl.Instance.selectedTool === InkTool.None && this.props.isSelected() && !DocumentDecorations.Instance.Interacting;
                 iframe.style.pointerEvents = interactive ? "all" : "none";
             }, { fireImmediately: true });
-            // if (startupTimecode) {
-            //     this.Playing = false;
-            //     this.Seek(startupTimecode);
-            // }
         }
         this._youtubePlayer = new YT.Player(`${this.youtubeVideoId + this._youtubeIframeId}-player`, {
-            playerVars: {
-                rel: 0,
-                start: NumCast(this.props.Document.curPage),
-                fs: 1,
-                modestbranding: 1, // Modest
-                controls: VideoBox._showControls ? 1 : 0// YT.Controls.ShowLoadPlayer : YT.Controls.Hide
-            },
             events: {
                 'onReady': onYoutubePlayerReady,
                 'onStateChange': onYoutubePlayerStateChange,
@@ -195,9 +183,11 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
         this._youtubeIframeId = VideoBox._youtubeIframeCounter++;
         this._youtubeContentCreated = this._forceCreateYouTubeIFrame ? true : true;
         let style = "videoBox-content-YouTube" + (this._fullScreen ? "-fullScreen" : "");
-        return <iframe key={this._youtubeIframeId} id={`${this.youtubeVideoId + this._youtubeIframeId.toString()}-player`}
+        let start = untracked(() => Math.round(NumCast(this.props.Document.curPage)));
+        return <iframe key={this._youtubeIframeId} id={`${this.youtubeVideoId + this._youtubeIframeId}-player`}
             onLoad={this.youtubeIframeLoaded} className={`${style}`} width="640" height="390"
-            src={`https://www.youtube.com/embed/${this.youtubeVideoId}?enablejsapi=1&fs=1&rel=0&start=32&controls=0`} />
+            src={`https://www.youtube.com/embed/${this.youtubeVideoId}?enablejsapi=1&rel=0&showinfo=1&autoplay=1&start=${start}&modestbranding=1&controls=${VideoBox._showControls ? 1 : 0}`}
+        ></iframe>;
     }
 
     render() {
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index c5f9e7adf..0d9fa540f 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -312,16 +312,20 @@ export namespace Doc {
     }
 
     export function UpdateDocumentExtensionForField(doc: Doc, fieldKey: string) {
-        if (doc[fieldKey + "_ext"] === undefined) {
+        let extensionDoc = doc[fieldKey + "_ext"];
+        if (extensionDoc === undefined) {
             setTimeout(() => {
                 let docExtensionForField = new Doc(doc[Id] + fieldKey, true);
                 docExtensionForField.title = "Extension of " + doc.title + "'s field:" + fieldKey;
+                docExtensionForField.extendsDoc = doc;
                 let proto: Doc | undefined = doc;
                 while (proto && !Doc.IsPrototype(proto)) {
                     proto = proto.proto;
                 }
                 (proto ? proto : doc)[fieldKey + "_ext"] = docExtensionForField;
             }, 0);
+        } else if (extensionDoc instanceof Doc && extensionDoc.extendsDoc === undefined) {
+            setTimeout(() => (extensionDoc as Doc).extendsDoc = doc, 0);
         }
     }
     export function MakeAlias(doc: Doc) {
-- 
cgit v1.2.3-70-g09d2

