From 74e4909a77ac143ecdb1d038ad182aae9c710129 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <samwilkins333@gmail.com>
Date: Wed, 3 Jul 2019 22:15:25 -0400
Subject: implemented directory import routine

---
 src/client/views/nodes/DocumentContentsView.tsx | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'src/client/views/nodes/DocumentContentsView.tsx')

diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 0da4888a1..e9fec1588 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -24,6 +24,7 @@ import { Without, OmitKeys } from "../../../Utils";
 import { Cast, StrCast, NumCast } from "../../../new_fields/Types";
 import { List } from "../../../new_fields/List";
 import { Doc } from "../../../new_fields/Doc";
+import ImportBox from "../../util/Import & Export/ImportBox";
 const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this?
 
 type BindingProps = Without<FieldViewProps, 'fieldKey'>;
@@ -106,7 +107,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
         if (this.props.renderDepth > 7) return (null);
         if (!this.layout && (this.props.layoutKey !== "overlayLayout" || !this.templates.length)) return (null);
         return <ObserverJsxParser
-            components={{ FormattedTextBox, ImageBox, IconBox, FieldView, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, CollectionVideoView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox, HistogramBox }}
+            components={{ FormattedTextBox, ImageBox, IconBox, ImportBox, FieldView, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, CollectionVideoView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox, HistogramBox }}
             bindings={this.CreateBindings(this.props.Document.layout instanceof Doc ? this.props.Document.layout : this.props.Document)}
             jsx={this.finalLayout}
             showWarnings={true}
-- 
cgit v1.2.3-70-g09d2


From aedd283fb9f9eff4145e27658bc6647982256032 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <samwilkins333@gmail.com>
Date: Fri, 5 Jul 2019 00:34:19 -0400
Subject: beginning implementation of key value tags for all imported documents

---
 src/client/documents/Documents.ts                  |  12 +-
 .../util/Import & Export/DirectoryImportBox.scss   |   0
 .../util/Import & Export/DirectoryImportBox.tsx    | 181 +++++++++++++++++++++
 src/client/util/Import & Export/ImageImporter.tsx  |  67 --------
 src/client/util/Import & Export/ImportBox.tsx      | 134 ---------------
 src/client/util/request-image-size.js              |   6 +-
 src/client/views/MainView.tsx                      |   1 -
 src/client/views/collections/CollectionSubView.tsx |   4 +-
 src/client/views/nodes/DocumentContentsView.tsx    |   4 +-
 src/client/views/nodes/ImageBox.tsx                |   4 +-
 10 files changed, 198 insertions(+), 215 deletions(-)
 create mode 100644 src/client/util/Import & Export/DirectoryImportBox.scss
 create mode 100644 src/client/util/Import & Export/DirectoryImportBox.tsx
 delete mode 100644 src/client/util/Import & Export/ImageImporter.tsx
 delete mode 100644 src/client/util/Import & Export/ImportBox.tsx

