From 7f42c98318899a51cb64080fc4f4e315e43bb150 Mon Sep 17 00:00:00 2001
From: 0x85FB9C51 <77808164+0x85FB9C51@users.noreply.github.com>
Date: Tue, 6 Jul 2021 23:47:38 -0400
Subject: reoganization of schema view files, partial

---
 .../schemaView/CollectionSchemaHeaders.tsx         | 518 +++++++++++++++++++++
 1 file changed, 518 insertions(+)
 create mode 100644 src/client/views/collections/schemaView/CollectionSchemaHeaders.tsx

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

diff --git a/src/client/views/collections/schemaView/CollectionSchemaHeaders.tsx b/src/client/views/collections/schemaView/CollectionSchemaHeaders.tsx
new file mode 100644
index 000000000..b825d6d96
--- /dev/null
+++ b/src/client/views/collections/schemaView/CollectionSchemaHeaders.tsx
@@ -0,0 +1,518 @@
+import React = require("react");
+import { IconProp, library } from "@fortawesome/fontawesome-svg-core";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { action, computed, observable, runInAction } from "mobx";
+import { observer } from "mobx-react";
+import { Doc, DocListCast, Opt } from "../../../../fields/Doc";
+import { listSpec } from "../../../../fields/Schema";
+import { PastelSchemaPalette, SchemaHeaderField } from "../../../../fields/SchemaHeaderField";
+import { ScriptField } from "../../../../fields/ScriptField";
+import { Cast, StrCast } from "../../../../fields/Types";
+import { undoBatch } from "../../../util/UndoManager";
+import { SearchBox } from "../../search/SearchBox";
+import { ColumnType } from "../CollectionSchemaView";
+import "./CollectionSchemaView.scss";
+import { CollectionView } from "../CollectionView";
+
+const higflyout = require("@hig/flyout");
+export const { anchorPoints } = higflyout;
+export const Flyout = higflyout.default;
+
+
+export interface AddColumnHeaderProps {
+    createColumn: () => void;
+}
+
+@observer
+export class CollectionSchemaAddColumnHeader extends React.Component<AddColumnHeaderProps> {
+    render() {
+        return (
+            <button className="add-column" onClick={() => this.props.createColumn()}><FontAwesomeIcon icon="plus" size="sm" /></button>
+        );
+    }
+}
+
+
+export interface ColumnMenuProps {
+    columnField: SchemaHeaderField;
+    // keyValue: string;
+    possibleKeys: string[];
+    existingKeys: string[];
+    // keyType: ColumnType;
+    typeConst: boolean;
+    menuButtonContent: JSX.Element;
+    addNew: boolean;
+    onSelect: (oldKey: string, newKey: string, addnew: boolean) => void;
+    setIsEditing: (isEditing: boolean) => void;
+    deleteColumn: (column: string) => void;
+    onlyShowOptions: boolean;
+    setColumnType: (column: SchemaHeaderField, type: ColumnType) => void;
+    setColumnSort: (column: SchemaHeaderField, desc: boolean | undefined) => void;
+    anchorPoint?: any;
+    setColumnColor: (column: SchemaHeaderField, color: string) => void;
+}
+@observer
+export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps> {
+    @observable private _isOpen: boolean = false;
+    @observable private _node: HTMLDivElement | null = null;
+
+    componentDidMount() { document.addEventListener("pointerdown", this.detectClick); }
+
+    componentWillUnmount() { document.removeEventListener("pointerdown", this.detectClick); }
+
+    @action
+    detectClick = (e: PointerEvent) => {
+        !this._node?.contains(e.target as Node) && this.props.setIsEditing(this._isOpen = false);
+    }
+
+    @action
+    toggleIsOpen = (): void => {
+        this.props.setIsEditing(this._isOpen = !this._isOpen);
+    }
+
+    changeColumnType = (type: ColumnType) => {
+        this.props.setColumnType(this.props.columnField, type);
+    }
+
+    changeColumnSort = (desc: boolean | undefined) => {
+        this.props.setColumnSort(this.props.columnField, desc);
+    }
+
+    changeColumnColor = (color: string) => {
+        this.props.setColumnColor(this.props.columnField, color);
+    }
+
+    @action
+    setNode = (node: HTMLDivElement): void => {
+        if (node) {
+            this._node = node;
+        }
+    }
+
+    renderTypes = () => {
+        if (this.props.typeConst) return (null);
+
+        const type = this.props.columnField.type;
+        return (
+            <div className="collectionSchema-headerMenu-group">
+                <label>Column type:</label>
+                <div className="columnMenu-types">
+                    <div className={"columnMenu-option" + (type === ColumnType.Any ? " active" : "")} onClick={() => this.changeColumnType(ColumnType.Any)}>
+                        <FontAwesomeIcon icon={"align-justify"} size="sm" />
+                        Any
+                    </div>
+                    <div className={"columnMenu-option" + (type === ColumnType.Number ? " active" : "")} onClick={() => this.changeColumnType(ColumnType.Number)}>
+                        <FontAwesomeIcon icon={"hashtag"} size="sm" />
+                        Number
+                    </div>
+                    <div className={"columnMenu-option" + (type === ColumnType.String ? " active" : "")} onClick={() => this.changeColumnType(ColumnType.String)}>
+                        <FontAwesomeIcon icon={"font"} size="sm" />
+                        Text
+                    </div>
+                    <div className={"columnMenu-option" + (type === ColumnType.Boolean ? " active" : "")} onClick={() => this.changeColumnType(ColumnType.Boolean)}>
+                        <FontAwesomeIcon icon={"check-square"} size="sm" />
+                        Checkbox
+                    </div>
+                    <div className={"columnMenu-option" + (type === ColumnType.List ? " active" : "")} onClick={() => this.changeColumnType(ColumnType.List)}>
+                        <FontAwesomeIcon icon={"list-ul"} size="sm" />
+                        List
+                    </div>
+                    <div className={"columnMenu-option" + (type === ColumnType.Doc ? " active" : "")} onClick={() => this.changeColumnType(ColumnType.Doc)}>
+                        <FontAwesomeIcon icon={"file"} size="sm" />
+                        Document
+                    </div>
+                    <div className={"columnMenu-option" + (type === ColumnType.Image ? " active" : "")} onClick={() => this.changeColumnType(ColumnType.Image)}>
+                        <FontAwesomeIcon icon={"image"} size="sm" />
+                        Image
+                    </div>
+                    <div className={"columnMenu-option" + (type === ColumnType.Date ? " active" : "")} onClick={() => this.changeColumnType(ColumnType.Date)}>
+                        <FontAwesomeIcon icon={"calendar"} size="sm" />
+                        Date
+                    </div>
+                </div>
+            </div >
+        );
+    }
+
+    renderSorting = () => {
+        const sort = this.props.columnField.desc;
+        return (
+            <div className="collectionSchema-headerMenu-group">
+                <label>Sort by:</label>
+                <div className="columnMenu-sort">
+                    <div className={"columnMenu-option" + (sort === true ? " active" : "")} onClick={() => this.changeColumnSort(true)}>
+                        <FontAwesomeIcon icon="sort-amount-down" size="sm" />
+                        Sort descending
+                    </div>
+                    <div className={"columnMenu-option" + (sort === false ? " active" : "")} onClick={() => this.changeColumnSort(false)}>
+                        <FontAwesomeIcon icon="sort-amount-up" size="sm" />
+                        Sort ascending
+                    </div>
+                    <div className="columnMenu-option" onClick={() => this.changeColumnSort(undefined)}>
+                        <FontAwesomeIcon icon="times" size="sm" />
+                        Clear sorting
+                    </div>
+                </div>
+            </div>
+        );
+    }
+
+    renderColors = () => {
+        const selected = this.props.columnField.color;
+
+        const pink = PastelSchemaPalette.get("pink2");
+        const purple = PastelSchemaPalette.get("purple2");
+        const blue = PastelSchemaPalette.get("bluegreen1");
+        const yellow = PastelSchemaPalette.get("yellow4");
+        const red = PastelSchemaPalette.get("red2");
+        const gray = "#f1efeb";
+
+        return (
+            <div className="collectionSchema-headerMenu-group">
+                <label>Color:</label>
+                <div className="columnMenu-colors">
+                    <div className={"columnMenu-colorPicker" + (selected === pink ? " active" : "")} style={{ backgroundColor: pink }} onClick={() => this.changeColumnColor(pink!)}></div>
+                    <div className={"columnMenu-colorPicker" + (selected === purple ? " active" : "")} style={{ backgroundColor: purple }} onClick={() => this.changeColumnColor(purple!)}></div>
+                    <div className={"columnMenu-colorPicker" + (selected === blue ? " active" : "")} style={{ backgroundColor: blue }} onClick={() => this.changeColumnColor(blue!)}></div>
+                    <div className={"columnMenu-colorPicker" + (selected === yellow ? " active" : "")} style={{ backgroundColor: yellow }} onClick={() => this.changeColumnColor(yellow!)}></div>
+                    <div className={"columnMenu-colorPicker" + (selected === red ? " active" : "")} style={{ backgroundColor: red }} onClick={() => this.changeColumnColor(red!)}></div>
+                    <div className={"columnMenu-colorPicker" + (selected === gray ? " active" : "")} style={{ backgroundColor: gray }} onClick={() => this.changeColumnColor(gray)}></div>
+                </div>
+            </div>
+        );
+    }
+
+    renderContent = () => {
+        return (
+            <div className="collectionSchema-header-menuOptions">
+                {this.props.onlyShowOptions ? <></> :
+                    <>
+                        {this.renderTypes()}
+                        {this.renderSorting()}
+                        {this.renderColors()}
+                        <div className="collectionSchema-headerMenu-group">
+                            <button onClick={() => this.props.deleteColumn(this.props.columnField.heading)}>Delete Column</button>
+                        </div>
+                    </>
+                }
+            </div>
+        );
+    }
+
+    render() {
+        return (
+            <div className="collectionSchema-header-menu" ref={this.setNode}>
+                <Flyout anchorPoint={this.props.anchorPoint ? this.props.anchorPoint : anchorPoints.TOP_CENTER} content={this.renderContent()}>
+                    <div className="collectionSchema-header-toggler" onClick={() => this.toggleIsOpen()}>{this.props.menuButtonContent}</div>
+                </ Flyout >
+            </div>
+        );
+    }
+}
+
+
+export interface KeysDropdownProps {
+    keyValue: string;
+    possibleKeys: string[];
+    existingKeys: string[];
+    canAddNew: boolean;
+    addNew: boolean;
+    onSelect: (oldKey: string, newKey: string, addnew: boolean, filter?: string) => void;
+    setIsEditing: (isEditing: boolean) => void;
+    width?: string;
+    docs?: Doc[];
+    Document: Doc;
+    dataDoc: Doc | undefined;
+    fieldKey: string;
+    ContainingCollectionDoc: Doc | undefined;
+    ContainingCollectionView: Opt<CollectionView>;
+    active?: (outsideReaction?: boolean) => boolean;
+    openHeader: (column: any, screenx: number, screeny: number) => void;
+    col: SchemaHeaderField;
+    icon: IconProp;
+}
+@observer
+export class KeysDropdown extends React.Component<KeysDropdownProps> {
+    @observable private _key: string = this.props.keyValue;
+    @observable private _searchTerm: string = this.props.keyValue;
+    @observable private _isOpen: boolean = false;
+    @observable private _node: HTMLDivElement | null = null;
+    @observable private _inputRef: React.RefObject<HTMLInputElement> = React.createRef();
+
+    @action setSearchTerm = (value: string): void => { this._searchTerm = value; };
+    @action setKey = (key: string): void => { this._key = key; };
+    @action setIsOpen = (isOpen: boolean): void => { this._isOpen = isOpen; };
+
+    @action
+    onSelect = (key: string): void => {
+        this.props.onSelect(this._key, key, this.props.addNew);
+        this.setKey(key);
+        this._isOpen = false;
+        this.props.setIsEditing(false);
+    }
+
+    @action
+    setNode = (node: HTMLDivElement): void => {
+        if (node) {
+            this._node = node;
+        }
+    }
+
+    componentDidMount() {
+        document.addEventListener("pointerdown", this.detectClick);
+        const filters = Cast(this.props.Document._docFilters, listSpec("string"));
+        if (filters?.some(filter => filter.split(":")[0] === this._key)) {
+            runInAction(() => this.closeResultsVisibility = "contents");
+        }
+    }
+
+    @action
+    detectClick = (e: PointerEvent): void => {
+        if (this._node && this._node.contains(e.target as Node)) {
+        } else {
+            this._isOpen = false;
+            this.props.setIsEditing(false);
+        }
+    }
+
+    private tempfilter: string = "";
+    @undoBatch
+    onKeyDown = (e: React.KeyboardEvent): void => {
+        if (e.key === "Enter") {
+            if (this._searchTerm.includes(":")) {
+                const colpos = this._searchTerm.indexOf(":");
+                const temp = this._searchTerm.slice(colpos + 1, this._searchTerm.length);
+                if (temp === "") {
+                    Doc.setDocFilter(this.props.Document, this._key, this.tempfilter, "remove");
+                    this.updateFilter();
+                }
+                else {
+                    Doc.setDocFilter(this.props.Document, this._key, this.tempfilter, "remove");
+                    this.tempfilter = temp;
+                    Doc.setDocFilter(this.props.Document, this._key, temp, "check");
+                    this.props.col.setColor("green");
+                    this.closeResultsVisibility = "contents";
+                }
+            }
+            else {
+                Doc.setDocFilter(this.props.Document, this._key, this.tempfilter, "remove");
+                this.updateFilter();
+                if (this.showKeys.length) {
+                    this.onSelect(this.showKeys[0]);
+                } else if (this._searchTerm !== "" && this.props.canAddNew) {
+                    this.setSearchTerm(this._searchTerm || this._key);
+                    this.onSelect(this._searchTerm);
+                }
+            }
+        }
+    }
+
+    onChange = (val: string): void => {
+        this.setSearchTerm(val);
+    }
+
+    @action
+    onFocus = (e: React.FocusEvent): void => {
+        this._isOpen = true;
+        this.props.setIsEditing(true);
+    }
+
+    @computed get showKeys() {
+        const whitelistKeys = ["context", "author", "*lastModified", "text", "data", "tags", "creationDate"];
+        const keyOptions = this._searchTerm === "" ? this.props.possibleKeys : this.props.possibleKeys.filter(key => key.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1);
+        const showKeys = new Set<string>();
+        [...keyOptions, ...whitelistKeys].forEach(key => (!Doc.UserDoc().noviceMode ||
+            whitelistKeys.includes(key)
+            || ((!key.startsWith("_") && key[0] === key[0].toUpperCase()) || key[0] === "#")) ? showKeys.add(key) : null);
+        return Array.from(showKeys.keys()).filter(key => !this._searchTerm || key.includes(this._searchTerm));
+    }
+    @action
+    renderOptions = (): JSX.Element[] | JSX.Element => {
+        if (!this._isOpen) {
+            this.defaultMenuHeight = 0;
+            return <></>;
+        }
+        const options = this.showKeys.map(key => {
+            return <div key={key} className="key-option" style={{
+                border: "1px solid lightgray",
+                width: this.props.width, maxWidth: this.props.width, overflowX: "hidden", background: "white",
+            }}
+                onPointerDown={e => {
+                    e.stopPropagation();
+                }}
+                onClick={() => {
+                    this.onSelect(key);
+                    this.setSearchTerm("");
+                }}>{key}</div>;
+        });
+
+        // if search term does not already exist as a group type, give option to create new group type
+
+        if (this._key !== this._searchTerm.slice(0, this._key.length)) {
+            if (this._searchTerm !== "" && this.props.canAddNew) {
+                options.push(<div key={""} className="key-option" style={{
+                    border: "1px solid lightgray", width: this.props.width, maxWidth: this.props.width, overflowX: "hidden", background: "white",
+                }}
+                    onClick={() => { this.onSelect(this._searchTerm); this.setSearchTerm(""); }}>
+                    Create "{this._searchTerm}" key</div>);
+            }
+        }
+
+        if (options.length === 0) {
+            this.defaultMenuHeight = 0;
+        }
+        else {
+            if (this.props.docs) {
+                const panesize = this.props.docs.length * 30;
+                options.length * 20 + 8 - 10 > panesize ? this.defaultMenuHeight = panesize : this.defaultMenuHeight = options.length * 20 + 8;
+            }
+            else {
+                options.length > 5 ? this.defaultMenuHeight = 108 : this.defaultMenuHeight = options.length * 20 + 8;
+            }
+        }
+        return options;
+    }
+
+    docSafe: Doc[] = [];
+
+    @action
+    renderFilterOptions = (): JSX.Element[] | JSX.Element => {
+        if (!this._isOpen || !this.props.dataDoc) {
+            this.defaultMenuHeight = 0;
+            return <></>;
+        }
+        const keyOptions: string[] = [];
+        const colpos = this._searchTerm.indexOf(":");
+        const temp = this._searchTerm.slice(colpos + 1, this._searchTerm.length);
+        if (this.docSafe.length === 0) {
+            this.docSafe = DocListCast(this.props.dataDoc[this.props.fieldKey]);
+        }
+        const docs = this.docSafe;
+        docs.forEach((doc) => {
+            const key = StrCast(doc[this._key]);
+            if (keyOptions.includes(key) === false && key.includes(temp) && key !== "") {
+                keyOptions.push(key);
+            }
+        });
+
+        const filters = Cast(this.props.Document._docFilters, listSpec("string"));
+        if (filters === undefined || filters.length === 0 || filters.some(filter => filter.split(":")[0] === this._key) === false) {
+            this.props.col.setColor("rgb(241, 239, 235)");
+            this.closeResultsVisibility = "none";
+        }
+        for (let i = 0; i < (filters?.length ?? 0) - 1; i++) {
+            if (filters![i] === this.props.col.heading && keyOptions.includes(filters![i].split(":")[1]) === false) {
+                keyOptions.push(filters![i + 1]);
+            }
+        }
+        const options = keyOptions.map(key => {
+            let bool = false;
+            if (filters !== undefined) {
+                const ind = filters.findIndex(filter => filter.split(":")[0] === key);
+                const fields = ind === -1 ? undefined : filters[ind].split(":");
+                bool = fields ? fields[1] === "check" : false;
+            }
+            return <div key={key} className="key-option" style={{
+                border: "1px solid lightgray", paddingLeft: 5, textAlign: "left",
+                width: this.props.width, maxWidth: this.props.width, overflowX: "hidden", background: "white", backgroundColor: "white",
+            }}
+            >
+                <input type="checkbox"
+                    onPointerDown={e => e.stopPropagation()}
+                    onClick={e => e.stopPropagation()}
+                    onChange={(e) => {
+                        e.target.checked === true ? Doc.setDocFilter(this.props.Document, this._key, key, "check") : Doc.setDocFilter(this.props.Document, this._key, key, "remove");
+                        e.target.checked === true ? this.closeResultsVisibility = "contents" : console.log("");
+                        e.target.checked === true ? this.props.col.setColor("green") : this.updateFilter();
+                        e.target.checked === true && SearchBox.Instance.filter === true ? Doc.setDocFilter(docs[0], this._key, key, "check") : Doc.setDocFilter(docs[0], this._key, key, "remove");
+                    }}
+                    checked={bool}
+                />
+                <span style={{ paddingLeft: 4 }}>
+                    {key}
+                </span>
+
+            </div>;
+        });
+        if (options.length === 0) {
+            this.defaultMenuHeight = 0;
+        }
+        else {
+            if (this.props.docs) {
+                const panesize = this.props.docs.length * 30;
+                options.length * 20 + 8 - 10 > panesize ? this.defaultMenuHeight = panesize : this.defaultMenuHeight = options.length * 20 + 8;
+            }
+            else {
+                options.length > 5 ? this.defaultMenuHeight = 108 : this.defaultMenuHeight = options.length * 20 + 8;
+            }
+
+        }
+        return options;
+    }
+
+    @observable defaultMenuHeight = 0;
+
+
+    updateFilter() {
+        const filters = Cast(this.props.Document._docFilters, listSpec("string"));
+        if (filters === undefined || filters.length === 0 || filters.some(filter => filter.split(":")[0] === this._key) === false) {
+            this.props.col.setColor("rgb(241, 239, 235)");
+            this.closeResultsVisibility = "none";
+        }
+    }
+
+    @computed get scriptField() {
+        const scriptText = "setDocFilter(containingTreeView, heading, this.title, checked)";
+        const script = ScriptField.MakeScript(scriptText, { this: Doc.name, heading: "string", checked: "string", containingTreeView: Doc.name });
+        return script ? () => script : undefined;
+    }
+    filterBackground = () => "rgba(105, 105, 105, 0.432)";
+    @observable filterOpen: boolean | undefined = undefined;
+    closeResultsVisibility: string = "none";
+
+    removeFilters = (e: React.PointerEvent): void => {
+        const keyOptions: string[] = [];
+        if (this.docSafe.length === 0 && this.props.dataDoc) {
+            this.docSafe = DocListCast(this.props.dataDoc[this.props.fieldKey]);
+        }
+        const docs = this.docSafe;
+        docs.forEach((doc) => {
+            const key = StrCast(doc[this._key]);
+            if (keyOptions.includes(key) === false) {
+                keyOptions.push(key);
+            }
+        });
+
+        Doc.setDocFilter(this.props.Document, this._key, "", "remove");
+        this.props.col.setColor("rgb(241, 239, 235)");
+        this.closeResultsVisibility = "none";
+    }
+    render() {
+        return (
+            <div style={{ display: "flex" }} ref={this.setNode}>
+                <FontAwesomeIcon onClick={e => { this.props.openHeader(this.props.col, e.clientX, e.clientY); e.stopPropagation(); }} icon={this.props.icon} size="lg" style={{ display: "inline", paddingBottom: "1px", paddingTop: "4px", cursor: "hand" }} />
+
+                {/* <FontAwesomeIcon icon={fa.faSearchMinus} size="lg" style={{ display: "inline", paddingBottom: "1px", paddingTop: "4px", cursor: "hand" }} onClick={e => {
+                    runInAction(() => { this._isOpen === undefined ? this._isOpen = true : this._isOpen = !this._isOpen })
+                }} /> */}
+
+                <div className="keys-dropdown" style={{ zIndex: 1, width: this.props.width, maxWidth: this.props.width }}>
+                    <input className="keys-search" style={{ width: "100%" }}
+                        ref={this._inputRef} type="text" value={this._searchTerm} placeholder="Column key" onKeyDown={this.onKeyDown}
+                        onChange={e => this.onChange(e.target.value)}
+                        onClick={(e) => { e.stopPropagation(); this._inputRef.current?.focus(); }}
+                        onFocus={this.onFocus} ></input>
+                    <div style={{ display: this.closeResultsVisibility }}>
+                        <FontAwesomeIcon onPointerDown={this.removeFilters} icon={"times-circle"} size="lg"
+                            style={{ cursor: "hand", color: "grey", padding: 2, left: -20, top: -1, height: 15, position: "relative" }} />
+                    </div>
+                    {!this._isOpen ? (null) : <div className="keys-options-wrapper" style={{
+                        width: this.props.width, maxWidth: this.props.width, height: "auto",
+                    }}>
+                        {this._searchTerm.includes(":") ? this.renderFilterOptions() : this.renderOptions()}
+                    </div>}
+                </div >
+            </div>
+        );
+    }
+}
-- 
cgit v1.2.3-70-g09d2


