diff options
author | Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> | 2024-09-22 15:29:28 -0400 |
---|---|---|
committer | Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> | 2024-09-22 15:29:28 -0400 |
commit | d8a43b76f101a2f38ef1e3e9cbf8ec036468481d (patch) | |
tree | 08fea673e890c1e3b5c22d7a58d6c06c45fdc1fe | |
parent | 24c6c3f0c9b43059cd013d344dfa065969f73389 (diff) |
header comments + change to cellfield updating
5 files changed, 69 insertions, 33 deletions
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 0e5a1e6b6..11a4e88f9 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -495,6 +495,26 @@ export class CollectionSchemaView extends CollectionSubView() { return adjIndex; }; + @action + setRelCursorIndex = (mouseY: number) => { + this._mouseCoordinates.y = mouseY; // updates this.rowDropIndex computed value to overwrite the old cached value + + const rowHeight = CollectionSchemaView._rowHeight; + const adjInitMouseY = mouseY - rowHeight - 100; // rowHeight: height of the column menu cells | 100: height of the top menu + const yOffset = this._lowestSelectedIndex * rowHeight; + + const heights = this._selectedDocs.map(() => this.rowHeightFunc()); + let index: number = 0; + heights.reduce((total, curr, i) => { + if (total <= adjInitMouseY && total + curr >= adjInitMouseY) { + if (adjInitMouseY <= total + curr) index = i; + else index = i + 1; + } + return total + curr; + }, yOffset); + this._relCursorIndex = index; + }; + highlightDraggedColumn = (index: number) => this._colEles.forEach((colRef, i) => { const edgeStyle = i === index ? `solid 2px ${Colors.MEDIUM_BLUE}` : ''; @@ -731,7 +751,7 @@ export class CollectionSchemaView extends CollectionSubView() { const field = this.columnKeys[col]; const refToAdd = `d${docIndex}.${field}` const editedField = this._referenceSelectMode.currEditing ? this._referenceSelectMode.currEditing as SchemaCellField : null; - editedField?.appendText(refToAdd, true); + editedField?.insertText(refToAdd, true); editedField?.setupRefSelect(false); return; } diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index 1ee79fa0b..72dcc00e6 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -9,6 +9,16 @@ import { ObjectField } from "../../../../fields/ObjectField"; import { Doc } from "../../../../fields/Doc"; import { DocumentView } from "../../nodes/DocumentView"; +/** + * The SchemaCellField renders text in schema cells while the user is editing, and updates the + * contents of the field based on user input. It handles some cell-side logic for equations, such + * as how equations are broken up within the text. + * + * The current implementation parses innerHTML to create spans based on the text in the cell. + * A more robust/safer approach would directly add elements in the react structure, but this + * has been challenging to implement. + */ + export interface SchemaCellFieldProps { contents: any; fieldContents?: FieldViewProps; @@ -147,20 +157,30 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro return chunkedText; } + /** + * Sets the rendered content of the cell to save user inputs. + * @param content the content to set + * @param restoreCursorPos whether the cursor should be set back to where it was rather than the 0th index; should usually be true + */ @action setContent = (content: string, restoreCursorPos?: boolean) => { const pos = this.cursorPosition; this._displayedContent = this.makeSpans(content); - console.log('print', content); restoreCursorPos && setTimeout(() => this.setCursorPosition(pos)); } + //Called from schemaview when a cell is selected to add a reference to the equation + /** + * Inserts text at the given index. + * @param text The text to append. + * @param atPos he index at which to insert the text. If empty, defaults to end. + */ @action - appendText = (text: string, atCursorPos?: boolean) => { + insertText = (text: string, atPos?: boolean) => { const content = this._unrenderedContent; const cursorPos = this.cursorPosition; const robustPos = cursorPos ?? content.length; - const newText = atCursorPos ? content.slice(0, robustPos) + text + content.slice(cursorPos ?? content.length) : this._unrenderedContent.concat(text); + const newText = atPos ? content.slice(0, robustPos) + text + content.slice(cursorPos ?? content.length) : this._unrenderedContent.concat(text); this.onChange(undefined, newText); setTimeout(() => this.setCursorPosition(robustPos + text.length)); } @@ -172,6 +192,9 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro return wasFocused !== this._editing; }; + /** + * Gets the cursor's position index within the text being edited. + */ get cursorPosition() { const selection = window.getSelection(); if (!selection || selection.rangeCount === 0 || !this._inputref) return null; @@ -185,6 +208,7 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro return adjRange.toString().length; } + setCursorPosition = (position: number | null) => { const selection = window.getSelection(); if (!selection || position === null || !this._inputref) return; @@ -220,9 +244,9 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro //This function checks if a visual update (eg. coloring a cell reference) should be made. It's meant to //save on processing upkeep vs. constantly rerendering, but I think the savings are minimal for now - // shouldUpdate = (prevVal: string, currVal: string) => { - // if (this._props.getCells(currVal).length !== this._props.getCells(prevVal).length) return true; - // }; + shouldUpdate = (prevVal: string, currVal: string) => { + if (this._props.getCells(currVal).length !== this._props.getCells(prevVal).length) return true; + }; onChange = (e: FormEvent<HTMLDivElement> | undefined, newText?: string) => { const prevVal = this._unrenderedContent; @@ -235,7 +259,7 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro } this._unrenderedContent = targVal; this._props.highlightCells?.(targVal); - this.setContent(targVal, true); + if (this.shouldUpdate(prevVal, targVal)) this.setContent(targVal, true); this.setupRefSelect(this.refSelectConditionMet); }; @@ -248,10 +272,7 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro @action onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => { if (e.nativeEvent.defaultPrevented) return; // hack .. DashFieldView grabs native events, but react ignores stoppedPropagation and preventDefault, so we need to check it here - // if (e.metaKey) { - // e.stopPropagation(); - // e.preventDefault(); - // } + switch (e.key) { case 'Tab': e.stopPropagation(); @@ -295,7 +316,6 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro } }; - @action onClick = (e?: React.MouseEvent) => { if (this._props.editing !== false) { @@ -312,6 +332,8 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro this._dependencyMessageShown = true; return; } + + this.setContent(this._unrenderedContent); if (this._props.SetValue(this._unrenderedContent, shiftDown, enterKey)) { this._editing = false; @@ -327,8 +349,6 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro } } - //<FieldView {...this._props.fieldContents}/> - staticDisplay = () => { return <span className='editableView-static'> { diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index 6da236d82..3495c5ab4 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -5,23 +5,19 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import { returnEmptyDoclist, returnEmptyFilter, returnFalse, returnZero, setupMoveUpEvents } from '../../../../ClientUtils'; import { emptyFunction } from '../../../../Utils'; -import { Colors } from '../../global/globalEnums'; import './CollectionSchemaView.scss'; import { EditableView } from '../../EditableView'; import { ObservableReactComponent } from '../../ObservableReactComponent'; import { DefaultStyleProvider, returnEmptyDocViewList } from '../../StyleProvider'; import { FieldViewProps } from '../../nodes/FieldView'; -import { Doc, Field } from '../../../../fields/Doc'; +import { Doc } from '../../../../fields/Doc'; import { dropActionType } from '../../../util/DropActionTypes'; import { Transform } from '../../../util/Transform'; import { SchemaTableCell } from './SchemaTableCell'; import { DocCast } from '../../../../fields/Types'; import { computedFn } from 'mobx-utils'; import { CollectionSchemaView } from './CollectionSchemaView'; -import { SnappingManager } from '../../../util/SnappingManager'; import { undoable } from '../../../util/UndoManager'; -import { FInfo } from '../../../documents/Documents'; -import { ColumnType } from '../../../../fields/SchemaHeaderField'; import { IconButton, Size } from 'browndash-components'; export enum SchemaFieldType { diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index ec94a8077..b928a5c67 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -25,6 +25,12 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { infoState } from '../collectionFreeForm/CollectionFreeFormInfoState'; import { TbShieldX } from 'react-icons/tb'; +/** + * The SchemaRowBox renders a doc as a row of cells, with each cell representing + * one field value of the doc. It mostly handles communication from the SchemaView + * to each SchemaCell, passing down necessary functions are props. + */ + interface SchemaRowBoxProps extends FieldViewProps { rowIndex: number; } @@ -51,10 +57,6 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() { return this.schemaView.Document; } - @computed get rowIndex() { - return this.schemaView?.rowIndex(this.Document) ?? -1; - } - componentDidMount(): void { this._props.setContentViewBox?.(this); } @@ -164,7 +166,6 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() { selectReference={this.selectReference} refSelectModeInfo={this.schemaView._referenceSelectMode} eqHighlightFunc={this.eqHighlightFunc} - equationHighlightRef={this.schemaView._cellHighlightColors} highlightCells={this.highlightCells} isolatedSelection={this.isolatedSelection} key={key} diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index e2a05da7f..1bca3c84d 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -30,12 +30,17 @@ import { Colors } from '../../global/globalEnums'; import { DocumentView } from '../../nodes/DocumentView'; import { FieldViewProps } from '../../nodes/FieldView'; import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; -import { CollectionSchemaView, FInfotoColType } from './CollectionSchemaView'; +import { FInfotoColType } from './CollectionSchemaView'; import './CollectionSchemaView.scss'; import { SchemaColumnHeader } from './SchemaColumnHeader'; -import { ContextMenu } from '../../ContextMenu'; import { SchemaCellField } from './SchemaCellField'; +/** + * SchemaTableCells make up the majority of the visual representation of the SchemaView. + * They are rendered for each cell in the SchemaView, and each represents one field value + * of a doc. Editing the content of the cell changes the corresponding doc's field value. + */ + export interface SchemaTableCellProps { Document: Doc; col: number; @@ -62,7 +67,6 @@ export interface SchemaTableCellProps { rowSelected: () => boolean; isolatedSelection: (doc: Doc) => [boolean, boolean]; highlightCells: (text: string) => void; - equationHighlightRef: ObservableMap<HTMLDivElement, string>; eqHighlightFunc: (text: string) => HTMLDivElement[] | []; refSelectModeInfo: {enabled: boolean, currEditing: SchemaCellField | undefined}; selectReference: (doc: Doc, col: number) => void; @@ -143,11 +147,6 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro return { color, textDecoration, fieldProps, cursor, pointerEvents }; } - // @action - // appendTextToField = (text: string) => { - // this._fieldRef?.appendText(text); - // } - adjustSelfReference = (field: string) => { const modField = field.replace(/\bthis.\b/g, `d${this.docIndex}.`); return modField; |