(limited to 'src/client/views/nodes/DocumentContentsView.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 5d637dd3a..26b5498a2 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -36,7 +36,7 @@ import { UndoManager } from "../util/UndoManager";
 import { RouteStore } from "../../server/RouteStore";
 import { LinkManager } from "../util/LinkManager";
 import { DocumentManager } from "../util/DocumentManager";
-import ImportBox from "../util/Import & Export/ImportBox";
+import DirectoryImportBox from "../util/Import & Export/DirectoryImportBox";
 var requestImageSize = require('../util/request-image-size');
 var path = require('path');
 
@@ -180,7 +180,7 @@ export namespace Docs {
     }
 
     function CreateImportPrototype(): Doc {
-        let importProto = setupPrototypeOptions(importProtoId, "IMPORT_PROTO", ImportBox.LayoutString(), { x: 0, y: 0, width: 600, height: 600, type: DocTypes.IMPORT });
+        let importProto = setupPrototypeOptions(importProtoId, "IMPORT_PROTO", DirectoryImportBox.LayoutString(), { x: 0, y: 0, width: 600, height: 600, type: DocTypes.IMPORT });
         return importProto;
     }
 
@@ -347,7 +347,7 @@ export namespace Docs {
         return CreateInstance(collProto, new List(documents), { ...options, viewType: CollectionViewType.Docking, dockingConfig: config }, id);
     }
 
-    export async function getDocumentFromType(type: string, path: string, options: DocumentOptions, addDocument?: (document: Doc, allowDuplicates?: boolean) => boolean): Promise<Opt<Doc>> {
+    export async function getDocumentFromType(type: string, path: string, options: DocumentOptions): Promise<Opt<Doc>> {
         let ctor: ((path: string, options: DocumentOptions) => (Doc | Promise<Doc | undefined>)) | undefined = undefined;
         if (type.indexOf("image") !== -1) {
             ctor = Docs.ImageDocument;
@@ -370,17 +370,17 @@ export namespace Docs {
             if (path.includes(window.location.hostname)) {
                 let s = path.split('/');
                 let id = s[s.length - 1];
-                DocServer.GetRefField(id).then(field => {
+                return DocServer.GetRefField(id).then(field => {
                     if (field instanceof Doc) {
                         let alias = Doc.MakeAlias(field);
                         alias.x = options.x || 0;
                         alias.y = options.y || 0;
                         alias.width = options.width || 300;
                         alias.height = options.height || options.width || 300;
-                        addDocument && addDocument(alias, false);
+                        return alias;
                     }
+                    return undefined;
                 });
-                return undefined;
             }
             ctor = Docs.WebDocument;
             options = { height: options.width, ...options, title: path, nativeWidth: undefined };
diff --git a/src/client/util/Import & Export/DirectoryImportBox.scss b/src/client/util/Import & Export/DirectoryImportBox.scss
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx
new file mode 100644
index 000000000..2d77f6ae6
--- /dev/null
+++ b/src/client/util/Import & Export/DirectoryImportBox.tsx	
@@ -0,0 +1,181 @@
+import "fs";
+import React = require("react");
+import { Doc } from "../../../new_fields/Doc";
+import { DocServer } from "../../DocServer";
+import { RouteStore } from "../../../server/RouteStore";
+import { action, observable, runInAction } from "mobx";
+import { FieldViewProps, FieldView } from "../../views/nodes/FieldView";
+import Measure, { ContentRect } from "react-measure";
+import { library } from '@fortawesome/fontawesome-svg-core';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faArrowUp, faTag, faFileExcel } from '@fortawesome/free-solid-svg-icons';
+import { Docs, DocumentOptions } from "../../documents/Documents";
+import { EditableView } from "../../views/EditableView";
+
+export default class DirectoryImportBox extends React.Component<FieldViewProps> {
+    private selector = React.createRef<HTMLInputElement>();
+    @observable private top = 0;
+    @observable private left = 0;
+    private dimensions = 50;
+
+    @observable private key = "Key";
+    @observable private value = "Value";
+
+    public static LayoutString() { return FieldView.LayoutString(DirectoryImportBox); }
+
+    constructor(props: FieldViewProps) {
+        super(props);
+        library.add(faArrowUp, faTag);
+    }
+
+    updateKey = (newKey: string) => {
+        runInAction(() => this.key = newKey);
+        console.log("KEY ", this.key);
+        return true;
+    }
+
+    updateValue = (newValue: string) => {
+        runInAction(() => this.value = newValue);
+        console.log("VALUE ", this.value);
+        return true;
+    }
+
+    handleSelection = async (e: React.ChangeEvent<HTMLInputElement>) => {
+        let promises: Promise<void>[] = [];
+        let docs: Doc[] = [];
+
+        let files = e.target.files;
+        if (!files || files.length === 0) return;
+
+        let directory = (files.item(0) as any).webkitRelativePath.split("/", 1);
+
+        for (let i = 0; i < files.length; i++) {
+            let uploaded_file = files.item(i);
+
+            if (!uploaded_file) {
+                continue;
+            }
+
+            let formData = new FormData();
+            formData.append('file', uploaded_file);
+            let dropFileName = uploaded_file ? uploaded_file.name : "-empty-";
+            let type = uploaded_file.type;
+
+            let prom = fetch(DocServer.prepend(RouteStore.upload), {
+                method: 'POST',
+                body: formData
+            }).then(async (res: Response) => {
+                (await res.json()).map(action((file: any) => {
+                    let path = DocServer.prepend(file);
+                    console.log(path);
+                    let docPromise = Docs.getDocumentFromType(type, path, { nativeWidth: 300, width: 300, title: dropFileName });
+                    docPromise.then(doc => doc && docs.push(doc));
+                }));
+            });
+            promises.push(prom);
+        }
+
+        await Promise.all(promises);
+
+        let doc = this.props.Document;
+        let options: DocumentOptions = { title: `Import of ${directory}`, width: 500, height: 500, x: Doc.GetT(doc, "x", "number"), y: Doc.GetT(doc, "y", "number") };
+        let parent = this.props.ContainingCollectionView;
+        if (parent) {
+            let importContainer = Docs.StackingDocument(docs, options);
+            Doc.AddDocToList(Doc.GetProto(parent.props.Document), "data", importContainer);
+            this.props.removeDocument && this.props.removeDocument(doc);
+        }
+    }
+
+    componentDidMount() {
+        this.selector.current!.setAttribute("directory", "");
+        this.selector.current!.setAttribute("webkitdirectory", "");
+    }
+
+    @action
+    preserveCentering = (rect: ContentRect) => {
+        let bounds = rect.offset!;
+        if (bounds.width === 0 || bounds.height === 0) {
+            return;
+        }
+        let offset = this.dimensions / 2;
+        this.left = bounds.width / 2 - offset;
+        this.top = bounds.height / 2 - offset;
+    }
+
+    render() {
+        let dimensions = 50;
+        let keyValueStyle = { paddingLeft: 5, width: "50%" };
+        return (
+            <Measure offset onResize={this.preserveCentering}>
+                {({ measureRef }) =>
+                    <div ref={measureRef} style={{ width: "100%", height: "100%", pointerEvents: "all" }} >
+                        <input
+                            id={"selector"}
+                            ref={this.selector}
+                            name={"selector"}
+                            onChange={this.handleSelection}
+                            type="file"
+                            style={{
+                                position: "absolute",
+                                display: "none"
+                            }} />
+                        <label htmlFor={"selector"}>
+                            <div style={{
+                                width: dimensions,
+                                height: dimensions,
+                                borderRadius: "50%",
+                                background: "black",
+                                position: "absolute",
+                                left: this.left,
+                                top: this.top
+                            }} />
+                            <div style={{
+                                position: "absolute",
+                                left: this.left + 12.5,
+                                top: this.top + 11
+                            }}>
+                                <FontAwesomeIcon icon={faArrowUp} color="#FFFFFF" size={"2x"} />
+                            </div>
+                        </label>
+                        <div style={{
+                            position: "absolute",
+                            top: 5,
+                            right: 5,
+                            borderRadius: "50%",
+                            width: 25,
+                            height: 25,
+                            background: "black"
+                        }} />
+                        <div style={{
+                            position: "absolute",
+                            right: 9.5,
+                            top: 11
+                        }}>
+                            <FontAwesomeIcon icon={faTag} color="#FFFFFF" size={"1x"} />
+                        </div>
+                        <div style={{ display: "flex", flexDirection: "row", borderBottom: "1px solid black", paddingBottom: 5 }} >
+                            <div className={"key_container"} style={keyValueStyle}>
+                                <EditableView
+                                    contents={this.key}
+                                    SetValue={this.updateKey}
+                                    GetValue={() => this.key}
+                                    oneLine={true}
+                                />
+                            </div>
+                            <div className={"value_container"} style={keyValueStyle}>
+                                <EditableView
+                                    contents={this.value}
+                                    SetValue={this.updateValue}
+                                    GetValue={() => this.value}
+                                    oneLine={true}
+                                />
+                            </div>
+                        </div>
+                    </div>
+                }
+            </Measure>
+        );
+    }
+
+}
\ No newline at end of file
diff --git a/src/client/util/Import & Export/ImageImporter.tsx b/src/client/util/Import & Export/ImageImporter.tsx
deleted file mode 100644
index d664f6487..000000000
--- a/src/client/util/Import & Export/ImageImporter.tsx	
+++ /dev/null
@@ -1,67 +0,0 @@
-import "fs";
-import React = require("react");
-import { Doc } from "../../../new_fields/Doc";
-import { DocServer } from "../../DocServer";
-import { RouteStore } from "../../../server/RouteStore";
-import { action } from "mobx";
-import { Docs } from "../../documents/Documents";
-import { FieldViewProps } from "../../views/nodes/FieldView";
-
-interface ImageImporterProps {
-    addSchema: (imageDocs: Doc[]) => void;
-}
-
-export default class BulkImporter extends React.Component<FieldViewProps> {
-    private selector = React.createRef<HTMLInputElement>();
-
-    handleSelection = async (e: React.ChangeEvent<HTMLInputElement>) => {
-        let promises: Promise<void>[] = [];
-        let docs: Doc[] = [];
-
-        let files = e.target.files;
-        if (!files) return;
-
-        for (let i = 0; i < files.length; i++) {
-            let target = files.item(i);
-
-            if (target === null) {
-                continue;
-            }
-
-            let type = target.type;
-            let formData = new FormData();
-            formData.append('file', target);
-            let dropFileName = target ? target.name : "-empty-";
-
-            let prom = fetch(DocServer.prepend(RouteStore.upload), {
-                method: 'POST',
-                body: formData
-            }).then(async (res: Response) => {
-                (await res.json()).map(action((file: any) => {
-                    let path = window.location.origin + file;
-                    let docPromise = Docs.getDocumentFromType(type, path, { nativeWidth: 300, width: 300, title: dropFileName });
-                    docPromise.then(doc => doc && docs.push(doc));
-                }));
-            });
-            promises.push(prom);
-        }
-
-        await Promise.all(promises);
-
-        let parent = Docs.SchemaDocument(["title", "data"], docs, { width: 300, height: 300, title: "Bulk Import from Directory" });
-    }
-
-    componentDidMount() {
-        this.selector.current!.setAttribute("directory", "true");
-        this.selector.current!.setAttribute("webkitdirectory", "true");
-    }
-
-    render() {
-        return (
-            <div>
-                <input ref={this.selector} name={"selector"} onChange={this.handleSelection} type="file" style={{ position: "absolute" }} />
-            </div>
-        );
-    }
-
-}
\ No newline at end of file
diff --git a/src/client/util/Import & Export/ImportBox.tsx b/src/client/util/Import & Export/ImportBox.tsx
deleted file mode 100644
index 630911710..000000000
--- a/src/client/util/Import & Export/ImportBox.tsx	
+++ /dev/null
@@ -1,134 +0,0 @@
-import "fs";
-import React = require("react");
-import { Doc } from "../../../new_fields/Doc";
-import { DocServer } from "../../DocServer";
-import { RouteStore } from "../../../server/RouteStore";
-import { action, observable } from "mobx";
-import { FieldViewProps, FieldView } from "../../views/nodes/FieldView";
-import Measure, { ContentRect } from "react-measure";
-import { library } from '@fortawesome/fontawesome-svg-core';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { faArrowUp } from '@fortawesome/free-solid-svg-icons';
-import { Docs, DocumentOptions } from "../../documents/Documents";
-
-interface ImageImporterProps {
-    addSchema: (imageDocs: Doc[]) => void;
-}
-
-export default class ImportBox extends React.Component<FieldViewProps> {
-    @observable private top = 0;
-    @observable private left = 0;
-    private dimensions = 50;
-
-    constructor(props: FieldViewProps) {
-        super(props);
-        library.add(faArrowUp);
-    }
-
-    public static LayoutString() { return FieldView.LayoutString(ImportBox); }
-
-    private selector = React.createRef<HTMLInputElement>();
-
-    handleSelection = async (e: React.ChangeEvent<HTMLInputElement>) => {
-        let promises: Promise<void>[] = [];
-        let docs: Doc[] = [];
-
-        let files = e.target.files;
-        if (!files || files.length === 0) return;
-
-        let directory = (files.item(0) as any).webkitRelativePath.split("/", 1);
-
-        for (let i = 0; i < files.length; i++) {
-            let uploaded_file = files.item(i);
-
-            if (!uploaded_file) {
-                continue;
-            }
-
-            let formData = new FormData();
-            formData.append('file', uploaded_file);
-            let dropFileName = uploaded_file ? uploaded_file.name : "-empty-";
-            let type = uploaded_file.type;
-
-            let prom = fetch(DocServer.prepend(RouteStore.upload), {
-                method: 'POST',
-                body: formData
-            }).then(async (res: Response) => {
-                (await res.json()).map(action((file: any) => {
-                    let path = DocServer.prepend(file);
-                    let docPromise = Docs.getDocumentFromType(type, path, { nativeWidth: 300, width: 300, title: dropFileName });
-                    docPromise.then(doc => doc && docs.push(doc));
-                }));
-            });
-            promises.push(prom);
-        }
-
-        await Promise.all(promises);
-
-        let doc = this.props.Document;
-        let options: DocumentOptions = { title: `Import of ${directory}`, width: 500, height: 500, x: Doc.GetT(doc, "x", "number"), y: Doc.GetT(doc, "y", "number") };
-        let parent = this.props.ContainingCollectionView;
-        if (parent) {
-            let importContainer = Docs.StackingDocument(docs, options);
-            Doc.AddDocToList(Doc.GetProto(parent.props.Document), "data", importContainer);
-            this.props.removeDocument && this.props.removeDocument(doc);
-        }
-    }
-
-    componentDidMount() {
-        this.selector.current!.setAttribute("directory", "true");
-        this.selector.current!.setAttribute("webkitdirectory", "true");
-    }
-
-    @action
-    preserveCentering = (rect: ContentRect) => {
-        let bounds = rect.offset!;
-        if (bounds.width === 0 || bounds.height === 0) {
-            return;
-        }
-        let offset = this.dimensions / 2;
-        this.left = bounds.width / 2 - offset;
-        this.top = bounds.height / 2 - offset;
-    }
-
-    render() {
-        let dimensions = 50;
-        return (
-            <Measure offset onResize={this.preserveCentering}>
-                {({ measureRef }) =>
-                    <div ref={measureRef} style={{ width: "100%", height: "100%", pointerEvents: "all" }} >
-                        <input
-                            id={"selector"}
-                            ref={this.selector}
-                            name={"selector"}
-                            onChange={this.handleSelection}
-                            type="file"
-                            style={{
-                                position: "absolute",
-                                display: "none"
-                            }} />
-                        <label htmlFor={"selector"}>
-                            <div style={{
-                                width: dimensions,
-                                height: dimensions,
-                                borderRadius: "50%",
-                                background: "black",
-                                position: "absolute",
-                                left: this.left,
-                                top: this.top
-                            }} />
-                            <div style={{
-                                position: "absolute",
-                                left: this.left + 12.5,
-                                top: this.top + 11
-                            }}>
-                                <FontAwesomeIcon icon={faArrowUp} color="#FFFFFF" size={"2x"} />
-                            </div>
-                        </label>
-                    </div>
-                }
-            </Measure>
-        );
-    }
-
-}
\ No newline at end of file
diff --git a/src/client/util/request-image-size.js b/src/client/util/request-image-size.js
index 0f9328872..27605d167 100644
--- a/src/client/util/request-image-size.js
+++ b/src/client/util/request-image-size.js
@@ -21,7 +21,9 @@ module.exports = function requestImageSize(options) {
     if (options && typeof options === 'object') {
         opts = Object.assign(options, opts);
     } else if (options && typeof options === 'string') {
-        opts = Object.assign({ uri: options }, opts);
+        opts = Object.assign({
+            uri: options
+        }, opts);
     } else {
         return Promise.reject(new Error('You should provide an URI string or a "request" options object.'));
     }
@@ -70,4 +72,4 @@ module.exports = function requestImageSize(options) {
 
         req.on('error', err => reject(err));
     });
-};
+};
\ No newline at end of file
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index e38fd3c8b..3d059b2f3 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -38,7 +38,6 @@ import PDFMenu from './pdf/PDFMenu';
 import { InkTool } from '../../new_fields/InkField';
 import _ from "lodash";
 import KeyManager from './GlobalKeyHandler';
-import BulkImporter from '../util/Import & Export/ImageImporter';
 
 @observer
 export class MainView extends React.Component {
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index e886ad84a..8cb2e1beb 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -182,7 +182,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
                         .then(result => {
                             let type = result["content-type"];
                             if (type) {
-                                Docs.getDocumentFromType(type, str, { ...options, width: 300, nativeWidth: 300 }, this.props.addDocument)
+                                Docs.getDocumentFromType(type, str, { ...options, width: 300, nativeWidth: 300 })
                                     .then(doc => doc && this.props.addDocument(doc, false));
                             }
                         });
@@ -204,7 +204,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
                     }).then(async (res: Response) => {
                         (await res.json()).map(action((file: any) => {
                             let path = window.location.origin + file;
-                            let docPromise = Docs.getDocumentFromType(type, path, { ...options, nativeWidth: 300, width: 300, title: dropFileName }, this.props.addDocument);
+                            let docPromise = Docs.getDocumentFromType(type, path, { ...options, nativeWidth: 300, width: 300, title: dropFileName });
                             docPromise.then(doc => doc && this.props.addDocument(doc));
                         }));
                     });
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index e9fec1588..0bfb2954f 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -24,7 +24,7 @@ import { Without, OmitKeys } from "../../../Utils";
 import { Cast, StrCast, NumCast } from "../../../new_fields/Types";
 import { List } from "../../../new_fields/List";
 import { Doc } from "../../../new_fields/Doc";
-import ImportBox from "../../util/Import & Export/ImportBox";
+import DirectoryImportBox from "../../util/Import & Export/DirectoryImportBox";
 const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this?
 
 type BindingProps = Without<FieldViewProps, 'fieldKey'>;
@@ -107,7 +107,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
         if (this.props.renderDepth > 7) return (null);
         if (!this.layout && (this.props.layoutKey !== "overlayLayout" || !this.templates.length)) return (null);
         return <ObserverJsxParser
-            components={{ FormattedTextBox, ImageBox, IconBox, ImportBox, FieldView, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, CollectionVideoView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox, HistogramBox }}
+            components={{ FormattedTextBox, ImageBox, IconBox, DirectoryImportBox, FieldView, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, CollectionVideoView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox, HistogramBox }}
             bindings={this.CreateBindings(this.props.Document.layout instanceof Doc ? this.props.Document.layout : this.props.Document)}
             jsx={this.finalLayout}
             showWarnings={true}
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 06bf65f73..88c122b61 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -213,7 +213,9 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD
                     }), 0);
                 }
             })