From 0ac0b74de8578062aa7f700779613ff0e18a12ea Mon Sep 17 00:00:00 2001
From: 0x85FB9C51 <77808164+0x85FB9C51@users.noreply.github.com>
Date: Thu, 8 Jul 2021 09:48:51 -0400
Subject: fixed file path mess

---
 src/client/views/collections/CollectionView.tsx    |  2 +-
 .../schemaView/CollectionSchemaCells.tsx           |  2 +-
 .../schemaView/CollectionSchemaHeaders.tsx         |  3 +-
 .../schemaView/CollectionSchemaMovableTableHOC.tsx | 18 +++++-----
 .../schemaView/CollectionSchemaView.tsx            | 38 +++++++++++-----------
 .../views/collections/schemaView/SchemaTable.tsx   |  2 +-
 src/client/views/search/SearchBox.tsx              |  4 +--
 7 files changed, 35 insertions(+), 34 deletions(-)

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

diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index fb60265e3..e5b1721f9 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -29,7 +29,7 @@ import CollectionMapView from './CollectionMapView';
 import { CollectionMulticolumnView } from './collectionMulticolumn/CollectionMulticolumnView';
 import { CollectionMultirowView } from './collectionMulticolumn/CollectionMultirowView';
 import { CollectionPileView } from './CollectionPileView';
