diff options
author | Sophie Zhang <sophie_zhang@brown.edu> | 2024-01-25 11:35:26 -0500 |
---|---|---|
committer | Sophie Zhang <sophie_zhang@brown.edu> | 2024-01-25 11:35:26 -0500 |
commit | f3dab2a56db5e4a6a3dca58185d94e1ff7d1dc32 (patch) | |
tree | a7bc895266b53bb620dbd2dd71bad2e83b555446 /src/client/views/collections/CollectionStackingViewFieldColumn.tsx | |
parent | b5c5410b4af5d2c68d2107d3f064f6e3ec4ac3f2 (diff) | |
parent | 136f3d9f349d54e8bdd73b6380ea47c19e5edebf (diff) |
Merge branch 'master' into sophie-ai-images
Diffstat (limited to 'src/client/views/collections/CollectionStackingViewFieldColumn.tsx')
-rw-r--r-- | src/client/views/collections/CollectionStackingViewFieldColumn.tsx | 157 |
1 files changed, 81 insertions, 76 deletions
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 3598d548a..c455f20d8 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -1,15 +1,15 @@ -import React = require('react'); import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, IReactionDisposer, observable, reaction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; import { Doc, DocListCast, Opt } from '../../../fields/Doc'; import { RichTextField } from '../../../fields/RichTextField'; import { PastelSchemaPalette, SchemaHeaderField } from '../../../fields/SchemaHeaderField'; import { ScriptField } from '../../../fields/ScriptField'; -import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types'; +import { BoolCast, NumCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; import { TraceMobx } from '../../../fields/util'; -import { emptyFunction, setupMoveUpEvents, returnFalse, returnEmptyString } from '../../../Utils'; +import { emptyFunction, returnEmptyString, setupMoveUpEvents } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; import { DragManager } from '../../util/DragManager'; @@ -19,14 +19,14 @@ import { undoBatch } from '../../util/UndoManager'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; import { EditableView } from '../EditableView'; -import './CollectionStackingView.scss'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; -import { Id } from '../../../fields/FieldSymbols'; +import { ObservableReactComponent } from '../ObservableReactComponent'; +import './CollectionStackingView.scss'; // So this is how we are storing a column interface CSVFieldColumnProps { Document: Doc; - DataDoc: Opt<Doc>; + TemplateDataDocument: Opt<Doc>; docList: Doc[]; heading: string; pivotField: string; @@ -49,16 +49,21 @@ interface CSVFieldColumnProps { } @observer -export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldColumnProps> { - @observable private _background = 'inherit'; - +export class CollectionStackingViewFieldColumn extends ObservableReactComponent<CSVFieldColumnProps> { private dropDisposer?: DragManager.DragDropDisposer; private _disposers: { [name: string]: IReactionDisposer } = {}; private _headerRef: React.RefObject<HTMLDivElement> = React.createRef(); - + @observable private _background = 'inherit'; @observable _paletteOn = false; - @observable _heading = this.props.headingObject ? this.props.headingObject.heading : this.props.heading; - @observable _color = this.props.headingObject ? this.props.headingObject.color : '#f1efeb'; + @observable _heading = ''; + @observable _color = ''; + + constructor(props: any) { + super(props); + makeObservable(this); + this._heading = this._props.headingObject ? this._props.headingObject.heading : this._props.heading; + this._color = this._props.headingObject ? this._props.headingObject.color : '#f1efeb'; + } _ele: HTMLElement | null = null; @@ -68,29 +73,29 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC this.dropDisposer?.(); if (ele) { this._ele = ele; - this.props.observeHeight(ele); - this.dropDisposer = DragManager.MakeDropTarget(ele, this.columnDrop.bind(this)); + this._props.observeHeight(ele); + this.dropDisposer = DragManager.MakeDropTarget(ele, this.columnDrop.bind(this), this._props.Document); } }; @action componentDidMount() { this._disposers.collapser = reaction( - () => this.props.headingObject?.collapsed, + () => this._props.headingObject?.collapsed, collapsed => (this.collapsed = collapsed !== undefined ? BoolCast(collapsed) : false), { fireImmediately: true } ); } componentWillUnmount() { this._disposers.collapser?.(); - this.props.unobserveHeight(this._ele); + this._props.unobserveHeight(this._ele); } //TODO: what is scripting? I found it in SetInPlace def but don't know what that is @undoBatch columnDrop = action((e: Event, de: DragManager.DropEvent) => { const drop = { docs: de.complete.docDragData?.droppedDocuments, val: this.getValue(this._heading) }; - this.props.pivotField && drop.docs?.forEach(d => Doc.SetInPlace(d, this.props.pivotField, drop.val, false)); + this._props.pivotField && drop.docs?.forEach(d => Doc.SetInPlace(d, this._props.pivotField, drop.val, false)); return true; }); getValue = (value: string): any => { @@ -105,13 +110,13 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC headingChanged = (value: string, shiftDown?: boolean) => { const castedValue = this.getValue(value); if (castedValue) { - if (this.props.colHeaderData?.map(i => i.heading).indexOf(castedValue.toString()) !== -1) { + if (this._props.colHeaderData?.map(i => i.heading).indexOf(castedValue.toString()) !== -1) { return false; } - this.props.docList.forEach(d => (d[this.props.pivotField] = castedValue)); - if (this.props.headingObject) { - this.props.headingObject.setHeading(castedValue.toString()); - this._heading = this.props.headingObject.heading; + this._props.docList.forEach(d => (d[this._props.pivotField] = castedValue)); + if (this._props.headingObject) { + this._props.headingObject.setHeading(castedValue.toString()); + this._heading = this._props.headingObject.heading; } return true; } @@ -120,41 +125,41 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC @action changeColumnColor = (color: string) => { - this.props.headingObject?.setColor(color); + this._props.headingObject?.setColor(color); this._color = color; }; - @action pointerEntered = () => SnappingManager.GetIsDragging() && (this._background = '#b4b4b4'); + @action pointerEntered = () => SnappingManager.IsDragging && (this._background = '#b4b4b4'); @action pointerLeave = () => (this._background = 'inherit'); @undoBatch typedNote = (char: string) => this.addNewTextDoc('-typed text-', false, true); @action addNewTextDoc = (value: string, shiftDown?: boolean, forceEmptyNote?: boolean) => { if (!value && !forceEmptyNote) return false; - const key = this.props.pivotField; + const key = this._props.pivotField; const newDoc = Docs.Create.TextDocument(value, { _height: 18, _width: 200, _layout_fitWidth: true, title: value, _layout_autoHeight: true }); - newDoc[key] = this.getValue(this.props.heading); - const maxHeading = this.props.docList.reduce((maxHeading, doc) => (NumCast(doc.heading) > maxHeading ? NumCast(doc.heading) : maxHeading), 0); - const heading = maxHeading === 0 || this.props.docList.length === 0 ? 1 : maxHeading === 1 ? 2 : 3; + newDoc[key] = this.getValue(this._props.heading); + const maxHeading = this._props.docList.reduce((maxHeading, doc) => (NumCast(doc.heading) > maxHeading ? NumCast(doc.heading) : maxHeading), 0); + const heading = maxHeading === 0 || this._props.docList.length === 0 ? 1 : maxHeading === 1 ? 2 : 3; newDoc.heading = heading; - FormattedTextBox.SelectOnLoad = newDoc[Id]; + FormattedTextBox.SetSelectOnLoad(newDoc); FormattedTextBox.SelectOnLoadChar = forceEmptyNote ? '' : ' '; - return this.props.addDocument?.(newDoc) || false; + return this._props.addDocument?.(newDoc) || false; }; @action deleteColumn = () => { - this.props.docList.forEach(d => (d[this.props.pivotField] = undefined)); - if (this.props.colHeaderData && this.props.headingObject) { - const index = this.props.colHeaderData.indexOf(this.props.headingObject); - this.props.colHeaderData.splice(index, 1); + this._props.docList.forEach(d => (d[this._props.pivotField] = undefined)); + if (this._props.colHeaderData && this._props.headingObject) { + const index = this._props.colHeaderData.indexOf(this._props.headingObject); + this._props.colHeaderData.splice(index, 1); } }; @action collapseSection = () => { - this.props.headingObject?.setCollapsed(!this.props.headingObject.collapsed); - this.collapsed = BoolCast(this.props.headingObject?.collapsed); + this._props.headingObject?.setCollapsed(!this._props.headingObject.collapsed); + this.collapsed = BoolCast(this._props.headingObject?.collapsed); }; headerDown = (e: React.PointerEvent<HTMLDivElement>) => setupMoveUpEvents(this, e, this.startDrag, emptyFunction, emptyFunction); @@ -162,12 +167,12 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC //TODO: I think this is where I'm supposed to edit stuff startDrag = (e: PointerEvent, down: number[], delta: number[]) => { // is MakeEmbedding a way to make a copy of a doc without rendering it? - const embedding = Doc.MakeEmbedding(this.props.Document); - embedding._width = this.props.columnWidth / (this.props.colHeaderData?.length || 1); + const embedding = Doc.MakeEmbedding(this._props.Document); + embedding._width = this._props.columnWidth / (this._props.colHeaderData?.length || 1); embedding._pivotField = undefined; let value = this.getValue(this._heading); value = typeof value === 'string' ? `"${value}"` : value; - embedding.viewSpecScript = ScriptField.MakeFunction(`doc.${this.props.pivotField} === ${value}`, { doc: Doc.name }); + embedding.viewSpecScript = ScriptField.MakeFunction(`doc.${this._props.pivotField} === ${value}`, { doc: Doc.name }); if (embedding.viewSpecScript) { DragManager.StartDocumentDrag([this._headerRef.current!], new DragManager.DocumentDragData([embedding]), e.clientX, e.clientY); return true; @@ -177,7 +182,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC renderColorPicker = () => { const gray = '#f1efeb'; - const selected = this.props.headingObject ? this.props.headingObject.color : gray; + const selected = this._props.headingObject ? this._props.headingObject.color : gray; const colors = ['pink2', 'purple4', 'bluegreen1', 'yellow4', 'gray', 'red2', 'bluegreen7', 'bluegreen5', 'orange1']; return ( <div className="collectionStackingView-colorPicker"> @@ -211,15 +216,15 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC ContextMenu.Instance.clearItems(); const layoutItems: ContextMenuProps[] = []; const docItems: ContextMenuProps[] = []; - const dataDoc = this.props.DataDoc || this.props.Document; + const dataDoc = this._props.TemplateDataDocument || this._props.Document; const width = this._ele ? Number(getComputedStyle(this._ele).width.replace('px', '')) : 0; const height = this._ele ? Number(getComputedStyle(this._ele).height.replace('px', '')) : 0; DocUtils.addDocumentCreatorMenuItems( doc => { - FormattedTextBox.SelectOnLoad = doc[Id]; - return this.props.addDocument?.(doc); + FormattedTextBox.SetSelectOnLoad(doc); + return this._props.addDocument?.(doc); }, - this.props.addDocument, + this._props.addDocument, 0, 0, true @@ -231,12 +236,12 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC docItems.push({ description: ':' + fieldKey, event: () => { - const created = DocUtils.DocumentFromField(dataDoc, fieldKey, Doc.GetProto(this.props.Document)); + const created = DocUtils.DocumentFromField(dataDoc, fieldKey, Doc.GetProto(this._props.Document)); if (created) { - if (this.props.Document.isTemplateDoc) { - Doc.MakeMetadataFieldTemplate(created, this.props.Document); + if (this._props.Document.isTemplateDoc) { + Doc.MakeMetadataFieldTemplate(created, this._props.Document); } - return this.props.addDocument?.(created); + return this._props.addDocument?.(created); } }, icon: 'compress-arrows-alt', @@ -250,12 +255,12 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC event: () => { const created = Docs.Create.CarouselDocument([], { _width: 400, _height: 200, title: fieldKey }); if (created) { - const container = this.props.Document.resolvedDataDoc ? Doc.GetProto(this.props.Document) : this.props.Document; + const container = this._props.Document.resolvedDataDoc ? Doc.GetProto(this._props.Document) : this._props.Document; if (container.isTemplateDoc) { Doc.MakeMetadataFieldTemplate(created, container); return Doc.AddDocToList(container, Doc.LayoutFieldKey(container), created); } - return this.props.addDocument?.(created) || false; + return this._props.addDocument?.(created) || false; } }, icon: 'compress-arrows-alt', @@ -264,16 +269,16 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC !Doc.noviceMode && ContextMenu.Instance.addItem({ description: 'Doc Fields ...', subitems: docItems, icon: 'eye' }); !Doc.noviceMode && ContextMenu.Instance.addItem({ description: 'Containers ...', subitems: layoutItems, icon: 'eye' }); ContextMenu.Instance.setDefaultItem('::', (name: string): void => { - Doc.GetProto(this.props.Document)[name] = ''; + Doc.GetProto(this._props.Document)[name] = ''; const created = Docs.Create.TextDocument('', { title: name, _width: 250, _layout_autoHeight: true }); if (created) { - if (this.props.Document.isTemplateDoc) { - Doc.MakeMetadataFieldTemplate(created, this.props.Document); + if (this._props.Document.isTemplateDoc) { + Doc.MakeMetadataFieldTemplate(created, this._props.Document); } - this.props.addDocument?.(created); + this._props.addDocument?.(created); } }); - const pt = this.props + const pt = this._props .screenToLocalTransform() .inverse() .transformPoint(width - 30, height); @@ -282,21 +287,21 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC @computed get innards() { TraceMobx(); - const key = this.props.pivotField; - const headings = this.props.headings(); + const key = this._props.pivotField; + const headings = this._props.headings(); const heading = this._heading; - const columnYMargin = this.props.headingObject ? 0 : this.props.yMargin; + const columnYMargin = this._props.headingObject ? 0 : this._props.yMargin; const uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx); const noValueHeader = `NO ${key.toUpperCase()} VALUE`; - const evContents = heading ? heading : this.props?.type === 'number' ? '0' : noValueHeader; - const headingView = this.props.headingObject ? ( + const evContents = heading ? heading : this._props?.type === 'number' ? '0' : noValueHeader; + const headingView = this._props.headingObject ? ( <div key={heading} className="collectionStackingView-sectionHeader" ref={this._headerRef} style={{ - marginTop: this.props.yMargin, - width: this.props.columnWidth / (uniqueHeadings.length + (this.props.chromeHidden ? 0 : 1) || 1), + marginTop: this._props.yMargin, + width: this._props.columnWidth / (uniqueHeadings.length + (this._props.chromeHidden ? 0 : 1) || 1), }}> {/* the default bucket (no key value) has a tooltip that describes what it is. Further, it does not have a color and cannot be deleted. */} @@ -326,35 +331,35 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC )} */} </div> <div - className={'collectionStackingView-collapseBar' + (this.props.headingObject.collapsed === true ? ' active' : '')} - style={{ display: this.props.headingObject.collapsed === true ? 'block' : undefined }} + className={'collectionStackingView-collapseBar' + (this._props.headingObject.collapsed === true ? ' active' : '')} + style={{ display: this._props.headingObject.collapsed === true ? 'block' : undefined }} onClick={this.collapseSection} /> </div> ) : null; - const templatecols = `${this.props.columnWidth / this.props.numGroupColumns}px `; - const type = this.props.Document.type; + const templatecols = `${this._props.columnWidth / this._props.numGroupColumns}px `; + const type = this._props.Document.type; return ( <> - {this.props.Document._columnsHideIfEmpty ? null : headingView} + {this._props.Document._columnsHideIfEmpty ? null : headingView} {this.collapsed ? null : ( <div> <div key={`${heading}-stack`} className={`collectionStackingView-masonrySingle`} style={{ - padding: `${columnYMargin}px ${0}px ${this.props.yMargin}px ${0}px`, + padding: `${columnYMargin}px ${0}px ${this._props.yMargin}px ${0}px`, margin: 'auto', width: 'max-content', //singleColumn ? undefined : `${cols * (style.columnWidth + style.gridGap) + 2 * style.xMargin - style.gridGap}px`, height: 'max-content', position: 'relative', - gridGap: this.props.gridGap, + gridGap: this._props.gridGap, gridTemplateColumns: templatecols, gridAutoRows: '0px', }}> - {this.props.renderChildren(this.props.docList)} + {this._props.renderChildren(this._props.docList)} </div> - {!this.props.chromeHidden && type !== DocumentType.PRES ? ( + {!this._props.chromeHidden && type !== DocumentType.PRES ? ( // TODO: this is the "new" button: see what you can work with here // change cursor to pointer for this, and update dragging cursor //TODO: there is a bug that occurs when adding a freeform document and trying to move it around @@ -365,7 +370,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC key={`${heading}-add-document`} onKeyDown={e => e.stopPropagation()} className="collectionStackingView-addDocumentButton" - style={{ width: 'calc(100% - 25px)', maxWidth: this.props.columnWidth / this.props.numGroupColumns - 25, marginBottom: 10 }}> + style={{ width: 'calc(100% - 25px)', maxWidth: this._props.columnWidth / this._props.numGroupColumns - 25, marginBottom: 10 }}> <EditableView GetValue={returnEmptyString} SetValue={this.addNewTextDoc} @@ -384,15 +389,15 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC render() { TraceMobx(); - const headings = this.props.headings(); + const headings = this._props.headings(); const heading = this._heading; const uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx); return ( <div - className={'collectionStackingViewFieldColumn' + (SnappingManager.GetIsDragging() ? 'Dragging' : '')} + className={'collectionStackingViewFieldColumn' + (SnappingManager.IsDragging ? 'Dragging' : '')} key={heading} style={{ - width: `${100 / (uniqueHeadings.length + (this.props.chromeHidden ? 0 : 1) || 1)}%`, + width: `${100 / (uniqueHeadings.length + (this._props.chromeHidden ? 0 : 1) || 1)}%`, height: undefined, // DraggingManager.GetIsDragging() ? "100%" : undefined, background: this._background, }} |