-            .catch((err: any) => console.log(err));
+            .catch((err: any) => {
+                console.log(err);
+            });
     }
 
     render() {
-- 
cgit v1.2.3-70-g09d2


From 7fdb33cafaa3e8593d648ddba994356a9625ff56 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <samwilkins333@gmail.com>
Date: Tue, 9 Jul 2019 13:52:35 -0400
Subject: string list to list of text doc map in scraper and cleaned up kv pane
 templating interaction code

---
 src/client/views/nodes/DocumentContentsView.tsx |  7 +--
 src/client/views/nodes/KeyValueBox.tsx          | 20 ++++++--
 src/scraping/buxton/scraper.py                  | 61 +++++++++++++++++++++++--
 3 files changed, 75 insertions(+), 13 deletions(-)

(limited to 'src/client/views/nodes/DocumentContentsView.tsx')

diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index b4c0e844f..eb786d537 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -69,7 +69,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
             // this document as the data document for the layout.
             return this.props.Document;
         }
-        return this.props.DataDoc
+        return this.props.DataDoc;
     }
     get layoutDoc() {
         // if this document's layout field contains a document (ie, a rendering template), then we will use that
@@ -124,13 +124,8 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
         if (this.props.renderDepth > 7) return (null);
         if (!this.layout && (this.props.layoutKey !== "overlayLayout" || !this.templates.length)) return (null);
         return <ObserverJsxParser
-<<<<<<< HEAD
             components={{ FormattedTextBox, ImageBox, IconBox, DirectoryImportBox, FieldView, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, CollectionVideoView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox, HistogramBox }}
-            bindings={this.CreateBindings(this.props.Document.layout instanceof Doc ? this.props.Document.layout : this.props.Document)}
-=======
-            components={{ FormattedTextBox, ImageBox, IconBox, FieldView, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, CollectionVideoView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox, HistogramBox }}
             bindings={this.CreateBindings()}
->>>>>>> b49fdb1c42b9758e006521e0f404634ba396a2ac
             jsx={this.finalLayout}
             showWarnings={true}
             onError={(test: any) => { console.log(test); }}
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index e27ab1589..e8619584e 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -161,7 +161,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
     getTemplate = async () => {
         let parent = Docs.StackingDocument([], { width: 800, height: 800, title: "Template" });
         parent.singleColumn = false;
-        parent.columnWidth = 50;
+        parent.columnWidth = 100;
         for (let row of this.rows.filter(row => row.isChecked)) {
             await this.createTemplateField(parent, row);
             row.uncheck();
@@ -175,7 +175,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
         if (!sourceDoc) {
             return;
         }
-        let fieldTemplate = this.inferType(sourceDoc[metaKey], metaKey);
+        let fieldTemplate = await this.inferType(sourceDoc[metaKey], metaKey);
 
         // move data doc fields to layout doc as needed (nativeWidth/nativeHeight, data, ??)
         let backgroundLayout = StrCast(fieldTemplate.backgroundLayout);
@@ -200,12 +200,24 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
         Cast(parentStackingDoc.data, listSpec(Doc))!.push(fieldTemplate);
     }
 
-    inferType = (data: FieldResult, metaKey: string) => {
+    inferType = async (data: FieldResult, metaKey: string) => {
         let options = { width: 300, height: 300, title: metaKey };
         if (data instanceof RichTextField || typeof data === "string" || typeof data === "number") {
             return Docs.TextDocument(options);
         } else if (data instanceof List) {
-            return Docs.StackingDocument([], options);
+            if (data.length === 0) {
+                return Docs.StackingDocument([], options);
+            }
+            let first = await Cast(data[0], Doc);
+            if (!first) {
+                return Docs.StackingDocument([], options);
+            }
+            switch (first.type) {
+                case "image":
+                    return Docs.StackingDocument([], options);
+                case "text":
+                    return Docs.TreeDocument([], options);
+            }
         } else if (data instanceof ImageField) {
             return Docs.ImageDocument("https://www.freepik.com/free-icon/picture-frame-with-mountain-image_748687.htm", options);
         }
diff --git a/src/scraping/buxton/scraper.py b/src/scraping/buxton/scraper.py
index 02c6d8b74..700269727 100644
--- a/src/scraping/buxton/scraper.py
+++ b/src/scraping/buxton/scraper.py
@@ -26,7 +26,7 @@ def extract_links(fileName):
         item = rels[rel]
         if item.reltype == RT.HYPERLINK and ".aspx" not in item._target:
             links.append(item._target)
-    return listify(links)
+    return text_doc_map(links)
 
 
 def extract_value(kv_string):
@@ -60,6 +60,12 @@ def protofy(fieldId):
     }
 
 
+def text_doc_map(string_list):
+    def guid_map(caption):
+        return write_text_doc(caption)
+    return listify(proxify_guids(list(map(guid_map, string_list))))
+
+
 def write_schema(parse_results, display_fields, storage_key):
     view_guids = parse_results["child_guids"]
 
@@ -110,6 +116,54 @@ def write_schema(parse_results, display_fields, storage_key):
     return view_doc_guid
 
 
+def write_text_doc(content):
+    data_doc_guid = guid()
+    view_doc_guid = guid()
+
+    view_doc = {
+        "_id": view_doc_guid,
+        "fields": {
+            "proto": protofy(data_doc_guid),
+            "x": 10,
+            "y": 10,
+            "width": 400,
+            "zIndex": 2,
+            "libraryBrush": False
+        },
+        "__type": "Doc"
+    }
+
+    data_doc = {
+        "_id": data_doc_guid,
+        "fields": {
+            "proto": protofy("textProto"),
+            "data": {
+                "Data": '{"doc":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"' + content + '"}]}]},"selection":{"type":"text","anchor":1,"head":1}' + '}',
+                "__type": "RichTextField"
+            },
+            "title": content,
+            "nativeWidth": 200,
+            "author": "Bill Buxton",
+            "creationDate": {
+                "date": datetime.datetime.utcnow().microsecond,
+                "__type": "date"
+            },
+            "isPrototype": True,
+            "autoHeight": True,
+            "page": -1,
+            "nativeHeight": 200,
+            "height": 200,
+            "data_text": content
+        },
+        "__type": "Doc"
+    }
+
+    db.newDocuments.insert_one(view_doc)
+    db.newDocuments.insert_one(data_doc)
+
+    return view_doc_guid
+
+
 def write_image(folder, name):
     path = f"http://localhost:1050/files/{folder}/{name}"
 
@@ -253,7 +307,7 @@ def parse_document(file_name: str):
     while lines[cur] != "Image":
         link_descriptions.append(lines[cur].strip())
         cur += 1
-    result["link_descriptions"] = listify(link_descriptions)
+    result["link_descriptions"] = text_doc_map(link_descriptions)
 
     result["hyperlinks"] = extract_links(source + "/" + file_name)
 
@@ -265,7 +319,8 @@ def parse_document(file_name: str):
         captions.append(lines[cur + 1])
         cur += 2
     result["images"] = listify(images)
-    result["captions"] = listify(captions)
+
+    result["captions"] = text_doc_map(captions)
 
     notes = []
     if (cur < len(lines) and lines[cur] == "NOTES:"):
-- 
cgit v1.2.3-70-g09d2