-import { CollectionSchemaView } from "./CollectionSchemaView";
+import { CollectionSchemaView } from "./schemaView/CollectionSchemaView";
 import { CollectionStackingView } from './CollectionStackingView';
 import { SubCollectionViewProps } from './CollectionSubView';
 import { CollectionTimeView } from './CollectionTimeView';
diff --git a/src/client/views/collections/schemaView/CollectionSchemaCells.tsx b/src/client/views/collections/schemaView/CollectionSchemaCells.tsx
index 2549beaae..f2df87d71 100644
--- a/src/client/views/collections/schemaView/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/schemaView/CollectionSchemaCells.tsx
@@ -24,7 +24,7 @@ import { CompileScript } from "../../../util/Scripting";
 import { SearchUtil } from "../../../util/SearchUtil";
 import { SnappingManager } from "../../../util/SnappingManager";
 import { undoBatch } from "../../../util/UndoManager";
-import '../DocumentDecorations.scss';
+import '../../../views/DocumentDecorations.scss';
 import { EditableView } from "../../EditableView";
 import { MAX_ROW_HEIGHT } from '../../globalCssVariables.scss';
 import { DocumentIconContainer } from "../../nodes/DocumentIcon";
diff --git a/src/client/views/collections/schemaView/CollectionSchemaHeaders.tsx b/src/client/views/collections/schemaView/CollectionSchemaHeaders.tsx
index b825d6d96..ab3076224 100644
--- a/src/client/views/collections/schemaView/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/schemaView/CollectionSchemaHeaders.tsx
@@ -10,7 +10,8 @@ import { ScriptField } from "../../../../fields/ScriptField";
 import { Cast, StrCast } from "../../../../fields/Types";
 import { undoBatch } from "../../../util/UndoManager";
 import { SearchBox } from "../../search/SearchBox";
