diff options
| author | geireann <geireann.lindfield@gmail.com> | 2021-10-14 15:01:19 -0400 |
|---|---|---|
| committer | geireann <geireann.lindfield@gmail.com> | 2021-10-14 15:01:19 -0400 |
| commit | 5bbd1b35d2c3855eae8405e26deb0c6679cc7c26 (patch) | |
| tree | c9d999f36b078d7fd8f55a74c94ce495c9fa8d4e /src/client/views/collections/collectionSchema | |
| parent | be4fd2492ad706f30af28f33133a4df0e8049e12 (diff) | |
| parent | ed68bbec549dedeb89bcb584151b097863b52d0d (diff) | |
Merge branch 'master' into schema-view-En-Hua
Diffstat (limited to 'src/client/views/collections/collectionSchema')
6 files changed, 141 insertions, 104 deletions
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx index 9a3ef1422..a439a7998 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx @@ -120,7 +120,6 @@ export class CollectionSchemaCell extends React.Component<CellProps> { this.props.changeFocusedCellByIndex(this.props.row, this.props.col); this.props.setPreviewDoc(this.props.rowProps.original); - // console.log("click cell"); let url: string; if (url = StrCast(this.props.rowProps.row.href)) { // opens up the the doc in a new window, blurring the old one @@ -338,12 +337,12 @@ export class CollectionSchemaCell extends React.Component<CellProps> { } } const script = CompileScript(inputSansCommas, { requiredType: type, typecheck: false, editable: true, addReturn: true, params: { this: Doc.name, $r: "number", $c: "number", $: "any" } }); - const changeMade = value.length !== value.length || value.length - 2 !== value.length; + const changeMade = value.length - 2 !== value.length; script.compiled && (retVal = this.applyToDoc(changeMade ? this._rowDoc : this._rowDataDoc, this.props.row, this.props.col, script.run)); // handle booleans } else if (inputIsBool) { const script = CompileScript(value, { requiredType: type, typecheck: false, editable: true, addReturn: true, params: { this: Doc.name, $r: "number", $c: "number", $: "any" } }); - const changeMade = value.length !== value.length || value.length - 2 !== value.length; + const changeMade = value.length - 2 !== value.length; script.compiled && (retVal = this.applyToDoc(changeMade ? this._rowDoc : this._rowDataDoc, this.props.row, this.props.col, script.run)); } } diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx index 52865eba6..074074bc5 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx @@ -1,18 +1,17 @@ import React = require("react"); -import { IconProp, library } from "@fortawesome/fontawesome-svg-core"; +import { IconProp } from "@fortawesome/fontawesome-svg-core"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, computed, observable, runInAction } from "mobx"; +import { action, computed, observable, runInAction, trace } from "mobx"; import { observer } from "mobx-react"; -import { Doc, DocListCast, Opt } from "../../../../fields/Doc"; +import { Doc, DocListCast, Opt, StrListCast } 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 { CollectionView } from "../CollectionView"; import { ColumnType } from "./CollectionSchemaView"; import "./CollectionSchemaView.scss"; -import { CollectionView } from "../CollectionView"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; @@ -27,9 +26,9 @@ export interface AddColumnHeaderProps { export class CollectionSchemaAddColumnHeader extends React.Component<AddColumnHeaderProps> { // the button that allows the user to add a column render() { - return ( - <button className="add-column" onClick={() => this.props.createColumn()}><FontAwesomeIcon icon="plus" size="sm" /></button> - ); + return <button className="add-column" onClick={() => this.props.createColumn()}> + <FontAwesomeIcon icon="plus" size="sm" /> + </button>; } } @@ -191,7 +190,7 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps> {this.renderSorting()} {this.renderColors()} <div className="collectionSchema-headerMenu-group"> - <button onClick={() => this.props.deleteColumn(this.props.columnField.heading)}>Delete Column</button> + <button onClick={() => this.props.deleteColumn(this.props.columnField.heading)}>Hide Column</button> </div> </> } @@ -234,7 +233,7 @@ export interface KeysDropdownProps { @observer export class KeysDropdown extends React.Component<KeysDropdownProps> { @observable private _key: string = this.props.keyValue; - @observable private _searchTerm: 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(); @@ -326,11 +325,11 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> { || ((!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 => { + + @computed get renderOptions() { if (!this._isOpen) { this.defaultMenuHeight = 0; - return <></>; + return (null); } const options = this.showKeys.map(key => { return <div key={key} className="key-option" style={{ @@ -373,30 +372,25 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> { return options; } - docSafe: Doc[] = []; + @computed get docSafe() { return DocListCast(this.props.dataDoc?.[this.props.fieldKey]); } - @action - renderFilterOptions = (): JSX.Element[] | JSX.Element => { + @computed get renderFilterOptions() { if (!this._isOpen || !this.props.dataDoc) { this.defaultMenuHeight = 0; - return <></>; + return (null); } 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) => { + this.docSafe.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) { + const filters = StrListCast(this.props.Document._docFilters); + if (filters.some(filter => filter.split(":")[0] === this._key) === false) { this.props.col.setColor("rgb(241, 239, 235)"); this.closeResultsVisibility = "none"; } @@ -408,24 +402,28 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> { const options = keyOptions.map(key => { let bool = false; if (filters !== undefined) { - const ind = filters.findIndex(filter => filter.split(":")[0] === key); + const ind = filters.findIndex(filter => filter.split(":")[1] === key); const fields = ind === -1 ? undefined : filters[ind].split(":"); - bool = fields ? fields[1] === "check" : false; + bool = fields ? fields[2] === "check" : false; } return <div key={key} className="key-option" style={{ - border: "1px solid lightgray", paddingLeft: 5, textAlign: "left", + 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 ? Doc.setDocFilter(docs[0], this._key, key, "check") : Doc.setDocFilter(docs[0], this._key, key, "remove"); - }} + onChange={action(e => { + if (e.target.checked) { + Doc.setDocFilter(this.props.Document, this._key, key, "check"); + this.closeResultsVisibility = "contents"; + this.props.col.setColor("green"); + } else { + Doc.setDocFilter(this.props.Document, this._key, key, "remove"); + this.updateFilter(); + } + })} checked={bool} /> <span style={{ paddingLeft: 4 }}> @@ -472,11 +470,7 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> { 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) => { + this.docSafe.forEach(doc => { const key = StrCast(doc[this._key]); if (keyOptions.includes(key) === false) { keyOptions.push(key); @@ -489,12 +483,10 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> { } 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 style={{ display: "flex", width: '100%', alignContent: 'center', alignItems: 'center' }} ref={this.setNode}> + <div className="schema-icon" onClick={e => { this.props.openHeader(this.props.col, e.clientX, e.clientY); e.stopPropagation(); }}> + <FontAwesomeIcon icon={this.props.icon} size="lg" style={{ display: "inline" }} /> + </div> <div className="keys-dropdown" style={{ zIndex: 1, width: this.props.width, maxWidth: this.props.width }}> <input className="keys-search" style={{ width: "100%" }} @@ -509,7 +501,7 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> { {!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()} + {this._searchTerm.includes(":") ? this.renderFilterOptions : this.renderOptions} </div>} </div > </div> diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaMovableRow.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaMovableRow.tsx index f48906ba5..0e19ef3d9 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaMovableRow.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaMovableRow.tsx @@ -134,9 +134,9 @@ export class MovableRow extends React.Component<MovableRowProps> { <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 className="row-option" onClick={undoBatch(() => this.props.removeDoc(this.props.rowInfo.original))}><FontAwesomeIcon icon="trash" size="sm" /></div> + <div className="row-option" style={{ cursor: "grab" }} ref={reference} onPointerDown={onItemDown}><FontAwesomeIcon icon="grip-vertical" size="sm" /></div> + <div className="row-option" onClick={() => this.props.addDocTab(this.props.rowInfo.original, "add:right")}><FontAwesomeIcon icon="external-link-alt" size="sm" /></div> </div> {children} </ReactTableDefaults.TrComponent> diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss index c17b79638..b64e9dac1 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss @@ -108,9 +108,7 @@ } .rt-th { padding: 0; - border: solid lightgray; - border-width: 0 1px; - border-bottom: 2px solid lightgray; + border-left: solid 1px $light-gray; } } .rt-th { @@ -220,6 +218,8 @@ } } + + .collectionSchemaView-header { height: 100%; color: gray; @@ -234,6 +234,15 @@ button.add-column { width: 28px; } +.collectionSchemaView-menuOptions-wrapper { + background: rgb(241, 239, 235); + display: flex; + cursor: default; + height: 100%; + align-content: center; + align-items: center; +} + .collectionSchema-header-menuOptions { color: black; width: 180px; @@ -279,6 +288,9 @@ button.add-column { width: 10px; } } + + + .keys-dropdown { position: relative; //width: 100%; @@ -294,26 +306,7 @@ button.add-column { font-weight: normal; } } - .keys-options-wrapper { - width: 100%; - max-height: 150px; - overflow-y: scroll; - position: absolute; - top: 28px; - box-shadow: 0 10px 16px rgba(0, 0, 0, 0.1); - background-color: white; - .key-option { - background-color: white; - border: 1px solid lightgray; - padding: 2px 3px; - &:not(:first-child) { - border-top: 0; - } - &:hover { - background-color: $light-gray; - } - } - } + } .columnMenu-colors { display: flex; @@ -332,11 +325,53 @@ button.add-column { } } +.schema-icon { + cursor: pointer; + width: 25px; + height: 25px; + display: flex; + align-items: center; + justify-content: center; + align-content: center; + background-color: $medium-blue; + color: white; + margin-right: 5px; + font-size: 10px; + border-radius: 3px; + +} + +.keys-options-wrapper { + position: absolute; + text-align: left; + height: fit-content; + top: 100%; + z-index: 21; + background-color: #ffffff; + box-shadow: 0px 3px 4px rgba(0,0,0,30%); + padding: 1px; + .key-option { + cursor: pointer; + color: #000000; + width: 100%; + height: 25px; + font-weight: 400; + display: flex; + justify-content: left; + align-items: center; + padding-left: 5px; + &:hover { + background-color: $light-gray; + } + } +} + .collectionSchema-row { height: 100%; background-color: white; &.row-focused .rt-td { - background-color: #bfffc0; //$light-gray; + background-color: $light-blue; //$light-gray; + overflow: visible; } &.row-wrapped { .rt-td { @@ -345,39 +380,40 @@ button.add-column { } .row-dragger { display: flex; - justify-content: space-around; - //flex: 50 0 auto; - width: 0; - max-width: 50px; - //height: 100%; + justify-content: space-evenly; + width: 58px; + position: absolute; + /* max-width: 50px; */ min-height: 30px; align-items: center; color: lightgray; background-color: white; transition: color 0.1s ease; .row-option { - // padding: 5px; + color: black; cursor: pointer; - position: absolute; + position: relative; transition: color 0.1s ease; display: flex; flex-direction: column; justify-content: center; z-index: 2; + border-radius: 3px; + padding: 3px; &:hover { - color: gray; + background-color: $light-gray; } } } .collectionSchema-row-wrapper { &.row-above { - border-top: 1px solid red; + border-top: 1px solid $medium-blue; } &.row-below { - border-bottom: 1px solid red; + border-bottom: 1px solid $medium-blue; } &.row-inside { - border: 1px solid red; + border: 2px dashed $medium-blue; } .row-dragging { background-color: blue; @@ -390,28 +426,37 @@ button.add-column { height: unset; } +.collectionSchemaView-cellContents { + width: 100%; +} + .collectionSchemaView-cellWrapper { + display: flex; height: 100%; - padding: 4px; text-align: left; padding-left: 19px; position: relative; + align-items: center; + align-content: center; &:focus { outline: none; } &.editing { padding: 0; + box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3); + transform: scale(1.1); + z-index: 40; input { outline: 0; border: none; - background-color: rgb(255, 217, 217); + background-color: $white; width: 100%; - height: 100%; - padding: 2px 3px; + height: fit-content; min-height: 26px; } } &.focused { + overflow: hidden; &.inactive { border: none; } diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index fed64b620..b89246489 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -1,6 +1,6 @@ import React = require("react"); import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, observable, untracked } from "mobx"; +import { action, computed, observable, untracked, trace } from "mobx"; import { observer } from "mobx-react"; import Measure from "react-measure"; import { Resize } from "react-table"; @@ -337,8 +337,9 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { {this.renderTypes(this._col)} {this.renderColors(this._col)} <div className="collectionSchema-headerMenu-group"> - <button onClick={() => { this.deleteColumn(this._col.heading); }} - >Delete Column</button> + <button onClick={() => { this.deleteColumn(this._col.heading); }}> + Hide Column + </button> </div> </div>; } @@ -353,7 +354,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @action setFocused = (doc: Doc) => this._focusedTable = doc; @action setPreviewDoc = (doc: Opt<Doc>) => { - SelectionManager.SelectSchemaView(this, doc); + SelectionManager.SelectSchemaViewDoc(doc); this._previewDoc = doc; } diff --git a/src/client/views/collections/collectionSchema/SchemaTable.tsx b/src/client/views/collections/collectionSchema/SchemaTable.tsx index 631f623c6..bc5a9559f 100644 --- a/src/client/views/collections/collectionSchema/SchemaTable.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTable.tsx @@ -1,7 +1,7 @@ import React = require("react"); import { IconProp } from '@fortawesome/fontawesome-svg-core'; 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 ReactTable, { CellInfo, Column, ComponentPropsGetterR, Resize, SortingRule } from "react-table"; import "react-table/react-table.css"; @@ -194,10 +194,10 @@ export class SchemaTable extends React.Component<SchemaTableProps> { const sortIcon = col.desc === undefined ? "caret-right" : col.desc === true ? "caret-down" : "caret-up"; const header = <div className="collectionSchemaView-menuOptions-wrapper" style={{ background: col.color, padding: "2px", display: "flex", cursor: "default", height: "100%", }}> {keysDropdown} - <div onClick={e => this.changeSorting(col)} style={{ width: 21, padding: 1, display: "inline", zIndex: 1, background: "inherit", cursor: "hand" }}> + <div onClick={e => this.changeSorting(col)} style={{ width: 21, padding: 1, display: "inline", zIndex: 1, background: "inherit", cursor: "pointer" }}> <FontAwesomeIcon icon={sortIcon} size="lg" /> </div> - {this.props.Document._chromeHidden || this.props.addDocument === returnFalse ? undefined : <div className="collectionSchemaView-addRow" onClick={this.createRow}>+ new</div>} + {/* {this.props.Document._chromeHidden || this.props.addDocument == returnFalse ? undefined : <div className="collectionSchemaView-addRow" onClick={this.createRow}>+ new</div>} */} </div>; return { @@ -386,13 +386,13 @@ export class SchemaTable extends React.Component<SchemaTableProps> { @undoBatch @action createColumn = () => { - let index = 0; - let found = this.props.columns.findIndex(col => col.heading.toUpperCase() === "New field".toUpperCase()) > -1; - while (found) { - index++; - found = this.props.columns.findIndex(col => col.heading.toUpperCase() === ("New field (" + index + ")").toUpperCase()) > -1; + const newFieldName = (index: number) => `New field${index ? ` (${index})` : ""}`; + for (let index = 0; index < 100; index++) { + if (this.props.columns.findIndex(col => col.heading === newFieldName(index)) === -1) { + this.props.columns.push(new SchemaHeaderField(newFieldName(index), "#f1efeb")); + break; + } } - this.props.columns.push(new SchemaHeaderField(`New field ${index ? "(" + index + ")" : ""}`, "#f1efeb")); } @action @@ -567,7 +567,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> { <div className="collectionSchemaView-documentPreview" ref="overlay" style={{ position: "absolute", width: 150, height: 150, - background: "dimGray", display: "block", top: 0, left: 0, + background: "dimgray", display: "block", top: 0, left: 0, transform: `translate(${this._showDocPos[0]}px, ${this._showDocPos[1] - 180}px)` }} > <DocumentView |
