diff options
| author | brynnchernosky <56202540+brynnchernosky@users.noreply.github.com> | 2023-05-16 21:24:15 -0400 |
|---|---|---|
| committer | brynnchernosky <56202540+brynnchernosky@users.noreply.github.com> | 2023-05-16 21:24:15 -0400 |
| commit | 3d12a980fee4eb5689bffa6ec82c7899e1509fa9 (patch) | |
| tree | 24ffd982396c53c74032303ba66bb6f72ced40f5 /src/client/views/collections/CollectionMasonryViewFieldRow.tsx | |
| parent | d8fe4e0b9924b6f7f6f79da7745642d68bef5436 (diff) | |
| parent | 2e6cba3995d82acc15bd34a7035e4a5786795211 (diff) | |
Merge branch 'master' into physics_simulation
Diffstat (limited to 'src/client/views/collections/CollectionMasonryViewFieldRow.tsx')
| -rw-r--r-- | src/client/views/collections/CollectionMasonryViewFieldRow.tsx | 311 |
1 files changed, 158 insertions, 153 deletions
diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx index a94e706eb..befd89e41 100644 --- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx +++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx @@ -1,24 +1,24 @@ -import React = require("react"); -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, computed, observable, runInAction } from "mobx"; -import { observer } from "mobx-react"; -import { DataSym, Doc, DocListCast } from "../../../fields/Doc"; -import { Id } from "../../../fields/FieldSymbols"; -import { PastelSchemaPalette, SchemaHeaderField } from "../../../fields/SchemaHeaderField"; -import { ScriptField } from "../../../fields/ScriptField"; -import { NumCast, StrCast } from "../../../fields/Types"; -import { emptyFunction, numberRange, returnEmptyString, setupMoveUpEvents } from "../../../Utils"; -import { Docs } from "../../documents/Documents"; -import { DragManager } from "../../util/DragManager"; -import { CompileScript } from "../../util/Scripting"; -import { SnappingManager } from "../../util/SnappingManager"; -import { Transform } from "../../util/Transform"; -import { undoBatch } from "../../util/UndoManager"; -import { EditableView } from "../EditableView"; -import { FormattedTextBox } from "../nodes/formattedText/FormattedTextBox"; -import { CollectionStackingView } from "./CollectionStackingView"; -import "./CollectionStackingView.scss"; -const higflyout = require("@hig/flyout"); +import React = require('react'); +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { action, computed, observable, runInAction } from 'mobx'; +import { observer } from 'mobx-react'; +import { DataSym, Doc, DocListCast } from '../../../fields/Doc'; +import { Id } from '../../../fields/FieldSymbols'; +import { PastelSchemaPalette, SchemaHeaderField } from '../../../fields/SchemaHeaderField'; +import { ScriptField } from '../../../fields/ScriptField'; +import { NumCast, StrCast } from '../../../fields/Types'; +import { emptyFunction, numberRange, returnEmptyString, setupMoveUpEvents } from '../../../Utils'; +import { Docs } from '../../documents/Documents'; +import { DragManager } from '../../util/DragManager'; +import { CompileScript } from '../../util/Scripting'; +import { SnappingManager } from '../../util/SnappingManager'; +import { Transform } from '../../util/Transform'; +import { undoBatch } from '../../util/UndoManager'; +import { EditableView } from '../EditableView'; +import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; +import { CollectionStackingView } from './CollectionStackingView'; +import './CollectionStackingView.scss'; +const higflyout = require('@hig/flyout'); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -32,7 +32,7 @@ interface CMVFieldRowProps { docList: Doc[]; parent: CollectionStackingView; pivotField: string; - type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined; + type: 'string' | 'number' | 'bigint' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function' | undefined; createDropTarget: (ele: HTMLDivElement) => void; screenToLocalTransform: () => Transform; setDocHeight: (key: string, thisHeight: number) => void; @@ -43,15 +43,21 @@ interface CMVFieldRowProps { @observer export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowProps> { - @observable private _background = "inherit"; + @observable private _background = 'inherit'; @observable private _createAliasSelected: boolean = false; - @observable private heading: string = ""; - @observable private color: string = "#f1efeb"; + @observable private heading: string = ''; + @observable private color: string = '#f1efeb'; @observable private collapsed: boolean = false; @observable private _paletteOn = false; - private set _heading(value: string) { runInAction(() => this.props.headingObject && (this.props.headingObject.heading = this.heading = value)); } - private set _color(value: string) { runInAction(() => this.props.headingObject && (this.props.headingObject.color = this.color = value)); } - private set _collapsed(value: boolean) { runInAction(() => this.props.headingObject && (this.props.headingObject.collapsed = this.collapsed = value)); } + private set _heading(value: string) { + runInAction(() => this.props.headingObject && (this.props.headingObject.heading = this.heading = value)); + } + private set _color(value: string) { + runInAction(() => this.props.headingObject && (this.props.headingObject.color = this.color = value)); + } + private set _collapsed(value: boolean) { + runInAction(() => this.props.headingObject && (this.props.headingObject.collapsed = this.collapsed = value)); + } private _dropDisposer?: DragManager.DragDropDisposer; private _headerRef: React.RefObject<HTMLDivElement> = React.createRef(); @@ -65,11 +71,11 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr this.props.observeHeight(ele); this._dropDisposer = DragManager.MakeDropTarget(ele, this.rowDrop.bind(this)); } - } + }; @action componentDidMount() { - this.heading = this.props.headingObject?.heading || ""; - this.color = this.props.headingObject?.color || "#f1efeb"; + this.heading = this.props.headingObject?.heading || ''; + this.color = this.props.headingObject?.color || '#f1efeb'; this.collapsed = this.props.headingObject?.collapsed || false; } componentWillUnmount() { @@ -85,14 +91,13 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr const trueHeight = rawHeight * transformScale; this.props.setDocHeight(this.heading, trueHeight); } - } + }; @undoBatch rowDrop = action((e: Event, de: DragManager.DropEvent) => { this._createAliasSelected = false; if (de.complete.docDragData) { - (this.props.parent.Document.dropConverter instanceof ScriptField) && - this.props.parent.Document.dropConverter.script.run({ dragData: de.complete.docDragData }); + this.props.parent.Document.dropConverter instanceof ScriptField && this.props.parent.Document.dropConverter.script.run({ dragData: de.complete.docDragData }); const key = this.props.pivotField; const castedValue = this.getValue(this.heading); const onLayoutDoc = this.onLayoutDoc(key); @@ -105,10 +110,10 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr getValue = (value: string): any => { const parsed = parseInt(value); if (!isNaN(parsed)) return parsed; - if (value.toLowerCase().indexOf("true") > -1) return true; - if (value.toLowerCase().indexOf("false") > -1) return false; + if (value.toLowerCase().indexOf('true') > -1) return true; + if (value.toLowerCase().indexOf('false') > -1) return false; return value; - } + }; @action headingChanged = (value: string, shiftDown?: boolean) => { @@ -126,58 +131,60 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr return true; } return false; - } + }; @action changeColumnColor = (color: string) => { this._createAliasSelected = false; this._color = color; - } + }; - pointerEnteredRow = action(() => SnappingManager.GetIsDragging() && (this._background = "#b4b4b4")); + pointerEnteredRow = action(() => SnappingManager.GetIsDragging() && (this._background = '#b4b4b4')); @action pointerLeaveRow = () => { this._createAliasSelected = false; - this._background = "inherit"; - } + this._background = 'inherit'; + }; @action addDocument = (value: string, shiftDown?: boolean, forceEmptyNote?: boolean) => { if (!value && !forceEmptyNote) return false; this._createAliasSelected = false; const key = this.props.pivotField; - const newDoc = Docs.Create.TextDocument("", { _autoHeight: true, _width: 200, _fitWidth: true, title: value }); + const newDoc = Docs.Create.TextDocument('', { _autoHeight: true, _width: 200, _fitWidth: true, title: value }); const onLayoutDoc = this.onLayoutDoc(key); FormattedTextBox.SelectOnLoad = newDoc[Id]; FormattedTextBox.SelectOnLoadChar = value; (onLayoutDoc ? newDoc : newDoc[DataSym])[key] = this.getValue(this.props.heading); const docs = this.props.parent.childDocList; return docs ? (docs.splice(0, 0, newDoc) ? true : false) : this.props.parent.props.addDocument?.(newDoc) || false; // should really extend addDocument to specify insertion point (at beginning of list) - } + }; - deleteRow = undoBatch(action(() => { - this._createAliasSelected = false; - const key = this.props.pivotField; - this.props.docList.forEach(d => Doc.SetInPlace(d, key, undefined, true)); - if (this.props.parent.columnHeaders && this.props.headingObject) { - const index = this.props.parent.columnHeaders.indexOf(this.props.headingObject); - this.props.parent.columnHeaders.splice(index, 1); - } - })); + deleteRow = undoBatch( + action(() => { + this._createAliasSelected = false; + const key = this.props.pivotField; + this.props.docList.forEach(d => Doc.SetInPlace(d, key, undefined, true)); + if (this.props.parent.columnHeaders && this.props.headingObject) { + const index = this.props.parent.columnHeaders.indexOf(this.props.headingObject); + this.props.parent.columnHeaders.splice(index, 1); + } + }) + ); @action collapseSection = (e: any) => { this._createAliasSelected = false; this.toggleVisibility(); e.stopPropagation(); - } + }; headerMove = (e: PointerEvent) => { const alias = Doc.MakeAlias(this.props.Document); const key = this.props.pivotField; let value = this.getValue(this.heading); - value = typeof value === "string" ? `"${value}"` : value; + value = typeof value === 'string' ? `"${value}"` : value; const script = `return doc.${key} === ${value}`; const compiled = CompileScript(script, { params: { doc: Doc.name } }); if (compiled.compiled) { @@ -185,7 +192,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr DragManager.StartDocumentDrag([this._headerRef.current!], new DragManager.DocumentDragData([alias]), e.clientX, e.clientY); } return true; - } + }; @action headerDown = (e: React.PointerEvent<HTMLDivElement>) => { @@ -193,7 +200,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr setupMoveUpEvents(this, e, this.headerMove, emptyFunction, e => !this.props.chromeHidden && this.collapseSection(e)); this._createAliasSelected = false; } - } + }; /** * Returns true if a key is on the layout doc of the documents in the collection. @@ -203,143 +210,141 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr if (Doc.Get(doc, key, true)) return true; }); return false; - } + }; renderColorPicker = () => { const selected = this.color; - const pink = PastelSchemaPalette.get("pink2"); - const purple = PastelSchemaPalette.get("purple4"); - const blue = PastelSchemaPalette.get("bluegreen1"); - const yellow = PastelSchemaPalette.get("yellow4"); - const red = PastelSchemaPalette.get("red2"); - const green = PastelSchemaPalette.get("bluegreen7"); - const cyan = PastelSchemaPalette.get("bluegreen5"); - const orange = PastelSchemaPalette.get("orange1"); - const gray = "#f1efeb"; + const pink = PastelSchemaPalette.get('pink2'); + const purple = PastelSchemaPalette.get('purple4'); + const blue = PastelSchemaPalette.get('bluegreen1'); + const yellow = PastelSchemaPalette.get('yellow4'); + const red = PastelSchemaPalette.get('red2'); + const green = PastelSchemaPalette.get('bluegreen7'); + const cyan = PastelSchemaPalette.get('bluegreen5'); + const orange = PastelSchemaPalette.get('orange1'); + const gray = '#f1efeb'; return ( <div className="collectionStackingView-colorPicker"> <div className="colorOptions"> - <div className={"colorPicker" + (selected === pink ? " active" : "")} style={{ backgroundColor: pink }} onClick={() => this.changeColumnColor(pink!)}></div> - <div className={"colorPicker" + (selected === purple ? " active" : "")} style={{ backgroundColor: purple }} onClick={() => this.changeColumnColor(purple!)}></div> - <div className={"colorPicker" + (selected === blue ? " active" : "")} style={{ backgroundColor: blue }} onClick={() => this.changeColumnColor(blue!)}></div> - <div className={"colorPicker" + (selected === yellow ? " active" : "")} style={{ backgroundColor: yellow }} onClick={() => this.changeColumnColor(yellow!)}></div> - <div className={"colorPicker" + (selected === red ? " active" : "")} style={{ backgroundColor: red }} onClick={() => this.changeColumnColor(red!)}></div> - <div className={"colorPicker" + (selected === gray ? " active" : "")} style={{ backgroundColor: gray }} onClick={() => this.changeColumnColor(gray)}></div> - <div className={"colorPicker" + (selected === green ? " active" : "")} style={{ backgroundColor: green }} onClick={() => this.changeColumnColor(green!)}></div> - <div className={"colorPicker" + (selected === cyan ? " active" : "")} style={{ backgroundColor: cyan }} onClick={() => this.changeColumnColor(cyan!)}></div> - <div className={"colorPicker" + (selected === orange ? " active" : "")} style={{ backgroundColor: orange }} onClick={() => this.changeColumnColor(orange!)}></div> + <div className={'colorPicker' + (selected === pink ? ' active' : '')} style={{ backgroundColor: pink }} onClick={() => this.changeColumnColor(pink!)}></div> + <div className={'colorPicker' + (selected === purple ? ' active' : '')} style={{ backgroundColor: purple }} onClick={() => this.changeColumnColor(purple!)}></div> + <div className={'colorPicker' + (selected === blue ? ' active' : '')} style={{ backgroundColor: blue }} onClick={() => this.changeColumnColor(blue!)}></div> + <div className={'colorPicker' + (selected === yellow ? ' active' : '')} style={{ backgroundColor: yellow }} onClick={() => this.changeColumnColor(yellow!)}></div> + <div className={'colorPicker' + (selected === red ? ' active' : '')} style={{ backgroundColor: red }} onClick={() => this.changeColumnColor(red!)}></div> + <div className={'colorPicker' + (selected === gray ? ' active' : '')} style={{ backgroundColor: gray }} onClick={() => this.changeColumnColor(gray)}></div> + <div className={'colorPicker' + (selected === green ? ' active' : '')} style={{ backgroundColor: green }} onClick={() => this.changeColumnColor(green!)}></div> + <div className={'colorPicker' + (selected === cyan ? ' active' : '')} style={{ backgroundColor: cyan }} onClick={() => this.changeColumnColor(cyan!)}></div> + <div className={'colorPicker' + (selected === orange ? ' active' : '')} style={{ backgroundColor: orange }} onClick={() => this.changeColumnColor(orange!)}></div> </div> </div> ); - } + }; - toggleAlias = action(() => this._createAliasSelected = true); - toggleVisibility = () => this._collapsed = !this.collapsed; + toggleAlias = action(() => (this._createAliasSelected = true)); + toggleVisibility = () => (this._collapsed = !this.collapsed); renderMenu = () => { const selected = this._createAliasSelected; - return (<div className="collectionStackingView-optionPicker"> - <div className="optionOptions"> - <div className={"optionPicker" + (selected === true ? " active" : "")} onClick={this.toggleAlias}>Create Alias</div> - <div className={"optionPicker" + (selected === true ? " active" : "")} onClick={this.deleteRow}>Delete</div> + return ( + <div className="collectionStackingView-optionPicker"> + <div className="optionOptions"> + <div className={'optionPicker' + (selected === true ? ' active' : '')} onClick={this.toggleAlias}> + Create Alias + </div> + <div className={'optionPicker' + (selected === true ? ' active' : '')} onClick={this.deleteRow}> + Delete + </div> + </div> </div> - </div>); - } + ); + }; @action textCallback = (char: string) => { - return this.addDocument("", false); - } + return this.addDocument('', false); + }; @computed get contentLayout() { const rows = Math.max(1, Math.min(this.props.docList.length, Math.floor((this.props.parent.props.PanelWidth() - 2 * this.props.parent.xMargin) / (this.props.parent.columnWidth + this.props.parent.gridGap)))); const showChrome = !this.props.chromeHidden; const stackPad = showChrome ? `0px ${this.props.parent.xMargin}px` : `${this.props.parent.yMargin}px ${this.props.parent.xMargin}px 0px ${this.props.parent.xMargin}px `; - return this.collapsed ? (null) : - <div style={{ position: "relative" }}> - {showChrome ? - <div className="collectionStackingView-addDocumentButton" + return this.collapsed ? null : ( + <div style={{ position: 'relative' }}> + {showChrome ? ( + <div + className="collectionStackingView-addDocumentButton" style={{ //width: style.columnWidth / style.numGroupColumns, - padding: `${NumCast(this.props.parent.layoutDoc._yPadding, this.props.parent.yMargin)}px 0px 0px 0px` + padding: `${NumCast(this.props.parent.layoutDoc._yPadding, this.props.parent.yMargin)}px 0px 0px 0px`, }}> - <EditableView - GetValue={returnEmptyString} - SetValue={this.addDocument} - textCallback={this.textCallback} - contents={"+ NEW"} - toggle={this.toggleVisibility} /> - </div> : null - } - <div className={`collectionStackingView-masonryGrid`} + <EditableView GetValue={returnEmptyString} SetValue={this.addDocument} textCallback={this.textCallback} contents={'+ NEW'} /> + </div> + ) : null} + <div + className={`collectionStackingView-masonryGrid`} ref={this._contRef} style={{ padding: stackPad, width: this.props.parent.NodeWidth, gridGap: this.props.parent.gridGap, - gridTemplateColumns: numberRange(rows).reduce((list: string, i: any) => list + ` ${this.props.parent.columnWidth}px`, ""), + gridTemplateColumns: numberRange(rows).reduce((list: string, i: any) => list + ` ${this.props.parent.columnWidth}px`, ''), }}> {this.props.parent.children(this.props.docList)} - {this.props.showHandle && this.props.parent.props.isContentActive() ? this.props.parent.columnDragger : (null)} + {this.props.showHandle && this.props.parent.props.isContentActive() ? this.props.parent.columnDragger : null} </div> - </div>; + </div> + ); } @computed get headingView() { const noChrome = this.props.chromeHidden; const key = this.props.pivotField; - const evContents = this.heading ? this.heading : this.props.type && this.props.type === "number" ? "0" : `NO ${key.toUpperCase()} VALUE`; - const editableHeaderView = <EditableView - GetValue={() => evContents} - SetValue={this.headingChanged} - contents={evContents} - oneLine={true} - toggle={this.toggleVisibility} />; - return this.props.Document.miniHeaders ? - <div className="collectionStackingView-miniHeader"> - {editableHeaderView} - </div> : - !this.props.headingObject ? (null) : - <div className="collectionStackingView-sectionHeader" ref={this._headerRef} > - <div className="collectionStackingView-sectionHeader-subCont" onPointerDown={this.headerDown} - title={evContents === `NO ${key.toUpperCase()} VALUE` ? - `Documents that don't have a ${key} value will go here. This column cannot be removed.` : ""} - style={{ background: evContents !== `NO ${key.toUpperCase()} VALUE` ? this.color : "lightgrey" }}> - {noChrome ? evContents : editableHeaderView} - {noChrome || evContents === `NO ${key.toUpperCase()} VALUE` ? (null) : - <div className="collectionStackingView-sectionColor"> - <button className="collectionStackingView-sectionColorButton" onClick={action(e => this._paletteOn = !this._paletteOn)}> - <FontAwesomeIcon icon="palette" size="lg" /> + const evContents = this.heading ? this.heading : this.props.type && this.props.type === 'number' ? '0' : `NO ${key.toUpperCase()} VALUE`; + const editableHeaderView = <EditableView GetValue={() => evContents} SetValue={this.headingChanged} contents={evContents} oneLine={true} />; + return this.props.Document.miniHeaders ? ( + <div className="collectionStackingView-miniHeader">{editableHeaderView}</div> + ) : !this.props.headingObject ? null : ( + <div className="collectionStackingView-sectionHeader" ref={this._headerRef}> + <div + className="collectionStackingView-sectionHeader-subCont" + onPointerDown={this.headerDown} + title={evContents === `NO ${key.toUpperCase()} VALUE` ? `Documents that don't have a ${key} value will go here. This column cannot be removed.` : ''} + style={{ background: evContents !== `NO ${key.toUpperCase()} VALUE` ? this.color : 'lightgrey' }}> + {noChrome ? evContents : editableHeaderView} + {noChrome || evContents === `NO ${key.toUpperCase()} VALUE` ? null : ( + <div className="collectionStackingView-sectionColor"> + <button className="collectionStackingView-sectionColorButton" onClick={action(e => (this._paletteOn = !this._paletteOn))}> + <FontAwesomeIcon icon="palette" size="lg" /> + </button> + {this._paletteOn ? this.renderColorPicker() : null} + </div> + )} + {noChrome ? null : ( + <button className="collectionStackingView-sectionDelete" onClick={noChrome ? undefined : this.collapseSection}> + <FontAwesomeIcon icon={this.collapsed ? 'chevron-down' : 'chevron-up'} size="lg" /> + </button> + )} + {noChrome || evContents === `NO ${key.toUpperCase()} VALUE` ? null : ( + <div className="collectionStackingView-sectionOptions"> + <Flyout anchorPoint={anchorPoints.TOP_CENTER} content={this.renderMenu()}> + <button className="collectionStackingView-sectionOptionButton"> + <FontAwesomeIcon icon="ellipsis-v" size="lg" /> </button> - {this._paletteOn ? this.renderColorPicker() : (null)} - </div> - } - {noChrome ? (null) : <button className="collectionStackingView-sectionDelete" onClick={noChrome ? undefined : this.collapseSection}> - <FontAwesomeIcon icon={this.collapsed ? "chevron-down" : "chevron-up"} size="lg" /> - </button>} - {noChrome || evContents === `NO ${key.toUpperCase()} VALUE` ? (null) : - <div className="collectionStackingView-sectionOptions"> - <Flyout anchorPoint={anchorPoints.TOP_CENTER} content={this.renderMenu()}> - <button className="collectionStackingView-sectionOptionButton"> - <FontAwesomeIcon icon="ellipsis-v" size="lg" /> - </button> - </Flyout> - </div> - } - </div> - </div>; + </Flyout> + </div> + )} + </div> + </div> + ); } render() { const background = this._background; - return <div className="collectionStackingView-masonrySection" - style={{ width: this.props.parent.NodeWidth, background }} - ref={this.createRowDropRef} - onPointerEnter={this.pointerEnteredRow} - onPointerLeave={this.pointerLeaveRow} - > - {this.headingView} - {this.contentLayout} - </div >; + return ( + <div className="collectionStackingView-masonrySection" style={{ width: this.props.parent.NodeWidth, background }} ref={this.createRowDropRef} onPointerEnter={this.pointerEnteredRow} onPointerLeave={this.pointerLeaveRow}> + {this.headingView} + {this.contentLayout} + </div> + ); } -}
\ No newline at end of file +} |