-import { ColumnType } from "../CollectionSchemaView";
+import { ColumnType } from "./CollectionSchemaView";
+import { ColumnType2 } from "../CollectionSchemaView";
 import "./CollectionSchemaView.scss";
 import { CollectionView } from "../CollectionView";
 
diff --git a/src/client/views/collections/schemaView/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/schemaView/CollectionSchemaMovableTableHOC.tsx
index 149677976..e1066caf4 100644
--- a/src/client/views/collections/schemaView/CollectionSchemaMovableTableHOC.tsx
+++ b/src/client/views/collections/schemaView/CollectionSchemaMovableTableHOC.tsx
@@ -2,15 +2,15 @@ import React = require("react");
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { action } from "mobx";
 import { ReactTableDefaults, RowInfo, TableCellRenderer } from "react-table";
-import { Doc } from "../../../fields/Doc";
-import { SchemaHeaderField } from "../../../fields/SchemaHeaderField";
-import { Cast, FieldValue, StrCast } from "../../../fields/Types";
-import { DocumentManager } from "../../util/DocumentManager";
-import { DragManager, dropActionType, SetupDrag } from "../../util/DragManager";
-import { SnappingManager } from "../../util/SnappingManager";
-import { Transform } from "../../util/Transform";
-import { undoBatch } from "../../util/UndoManager";
-import { ContextMenu } from "../ContextMenu";
+import { Doc } from "../../../../fields/Doc";
+import { SchemaHeaderField } from "../../../../fields/SchemaHeaderField";
+import { Cast, FieldValue, StrCast } from "../../../../fields/Types";
+import { DocumentManager } from "../../../util/DocumentManager";
+import { DragManager, dropActionType, SetupDrag } from "../../../util/DragManager";
+import { SnappingManager } from "../../../util/SnappingManager";
+import { Transform } from "../../../util/Transform";
+import { undoBatch } from "../../../util/UndoManager";
+import { ContextMenu } from "../../ContextMenu";
 import "./CollectionSchemaView.scss";
 
 export interface MovableColumnProps {
diff --git a/src/client/views/collections/schemaView/CollectionSchemaView.tsx b/src/client/views/collections/schemaView/CollectionSchemaView.tsx
index b33c437a9..ef28f75c8 100644
--- a/src/client/views/collections/schemaView/CollectionSchemaView.tsx
+++ b/src/client/views/collections/schemaView/CollectionSchemaView.tsx
@@ -5,27 +5,27 @@ import { observer } from "mobx-react";
 import Measure from "react-measure";
 import { Resize } from "react-table";
 import "react-table/react-table.css";
-import { Doc, Opt } from "../../../fields/Doc";
-import { List } from "../../../fields/List";
-import { listSpec } from "../../../fields/Schema";
-import { PastelSchemaPalette, SchemaHeaderField } from "../../../fields/SchemaHeaderField";
-import { Cast, NumCast } from "../../../fields/Types";
-import { TraceMobx } from "../../../fields/util";
-import { emptyFunction, emptyPath, returnFalse, setupMoveUpEvents, returnEmptyDoclist, returnTrue } from "../../../Utils";
-import { SelectionManager } from "../../util/SelectionManager";
-import { SnappingManager } from "../../util/SnappingManager";
-import { Transform } from "../../util/Transform";
-import { undoBatch } from "../../util/UndoManager";
-import { COLLECTION_BORDER_WIDTH, SCHEMA_DIVIDER_WIDTH } from '../../views/globalCssVariables.scss';
-import { ContextMenu } from "../ContextMenu";
-import { ContextMenuProps } from "../ContextMenuItem";
-import '../DocumentDecorations.scss';
-import { DocumentView } from "../nodes/DocumentView";
-import { DefaultStyleProvider } from "../StyleProvider";
+import { Doc, Opt } from "../../../../fields/Doc";
+import { List } from "../../../../fields/List";
+import { listSpec } from "../../../../fields/Schema";
+import { PastelSchemaPalette, SchemaHeaderField } from "../../../../fields/SchemaHeaderField";
+import { Cast, NumCast } from "../../../../fields/Types";
+import { TraceMobx } from "../../../../fields/util";
+import { emptyFunction, emptyPath, returnFalse, setupMoveUpEvents, returnEmptyDoclist, returnTrue } from "../../../../Utils";
+import { SelectionManager } from "../../../util/SelectionManager";
+import { SnappingManager } from "../../../util/SnappingManager";
+import { Transform } from "../../../util/Transform";
+import { undoBatch } from "../../../util/UndoManager";
+import { COLLECTION_BORDER_WIDTH, SCHEMA_DIVIDER_WIDTH } from '../../globalCssVariables.scss';
+import { ContextMenu } from "../../ContextMenu";
+import { ContextMenuProps } from "../../ContextMenuItem";
+import '../../../views/DocumentDecorations.scss';
+import { DocumentView } from "../../nodes/DocumentView";
+import { DefaultStyleProvider } from "../../StyleProvider";
 import "./CollectionSchemaView.scss";
-import { CollectionSubView } from "./CollectionSubView";
+import { CollectionSubView } from "../CollectionSubView";
 import { SchemaTable } from "./SchemaTable";
-import { DocUtils } from "../../documents/Documents";
+import { DocUtils } from "../../../documents/Documents";
 // bcz: need to add drag and drop of rows and columns.  This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
 
 export enum ColumnType {
diff --git a/src/client/views/collections/schemaView/SchemaTable.tsx b/src/client/views/collections/schemaView/SchemaTable.tsx
index c305f6806..05d77a739 100644
--- a/src/client/views/collections/schemaView/SchemaTable.tsx
+++ b/src/client/views/collections/schemaView/SchemaTable.tsx
@@ -23,7 +23,7 @@ import { Transform } from "../../../util/Transform";
 import { undoBatch } from "../../../util/UndoManager";
 import { COLLECTION_BORDER_WIDTH, SCHEMA_DIVIDER_WIDTH } from '../../globalCssVariables.scss';
 import { ContextMenu } from "../../ContextMenu";
-import '../DocumentDecorations.scss';
+import '../../../views/DocumentDecorations.scss';
 import { DocumentView } from "../../nodes/DocumentView";
 import { DefaultStyleProvider } from "../../StyleProvider";
 import { CellProps, CollectionSchemaButtons, CollectionSchemaCell, CollectionSchemaCheckboxCell, CollectionSchemaDateCell, CollectionSchemaDocCell, CollectionSchemaImageCell, CollectionSchemaListCell, CollectionSchemaNumberCell, CollectionSchemaStringCell } from "./CollectionSchemaCells";
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index 5c168d8a9..a671c955d 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -18,7 +18,7 @@ import { SetupDrag } from '../../util/DragManager';
 import { SearchUtil } from '../../util/SearchUtil';
 import { Transform } from '../../util/Transform';
 import { CollectionDockingView } from "../collections/CollectionDockingView";
-import { CollectionSchemaView, ColumnType } from "../collections/CollectionSchemaView";
+import { CollectionSchemaView, ColumnType } from "../collections/schemaView/CollectionSchemaView";
 import { CollectionViewType } from '../collections/CollectionView';
 import { ViewBoxBaseComponent } from "../DocComponent";
 import { FieldView, FieldViewProps } from '../nodes/FieldView';
@@ -119,7 +119,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
 
     getFinalQuery(query: string): string {
         //alters the query so it looks in the correct fields
-        //if this is true, th`en not all of the field boxes are checked
+        //if this is true, then not all of the field boxes are checked
         //TODO: data
         const initialfilters = Cast(this.props.Document._docFilters, listSpec("string"), []);
 
-- 
cgit v1.2.3-70-g09d2


From a5c099cb5ae455064f65989dc977870ce2c3f7fc Mon Sep 17 00:00:00 2001
From: 0x85FB9C51 <77808164+0x85FB9C51@users.noreply.github.com>
Date: Sat, 10 Jul 2021 16:57:45 -0400
Subject: added indentation for visibility of hierarchy

---
 src/client/util/SelectionManager.ts                |   2 +-
 .../schemaView/CollectionSchemaHeaders.tsx         |   1 -
 .../schemaView/CollectionSchemaMovableColumn.tsx   | 133 ---------------------
 .../views/collections/schemaView/SchemaTable.tsx   |   3 +-
 src/fields/SchemaHeaderField.ts                    |   2 +-
 5 files changed, 4 insertions(+), 137 deletions(-)

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

diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index ca5ef75d2..a624d5b7c 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -1,7 +1,7 @@
 import { action, observable, ObservableMap } from "mobx";
 import { computedFn } from "mobx-utils";
 import { Doc, Opt } from "../../fields/Doc";
-import { CollectionSchemaView } from "../views/collections/CollectionSchemaView";
+import { CollectionSchemaView } from "../views/collections/schemaView/CollectionSchemaView";
 import { CollectionViewType } from "../views/collections/CollectionView";
 import { DocumentView } from "../views/nodes/DocumentView";
 
diff --git a/src/client/views/collections/schemaView/CollectionSchemaHeaders.tsx b/src/client/views/collections/schemaView/CollectionSchemaHeaders.tsx
index ab3076224..b2115b22e 100644
--- a/src/client/views/collections/schemaView/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/schemaView/CollectionSchemaHeaders.tsx
@@ -11,7 +11,6 @@ import { Cast, StrCast } from "../../../../fields/Types";
 import { undoBatch } from "../../../util/UndoManager";
 import { SearchBox } from "../../search/SearchBox";
 import { ColumnType } from "./CollectionSchemaView";
-import { ColumnType2 } from "../CollectionSchemaView";
 import "./CollectionSchemaView.scss";
 import { CollectionView } from "../CollectionView";
 
diff --git a/src/client/views/collections/schemaView/CollectionSchemaMovableColumn.tsx b/src/client/views/collections/schemaView/CollectionSchemaMovableColumn.tsx
index e1066caf4..456c38c68 100644
--- a/src/client/views/collections/schemaView/CollectionSchemaMovableColumn.tsx
+++ b/src/client/views/collections/schemaView/CollectionSchemaMovableColumn.tsx
@@ -126,136 +126,3 @@ export class MovableColumn extends React.Component<MovableColumnProps> {
         );
     }
 }
-
-export interface MovableRowProps {
-    rowInfo: RowInfo;
-    ScreenToLocalTransform: () => Transform;
-    addDoc: (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => boolean;
-    removeDoc: (doc: Doc | Doc[]) => boolean;
-    rowFocused: boolean;
-    textWrapRow: (doc: Doc) => void;
-    rowWrapped: boolean;
-    dropAction: string;
-    addDocTab: any;
-}
-
-export class MovableRow extends React.Component<MovableRowProps> {
-    private _header?: React.RefObject<HTMLDivElement> = React.createRef();
-    private _rowDropDisposer?: DragManager.DragDropDisposer;
-
-    // Event listeners are only necessary when the user is hovering over the table
-    // Create one when the mouse starts hovering...
-    onPointerEnter = (e: React.PointerEvent): void => {
-        if (e.buttons === 1 && SnappingManager.GetIsDragging()) {
-            this._header!.current!.className = "collectionSchema-row-wrapper";
-            document.addEventListener("pointermove", this.onDragMove, true);
-        }
-    }
-    // ... and delete it when the mouse leaves
-    onPointerLeave = (e: React.PointerEvent): void => {
-        this._header!.current!.className = "collectionSchema-row-wrapper";
-        document.removeEventListener("pointermove", this.onDragMove, true);
-    }
-    // The method for the event listener, reorders columns when dragged to their new locations.
-    onDragMove = (e: PointerEvent): void => {
-        const x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY);
-        const rect = this._header!.current!.getBoundingClientRect();
-        const bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2);
-        const before = x[1] < bounds[1];
-        this._header!.current!.className = "collectionSchema-row-wrapper";
-        if (before) this._header!.current!.className += " row-above";
-        if (!before) this._header!.current!.className += " row-below";
-        e.stopPropagation();
-    }
-    componentWillUnmount() {
-
-        this._rowDropDisposer?.();
-    }
-    //
-    createRowDropTarget = (ele: HTMLDivElement) => {
-        this._rowDropDisposer?.();
-        if (ele) {
-            this._rowDropDisposer = DragManager.MakeDropTarget(ele, this.rowDrop.bind(this));
-        }
-    }
-    // Controls what hppens when a row is dragged and dropped
-    rowDrop = (e: Event, de: DragManager.DropEvent) => {
-        this.onPointerLeave(e as any);
-        const rowDoc = FieldValue(Cast(this.props.rowInfo.original, Doc));
-        if (!rowDoc) return false;
-
-        const x = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y);
-        const rect = this._header!.current!.getBoundingClientRect();
-        const bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2);
-        const before = x[1] < bounds[1];
-
-        const docDragData = de.complete.docDragData;
-        if (docDragData) {
-            e.stopPropagation();
-            if (docDragData.draggedDocuments[0] === rowDoc) return true;
-            const addDocument = (doc: Doc | Doc[]) => this.props.addDoc(doc, rowDoc, before);
-            const movedDocs = docDragData.draggedDocuments;
-            return (docDragData.dropAction || docDragData.userDropAction) ?
-                docDragData.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before) || added, false)
-                : (docDragData.moveDocument) ?
-                    movedDocs.reduce((added: boolean, d) => docDragData.moveDocument?.(d, rowDoc, addDocument) || added, false)
-                    : docDragData.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before), false);
-        }
-        return false;
-    }
-
-    onRowContextMenu = (e: React.MouseEvent): void => {
-        const description = this.props.rowWrapped ? "Unwrap text on row" : "Text wrap row";
-        ContextMenu.Instance.addItem({ description: description, event: () => this.props.textWrapRow(this.props.rowInfo.original), icon: "file-pdf" });
-    }
-
-    @undoBatch
-    @action
-    move: DragManager.MoveFunction = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDoc) => {
-        const targetView = targetCollection && DocumentManager.Instance.getDocumentView(targetCollection);
-        return doc !== targetCollection && doc !== targetView?.props.ContainingCollectionDoc && this.props.removeDoc(doc) && addDoc(doc);
-    }
-
-    @action
-    onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
-        console.log("yes");
-        if (e.key === "Backspace" || e.key === "Delete") {
-            undoBatch(() => this.props.removeDoc(this.props.rowInfo.original));
-        }
-    }
-
-    render() {
-        const { children = null, rowInfo } = this.props;
-
-        if (!rowInfo) {
-            return <ReactTableDefaults.TrComponent>{children}</ReactTableDefaults.TrComponent>;
-        }
-
-        const { original } = rowInfo;
-        const doc = FieldValue(Cast(original, Doc));
-
-        if (!doc) return (null);
-
-        const reference = React.createRef<HTMLDivElement>();
-        const onItemDown = SetupDrag(reference, () => doc, this.move, StrCast(this.props.dropAction) as dropActionType);
-
-        let className = "collectionSchema-row";
-        if (this.props.rowFocused) className += " row-focused";
-        if (this.props.rowWrapped) className += " row-wrapped";
-
-        return (
-            <div className={className} onKeyPress={this.onKeyDown} ref={this.createRowDropTarget} onContextMenu={this.onRowContextMenu}>
-                <div className="collectionSchema-row-wrapper" onKeyPress={this.onKeyDown} ref={this._header} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}>
-                    <ReactTableDefaults.TrComponent onKeyPress={this.onKeyDown} >
-                        <div className="row-dragger">
-                            <div className="row-option" style={{ left: 5 }} onClick={undoBatch(() => this.props.removeDoc(this.props.rowInfo.original))}><FontAwesomeIcon icon="trash" size="sm" /></div>
-                            <div className="row-option" style={{ cursor: "grab", left: 25 }} ref={reference} onPointerDown={onItemDown}><FontAwesomeIcon icon="grip-vertical" size="sm" /></div>
-                            <div className="row-option" style={{ left: 40 }} onClick={() => this.props.addDocTab(this.props.rowInfo.original, "add:right")}><FontAwesomeIcon icon="external-link-alt" size="sm" /></div>
-                        </div>
-                        {children}
-                    </ReactTableDefaults.TrComponent>
-                </div>
-            </div>
-        );
-    }
-}
\ No newline at end of file
diff --git a/src/client/views/collections/schemaView/SchemaTable.tsx b/src/client/views/collections/schemaView/SchemaTable.tsx
index a735d4257..0d5c9e077 100644
--- a/src/client/views/collections/schemaView/SchemaTable.tsx
+++ b/src/client/views/collections/schemaView/SchemaTable.tsx
@@ -458,8 +458,9 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
             expanded={expanded}
             resized={this.resized}
             onResizedChange={this.props.onResizedChange}
+            // if it has a child, render another table with the children
             SubComponent={!hasCollectionChild ? undefined : row => (row.original.type !== DocumentType.COL) ? (null) :
-                <div className="reactTable-sub"><SchemaTable {...this.props} Document={row.original} dataDoc={undefined} childDocs={undefined} /></div>}
+                <div style={{ paddingLeft: 57 + "px" }} className="reactTable-sub"><SchemaTable {...this.props} Document={row.original} dataDoc={undefined} childDocs={undefined} /></div>}
 
         />;
     }
diff --git a/src/fields/SchemaHeaderField.ts b/src/fields/SchemaHeaderField.ts
index 88de3a19f..74cf934f2 100644
--- a/src/fields/SchemaHeaderField.ts
+++ b/src/fields/SchemaHeaderField.ts
@@ -3,7 +3,7 @@ import { serializable, primitive } from "serializr";
 import { ObjectField } from "./ObjectField";
 import { Copy, ToScriptString, ToString, OnUpdate } from "./FieldSymbols";
 import { scriptingGlobal } from "../client/util/Scripting";
-import { ColumnType } from "../client/views/collections/CollectionSchemaView";
+import { ColumnType } from "../client/views/collections/schemaView/CollectionSchemaView";
 
 export const PastelSchemaPalette = new Map<string, string>([
     // ["pink1", "#FFB4E8"],
-- 
cgit v1.2.3-70-g09d2

