From 2e27b90ded41146b249649b0b0c3267b46c68363 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Tue, 7 May 2024 04:51:15 -0400 Subject: dynamic dragged column index alignment; started filtered menukeys --- .../collectionSchema/CollectionSchemaView.tsx | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index b684b65e5..27e1eabcf 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -393,6 +393,9 @@ export class CollectionSchemaView extends CollectionSubView() { }; findColDropIndex = (mouseX: number) => { + let leftOffset: number = this._props.ScreenToLocalTransform().inverse().transformPoint(0,0)[0] + console.log(leftOffset) + console.log(CollectionSchemaView._rowMenuWidth) let index: number | undefined; this.displayColumnWidths.reduce((total, curr, i) => { if (total <= mouseX && total + curr >= mouseX) { @@ -400,7 +403,7 @@ export class CollectionSchemaView extends CollectionSubView() { else index = i + 1; } return total + curr; - }, 2 * CollectionSchemaView._rowMenuWidth); //probably prone to issues; find better implementation (!!!) + }, leftOffset + CollectionSchemaView._rowMenuWidth); //probably prone to issues; find better implementation (!!!) return index; }; @@ -587,6 +590,7 @@ export class CollectionSchemaView extends CollectionSubView() { this.clearSelection(); draggedDocs.forEach(doc => { DocumentView.addViewRenderedCb(doc, dv => dv.select(true)); + console.log(doc.x); }); this._lowestSelectedIndex = Math.min(...draggedDocs?.map(doc => this.rowIndex(doc))); return true; @@ -740,6 +744,19 @@ export class CollectionSchemaView extends CollectionSubView() { return true; }; + @computed + get activeMenuKeys() { + let activeKeys = this.documentKeys.filter(key => this.childDocsInclude(key)); + return activeKeys + } + + childDocsInclude = (key: string) => { + this.childDocs.forEach(doc => { + //TODO: if childdoc fieldkeys contain the key, return true + }) + return false + } + @action openColumnMenu = (index: number, newCol: boolean) => { this._makeNewColumn = false; @@ -937,6 +954,7 @@ export class CollectionSchemaView extends CollectionSubView() { return (
e.stopPropagation()} /> + {this._makeNewField ? this.newFieldMenu : this.keysDropdown}
); -- cgit v1.2.3-70-g09d2 From 5cb549b88836f6674c7d346c75a679a73672e1fa Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Tue, 7 May 2024 18:27:21 -0400 Subject: key filtering for colkeymenu working (still need to implement UI) --- .../collectionSchema/CollectionSchemaView.tsx | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 27e1eabcf..4490b8dec 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -32,6 +32,7 @@ import { CollectionSubView } from '../CollectionSubView'; import './CollectionSchemaView.scss'; import { SchemaColumnHeader } from './SchemaColumnHeader'; import { SchemaRowBox } from './SchemaRowBox'; +import { ActionButton } from '@adobe/react-spectrum'; const { SCHEMA_NEW_NODE_HEIGHT } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore @@ -393,9 +394,7 @@ export class CollectionSchemaView extends CollectionSubView() { }; findColDropIndex = (mouseX: number) => { - let leftOffset: number = this._props.ScreenToLocalTransform().inverse().transformPoint(0,0)[0] - console.log(leftOffset) - console.log(CollectionSchemaView._rowMenuWidth) + let xOffset: number = this._props.ScreenToLocalTransform().inverse().transformPoint(0,0)[0] + CollectionSchemaView._rowMenuWidth; let index: number | undefined; this.displayColumnWidths.reduce((total, curr, i) => { if (total <= mouseX && total + curr >= mouseX) { @@ -403,7 +402,7 @@ export class CollectionSchemaView extends CollectionSubView() { else index = i + 1; } return total + curr; - }, leftOffset + CollectionSchemaView._rowMenuWidth); //probably prone to issues; find better implementation (!!!) + }, xOffset); return index; }; @@ -744,17 +743,15 @@ export class CollectionSchemaView extends CollectionSubView() { return true; }; - @computed - get activeMenuKeys() { + activeMenuKeys = () => { let activeKeys = this.documentKeys.filter(key => this.childDocsInclude(key)); return activeKeys } childDocsInclude = (key: string) => { - this.childDocs.forEach(doc => { - //TODO: if childdoc fieldkeys contain the key, return true - }) - return false + let keyExists: boolean = false; + this.childDocs.forEach(doc => {if (Object.keys(doc).includes(key)) keyExists = true;}) + return keyExists } @action @@ -954,7 +951,7 @@ export class CollectionSchemaView extends CollectionSubView() { return (
e.stopPropagation()} /> - + {this._makeNewField ? this.newFieldMenu : this.keysDropdown}
); -- cgit v1.2.3-70-g09d2 From 921c3b95b22d5e4125435abb45cd322fc170ccb3 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 8 May 2024 02:43:52 -0400 Subject: code written for parser (completely untested fingers crossed???) --- .../collectionSchema/CollectionSchemaView.tsx | 63 +++++++++++++++++----- 1 file changed, 49 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 4490b8dec..647986568 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -1,7 +1,7 @@ /* eslint-disable no-restricted-syntax */ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Popup, PopupTrigger, Type } from 'browndash-components'; -import { ObservableMap, action, computed, makeObservable, observable, observe } from 'mobx'; +import { ObservableMap, action, autorun, computed, makeObservable, observable, observe } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../ClientUtils'; @@ -85,10 +85,11 @@ export class CollectionSchemaView extends CollectionSubView() { @observable _selectedCol: number = 0; @observable _selectedCells: Array = []; @observable _mouseCoordinates = { x: 0, y: 0 }; - @observable _lowestSelectedIndex = -1; //lowest index among selected rows; used to properly sync dragged docs with cursor position - @observable _relCursorIndex = -1; //cursor index relative to the current selected cells - @observable _draggedColIndex = 0; - @observable _colBeingDragged = false; + @observable _lowestSelectedIndex: number = -1; //lowest index among selected rows; used to properly sync dragged docs with cursor position + @observable _relCursorIndex: number = -1; //cursor index relative to the current selected cells + @observable _draggedColIndex: number = 0; + @observable _colBeingDragged: boolean = false; + @observable _colKeysFiltered: boolean = false; // target HTMLelement portal for showing a popup menu to edit cell values. public get MenuTarget() { @@ -282,7 +283,7 @@ export class CollectionSchemaView extends CollectionSubView() { @undoBatch changeColumnKey = (index: number, newKey: string, defaultVal?: any) => { if (!this.documentKeys.includes(newKey)) { - this.addNewKey(newKey, defaultVal); + this.addNewKey(newKey, defaultVal, false); } const currKeys = [...this.columnKeys]; @@ -293,7 +294,7 @@ export class CollectionSchemaView extends CollectionSubView() { @undoBatch addColumn = (key: string, defaultVal?: any) => { if (!this.documentKeys.includes(key)) { - this.addNewKey(key, defaultVal); + this.addNewKey(key, defaultVal, false); } const newColWidth = this.tableWidth / (this.storedColumnWidths.length + 1); @@ -308,10 +309,37 @@ export class CollectionSchemaView extends CollectionSubView() { }; @action - addNewKey = (key: string, defaultVal: any) => - this.childDocs.forEach(doc => { - doc[DocData][key] = defaultVal; + addNewKey = (key: string, defaultVal: any, isEquation: boolean) => { + if (isEquation) { + this.childDocs.forEach(doc => { + const eq = this.parseEquation(key); + doc[DocData][key] = this.parsedEquationResult(eq); + this.setupAutoUpdate(eq, doc); + }); + } else { + this.childDocs.forEach(doc => { + doc[DocData][key] = defaultVal; + }); + } + } + + @action + setupAutoUpdate = (equation: string, doc: Doc) => { + return autorun(() => { + const result = this.parsedEquationResult(equation); + doc[DocData][equation] = result; }); + } + + parseEquation = (eq: string): string => { + const variablePattern = /[a-z]+/gi; + return eq.replace(variablePattern, (match) => `doc[DocData]['${match}']`); + } + + parsedEquationResult = (eq: string): number => { + const result = new Function('return ' + eq).call(this); + return result; + } @undoBatch removeColumn = (index: number) => { @@ -743,9 +771,15 @@ export class CollectionSchemaView extends CollectionSubView() { return true; }; - activeMenuKeys = () => { - let activeKeys = this.documentKeys.filter(key => this.childDocsInclude(key)); - return activeKeys + @action + toggleMenuKeyFilter = () => { + if (!this._colKeysFiltered){ + this._colKeysFiltered = true; + this._menuKeys = this.documentKeys.filter(key => this.childDocsInclude(key)); + } else { + this._colKeysFiltered = false; + this._menuKeys = this.documentKeys; + } } childDocsInclude = (key: string) => { @@ -947,11 +981,12 @@ export class CollectionSchemaView extends CollectionSubView() { ); } + get renderKeysMenu() { return (
e.stopPropagation()} /> - + {this._makeNewField ? this.newFieldMenu : this.keysDropdown}
); -- cgit v1.2.3-70-g09d2 From 920b4ec7a51e88769940b619c1b90b230b353ccb Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 8 May 2024 04:14:00 -0400 Subject: equation parser working in dash; need to fix auto-updating --- .../collectionSchema/CollectionSchemaView.tsx | 50 ++++++++++++++++------ src/fields/SchemaHeaderField.ts | 1 + 2 files changed, 39 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index de38d0c56..d84dd33ff 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -273,7 +273,7 @@ export class CollectionSchemaView extends CollectionSubView() { @undoBatch changeColumnKey = (index: number, newKey: string, defaultVal?: any) => { if (!this.documentKeys.includes(newKey)) { - this.addNewKey(newKey, defaultVal, false); + this.addNewKey(newKey, defaultVal); } const currKeys = this.columnKeys.slice(); // copy the column key array first, then change it. @@ -284,7 +284,7 @@ export class CollectionSchemaView extends CollectionSubView() { @undoBatch addColumn = (key: string, defaultVal?: any) => { if (!this.documentKeys.includes(key)) { - this.addNewKey(key, defaultVal, false); + this.addNewKey(key, defaultVal); } const newColWidth = this.tableWidth / (this.storedColumnWidths.length + 1); @@ -299,11 +299,11 @@ export class CollectionSchemaView extends CollectionSubView() { }; @action - addNewKey = (key: string, defaultVal: any, isEquation: boolean) => { - if (isEquation) { + addNewKey = (key: string, defaultVal: any) => { + if (this._newFieldType == ColumnType.Equation) { this.childDocs.forEach(doc => { - const eq = this.parseEquation(key); - doc[DocData][key] = this.parsedEquationResult(eq); + const eq = this.parseEquation(defaultVal, doc); + doc[DocData][key] = this.parsedEquationResult(eq, doc); this.setupAutoUpdate(eq, doc); }); } else { @@ -316,19 +316,19 @@ export class CollectionSchemaView extends CollectionSubView() { @action setupAutoUpdate = (equation: string, doc: Doc) => { return autorun(() => { - const result = this.parsedEquationResult(equation); + const result = this.parsedEquationResult(equation, doc); doc[DocData][equation] = result; }); } - parseEquation = (eq: string): string => { + parseEquation = (eq: string, doc: Doc): string => { const variablePattern = /[a-z]+/gi; - return eq.replace(variablePattern, (match) => `doc[DocData]['${match}']`); + return eq.replace(variablePattern, (match) => `doc.${match}`); } - parsedEquationResult = (eq: string): number => { - const result = new Function('return ' + eq).call(this); - return result; + parsedEquationResult = (eq: string, doc: any): number => { + const func = new Function('doc', 'return ' + eq); + return func(doc); } @undoBatch @@ -691,6 +691,19 @@ export class CollectionSchemaView extends CollectionSubView() { })} /> ); + case ColumnType.Equation: + return ( + e.stopPropagation()} + onChange={action((e: any) => { + this._newFieldDefault = e.target.value; + })} + /> + ); default: return undefined; } @@ -714,6 +727,7 @@ export class CollectionSchemaView extends CollectionSubView() { @action setKey = (key: string, defaultVal?: any) => { + console.log("called") if (this._makeNewColumn) { this.addColumn(key, defaultVal); } else { @@ -881,6 +895,18 @@ export class CollectionSchemaView extends CollectionSubView() { /> string +
+ { + this._newFieldType = ColumnType.Equation; + this._newFieldDefault = ''; + })} + /> + equation +
value: {this.fieldDefaultInput}
{this._newFieldWarning}
Date: Wed, 8 May 2024 04:14:49 -0400 Subject: c --- .../views/collections/collectionSchema/CollectionSchemaView.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index d84dd33ff..db7bf8c43 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -302,7 +302,7 @@ export class CollectionSchemaView extends CollectionSubView() { addNewKey = (key: string, defaultVal: any) => { if (this._newFieldType == ColumnType.Equation) { this.childDocs.forEach(doc => { - const eq = this.parseEquation(defaultVal, doc); + const eq = this.parseEquation(defaultVal); doc[DocData][key] = this.parsedEquationResult(eq, doc); this.setupAutoUpdate(eq, doc); }); @@ -321,7 +321,7 @@ export class CollectionSchemaView extends CollectionSubView() { }); } - parseEquation = (eq: string, doc: Doc): string => { + parseEquation = (eq: string): string => { const variablePattern = /[a-z]+/gi; return eq.replace(variablePattern, (match) => `doc.${match}`); } -- cgit v1.2.3-70-g09d2 From 0766ba00727e9e13ced2e16cfb049d49711fa738 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 8 May 2024 23:50:29 -0400 Subject: schema cell tag functions written --- .../collectionSchema/CollectionSchemaView.tsx | 59 ++++++++++++++++++++-- .../collectionSchema/SchemaTableCell.tsx | 20 +++++--- 2 files changed, 67 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index db7bf8c43..f7a553da3 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -89,6 +89,7 @@ export class CollectionSchemaView extends CollectionSubView() { @observable _draggedColIndex: number = 0; @observable _colBeingDragged: boolean = false; @observable _colKeysFiltered: boolean = false; + @observable _cellTags: ObservableMap = new ObservableMap>(); // target HTMLelement portal for showing a popup menu to edit cell values. public get MenuTarget() { @@ -302,9 +303,11 @@ export class CollectionSchemaView extends CollectionSubView() { addNewKey = (key: string, defaultVal: any) => { if (this._newFieldType == ColumnType.Equation) { this.childDocs.forEach(doc => { - const eq = this.parseEquation(defaultVal); - doc[DocData][key] = this.parsedEquationResult(eq, doc); - this.setupAutoUpdate(eq, doc); + const parsedEquation = this.parseEquation(defaultVal); + const val = computed(() => { return this.parsedEquationResult(parsedEquation, doc);}) + doc[DocData][key] = val.get(); + // doc[DocData][key] = this.parsedEquationResult(eq, doc); + // this.setupAutoUpdate(eq, doc); }); } else { this.childDocs.forEach(doc => { @@ -542,11 +545,55 @@ export class CollectionSchemaView extends CollectionSubView() { } else this.addDocToSelection(doc, false); this._selectedCol = col; + if (this._lowestSelectedIndex === -1 || index < this._lowestSelectedIndex) this._lowestSelectedIndex = index; // let selectedIndexes: Array = this._selectedCells.map(doc => this.rowIndex(doc)); }; + getCellTag = (doc: Doc, col: number) => { + return this._cellTags.get(doc)[col]; + } + + populateCellTags = () => { + this.childDocs.forEach(doc => this.addTags(doc)); + } + + addTags = (doc: Doc) => { + const row = this.rowIndex(doc) + 1; + const tags = []; + for (let col = 1; col <= this._colEles.length; ++col){ + tags.push(this.numToChar(col) + row.toString()) + } + this._cellTags.set(doc, tags) + } + + modifyCellTags = (addingColumn: boolean) => { + if (addingColumn) { + const colTag = this.numToChar(this._colEles.length); + this._cellTags.forEach((tags, row) => { + const newTag = colTag + this.rowIndex(row); + tags.push(newTag); + }); + } else { + this._cellTags.forEach(tags => { + if (tags.length > 0) { + tags.pop(); + } + }) + } + } + + numToChar = (num: number) => { + let result = ''; + while (num > 0) { + let remainder = (num - 1) % 26; + result = String.fromCharCode(65 + remainder) + result; + num = Math.floor((num - 1) / 26); + } + return result; + } + @action deselectCell = (doc: Doc) => { this._selectedCells && (this._selectedCells = this._selectedCells.filter(d => d !== doc)); @@ -936,6 +983,11 @@ export class CollectionSchemaView extends CollectionSubView() { @computed get keysDropdown() { return (
+
{ @@ -989,7 +1041,6 @@ export class CollectionSchemaView extends CollectionSubView() { return (
e.stopPropagation()} /> - {this._makeNewField ? this.newFieldMenu : this.keysDropdown}
); diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index b017eb62b..8192c5e2a 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -184,20 +184,24 @@ export class SchemaTableCell extends ObservableReactComponent) => { + if (this._props.isRowActive?.() !== false) { + if (this.selected && ctrl) { + this._props.selectCell(this._props.Document, this._props.col, shift, ctrl); + e.stopPropagation(); + } else !this.selected && this._props.selectCell(this._props.Document, this._props.col, shift, ctrl); + } + } + render() { return (
StopEvent(e)} onPointerDown={action(e => { - const shift: boolean = e.shiftKey; - const ctrl: boolean = e.ctrlKey; - if (this._props.isRowActive?.() !== false) { - if (this.selected && ctrl) { - this._props.selectCell(this._props.Document, this._props.col, shift, ctrl); - e.stopPropagation(); - } else !this.selected && this._props.selectCell(this._props.Document, this._props.col, shift, ctrl); - } + + this.select(e.shiftKey, e.ctrlKey, e); + })} style={{ padding: this._props.padding, maxWidth: this._props.maxWidth?.(), width: this._props.columnWidth() || undefined, border: this.selected ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined }}> {this.content} -- cgit v1.2.3-70-g09d2 From d6e449b84e1b35cf434b49f0476aa7242cc6c03b Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Thu, 9 May 2024 00:06:12 -0400 Subject: fixed merge --- .../collectionSchema/SchemaTableCell.tsx | 86 +++++++++------------- 1 file changed, 35 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index c1677b024..67991b8a2 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -25,9 +25,9 @@ import { Transform } from '../../../util/Transform'; import { undoBatch, undoable } from '../../../util/UndoManager'; import { EditableView } from '../../EditableView'; import { ObservableReactComponent } from '../../ObservableReactComponent'; -import { DefaultStyleProvider } from '../../StyleProvider'; +import { DefaultStyleProvider, returnEmptyDocViewList } from '../../StyleProvider'; import { Colors } from '../../global/globalEnums'; -import { DocFocusOrOpen, returnEmptyDocViewList } from '../../nodes/DocumentView'; +import { DocumentView } from '../../nodes/DocumentView'; import { FieldViewProps } from '../../nodes/FieldView'; import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; import { FInfotoColType } from './CollectionSchemaView'; @@ -59,6 +59,14 @@ export interface SchemaTableCellProps { rootSelected?: () => boolean; } +function selectedCell(props: SchemaTableCellProps) { + return ( + props.isRowActive() && + props.selectedCol() === props.col && // + props.selectedCells()?.filter(d => d === props.Document)?.length + ); +} + @observer export class SchemaTableCell extends ObservableReactComponent { constructor(props: SchemaTableCellProps) { @@ -67,7 +75,7 @@ export class SchemaTableCell extends ObservableReactComponent { - DocFocusOrOpen(toList(docs)[0]); + DocumentView.FocusOrOpen(toList(docs)[0]); return true; }; public static renderProps(props: SchemaTableCellProps) { @@ -114,11 +122,6 @@ export class SchemaTableCell extends ObservableReactComponent doc === this._props.Document).length !== 0 && this._props.selectedCol() === this._props.col; - } - @computed get defaultCellContent() { const { color, textDecoration, fieldProps, pointerEvents } = SchemaTableCell.renderProps(this._props); @@ -132,12 +135,12 @@ export class SchemaTableCell extends ObservableReactComponent this.selected && this._props.autoFocus && r?.setIsFocused(true)} + ref={r => selectedCell(this._props) && this._props.autoFocus && r?.setIsFocused(true)} oneLine={this._props.oneLine} allowCRs={this._props.allowCRs} contents={undefined} fieldContents={fieldProps} - editing={this.selected ? undefined : false} + editing={selectedCell(this._props) ? undefined : false} GetValue={() => Field.toKeyValueString(fieldProps.Document, this._props.fieldKey, SnappingManager.MetaKey)} SetValue={undoable((value: string, shiftDown?: boolean, enterKey?: boolean) => { if (shiftDown && enterKey) { @@ -157,39 +160,27 @@ export class SchemaTableCell extends ObservableReactComponent; - case ColumnType.Boolean: return ; - case ColumnType.RTF: return ; + switch (this.getCellType) { + case ColumnType.Image: return ; + case ColumnType.Boolean: return ; + case ColumnType.RTF: return ; case ColumnType.Enumeration: return Field.toString(val))} />; - case ColumnType.Date: return ; - default: return this.defaultCellContent; - } - } - - select = (shift: boolean, ctrl: boolean, e: React.MouseEvent) => { - if (this._props.isRowActive?.() !== false) { - if (this.selected && ctrl) { - this._props.selectCell(this._props.Document, this._props.col, shift, ctrl); - e.stopPropagation(); - } else !this.selected && this._props.selectCell(this._props.Document, this._props.col, shift, ctrl); + case ColumnType.Date: return ; + default: return this.defaultCellContent; } } @@ -199,9 +190,16 @@ export class SchemaTableCell extends ObservableReactComponent StopEvent(e)} onPointerDown={action(e => { - this.select(e.shiftKey, e.ctrlKey, e); + const shift: boolean = e.shiftKey; + const ctrl: boolean = e.ctrlKey; + if (this._props.isRowActive?.() !== false) { + if (selectedCell(this._props) && ctrl) { + this._props.selectCell(this._props.Document, this._props.col, shift, ctrl); + e.stopPropagation(); + } else !selectedCell(this._props) && this._props.selectCell(this._props.Document, this._props.col, shift, ctrl); + } })} - style={{ padding: this._props.padding, maxWidth: this._props.maxWidth?.(), width: this._props.columnWidth() || undefined, border: this.selected ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined }}> + style={{ padding: this._props.padding, maxWidth: this._props.maxWidth?.(), width: this._props.columnWidth() || undefined, border: selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined }}> {this.content}
); @@ -331,20 +329,14 @@ export class SchemaRTFCell extends ObservableReactComponent doc === this._props.Document).length !== 0 && this._props.selectedCol() === this._props.col; - // return this._props.isRowActive() && selected?.[0] === this._props.Document && selected[1] === this._props.col; - } - // if the text box blurs and none of its contents are focused(), then the edit finishes - selectedFunc = () => this.selected; + selectedFunc = () => !!selectedCell(this._props); render() { const { color, textDecoration, fieldProps, cursor, pointerEvents } = SchemaTableCell.renderProps(this._props); fieldProps.isContentActive = this.selectedFunc; return ( -
- {this.selected ? this._props.finishEdit?.()} /> : (field => (field ? Field.toString(field) : ''))(FieldValue(fieldProps.Document[fieldProps.fieldKey]))} +
+ {selectedCell(this._props) ? this._props.finishEdit?.()} /> : (field => (field ? Field.toString(field) : ''))(FieldValue(fieldProps.Document[fieldProps.fieldKey]))}
); } @@ -356,10 +348,6 @@ export class SchemaBoolCell extends ObservableReactComponent doc === this._props.Document).length !== 0 && this._props.selectedCol() === this._props.col; - } render() { const { color, textDecoration, fieldProps, cursor, pointerEvents } = SchemaTableCell.renderProps(this._props); return ( @@ -377,7 +365,7 @@ export class SchemaBoolCell extends ObservableReactComponent Field.toKeyValueString(this._props.Document, this._props.fieldKey)} SetValue={undoBatch((value: string, shiftDown?: boolean, enterKey?: boolean) => { if (shiftDown && enterKey) { @@ -401,10 +389,6 @@ export class SchemaEnumerationCell extends ObservableReactComponent doc === this._props.Document).length !== 0 && this._props.selectedCol() === this._props.col; - } render() { const { color, textDecoration, cursor, pointerEvents } = SchemaTableCell.renderProps(this._props); const options = this._props.options?.map(facet => ({ value: facet, label: facet })); @@ -457,4 +441,4 @@ export class SchemaEnumerationCell extends ObservableReactComponent ); } -} +} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 4a1395a1fc72f0ebcdd29356aa0425804da55d67 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Thu, 9 May 2024 03:32:18 -0400 Subject: tag reference parsing in progress --- .../collectionSchema/CollectionSchemaView.tsx | 73 +++++++++++++++++----- 1 file changed, 56 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index f7a553da3..2704b5234 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -324,9 +324,24 @@ export class CollectionSchemaView extends CollectionSubView() { }); } - parseEquation = (eq: string): string => { + parseEquation = (eq: string): [string, Map] => { const variablePattern = /[a-z]+/gi; - return eq.replace(variablePattern, (match) => `doc.${match}`); + const tagRefPattern = /{([^}]*)}/g; + const tagRefs = eq.match(tagRefPattern) + const docTagRefPairs = new Map; + let modifiedEq = eq; + + if (tagRefs){ + tagRefs.forEach(ref => { + const [doc, key] = this.getCellInfoFromTag(ref); + docTagRefPairs.set(ref, doc); + const replacement = `docTagRefPairs.get('${ref}').${key}`; + modifiedEq = modifiedEq.replace(new RegExp(ref, 'g'), replacement); + }) + } + modifiedEq = modifiedEq.replace(variablePattern, (match) => `doc.${match}`); + + return [eq, docTagRefPairs] } parsedEquationResult = (eq: string, doc: any): number => { @@ -529,6 +544,9 @@ export class CollectionSchemaView extends CollectionSubView() { @action selectCell = (doc: Doc, col: number, shiftKey: boolean, ctrlKey: boolean) => { + this.populateCellTags(); + console.log(this.getCellTag(doc, col)); + console.log(this.getCellInfoFromTag("C1")); if (!shiftKey && !ctrlKey) this.clearSelection(); !this._selectedCells && (this._selectedCells = []); !shiftKey && this._selectedCells && this._selectedCells.push(doc); @@ -551,10 +569,46 @@ export class CollectionSchemaView extends CollectionSubView() { // let selectedIndexes: Array = this._selectedCells.map(doc => this.rowIndex(doc)); }; + @action + deselectCell = (doc: Doc) => { + this._selectedCells && (this._selectedCells = this._selectedCells.filter(d => d !== doc)); + if (this.rowIndex(doc) === this._lowestSelectedIndex) this._lowestSelectedIndex = Math.min(...this._selectedDocs.map(d => this.rowIndex(d))); + }; + + @action + deselectAllCells = () => { + this._selectedCells = []; + this._lowestSelectedIndex = -1; + }; + + sortedSelectedDocs = () => this.sortedDocs.docs.filter(doc => this._selectedDocs.includes(doc)); + + getCellTag = (doc: Doc, col: number) => { return this._cellTags.get(doc)[col]; } + getCellInfoFromTag = (tag: string): [Doc, string] => { + const lettersToNumber = (letters: string) => { + let number = 0; + let length = letters.length; + for (let i = 0; i < length; i++) { + number *= 26; + number += (letters.charCodeAt(i) - 'A'.charCodeAt(0) + 1); + } + return number; + } + + const colTag = tag.replace(/[^A-Z]/g, ''); + const col = lettersToNumber(colTag); + const key: string = this.columnKeys[col]; + + const rowNum = Number(tag.replace(/[^\d]/g, '')); + const doc = this.childDocs[rowNum]; + + return [doc, key]; + } + populateCellTags = () => { this.childDocs.forEach(doc => this.addTags(doc)); } @@ -594,20 +648,6 @@ export class CollectionSchemaView extends CollectionSubView() { return result; } - @action - deselectCell = (doc: Doc) => { - this._selectedCells && (this._selectedCells = this._selectedCells.filter(d => d !== doc)); - if (this.rowIndex(doc) === this._lowestSelectedIndex) this._lowestSelectedIndex = Math.min(...this._selectedDocs.map(d => this.rowIndex(d))); - }; - - @action - deselectAllCells = () => { - this._selectedCells = []; - this._lowestSelectedIndex = -1; - }; - - sortedSelectedDocs = () => this.sortedDocs.docs.filter(doc => this._selectedDocs.includes(doc)); - @computed get rowDropIndex() { const mouseY = this.ScreenToLocalBoxXf().transformPoint(this._mouseCoordinates.x, this._mouseCoordinates.y)[1]; @@ -774,7 +814,6 @@ export class CollectionSchemaView extends CollectionSubView() { @action setKey = (key: string, defaultVal?: any) => { - console.log("called") if (this._makeNewColumn) { this.addColumn(key, defaultVal); } else { -- cgit v1.2.3-70-g09d2 From 8fe221d77d8c5e0ffce67a1dd0483b41368820ee Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Thu, 9 May 2024 04:20:18 -0400 Subject: parse function close to properly registering tags --- .../collectionSchema/CollectionSchemaView.tsx | 53 +++++++++++----------- 1 file changed, 27 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 2704b5234..19d170c81 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -287,7 +287,8 @@ export class CollectionSchemaView extends CollectionSubView() { if (!this.documentKeys.includes(key)) { this.addNewKey(key, defaultVal); } - + + this.modifyCellTags(true); const newColWidth = this.tableWidth / (this.storedColumnWidths.length + 1); const currWidths = this.storedColumnWidths.slice(); currWidths.splice(0, 0, newColWidth); @@ -316,37 +317,37 @@ export class CollectionSchemaView extends CollectionSubView() { } } - @action - setupAutoUpdate = (equation: string, doc: Doc) => { - return autorun(() => { - const result = this.parsedEquationResult(equation, doc); - doc[DocData][equation] = result; - }); - } + // @action + // setupAutoUpdate = (equation: string, doc: Doc) => { + // return autorun(() => { + // const result = this.parsedEquationResult(equation, doc); + // doc[DocData][equation] = result; + // }); + // } parseEquation = (eq: string): [string, Map] => { const variablePattern = /[a-z]+/gi; const tagRefPattern = /{([^}]*)}/g; - const tagRefs = eq.match(tagRefPattern) - const docTagRefPairs = new Map; + const docTagRefPairs = new Map(); let modifiedEq = eq; - - if (tagRefs){ - tagRefs.forEach(ref => { - const [doc, key] = this.getCellInfoFromTag(ref); - docTagRefPairs.set(ref, doc); - const replacement = `docTagRefPairs.get('${ref}').${key}`; - modifiedEq = modifiedEq.replace(new RegExp(ref, 'g'), replacement); - }) + let match; + + while (match = tagRefPattern.exec(eq)) { + const ref = match[1]; + const [doc, key] = this.getCellInfoFromTag(ref); + docTagRefPairs.set(ref, doc); + const replacement = `docTagRefPairs.get('${ref}').${key}`; + modifiedEq = modifiedEq.replace(new RegExp(`{${ref}}`, 'g'), replacement); } - modifiedEq = modifiedEq.replace(variablePattern, (match) => `doc.${match}`); - - return [eq, docTagRefPairs] + + //modifiedEq = modifiedEq.replace(variablePattern, (match) => `doc.${match}`); + + return [modifiedEq, docTagRefPairs]; } - - parsedEquationResult = (eq: string, doc: any): number => { - const func = new Function('doc', 'return ' + eq); - return func(doc); + + parsedEquationResult = (eq: [string, Map], doc: any): number => { + const func = new Function('doc', 'docTagRefPairs', 'return ' + eq[0]); + return func(doc, eq[1]); } @undoBatch @@ -604,7 +605,7 @@ export class CollectionSchemaView extends CollectionSubView() { const key: string = this.columnKeys[col]; const rowNum = Number(tag.replace(/[^\d]/g, '')); - const doc = this.childDocs[rowNum]; + const doc = this.childDocs[rowNum - 1]; return [doc, key]; } -- cgit v1.2.3-70-g09d2 From 2d7037dd5664700cda04b1fb0c6c77fe6f49d66c Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Thu, 9 May 2024 23:33:17 -0400 Subject: goodbye old parser ;( hello new parser :) --- src/client/documents/Documents.ts | 2 +- src/client/views/FieldsDropdown.tsx | 4 +- .../collectionSchema/CollectionSchemaView.tsx | 75 +++++++++++----------- .../collections/collectionSchema/SchemaRowBox.tsx | 2 + .../collectionSchema/SchemaTableCell.tsx | 6 +- 5 files changed, 48 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 1c18c0d84..f0974f5dd 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -43,7 +43,7 @@ export class FInfo { readOnly: boolean = false; fieldType?: FInfoFieldType; values?: FieldType[]; - + onLayout?: boolean; filterable?: boolean = true; // can be used as a Filter in FilterPanel // format?: string; // format to display values (e.g, decimal places, $, etc) // parse?: ScriptField; // parse a value from a string diff --git a/src/client/views/FieldsDropdown.tsx b/src/client/views/FieldsDropdown.tsx index 0ea0ebd83..011cd51b3 100644 --- a/src/client/views/FieldsDropdown.tsx +++ b/src/client/views/FieldsDropdown.tsx @@ -34,7 +34,7 @@ export class FieldsDropdown extends ObservableReactComponent(); SearchUtil.foreachRecursiveDoc([this._props.Document], (depth, doc) => allDocs.add(doc)); return Array.from(allDocs); @@ -57,7 +57,7 @@ export class FieldsDropdown extends ObservableReactComponent facet[0] === facet.charAt(0).toUpperCase())]; Object.entries(DocOptions) - .filter(opts => opts[1].filterable) + .filter(opts => opts[1].filterable) //!!! .forEach((pair: [string, FInfo]) => filteredOptions.push(pair[0])); const options = filteredOptions.sort().map(facet => ({ value: facet, label: facet })); diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 19d170c81..e493b2e5d 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -6,7 +6,7 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import { returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../ClientUtils'; import { emptyFunction } from '../../../../Utils'; -import { Doc, DocListCast, Field, FieldType, NumListCast, Opt, StrListCast } from '../../../../fields/Doc'; +import { Doc, DocListCast, Field, FieldType, IdToDoc, NumListCast, Opt, StrListCast } from '../../../../fields/Doc'; import { DocData } from '../../../../fields/DocSymbols'; import { Id } from '../../../../fields/FieldSymbols'; import { List } from '../../../../fields/List'; @@ -288,7 +288,6 @@ export class CollectionSchemaView extends CollectionSubView() { this.addNewKey(key, defaultVal); } - this.modifyCellTags(true); const newColWidth = this.tableWidth / (this.storedColumnWidths.length + 1); const currWidths = this.storedColumnWidths.slice(); currWidths.splice(0, 0, newColWidth); @@ -302,19 +301,24 @@ export class CollectionSchemaView extends CollectionSubView() { @action addNewKey = (key: string, defaultVal: any) => { - if (this._newFieldType == ColumnType.Equation) { - this.childDocs.forEach(doc => { - const parsedEquation = this.parseEquation(defaultVal); - const val = computed(() => { return this.parsedEquationResult(parsedEquation, doc);}) - doc[DocData][key] = val.get(); - // doc[DocData][key] = this.parsedEquationResult(eq, doc); - // this.setupAutoUpdate(eq, doc); - }); - } else { - this.childDocs.forEach(doc => { - doc[DocData][key] = defaultVal; - }); + this.childDocs.forEach(doc => { + doc[DocData][key] = defaultVal; + }); + } + + cleanupComputedField = (field: string) => { + const idPattern = /idToDoc\((.*?)\)/g; + let modField = field.slice(); + let matches; + let results = new Map(); + while ((matches = idPattern.exec(field)) !== null) { + results.set(matches[0], matches[1].replace(/"/g, '')); } + console.log(results); + results.forEach((id, funcId) => { + modField = modField.replace(funcId, 'd' + (this.rowIndex(IdToDoc(id)) + 1).toString()); + }) + return modField; } // @action @@ -325,30 +329,30 @@ export class CollectionSchemaView extends CollectionSubView() { // }); // } - parseEquation = (eq: string): [string, Map] => { - const variablePattern = /[a-z]+/gi; - const tagRefPattern = /{([^}]*)}/g; - const docTagRefPairs = new Map(); - let modifiedEq = eq; - let match; + // parseEquation = (eq: string): [string, Map] => { + // const variablePattern = /[a-z]+/gi; + // const tagRefPattern = /{([^}]*)}/g; + // const docTagRefPairs = new Map(); + // let modifiedEq = eq; + // let match; - while (match = tagRefPattern.exec(eq)) { - const ref = match[1]; - const [doc, key] = this.getCellInfoFromTag(ref); - docTagRefPairs.set(ref, doc); - const replacement = `docTagRefPairs.get('${ref}').${key}`; - modifiedEq = modifiedEq.replace(new RegExp(`{${ref}}`, 'g'), replacement); - } + // while (match = tagRefPattern.exec(eq)) { + // const ref = match[1]; + // const [doc, key] = this.getCellInfoFromTag(ref); + // docTagRefPairs.set(ref, doc); + // const replacement = `docTagRefPairs.get('${ref}').${key}`; + // modifiedEq = modifiedEq.replace(new RegExp(`{${ref}}`, 'g'), replacement); + // } - //modifiedEq = modifiedEq.replace(variablePattern, (match) => `doc.${match}`); + // modifiedEq = modifiedEq.replace(variablePattern, (match) => `doc.${match}`); - return [modifiedEq, docTagRefPairs]; - } + // return [modifiedEq, docTagRefPairs]; + // } - parsedEquationResult = (eq: [string, Map], doc: any): number => { - const func = new Function('doc', 'docTagRefPairs', 'return ' + eq[0]); - return func(doc, eq[1]); - } + // parsedEquationResult = (eq: [string, Map], doc: any): number => { + // const func = new Function('doc', 'docTagRefPairs', 'return ' + eq[0]); + // return func(doc, eq[1]); + // } @undoBatch removeColumn = (index: number) => { @@ -547,7 +551,6 @@ export class CollectionSchemaView extends CollectionSubView() { selectCell = (doc: Doc, col: number, shiftKey: boolean, ctrlKey: boolean) => { this.populateCellTags(); console.log(this.getCellTag(doc, col)); - console.log(this.getCellInfoFromTag("C1")); if (!shiftKey && !ctrlKey) this.clearSelection(); !this._selectedCells && (this._selectedCells = []); !shiftKey && this._selectedCells && this._selectedCells.push(doc); @@ -602,7 +605,7 @@ export class CollectionSchemaView extends CollectionSubView() { const colTag = tag.replace(/[^A-Z]/g, ''); const col = lettersToNumber(colTag); - const key: string = this.columnKeys[col]; + const key: string = this.columnKeys[col - 1]; const rowNum = Number(tag.replace(/[^\d]/g, '')); const doc = this.childDocs[rowNum - 1]; diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index 760089ffb..3295c9ab1 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -52,6 +52,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { this._props.setContentViewBox?.(this); } + cleanupField = (field: string) => this.schemaView.cleanupComputedField(field) setCursorIndex = (mouseY: number) => this.schemaView?.setRelCursorIndex(mouseY); selectedCol = () => this.schemaView._selectedCol; getFinfo = computedFn((fieldKey: string) => this.schemaView?.fieldInfos.get(fieldKey)); @@ -149,6 +150,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { setSelectedColumnValues={this.setSelectedColumnValues} oneLine={BoolCast(this.schemaDoc?._singleLine)} menuTarget={this.schemaView.MenuTarget} + cleanupField={this.cleanupField} transform={() => { const ind = index === this.schemaView.columnKeys.length - 1 ? this.schemaView.columnKeys.length - 3 : index; const x = this.schemaView?.displayColumnWidths.reduce((p, c, i) => (i <= ind ? p + c : p), 0); diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 67991b8a2..d11af6b3c 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -57,6 +57,7 @@ export interface SchemaTableCellProps { transform: () => Transform; autoFocus?: boolean; // whether to set focus on creation, othwerise wait for a click rootSelected?: () => boolean; + cleanupField: (field: string) => string; } function selectedCell(props: SchemaTableCellProps) { @@ -141,14 +142,15 @@ export class SchemaTableCell extends ObservableReactComponent Field.toKeyValueString(fieldProps.Document, this._props.fieldKey, SnappingManager.MetaKey)} + GetValue={() => this._props.cleanupField(Field.toKeyValueString(fieldProps.Document, this._props.fieldKey, SnappingManager.MetaKey))} //TODO: feed this into parser that handles idToDoc SetValue={undoable((value: string, shiftDown?: boolean, enterKey?: boolean) => { if (shiftDown && enterKey) { this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), value); this._props.finishEdit?.(); return true; } - const ret = Doc.SetField(fieldProps.Document, this._props.fieldKey.replace(/^_/, ''), value, Doc.IsDataProto(fieldProps.Document) ? true : undefined); + const hasNoLayout = Doc.IsDataProto(fieldProps.Document) ? true : undefined; // the "delegate" is a a data document so never write to it's proto + const ret = Doc.SetField(fieldProps.Document, this._props.fieldKey.replace(/^_/, ''), value, hasNoLayout); this._props.finishEdit?.(); return ret; }, 'edit schema cell')} -- cgit v1.2.3-70-g09d2 From 3b5cecea920b62a5d1633d8c6603b3b152794611 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Mon, 13 May 2024 00:54:49 -0400 Subject: editable column header started --- src/client/documents/Documents.ts | 1 + .../collectionSchema/CollectionSchemaView.tsx | 3 +- .../collectionSchema/SchemaColumnHeader.tsx | 90 ++++++++++++++++++++-- .../collectionSchema/SchemaTableCell.tsx | 2 +- 4 files changed, 88 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index f0974f5dd..3cc0d5604 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -87,6 +87,7 @@ class DocInfo extends FInfo { constructor(d: string, filterable?: boolean, values?: Doc[]) { super(d, true); this.values = values; + console.log(this.values); this.filterable = filterable; } override searchable = () => false; diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index e493b2e5d..c9d5307c9 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -312,9 +312,8 @@ export class CollectionSchemaView extends CollectionSubView() { let matches; let results = new Map(); while ((matches = idPattern.exec(field)) !== null) { - results.set(matches[0], matches[1].replace(/"/g, '')); + results.set(matches[0], matches[1]); } - console.log(results); results.forEach((id, funcId) => { modField = modField.replace(funcId, 'd' + (this.rowIndex(IdToDoc(id)) + 1).toString()); }) diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index 6b5a34ec0..dad0c214b 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -1,14 +1,20 @@ /* eslint-disable react/no-unused-prop-types */ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action } from 'mobx'; +import { action, computed, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { setupMoveUpEvents } from '../../../../ClientUtils'; +import { returnEmptyDoclist, returnEmptyFilter, returnFalse, setupMoveUpEvents } from '../../../../ClientUtils'; import { emptyFunction } from '../../../../Utils'; import { Colors } from '../../global/globalEnums'; import './CollectionSchemaView.scss'; +import { EditableView } from '../../EditableView'; +import { DefaultStyleProvider, returnEmptyDocViewList } from '../../StyleProvider'; +import { FieldViewProps } from '../../nodes/FieldView'; export interface SchemaColumnHeaderProps { + autoFocus?: boolean; + oneLine?: boolean; // whether all input should fit on one line vs allowing textare multiline inputs + allowCRs?: boolean; // allow carriage returns in text input (othewrise CR ends the edit) columnKeys: string[]; columnWidths: number[]; columnIndex: number; @@ -26,6 +32,9 @@ export interface SchemaColumnHeaderProps { @observer export class SchemaColumnHeader extends React.Component { + + @observable _editing: boolean = false; + get fieldKey() { return this.props.columnKeys[this.props.columnIndex]; } @@ -44,10 +53,81 @@ export class SchemaColumnHeader extends React.Component }; @action - onPointerDown = (e: React.PointerEvent) => { + setupDrag = (e: React.PointerEvent) => { this.props.isContentActive(true) && setupMoveUpEvents(this, e, moveEv => this.props.dragColumn(moveEv, this.props.columnIndex), emptyFunction, emptyFunction); }; + public static renderProps(props: SchemaColumnHeaderProps) { + const { Document, fieldKey, getFinfo, columnWidth, isContentActive } = props; + let protoCount = 0; + let doc: Doc | undefined = Document; + while (doc) { + if (Object.keys(doc).includes(fieldKey.replace(/^_/, ''))) { + break; + } + protoCount++; + doc = DocCast(doc.proto); + } + const parenCount = Math.max(0, protoCount - 1); + const color = protoCount === 0 || (fieldKey.startsWith('_') && Document[fieldKey] === undefined) ? 'black' : 'blue'; // color of text in cells + const textDecoration = color !== 'black' && parenCount ? 'underline' : ''; + const fieldProps: FieldViewProps = { + childFilters: returnEmptyFilter, + childFiltersByRanges: returnEmptyFilter, + docViewPath: returnEmptyDocViewList, + searchFilterDocs: returnEmptyDoclist, + styleProvider: DefaultStyleProvider, + isSelected: returnFalse, + setHeight: returnFalse, + select: emptyFunction, + dragAction: dropActionType.move, + renderDepth: 1, + noSidebar: true, + isContentActive: returnFalse, + whenChildContentsActiveChanged: emptyFunction, + ScreenToLocalTransform: Transform.Identity, + focus: emptyFunction, + addDocTab: SchemaTableCell.addFieldDoc, + pinToPres: returnZero, + Document: DocCast(Document.rootDocument, Document), + fieldKey: fieldKey, + PanelWidth: columnWidth, + PanelHeight: props.rowHeight, + rootSelected: props.rootSelected, + }; + const readOnly = getFinfo(fieldKey)?.readOnly ?? false; + const cursor = !readOnly ? 'text' : 'default'; + const pointerEvents = 'all'; + return { color, textDecoration, fieldProps, cursor, pointerEvents }; + } + + @computed get editableView() { + const { color, textDecoration, fieldProps, pointerEvents } = SchemaColumnHeader.renderProps(this.props); + + return this.props.autoFocus && r?.setIsFocused(true)} + oneLine={this.props.oneLine} + allowCRs={this.props.allowCRs} + contents={undefined} + fieldContents={fieldProps} + editing={this._editing ? undefined : false} + GetValue={() => this._props.cleanupField(Field.toKeyValueString(fieldProps.Document, this._props.fieldKey, SnappingManager.MetaKey)).replace(/[";]/g, '')} //TODO: feed this into parser that handles idToDoc + SetValue={undoable((value: string, shiftDown?: boolean, enterKey?: boolean) => { + if (shiftDown && enterKey) { + this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), value); + this._props.finishEdit?.(); + return true; + } + const hasNoLayout = Doc.IsDataProto(fieldProps.Document) ? true : undefined; // the "delegate" is a a data document so never write to it's proto + const ret = Doc.SetField(fieldProps.Document, this._props.fieldKey.replace(/^_/, ''), value, hasNoLayout); + this._props.finishEdit?.(); + return ret; + }, 'edit schema cell')} + /> + } + render() { return (
style={{ width: this.props.columnWidths[this.props.columnIndex], }} - onPointerDown={this.onPointerDown} + onPointerDown={this.setupDrag} ref={col => { if (col) { this.props.setColRef(this.props.columnIndex, col); } }}>
this.props.resizeColumn(e, this.props.columnIndex)} /> -
{this.fieldKey}
+
{this._editing = true; console.log(this._editing)}}>{this.fieldKey}
this.props.openContextMenu(e.clientX, e.clientY, this.props.columnIndex)}> diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index d11af6b3c..733cf3722 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -142,7 +142,7 @@ export class SchemaTableCell extends ObservableReactComponent this._props.cleanupField(Field.toKeyValueString(fieldProps.Document, this._props.fieldKey, SnappingManager.MetaKey))} //TODO: feed this into parser that handles idToDoc + GetValue={() => this._props.cleanupField(Field.toKeyValueString(fieldProps.Document, this._props.fieldKey, SnappingManager.MetaKey)).replace(/[";]/g, '')} //TODO: feed this into parser that handles idToDoc SetValue={undoable((value: string, shiftDown?: boolean, enterKey?: boolean) => { if (shiftDown && enterKey) { this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), value); -- cgit v1.2.3-70-g09d2 From 58692ef043125ebd3113d81f3ca7161a7e6521cb Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Mon, 13 May 2024 18:44:23 -0400 Subject: equation parser works but occasional call stack error --- src/client/documents/Documents.ts | 1 + src/client/util/DocumentManager.ts | 11 ++ src/client/util/Scripting.ts | 1 - .../collectionSchema/CollectionSchemaView.tsx | 10 +- .../collectionSchema/SchemaColumnHeader.tsx | 140 +++++++++++---------- src/client/views/nodes/DocumentIcon.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 1 + 7 files changed, 92 insertions(+), 74 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 3cc0d5604..5e1b173dc 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -178,6 +178,7 @@ export class DocumentOptions { map_pitch?: NUMt = new NumInfo('pitch of a map view', false); map_bearing?: NUMt = new NumInfo('bearing of a map view', false); map_style?: STRt = new StrInfo('mapbox style for a map view', false); + identifier?: STRt = new StrInfo('documentIcon displayed for each doc as "d[x]"', false); date_range?: STRt = new StrInfo('date range for calendar', false); diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 97051207b..8dba54541 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -46,6 +46,7 @@ export class DocumentManager { DocumentView.addViewRenderedCb = this.AddViewRenderedCb; DocumentView.getFirstDocumentView = this.getFirstDocumentView; DocumentView.getDocumentView = this.getDocumentView; + DocumentView.getDocViewIndex = this.getDocViewIndex; DocumentView.getContextPath = DocumentManager.GetContextPath; DocumentView.getLightboxDocumentView = this.getLightboxDocumentView; observe(Doc.CurrentlyLoading, change => { @@ -138,6 +139,16 @@ export class DocumentManager { ); } + public getDocViewIndex(target: Doc): number { + const docViewArray = DocumentManager.Instance.DocumentViews; + for (let i = 0; i < docViewArray.length; ++i){ + if (docViewArray[i].Document == target){ + return i; + } + } + return -1; + } + public getLightboxDocumentView = (toFind: Doc): DocumentView | undefined => { const views: DocumentView[] = []; DocumentManager.Instance.DocumentViews.forEach(view => DocumentView.LightboxContains(view) && Doc.AreProtosEqual(view.Document, toFind) && views.push(view)); diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index 6948469cc..6ef592ef2 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -88,7 +88,6 @@ function Run(script: string | undefined, customParams: string[], diagnostics: an if (!options.editable) { batch = Doc.MakeReadOnly(); } - const result = compiledFunction.apply(thisParam, params).apply(thisParam, argsArray); batch?.end(); return { success: true, result }; diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index c9d5307c9..deeba3c7a 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -312,10 +312,10 @@ export class CollectionSchemaView extends CollectionSubView() { let matches; let results = new Map(); while ((matches = idPattern.exec(field)) !== null) { - results.set(matches[0], matches[1]); + results.set(matches[0], matches[1].replace(/"/g, '')); } results.forEach((id, funcId) => { - modField = modField.replace(funcId, 'd' + (this.rowIndex(IdToDoc(id)) + 1).toString()); + modField = modField.replace(funcId, 'd' + (DocumentView.getDocViewIndex(IdToDoc(id))).toString()); }) return modField; } @@ -549,7 +549,7 @@ export class CollectionSchemaView extends CollectionSubView() { @action selectCell = (doc: Doc, col: number, shiftKey: boolean, ctrlKey: boolean) => { this.populateCellTags(); - console.log(this.getCellTag(doc, col)); + //docs.findIndex(doc); if (!shiftKey && !ctrlKey) this.clearSelection(); !this._selectedCells && (this._selectedCells = []); !shiftKey && this._selectedCells && this._selectedCells.push(doc); @@ -1211,6 +1211,10 @@ export class CollectionSchemaView extends CollectionSubView() { {this.columnKeys.map((key, index) => ( CollectionSchemaView._minColWidth} //TODO: update + Document={this.Document} key={index} columnIndex={index} columnKeys={this.columnKeys} diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index dad0c214b..b498a4850 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -3,15 +3,26 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { returnEmptyDoclist, returnEmptyFilter, returnFalse, setupMoveUpEvents } from '../../../../ClientUtils'; +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 { DefaultStyleProvider, returnEmptyDocViewList } from '../../StyleProvider'; import { FieldViewProps } from '../../nodes/FieldView'; +import { Doc, Field } from '../../../../fields/Doc'; +import { dropActionType } from '../../../util/DropActionTypes'; +import { Transform } from 'prosemirror-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'; export interface SchemaColumnHeaderProps { + Document: Doc; autoFocus?: boolean; oneLine?: boolean; // whether all input should fit on one line vs allowing textare multiline inputs allowCRs?: boolean; // allow carriage returns in text input (othewrise CR ends the edit) @@ -20,6 +31,8 @@ export interface SchemaColumnHeaderProps { columnIndex: number; sortField: string; sortDesc: boolean; + schemaView: CollectionSchemaView; + //cleanupField: (s: string) => string; isContentActive: (outsideReaction?: boolean | undefined) => boolean | undefined; setSort: (field: string | undefined, desc?: boolean) => void; removeColumn: (index: number) => void; @@ -28,6 +41,10 @@ export interface SchemaColumnHeaderProps { dragColumn: (e: any, index: number) => boolean; openContextMenu: (x: number, y: number, index: number) => void; setColRef: (index: number, ref: HTMLDivElement) => void; + rootSelected?: () => boolean; + columnWidth: () => number; + finishEdit?: () => void; // notify container that edit is over (eg. to hide view in DashFieldView) + //transform: () => Transform; } @observer @@ -39,6 +56,9 @@ export class SchemaColumnHeader extends React.Component return this.props.columnKeys[this.props.columnIndex]; } + // getFinfo = computedFn((fieldKey: string) => this.props.schemaView?.fieldInfos.get(fieldKey)); + // setColumnValues = (field: string, value: string) => this.props.schemaView?.setColumnValues(field, value); + @action sortClicked = (e: React.PointerEvent) => { e.stopPropagation(); @@ -57,76 +77,58 @@ export class SchemaColumnHeader extends React.Component this.props.isContentActive(true) && setupMoveUpEvents(this, e, moveEv => this.props.dragColumn(moveEv, this.props.columnIndex), emptyFunction, emptyFunction); }; - public static renderProps(props: SchemaColumnHeaderProps) { - const { Document, fieldKey, getFinfo, columnWidth, isContentActive } = props; - let protoCount = 0; - let doc: Doc | undefined = Document; - while (doc) { - if (Object.keys(doc).includes(fieldKey.replace(/^_/, ''))) { - break; - } - protoCount++; - doc = DocCast(doc.proto); - } - const parenCount = Math.max(0, protoCount - 1); - const color = protoCount === 0 || (fieldKey.startsWith('_') && Document[fieldKey] === undefined) ? 'black' : 'blue'; // color of text in cells - const textDecoration = color !== 'black' && parenCount ? 'underline' : ''; - const fieldProps: FieldViewProps = { - childFilters: returnEmptyFilter, - childFiltersByRanges: returnEmptyFilter, - docViewPath: returnEmptyDocViewList, - searchFilterDocs: returnEmptyDoclist, - styleProvider: DefaultStyleProvider, - isSelected: returnFalse, - setHeight: returnFalse, - select: emptyFunction, - dragAction: dropActionType.move, - renderDepth: 1, - noSidebar: true, - isContentActive: returnFalse, - whenChildContentsActiveChanged: emptyFunction, - ScreenToLocalTransform: Transform.Identity, - focus: emptyFunction, - addDocTab: SchemaTableCell.addFieldDoc, - pinToPres: returnZero, - Document: DocCast(Document.rootDocument, Document), - fieldKey: fieldKey, - PanelWidth: columnWidth, - PanelHeight: props.rowHeight, - rootSelected: props.rootSelected, - }; - const readOnly = getFinfo(fieldKey)?.readOnly ?? false; - const cursor = !readOnly ? 'text' : 'default'; - const pointerEvents = 'all'; - return { color, textDecoration, fieldProps, cursor, pointerEvents }; - } - - @computed get editableView() { - const { color, textDecoration, fieldProps, pointerEvents } = SchemaColumnHeader.renderProps(this.props); - - return this.props.autoFocus && r?.setIsFocused(true)} - oneLine={this.props.oneLine} - allowCRs={this.props.allowCRs} - contents={undefined} - fieldContents={fieldProps} - editing={this._editing ? undefined : false} - GetValue={() => this._props.cleanupField(Field.toKeyValueString(fieldProps.Document, this._props.fieldKey, SnappingManager.MetaKey)).replace(/[";]/g, '')} //TODO: feed this into parser that handles idToDoc - SetValue={undoable((value: string, shiftDown?: boolean, enterKey?: boolean) => { - if (shiftDown && enterKey) { - this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), value); - this._props.finishEdit?.(); - return true; - } - const hasNoLayout = Doc.IsDataProto(fieldProps.Document) ? true : undefined; // the "delegate" is a a data document so never write to it's proto - const ret = Doc.SetField(fieldProps.Document, this._props.fieldKey.replace(/^_/, ''), value, hasNoLayout); - this._props.finishEdit?.(); - return ret; - }, 'edit schema cell')} - /> - } + // return this.props.autoFocus && r?.setIsFocused(true)} + // oneLine={this.props.oneLine} + // allowCRs={this.props.allowCRs} + // contents={undefined} + // fieldContents={fieldProps} + // editing={this._editing ? undefined : false} + // GetValue={() => this.props.cleanupField(Field.toKeyValueString(fieldProps.Document, this.fieldKey, SnappingManager.MetaKey)).replace(/[";]/g, '')} //TODO: feed this into parser that handles idToDoc + // SetValue={undoable((value: string, enterKey?: boolean) => { + // if (enterKey) this.setColumnValues(this.fieldKey.replace(/^_/, ''), value); + // this.props.finishEdit?.(); + // return true; + // }, 'edit schema cell')} + // /> + // } render() { return ( diff --git a/src/client/views/nodes/DocumentIcon.tsx b/src/client/views/nodes/DocumentIcon.tsx index 23d934edb..bfca6cad8 100644 --- a/src/client/views/nodes/DocumentIcon.tsx +++ b/src/client/views/nodes/DocumentIcon.tsx @@ -47,7 +47,7 @@ export class DocumentIcon extends ObservableReactComponent { } } -@observer +@observer export class DocumentIconContainer extends React.Component { public static getTransformer(): Transformer { const usedDocuments = new Set(); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 8df28a770..32480447d 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1025,6 +1025,7 @@ export class DocumentView extends DocComponent() { public static getViews = (doc?: Doc) => Array.from(doc?.[DocViews] ?? []) as DocumentView[]; public static getFirstDocumentView: (toFind: Doc) => DocumentView | undefined; public static getDocumentView: (target: Doc | undefined, preferredCollection?: DocumentView) => Opt; + public static getDocViewIndex: (target: Doc) => number; public static getContextPath: (doc: Opt, includeExistingViews?: boolean) => Doc[]; public static getLightboxDocumentView: (toFind: Doc) => Opt; public static showDocumentView: (targetDocView: DocumentView, options: FocusViewOptions) => Promise; -- cgit v1.2.3-70-g09d2 From 12184969abe9b88f34fd653c423fe0af491155bb Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Mon, 13 May 2024 18:46:59 -0400 Subject: console.logs removed --- src/client/documents/Documents.ts | 1 - src/client/views/collections/collectionSchema/CollectionSchemaView.tsx | 2 -- 2 files changed, 3 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 5e1b173dc..99665c22c 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -87,7 +87,6 @@ class DocInfo extends FInfo { constructor(d: string, filterable?: boolean, values?: Doc[]) { super(d, true); this.values = values; - console.log(this.values); this.filterable = filterable; } override searchable = () => false; diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index deeba3c7a..4e4a618bf 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -682,12 +682,10 @@ export class CollectionSchemaView extends CollectionSubView() { const draggedDocs = de.complete.docDragData?.draggedDocuments; if (draggedDocs && super.onInternalDrop(e, de) && !this.sortField) { const map = draggedDocs?.map(doc => this.rowIndex(doc)); - console.log(map); this.dataDoc[this.fieldKey ?? 'data'] = new List([...this.sortedDocs.docs]); this.clearSelection(); draggedDocs.forEach(doc => { DocumentView.addViewRenderedCb(doc, dv => dv.select(true)); - console.log(doc.x); }); this._lowestSelectedIndex = Math.min(...(draggedDocs?.map(doc => this.rowIndex(doc)) ?? [])); return true; -- cgit v1.2.3-70-g09d2 From 5cf0765e934ca183f0431bb3e6c9d57c2f9494f9 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Mon, 13 May 2024 18:51:19 -0400 Subject: removed cell tag logic ;( --- .../collectionSchema/CollectionSchemaView.tsx | 70 ---------------------- 1 file changed, 70 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 4e4a618bf..d844fdefc 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -548,8 +548,6 @@ export class CollectionSchemaView extends CollectionSubView() { @action selectCell = (doc: Doc, col: number, shiftKey: boolean, ctrlKey: boolean) => { - this.populateCellTags(); - //docs.findIndex(doc); if (!shiftKey && !ctrlKey) this.clearSelection(); !this._selectedCells && (this._selectedCells = []); !shiftKey && this._selectedCells && this._selectedCells.push(doc); @@ -566,10 +564,7 @@ export class CollectionSchemaView extends CollectionSubView() { } else this.addDocToSelection(doc, false); this._selectedCol = col; - if (this._lowestSelectedIndex === -1 || index < this._lowestSelectedIndex) this._lowestSelectedIndex = index; - - // let selectedIndexes: Array = this._selectedCells.map(doc => this.rowIndex(doc)); }; @action @@ -586,71 +581,6 @@ export class CollectionSchemaView extends CollectionSubView() { sortedSelectedDocs = () => this.sortedDocs.docs.filter(doc => this._selectedDocs.includes(doc)); - - getCellTag = (doc: Doc, col: number) => { - return this._cellTags.get(doc)[col]; - } - - getCellInfoFromTag = (tag: string): [Doc, string] => { - const lettersToNumber = (letters: string) => { - let number = 0; - let length = letters.length; - for (let i = 0; i < length; i++) { - number *= 26; - number += (letters.charCodeAt(i) - 'A'.charCodeAt(0) + 1); - } - return number; - } - - const colTag = tag.replace(/[^A-Z]/g, ''); - const col = lettersToNumber(colTag); - const key: string = this.columnKeys[col - 1]; - - const rowNum = Number(tag.replace(/[^\d]/g, '')); - const doc = this.childDocs[rowNum - 1]; - - return [doc, key]; - } - - populateCellTags = () => { - this.childDocs.forEach(doc => this.addTags(doc)); - } - - addTags = (doc: Doc) => { - const row = this.rowIndex(doc) + 1; - const tags = []; - for (let col = 1; col <= this._colEles.length; ++col){ - tags.push(this.numToChar(col) + row.toString()) - } - this._cellTags.set(doc, tags) - } - - modifyCellTags = (addingColumn: boolean) => { - if (addingColumn) { - const colTag = this.numToChar(this._colEles.length); - this._cellTags.forEach((tags, row) => { - const newTag = colTag + this.rowIndex(row); - tags.push(newTag); - }); - } else { - this._cellTags.forEach(tags => { - if (tags.length > 0) { - tags.pop(); - } - }) - } - } - - numToChar = (num: number) => { - let result = ''; - while (num > 0) { - let remainder = (num - 1) % 26; - result = String.fromCharCode(65 + remainder) + result; - num = Math.floor((num - 1) / 26); - } - return result; - } - @computed get rowDropIndex() { const mouseY = this.ScreenToLocalBoxXf().transformPoint(this._mouseCoordinates.x, this._mouseCoordinates.y)[1]; -- cgit v1.2.3-70-g09d2 From 4770a958a7b1003d636a4f9ea2cfdb76558e61b9 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Mon, 13 May 2024 23:13:15 -0400 Subject: columnheader editing progress --- src/client/views/EditableView.tsx | 2 +- .../collectionSchema/CollectionSchemaView.tsx | 11 +- .../collectionSchema/SchemaColumnHeader.tsx | 144 +++++++++++---------- .../collections/collectionSchema/SchemaRowBox.tsx | 2 +- 4 files changed, 88 insertions(+), 71 deletions(-) (limited to 'src') diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 684b948af..05c926399 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -155,7 +155,7 @@ export class EditableView extends ObservableReactComponent { case 'ArrowDown': case 'ArrowLeft': case 'ArrowRight': - e.stopPropagation(); + //e.stopPropagation(); break; case 'Shift': case 'Alt': diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index d844fdefc..d74cb56cf 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -275,6 +275,7 @@ export class CollectionSchemaView extends CollectionSubView() { changeColumnKey = (index: number, newKey: string, defaultVal?: any) => { if (!this.documentKeys.includes(newKey)) { this.addNewKey(newKey, defaultVal); + console.log("added") } const currKeys = this.columnKeys.slice(); // copy the column key array first, then change it. @@ -745,15 +746,23 @@ export class CollectionSchemaView extends CollectionSubView() { @action setKey = (key: string, defaultVal?: any) => { + console.log("setKey called with" + key) if (this._makeNewColumn) { this.addColumn(key, defaultVal); + this._makeNewColumn = false; } else { this.changeColumnKey(this._columnMenuIndex!, key, defaultVal); + console.log("changed") } this.closeColumnMenu(); }; - setColumnValues = (key: string, value: string) => { + setColumnValue = () => { + + } + + setCellValues = (key: string, value: string) => { + console.log("field: " + key + " vale: " + value); const selectedDocs: Doc[] = []; this.childDocs.forEach(doc => { const docIsSelected = this._selectedCells && !(this._selectedCells?.filter(d => d === doc).length === 0); diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index b498a4850..b74b2ace9 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -8,11 +8,12 @@ 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 { dropActionType } from '../../../util/DropActionTypes'; -import { Transform } from 'prosemirror-transform'; +import { Transform } from '../../../util/Transform'; import { SchemaTableCell } from './SchemaTableCell'; import { DocCast } from '../../../../fields/Types'; import { computedFn } from 'mobx-utils'; @@ -48,110 +49,117 @@ export interface SchemaColumnHeaderProps { } @observer -export class SchemaColumnHeader extends React.Component { +export class SchemaColumnHeader extends ObservableReactComponent { @observable _editing: boolean = false; get fieldKey() { - return this.props.columnKeys[this.props.columnIndex]; + return this._props.columnKeys[this._props.columnIndex]; } - // getFinfo = computedFn((fieldKey: string) => this.props.schemaView?.fieldInfos.get(fieldKey)); - // setColumnValues = (field: string, value: string) => this.props.schemaView?.setColumnValues(field, value); + getFinfo = computedFn((fieldKey: string) => this._props.schemaView?.fieldInfos.get(fieldKey)); + setColumnValues = (field: string, defaultValue: string) => {this._props.schemaView?.setKey(field, defaultValue);} @action sortClicked = (e: React.PointerEvent) => { e.stopPropagation(); e.preventDefault(); - if (this.props.sortField === this.fieldKey && this.props.sortDesc) { - this.props.setSort(undefined); - } else if (this.props.sortField === this.fieldKey) { - this.props.setSort(this.fieldKey, true); + if (this._props.sortField === this.fieldKey && this._props.sortDesc) { + this._props.setSort(undefined); + } else if (this._props.sortField === this.fieldKey) { + this._props.setSort(this.fieldKey, true); } else { - this.props.setSort(this.fieldKey, false); + this._props.setSort(this.fieldKey, false); } }; @action setupDrag = (e: React.PointerEvent) => { - this.props.isContentActive(true) && setupMoveUpEvents(this, e, moveEv => this.props.dragColumn(moveEv, this.props.columnIndex), emptyFunction, emptyFunction); + this._props.isContentActive(true) && setupMoveUpEvents(this, e, moveEv => this._props.dragColumn(moveEv, this._props.columnIndex), emptyFunction, emptyFunction); }; - // public static renderProps(props: SchemaColumnHeaderProps) { - // const { columnKeys, columnWidth, isContentActive, Document } = props; - // const fieldKey = columnKeys[props.columnIndex]; - // const color = 'black'; // color of text in cells - // const fieldProps: FieldViewProps = { - // childFilters: returnEmptyFilter, - // childFiltersByRanges: returnEmptyFilter, - // docViewPath: returnEmptyDocViewList, - // searchFilterDocs: returnEmptyDoclist, - // styleProvider: DefaultStyleProvider, - // isSelected: returnFalse, - // setHeight: returnFalse, - // select: emptyFunction, - // dragAction: dropActionType.move, - // renderDepth: 1, - // noSidebar: true, - // isContentActive: returnFalse, - // whenChildContentsActiveChanged: emptyFunction, - // ScreenToLocalTransform: Transform.Identity, - // focus: emptyFunction, - // addDocTab: SchemaTableCell.addFieldDoc, - // pinToPres: returnZero, - // Document: DocCast(Document.rootDocument, Document), - // fieldKey: fieldKey, - // PanelWidth: columnWidth, - // PanelHeight: props.rowHeight, - // rootSelected: props.rootSelected, - // }; - // const readOnly = getFinfo(fieldKey)?.readOnly ?? false; - // const cursor = !readOnly ? 'text' : 'default'; - // const pointerEvents = 'all'; - // return { color, fieldProps, cursor, pointerEvents }; - // } + renderProps = (props: SchemaColumnHeaderProps) => { + const { columnKeys, columnWidth, Document } = props; + const fieldKey = columnKeys[props.columnIndex]; + const color = 'black'; // color of text in cells + const fieldProps: FieldViewProps = { + childFilters: returnEmptyFilter, + childFiltersByRanges: returnEmptyFilter, + docViewPath: returnEmptyDocViewList, + searchFilterDocs: returnEmptyDoclist, + styleProvider: DefaultStyleProvider, + isSelected: returnFalse, + setHeight: returnFalse, + select: emptyFunction, + dragAction: dropActionType.move, + renderDepth: 1, + noSidebar: true, + isContentActive: returnFalse, + whenChildContentsActiveChanged: emptyFunction, + ScreenToLocalTransform: Transform.Identity, + focus: emptyFunction, + addDocTab: SchemaTableCell.addFieldDoc, + pinToPres: returnZero, + Document: DocCast(Document.rootDocument, Document), + fieldKey: fieldKey, + PanelWidth: columnWidth, + PanelHeight: props.rowHeight, + rootSelected: props.rootSelected, + }; + const readOnly = this.getFinfo(fieldKey)?.readOnly ?? false; + const cursor = !readOnly ? 'text' : 'default'; + const pointerEvents = 'all'; + return { color, fieldProps, cursor, pointerEvents }; + } + + @computed get editableView() { + const { color, fieldProps, pointerEvents } = this.renderProps(this._props); - // @computed get editableView() { - // const { color, fieldProps, pointerEvents } = SchemaColumnHeader.renderProps(this.props); + return
+ this._props.autoFocus && r?.setIsFocused(true)} + oneLine={this._props.oneLine} + allowCRs={this._props.allowCRs} + contents={undefined} + fieldContents={fieldProps} + editing={this._editing ? undefined : false} + GetValue={() => Field.toKeyValueString(fieldProps.Document, this.fieldKey, SnappingManager.MetaKey).replace(/[";]/g, '')} + SetValue={undoable((value: string) => { + this.setColumnValues(value, value); + this._props.finishEdit?.(); + return true; + }, 'edit column header')} + /> +
+ } - // return this.props.autoFocus && r?.setIsFocused(true)} - // oneLine={this.props.oneLine} - // allowCRs={this.props.allowCRs} - // contents={undefined} - // fieldContents={fieldProps} - // editing={this._editing ? undefined : false} - // GetValue={() => this.props.cleanupField(Field.toKeyValueString(fieldProps.Document, this.fieldKey, SnappingManager.MetaKey)).replace(/[";]/g, '')} //TODO: feed this into parser that handles idToDoc - // SetValue={undoable((value: string, enterKey?: boolean) => { - // if (enterKey) this.setColumnValues(this.fieldKey.replace(/^_/, ''), value); - // this.props.finishEdit?.(); - // return true; - // }, 'edit schema cell')} - // /> - // } + staticView = () => { + return
{this._editing = true; console.log(this._editing)}}>{this.fieldKey}
+ } render() { return (
{ if (col) { - this.props.setColRef(this.props.columnIndex, col); + this._props.setColRef(this._props.columnIndex, col); } }}> -
this.props.resizeColumn(e, this.props.columnIndex)} /> -
{this._editing = true; console.log(this._editing)}}>{this.fieldKey}
+
this._props.resizeColumn(e, this._props.columnIndex)} /> + +
{this._editing ? this.editableView : this.staticView()}
-
this.props.openContextMenu(e.clientX, e.clientY, this.props.columnIndex)}> +
this._props.openContextMenu(e.clientX, e.clientY, this._props.columnIndex)}>
-
- +
+
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index 3295c9ab1..908939ecc 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -59,7 +59,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { selectCell = (doc: Doc, col: number, shift: boolean, ctrl: boolean) => this.schemaView?.selectCell(doc, col, shift, ctrl); deselectCell = () => this.schemaView?.deselectAllCells(); selectedCells = () => this.schemaView?._selectedDocs; - setColumnValues = (field: any, value: any) => this.schemaView?.setColumnValues(field, value) ?? false; + setColumnValues = (field: any, value: any) => this.schemaView?.setCellValues(field, value) ?? false; setSelectedColumnValues = (field: any, value: any) => this.schemaView?.setSelectedColumnValues(field, value) ?? false; columnWidth = computedFn((index: number) => () => this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth); render() { -- cgit v1.2.3-70-g09d2 From b27056fc67c654dea72338f928cd69026a501c0f Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Tue, 14 May 2024 15:58:23 -0400 Subject: editable columnheader progress; still not updating properly on adding new col --- src/client/views/EditableView.tsx | 10 ++++-- .../collectionSchema/CollectionSchemaView.scss | 12 +++++++ .../collectionSchema/CollectionSchemaView.tsx | 39 ++-------------------- .../collectionSchema/SchemaColumnHeader.tsx | 34 ++++++++++++------- .../collectionSchema/SchemaTableCell.tsx | 2 +- 5 files changed, 45 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 05c926399..1eec11e64 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -54,6 +54,8 @@ export interface EditableProps { background?: string | undefined; placeholder?: string; wrap?: string; // nowrap, pre-wrap, etc + + isColHeader?: boolean; } /** @@ -135,7 +137,9 @@ export class EditableView extends ObservableReactComponent { if (!e.currentTarget.value) this._props.OnEmpty?.(); break; case 'Enter': + console.log("enter press detected") if (this._props.allowCRs !== true) { + console.log("noCrs??") e.stopPropagation(); if (!e.ctrlKey) { this.finalizeEdit(e.currentTarget.value, e.shiftKey, false, true); @@ -242,9 +246,9 @@ export class EditableView extends ObservableReactComponent { /> ) : this._props.oneLine !== false && this._props.GetValue()?.toString().indexOf('\n') === -1 ? ( { this._inputref = r; }} // prettier-ignore - style={{ display: this._props.display, overflow: 'auto', fontSize: this._props.fontSize, minWidth: 20, background: this._props.background }} + style={{ display: this._props.display, overflow: 'auto', fontSize: this._props.fontSize, minWidth: 20, background: this._props.background}} placeholder={this._props.placeholder} onBlur={e => this.finalizeEdit(e.currentTarget.value, false, true, false)} defaultValue={this._props.GetValue()} @@ -277,7 +281,7 @@ export class EditableView extends ObservableReactComponent { render() { const gval = this._props.GetValue()?.replace(/\n/g, '\\r\\n'); - if (this._editing && gval !== undefined) { + if ((this._editing && gval !== undefined) || this._props.isColHeader) { return this._props.sizeToContent ? (
{gval}
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss index 6fb8e40db..269bb4de5 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss @@ -162,6 +162,13 @@ min-width: 20%; } + .schema-column-edit-wrapper { + flex-grow: 2; + margin: 5px; + overflow: hidden; + min-width: 20%; + } + .schema-header-menu { margin: 5px; } @@ -176,6 +183,11 @@ } } + .editableView-input { + border: none; + outline: none; + } + /*.schema-column-resizer.left { min-width: 5px; transform: translate(-3px, 0px); diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index d74cb56cf..2d181a772 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -277,6 +277,7 @@ export class CollectionSchemaView extends CollectionSubView() { this.addNewKey(newKey, defaultVal); console.log("added") } + console.log("changed " + index) const currKeys = this.columnKeys.slice(); // copy the column key array first, then change it. currKeys[index] = newKey; @@ -321,39 +322,6 @@ export class CollectionSchemaView extends CollectionSubView() { return modField; } - // @action - // setupAutoUpdate = (equation: string, doc: Doc) => { - // return autorun(() => { - // const result = this.parsedEquationResult(equation, doc); - // doc[DocData][equation] = result; - // }); - // } - - // parseEquation = (eq: string): [string, Map] => { - // const variablePattern = /[a-z]+/gi; - // const tagRefPattern = /{([^}]*)}/g; - // const docTagRefPairs = new Map(); - // let modifiedEq = eq; - // let match; - - // while (match = tagRefPattern.exec(eq)) { - // const ref = match[1]; - // const [doc, key] = this.getCellInfoFromTag(ref); - // docTagRefPairs.set(ref, doc); - // const replacement = `docTagRefPairs.get('${ref}').${key}`; - // modifiedEq = modifiedEq.replace(new RegExp(`{${ref}}`, 'g'), replacement); - // } - - // modifiedEq = modifiedEq.replace(variablePattern, (match) => `doc.${match}`); - - // return [modifiedEq, docTagRefPairs]; - // } - - // parsedEquationResult = (eq: [string, Map], doc: any): number => { - // const func = new Function('doc', 'docTagRefPairs', 'return ' + eq[0]); - // return func(doc, eq[1]); - // } - @undoBatch removeColumn = (index: number) => { if (this.columnKeys.length === 1) return; @@ -745,14 +713,13 @@ export class CollectionSchemaView extends CollectionSubView() { }; @action - setKey = (key: string, defaultVal?: any) => { + setKey = (key: string, defaultVal?: any, index?: number) => { console.log("setKey called with" + key) if (this._makeNewColumn) { this.addColumn(key, defaultVal); this._makeNewColumn = false; } else { - this.changeColumnKey(this._columnMenuIndex!, key, defaultVal); - console.log("changed") + this.changeColumnKey(this._columnMenuIndex! | index!, key, defaultVal); } this.closeColumnMenu(); }; diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index b74b2ace9..794d5d8ac 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -53,12 +53,12 @@ export class SchemaColumnHeader extends ObservableReactComponent this._props.schemaView?.fieldInfos.get(fieldKey)); - setColumnValues = (field: string, defaultValue: string) => {this._props.schemaView?.setKey(field, defaultValue);} + setColumnValues = (field: string, defaultValue: string) => {this._props.schemaView?.setKey(field, defaultValue, this._props.columnIndex);} @action sortClicked = (e: React.PointerEvent) => { @@ -108,24 +108,34 @@ export class SchemaColumnHeader extends ObservableReactComponent + return
this._props.autoFocus && r?.setIsFocused(true)} oneLine={this._props.oneLine} allowCRs={this._props.allowCRs} contents={undefined} fieldContents={fieldProps} - editing={this._editing ? undefined : false} - GetValue={() => Field.toKeyValueString(fieldProps.Document, this.fieldKey, SnappingManager.MetaKey).replace(/[";]/g, '')} - SetValue={undoable((value: string) => { - this.setColumnValues(value, value); + editing={undefined} + isColHeader={true} + GetValue={() => {console.log(this.fieldKey); return this.fieldKey}} + SetValue={undoable((value: string, shiftKey?: boolean, enterKey?: boolean) => { + if (shiftKey && enterKey) { + this.setColumnValues(value, value); + this._props.finishEdit?.(); + return true; + } this._props.finishEdit?.(); return true; }, 'edit column header')} @@ -133,9 +143,9 @@ export class SchemaColumnHeader extends ObservableReactComponent } - staticView = () => { - return
{this._editing = true; console.log(this._editing)}}>{this.fieldKey}
- } + // staticView = () => { + // return
{this._editing = true; console.log(this._editing)}}>{this.fieldKey}
+ // } render() { return ( @@ -152,7 +162,7 @@ export class SchemaColumnHeader extends ObservableReactComponent
this._props.resizeColumn(e, this._props.columnIndex)} /> -
{this._editing ? this.editableView : this.staticView()}
+
{this.editableView}
this._props.openContextMenu(e.clientX, e.clientY, this._props.columnIndex)}> diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 733cf3722..51a92ff35 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -194,7 +194,7 @@ export class SchemaTableCell extends ObservableReactComponent { const shift: boolean = e.shiftKey; const ctrl: boolean = e.ctrlKey; - if (this._props.isRowActive?.() !== false) { + if (this._props.isRowActive?.()) { if (selectedCell(this._props) && ctrl) { this._props.selectCell(this._props.Document, this._props.col, shift, ctrl); e.stopPropagation(); -- cgit v1.2.3-70-g09d2 From 04b650dee835be1a4446a2499b8acd525b92daf9 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Tue, 14 May 2024 16:25:36 -0400 Subject: removed logs; added some comments; added safeguard against duplicate fields --- src/client/views/EditableView.tsx | 2 -- .../collectionSchema/CollectionSchemaView.tsx | 18 ++++++++---------- .../collectionSchema/SchemaColumnHeader.tsx | 12 +++++------- 3 files changed, 13 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 1eec11e64..011b6c77a 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -137,9 +137,7 @@ export class EditableView extends ObservableReactComponent { if (!e.currentTarget.value) this._props.OnEmpty?.(); break; case 'Enter': - console.log("enter press detected") if (this._props.allowCRs !== true) { - console.log("noCrs??") e.stopPropagation(); if (!e.ctrlKey) { this.finalizeEdit(e.currentTarget.value, e.shiftKey, false, true); diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 2d181a772..3d7c7882e 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -275,9 +275,7 @@ export class CollectionSchemaView extends CollectionSubView() { changeColumnKey = (index: number, newKey: string, defaultVal?: any) => { if (!this.documentKeys.includes(newKey)) { this.addNewKey(newKey, defaultVal); - console.log("added") } - console.log("changed " + index) const currKeys = this.columnKeys.slice(); // copy the column key array first, then change it. currKeys[index] = newKey; @@ -308,6 +306,7 @@ export class CollectionSchemaView extends CollectionSubView() { }); } + // parses a field from the "idToDoc(####)" format to DocumentId (d#) format for readability cleanupComputedField = (field: string) => { const idPattern = /idToDoc\((.*?)\)/g; let modField = field.slice(); @@ -403,7 +402,7 @@ export class CollectionSchemaView extends CollectionSubView() { }; findColDropIndex = (mouseX: number) => { - let xOffset: number = this._props.ScreenToLocalTransform().inverse().transformPoint(0,0)[0] + CollectionSchemaView._rowMenuWidth; + let xOffset: number = this._props.ScreenToLocalTransform().inverse().transformPoint(0,0)[0] + CollectionSchemaView._rowMenuWidth; let index: number | undefined; this.displayColumnWidths.reduce((total, curr, i) => { if (total <= mouseX && total + curr >= mouseX) { @@ -466,7 +465,7 @@ export class CollectionSchemaView extends CollectionSubView() { const edgeStyle = i === index ? `solid 2px ${Colors.MEDIUM_BLUE}` : ''; const cellEles = [ colRef, - ...this.childDocs // + ...this.childDocs .filter(doc => i !== this._selectedCol || !this._selectedDocs.includes(doc)) .map(doc => this._rowEles.get(doc).children[1].children[i]), ]; @@ -714,7 +713,11 @@ export class CollectionSchemaView extends CollectionSubView() { @action setKey = (key: string, defaultVal?: any, index?: number) => { - console.log("setKey called with" + key) + if (this.columnKeys.includes(key)){ + this._newFieldWarning = 'Field already exists'; + return; + } + if (this._makeNewColumn) { this.addColumn(key, defaultVal); this._makeNewColumn = false; @@ -724,12 +727,7 @@ export class CollectionSchemaView extends CollectionSubView() { this.closeColumnMenu(); }; - setColumnValue = () => { - - } - setCellValues = (key: string, value: string) => { - console.log("field: " + key + " vale: " + value); const selectedDocs: Doc[] = []; this.childDocs.forEach(doc => { const docIsSelected = this._selectedCells && !(this._selectedCells?.filter(d => d === doc).length === 0); diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index 794d5d8ac..58ac4e45d 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -25,8 +25,6 @@ import { FInfo } from '../../../documents/Documents'; export interface SchemaColumnHeaderProps { Document: Doc; autoFocus?: boolean; - oneLine?: boolean; // whether all input should fit on one line vs allowing textare multiline inputs - allowCRs?: boolean; // allow carriage returns in text input (othewrise CR ends the edit) columnKeys: string[]; columnWidths: number[]; columnIndex: number; @@ -123,20 +121,20 @@ export class SchemaColumnHeader extends ObservableReactComponent this._props.autoFocus && r?.setIsFocused(true)} - oneLine={this._props.oneLine} - allowCRs={this._props.allowCRs} + oneLine={true} + allowCRs={false} contents={undefined} fieldContents={fieldProps} editing={undefined} - isColHeader={true} + isColHeader={true} // tells the EditableView to display the fieldKey itself, and not its value GetValue={() => {console.log(this.fieldKey); return this.fieldKey}} SetValue={undoable((value: string, shiftKey?: boolean, enterKey?: boolean) => { - if (shiftKey && enterKey) { + if (shiftKey && enterKey) { // if shift & enter, set value of each cell in column this.setColumnValues(value, value); this._props.finishEdit?.(); return true; } - this._props.finishEdit?.(); + this._props.finishEdit?.(); // else save new value to header field return true; }, 'edit column header')} /> -- cgit v1.2.3-70-g09d2 From 52b8410f14c4e522b0d7bbdbfb64d8fdbd5c3023 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 15 May 2024 22:26:42 -0400 Subject: columheader editing working!! (kinda hacky using readonly input revisit) --- src/client/views/EditableView.scss | 3 ++ src/client/views/EditableView.tsx | 44 +++++++++++++------ .../collectionSchema/CollectionSchemaView.scss | 2 +- .../collectionSchema/CollectionSchemaView.tsx | 49 +++++++++------------- .../collectionSchema/SchemaColumnHeader.tsx | 22 ++++++---- 5 files changed, 70 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/client/views/EditableView.scss b/src/client/views/EditableView.scss index 27b260450..e492068c8 100644 --- a/src/client/views/EditableView.scss +++ b/src/client/views/EditableView.scss @@ -5,6 +5,7 @@ hyphens: auto; overflow: hidden; height: 100%; + width: 100%; min-width: 20; text-overflow: ellipsis; } @@ -33,6 +34,8 @@ pointer-events: all; } + + .editableView-input:focus { border: none; outline: none; diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 011b6c77a..4c4ef227a 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -1,6 +1,6 @@ /* eslint-disable jsx-a11y/no-static-element-interactions */ /* eslint-disable jsx-a11y/click-events-have-key-events */ -import { action, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import * as Autosuggest from 'react-autosuggest'; @@ -55,7 +55,7 @@ export interface EditableProps { placeholder?: string; wrap?: string; // nowrap, pre-wrap, etc - isColHeader?: boolean; + showKeyNotVal?: boolean; } /** @@ -277,9 +277,35 @@ export class EditableView extends ObservableReactComponent { ); } + display = () => { + let toDisplay; + const gval = this._props.GetValue()?.replace(/\n/g, '\\r\\n'); + if (this._props.showKeyNotVal){ + toDisplay = + } else { + toDisplay = ( + { + // eslint-disable-next-line react/jsx-props-no-spreading + this._props.fieldContents ? : this.props.contents ? this._props.contents?.valueOf() : '' + } + ) + } + + return toDisplay; + } + render() { const gval = this._props.GetValue()?.replace(/\n/g, '\\r\\n'); - if ((this._editing && gval !== undefined) || this._props.isColHeader) { + if ((this._editing && gval !== undefined)) { return this._props.sizeToContent ? (
{gval}
@@ -300,21 +326,13 @@ export class EditableView extends ObservableReactComponent { minHeight: '10px', whiteSpace: this._props.oneLine ? 'nowrap' : 'pre-line', height: this._props.height, + width: '100%', maxHeight: this._props.maxHeight, fontStyle: this._props.fontStyle, fontSize: this._props.fontSize, }} onClick={this.onClick}> - - { - // eslint-disable-next-line react/jsx-props-no-spreading - this._props.fieldContents ? : this.props.contents ? this._props.contents?.valueOf() : '' - } - + {this.display()}
); } diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss index 269bb4de5..fd2e882d9 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss @@ -159,7 +159,7 @@ flex-grow: 2; margin: 5px; overflow: hidden; - min-width: 20%; + min-width: 100%; } .schema-column-edit-wrapper { diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 3d7c7882e..db23f874e 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -331,7 +331,7 @@ export class CollectionSchemaView extends CollectionSubView() { const currKeys = this.columnKeys.slice(); currKeys.splice(index, 1); - this.layoutDoc.schema_columnKeys = new List(currKeys); + this.layoutDoc.schema_columnKeys = new List(currKeys); }; @action @@ -677,19 +677,6 @@ export class CollectionSchemaView extends CollectionSubView() { })} /> ); - case ColumnType.Equation: - return ( - e.stopPropagation()} - onChange={action((e: any) => { - this._newFieldDefault = e.target.value; - })} - /> - ); default: return undefined; } @@ -714,7 +701,6 @@ export class CollectionSchemaView extends CollectionSubView() { @action setKey = (key: string, defaultVal?: any, index?: number) => { if (this.columnKeys.includes(key)){ - this._newFieldWarning = 'Field already exists'; return; } @@ -798,12 +784,29 @@ export class CollectionSchemaView extends CollectionSubView() { this._filterColumnIndex = undefined; }; - openContextMenu = (x: number, y: number, index: number) => { + openContextMenu = (x: number, y: number, index: number, fieldType: ColumnType) => { this.closeColumnMenu(); this.closeFilterMenu(); + + let toDisplay: string = ''; + switch (fieldType) { + case ColumnType.Number: + toDisplay = 'number'; + break; + case ColumnType.String: + toDisplay = 'string'; + break; + case ColumnType.Boolean: + toDisplay = 'boolean'; + break; + default: + toDisplay = 'string'; + break; + } + ContextMenu.Instance.clearItems(); ContextMenu.Instance.addItem({ - description: 'Change field', + description: `Field type: ${toDisplay}`, event: () => this.openColumnMenu(index, false), icon: 'pencil-alt', }); @@ -886,18 +889,6 @@ export class CollectionSchemaView extends CollectionSubView() { /> string
-
- { - this._newFieldType = ColumnType.Equation; - this._newFieldDefault = ''; - })} - /> - equation -
value: {this.fieldDefaultInput}
{this._newFieldWarning}
number; resizeColumn: (e: any, index: number) => void; dragColumn: (e: any, index: number) => boolean; - openContextMenu: (x: number, y: number, index: number) => void; + openContextMenu: (x: number, y: number, index: number, fieldType: ColumnType) => void; setColRef: (index: number, ref: HTMLDivElement) => void; rootSelected?: () => boolean; columnWidth: () => number; @@ -49,7 +50,8 @@ export interface SchemaColumnHeaderProps { @observer export class SchemaColumnHeader extends ObservableReactComponent { - @observable _editing: boolean = false; + @observable _editing: boolean | undefined = false; + @observable _fieldType: ColumnType = ColumnType.String; @computed get fieldKey() { return this._props.columnKeys[this._props.columnIndex]; @@ -125,9 +127,9 @@ export class SchemaColumnHeader extends ObservableReactComponent {console.log(this.fieldKey); return this.fieldKey}} + editing={undefined} + showKeyNotVal={true} // tells the EditableView to display the fieldKey itself, and not its value + GetValue={() => this.fieldKey} SetValue={undoable((value: string, shiftKey?: boolean, enterKey?: boolean) => { if (shiftKey && enterKey) { // if shift & enter, set value of each cell in column this.setColumnValues(value, value); @@ -142,7 +144,7 @@ export class SchemaColumnHeader extends ObservableReactComponent { - // return
{this._editing = true; console.log(this._editing)}}>{this.fieldKey}
+ // return
{this._editing = true; console.log(this._editing)}}>{this.fieldKey}
// } render() { @@ -153,6 +155,12 @@ export class SchemaColumnHeader extends ObservableReactComponent { + // console.log(true); + // this._editing = true}} + // onPointerLeave={() => { + // console.log(false); + // this._editing = false}} ref={col => { if (col) { this._props.setColRef(this._props.columnIndex, col); @@ -163,7 +171,7 @@ export class SchemaColumnHeader extends ObservableReactComponent{this.editableView}
-
this._props.openContextMenu(e.clientX, e.clientY, this._props.columnIndex)}> +
this._props.openContextMenu(e.clientX, e.clientY, this._props.columnIndex, this._fieldType)}>
-- cgit v1.2.3-70-g09d2 From 5b6e6b27a191a880fd454ebbc5ed3816cd5cd59c Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Mon, 3 Jun 2024 10:23:38 -0400 Subject: new columns display blank --- src/client/views/EditableView.tsx | 2 + .../collectionSchema/CollectionSchemaView.scss | 10 +++-- .../collectionSchema/CollectionSchemaView.tsx | 48 ++++++---------------- .../collectionSchema/SchemaColumnHeader.tsx | 34 ++++++++------- .../collectionSchema/SchemaTableCell.tsx | 4 +- 5 files changed, 43 insertions(+), 55 deletions(-) (limited to 'src') diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 4c4ef227a..5b691c507 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -56,6 +56,7 @@ export interface EditableProps { wrap?: string; // nowrap, pre-wrap, etc showKeyNotVal?: boolean; + updateAlt?: (newAlt: string) => void; } /** @@ -182,6 +183,7 @@ export class EditableView extends ObservableReactComponent { @action onClick = (e: React.MouseEvent) => { + if (this._props.GetValue() == 'None' && this._props.updateAlt) this._props.updateAlt('.'); if (this._props.editing !== false) { e.nativeEvent.stopPropagation(); if (this._ref.current && this._props.showMenuOnLoad) { diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss index fd2e882d9..1dbe75a8d 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss @@ -50,13 +50,15 @@ .schema-column-menu, .schema-filter-menu { background: $light-gray; - position: relative; - min-width: 200px; - max-width: 400px; + position: absolute; + min-width: 150px; + max-width: 300px; + max-height: 300px; display: flex; + overflow: hidden; flex-direction: column; align-items: flex-start; - z-index: 1; + z-index: 5; .schema-key-search-input { width: calc(100% - 20px); diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index db23f874e..c673f0e56 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -32,6 +32,7 @@ import './CollectionSchemaView.scss'; import { SchemaColumnHeader } from './SchemaColumnHeader'; import { SchemaRowBox } from './SchemaRowBox'; import { ActionButton } from '@adobe/react-spectrum'; +import { CollectionMasonryViewFieldRow } from '../CollectionMasonryViewFieldRow'; const { SCHEMA_NEW_NODE_HEIGHT } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore @@ -273,9 +274,7 @@ export class CollectionSchemaView extends CollectionSubView() { @undoBatch changeColumnKey = (index: number, newKey: string, defaultVal?: any) => { - if (!this.documentKeys.includes(newKey)) { - this.addNewKey(newKey, defaultVal); - } + if (!this.documentKeys.includes(newKey)) this.addNewKey(newKey, defaultVal); const currKeys = this.columnKeys.slice(); // copy the column key array first, then change it. currKeys[index] = newKey; @@ -283,10 +282,8 @@ export class CollectionSchemaView extends CollectionSubView() { }; @undoBatch - addColumn = (key: string, defaultVal?: any) => { - if (!this.documentKeys.includes(key)) { - this.addNewKey(key, defaultVal); - } + addColumn = (key?: string, defaultVal?: any) => { + if (key && !this.documentKeys.includes(key)) this.addNewKey(key, defaultVal); const newColWidth = this.tableWidth / (this.storedColumnWidths.length + 1); const currWidths = this.storedColumnWidths.slice(); @@ -295,7 +292,9 @@ export class CollectionSchemaView extends CollectionSubView() { this.layoutDoc.schema_columnWidths = new List(currWidths.map(w => (w / newDesiredTableWidth) * (this.tableWidth - CollectionSchemaView._rowMenuWidth))); const currKeys = this.columnKeys.slice(); + if (!key) key = 'EmptyColumnKey' + Math.floor(Math.random() * 1000000000000000).toString(); currKeys.splice(0, 0, key); + this.changeColumnKey(0, 'EmptyColumnKey' + Math.floor(Math.random() * 1000000000000000).toString()); this.layoutDoc.schema_columnKeys = new List(currKeys); }; @@ -332,6 +331,7 @@ export class CollectionSchemaView extends CollectionSubView() { const currKeys = this.columnKeys.slice(); currKeys.splice(index, 1); this.layoutDoc.schema_columnKeys = new List(currKeys); + console.log(...currKeys); }; @action @@ -784,29 +784,13 @@ export class CollectionSchemaView extends CollectionSubView() { this._filterColumnIndex = undefined; }; - openContextMenu = (x: number, y: number, index: number, fieldType: ColumnType) => { + openContextMenu = (x: number, y: number, index: number) => { this.closeColumnMenu(); this.closeFilterMenu(); - let toDisplay: string = ''; - switch (fieldType) { - case ColumnType.Number: - toDisplay = 'number'; - break; - case ColumnType.String: - toDisplay = 'string'; - break; - case ColumnType.Boolean: - toDisplay = 'boolean'; - break; - default: - toDisplay = 'string'; - break; - } - ContextMenu.Instance.clearItems(); ContextMenu.Instance.addItem({ - description: `Field type: ${toDisplay}`, + description: `Change field`, event: () => this.openColumnMenu(index, false), icon: 'pencil-alt', }); @@ -923,14 +907,6 @@ export class CollectionSchemaView extends CollectionSubView() { onClick={() => this.toggleMenuKeyFilter()}> {this._colKeysFiltered ? "All keys" : "Active keys only"} -
{ - e.stopPropagation(); - this._makeNewField = true; - })}> - + new field -
{ @@ -1077,7 +1053,9 @@ export class CollectionSchemaView extends CollectionSubView() { _oldWheel: any; render() { return ( -
this.createDashEventsTarget(ele)} onDrop={this.onExternalDrop.bind(this)} onPointerMove={e => this.onPointerMove(e)}> +
this.createDashEventsTarget(ele)} + onDrop={this.onExternalDrop.bind(this)} + onPointerMove={e => this.onPointerMove(e)} >
this.openColumnMenu(-1, true)} icon="plus" />} + toggle={ this.addColumn()} icon="plus" />} //here trigger={PopupTrigger.CLICK} type={Type.TERT} isOpen={this._columnMenuIndex !== -1 ? false : undefined} diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index f404eb444..6e2f85cc0 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -39,7 +39,7 @@ export interface SchemaColumnHeaderProps { rowHeight: () => number; resizeColumn: (e: any, index: number) => void; dragColumn: (e: any, index: number) => boolean; - openContextMenu: (x: number, y: number, index: number, fieldType: ColumnType) => void; + openContextMenu: (x: number, y: number, index: number) => void; setColRef: (index: number, ref: HTMLDivElement) => void; rootSelected?: () => boolean; columnWidth: () => number; @@ -50,15 +50,21 @@ export interface SchemaColumnHeaderProps { @observer export class SchemaColumnHeader extends ObservableReactComponent { - @observable _editing: boolean | undefined = false; - @observable _fieldType: ColumnType = ColumnType.String; + @observable _altTitle: string | undefined = undefined; @computed get fieldKey() { return this._props.columnKeys[this._props.columnIndex]; } + isDefaultTitle = (key: string) => { + const defaultPattern = /EmptyColumnKey/; + let isDefault: boolean = (defaultPattern.exec(key) != null); + return isDefault; + } + getFinfo = computedFn((fieldKey: string) => this._props.schemaView?.fieldInfos.get(fieldKey)); setColumnValues = (field: string, defaultValue: string) => {this._props.schemaView?.setKey(field, defaultValue, this._props.columnIndex);} + @action updateAlt = (newAlt: string) => {this._altTitle = newAlt;} @action sortClicked = (e: React.PointerEvent) => { @@ -128,15 +134,21 @@ export class SchemaColumnHeader extends ObservableReactComponent this.fieldKey} + GetValue={() => { + if (this.isDefaultTitle(this.fieldKey)) return ''; + else if (this._altTitle) return this._altTitle; + else return this.fieldKey; + }} SetValue={undoable((value: string, shiftKey?: boolean, enterKey?: boolean) => { if (shiftKey && enterKey) { // if shift & enter, set value of each cell in column - this.setColumnValues(value, value); + this.setColumnValues(value, ''); + this._altTitle = undefined; this._props.finishEdit?.(); return true; - } - this._props.finishEdit?.(); // else save new value to header field + } else if (enterKey) this.updateAlt(value); + this._props.finishEdit?.(); return true; }, 'edit column header')} /> @@ -155,12 +167,6 @@ export class SchemaColumnHeader extends ObservableReactComponent { - // console.log(true); - // this._editing = true}} - // onPointerLeave={() => { - // console.log(false); - // this._editing = false}} ref={col => { if (col) { this._props.setColRef(this._props.columnIndex, col); @@ -171,7 +177,7 @@ export class SchemaColumnHeader extends ObservableReactComponent{this.editableView}
-
this._props.openContextMenu(e.clientX, e.clientY, this._props.columnIndex, this._fieldType)}> +
this._props.openContextMenu(e.clientX, e.clientY, this._props.columnIndex)}>
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 51a92ff35..4531f30a8 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -142,7 +142,7 @@ export class SchemaTableCell extends ObservableReactComponent this._props.cleanupField(Field.toKeyValueString(fieldProps.Document, this._props.fieldKey, SnappingManager.MetaKey)).replace(/[";]/g, '')} //TODO: feed this into parser that handles idToDoc + GetValue={() => this._props.cleanupField(Field.toKeyValueString(fieldProps.Document, this._props.fieldKey, SnappingManager.MetaKey))} //TODO: feed this into parser that handles idToDoc SetValue={undoable((value: string, shiftDown?: boolean, enterKey?: boolean) => { if (shiftDown && enterKey) { this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), value); @@ -150,7 +150,7 @@ export class SchemaTableCell extends ObservableReactComponent Date: Mon, 3 Jun 2024 13:33:25 -0400 Subject: merge prep --- .../collectionSchema/CollectionSchemaView.tsx | 34 +++++----------------- .../collections/collectionSchema/SchemaRowBox.tsx | 2 -- .../collectionSchema/SchemaTableCell.tsx | 1 - src/client/views/global/globalScripts.ts | 2 ++ 4 files changed, 10 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index c673f0e56..ef1819120 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -700,42 +700,24 @@ export class CollectionSchemaView extends CollectionSubView() { @action setKey = (key: string, defaultVal?: any, index?: number) => { - if (this.columnKeys.includes(key)){ - return; - } - + if (this.columnKeys.includes(key)) return; + if (this._makeNewColumn) { this.addColumn(key, defaultVal); this._makeNewColumn = false; - } else { - this.changeColumnKey(this._columnMenuIndex! | index!, key, defaultVal); - } + } else this.changeColumnKey(this._columnMenuIndex! | index!, key, defaultVal); + this.closeColumnMenu(); }; setCellValues = (key: string, value: string) => { const selectedDocs: Doc[] = []; this.childDocs.forEach(doc => { - const docIsSelected = this._selectedCells && !(this._selectedCells?.filter(d => d === doc).length === 0); - if (docIsSelected) { - selectedDocs.push(doc); - } - }); - if (selectedDocs.length === 1) { - this.childDocs.forEach(doc => Doc.SetField(doc, key, value)); - } else { - selectedDocs.forEach(doc => Doc.SetField(doc, key, value)); - } - return true; - }; - - setSelectedColumnValues = (key: string, value: string) => { - this.childDocs.forEach(doc => { - const docIsSelected = this._selectedCells && !(this._selectedCells?.filter(d => d === doc).length === 0); - if (docIsSelected) { - Doc.SetField(doc, key, value); - } + const isSelected = this._selectedCells && !(this._selectedCells?.filter(d => d === doc).length === 0); + isSelected && selectedDocs.push(doc); }); + if (selectedDocs.length === 1) this.childDocs.forEach(doc => Doc.SetField(doc, key, value)); // if only one cell selected, fill all + else selectedDocs.forEach(doc => Doc.SetField(doc, key, value)); // else only fill selected cells return true; }; diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index 908939ecc..da272cd18 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -60,7 +60,6 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { deselectCell = () => this.schemaView?.deselectAllCells(); selectedCells = () => this.schemaView?._selectedDocs; setColumnValues = (field: any, value: any) => this.schemaView?.setCellValues(field, value) ?? false; - setSelectedColumnValues = (field: any, value: any) => this.schemaView?.setSelectedColumnValues(field, value) ?? false; columnWidth = computedFn((index: number) => () => this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth); render() { return ( @@ -147,7 +146,6 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { selectedCells={this.selectedCells} selectedCol={this.selectedCol} setColumnValues={this.setColumnValues} - setSelectedColumnValues={this.setSelectedColumnValues} oneLine={BoolCast(this.schemaDoc?._singleLine)} menuTarget={this.schemaView.MenuTarget} cleanupField={this.cleanupField} diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 4531f30a8..e6660f379 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -48,7 +48,6 @@ export interface SchemaTableCellProps { isRowActive: () => boolean | undefined; getFinfo: (fieldKey: string) => FInfo | undefined; setColumnValues: (field: string, value: string) => boolean; - setSelectedColumnValues: (field: string, value: string) => boolean; oneLine?: boolean; // whether all input should fit on one line vs allowing textare multiline inputs allowCRs?: boolean; // allow carriage returns in text input (othewrise CR ends the edit) finishEdit?: () => void; // notify container that edit is over (eg. to hide view in DashFieldView) diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index c595681b7..8e5c39ddf 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -66,6 +66,8 @@ ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: b } else { const dataKey = Doc.LayoutFieldKey(dv.Document); const alternate = (dv.layoutDoc[dataKey + '_usePath'] ? '_' + dv.layoutDoc[dataKey + '_usePath'] : '').replace(':hover', ''); + console.log('color: ' + dv.dataDoc[fieldKey + alternate] + ' to set to: ' + color) + dv.layoutDoc[fieldKey + alternate] = undefined; dv.dataDoc[fieldKey + alternate] = color; } }); -- cgit v1.2.3-70-g09d2 From d215534d6f0d66db9d5bf15f9fefef3fe5398024 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Tue, 4 Jun 2024 13:01:47 -0400 Subject: c --- .../collectionSchema/CollectionSchemaView.scss | 5 ++ .../collectionSchema/CollectionSchemaView.tsx | 9 +-- .../collectionSchema/SchemaColumnHeader.tsx | 66 ++++++++++++---------- .../collectionSchema/SchemaTableCell.tsx | 4 +- 4 files changed, 45 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss index 1dbe75a8d..3d89a479a 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss @@ -301,3 +301,8 @@ width: 12px; } } + +.header-dropdown-container { + height: 0px; + width: 60px; +} diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index ef1819120..92cc58f54 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -33,6 +33,7 @@ import { SchemaColumnHeader } from './SchemaColumnHeader'; import { SchemaRowBox } from './SchemaRowBox'; import { ActionButton } from '@adobe/react-spectrum'; import { CollectionMasonryViewFieldRow } from '../CollectionMasonryViewFieldRow'; +import { Func } from 'mocha'; const { SCHEMA_NEW_NODE_HEIGHT } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore @@ -706,7 +707,7 @@ export class CollectionSchemaView extends CollectionSubView() { this.addColumn(key, defaultVal); this._makeNewColumn = false; } else this.changeColumnKey(this._columnMenuIndex! | index!, key, defaultVal); - + this.closeColumnMenu(); }; @@ -884,11 +885,6 @@ export class CollectionSchemaView extends CollectionSubView() { @computed get keysDropdown() { return (
-
{ @@ -1065,6 +1061,7 @@ export class CollectionSchemaView extends CollectionSubView() { CollectionSchemaView._minColWidth} //TODO: update Document={this.Document} diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index 6e2f85cc0..4f9d53d18 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -32,6 +32,7 @@ export interface SchemaColumnHeaderProps { sortField: string; sortDesc: boolean; schemaView: CollectionSchemaView; + keysDropdown: React.JSX.Element; //cleanupField: (s: string) => string; isContentActive: (outsideReaction?: boolean | undefined) => boolean | undefined; setSort: (field: string | undefined, desc?: boolean) => void; @@ -51,17 +52,12 @@ export interface SchemaColumnHeaderProps { export class SchemaColumnHeader extends ObservableReactComponent { @observable _altTitle: string | undefined = undefined; + @observable _displayKeysDropdown: boolean = false; @computed get fieldKey() { return this._props.columnKeys[this._props.columnIndex]; } - - isDefaultTitle = (key: string) => { - const defaultPattern = /EmptyColumnKey/; - let isDefault: boolean = (defaultPattern.exec(key) != null); - return isDefault; - } - + getFinfo = computedFn((fieldKey: string) => this._props.schemaView?.fieldInfos.get(fieldKey)); setColumnValues = (field: string, defaultValue: string) => {this._props.schemaView?.setKey(field, defaultValue, this._props.columnIndex);} @action updateAlt = (newAlt: string) => {this._altTitle = newAlt;} @@ -79,6 +75,11 @@ export class SchemaColumnHeader extends ObservableReactComponent { + this._props.schemaView.openColumnMenu(this._props.columnIndex, false) + this._displayKeysDropdown = true; + } + @action setupDrag = (e: React.PointerEvent) => { this._props.isContentActive(true) && setupMoveUpEvents(this, e, moveEv => this._props.dragColumn(moveEv, this._props.columnIndex), emptyFunction, emptyFunction); @@ -121,7 +122,7 @@ export class SchemaColumnHeader extends ObservableReactComponent this._props.schemaView.openColumnMenu(this._props.columnIndex, false)} style={{ color, width: '100%', @@ -148,6 +149,7 @@ export class SchemaColumnHeader extends ObservableReactComponent } - // staticView = () => { - // return
{this._editing = true; console.log(this._editing)}}>{this.fieldKey}
- // } + isDefaultTitle = (key: string) => { + const defaultPattern = /EmptyColumnKey/; + let isDefault: boolean = (defaultPattern.exec(key) != null); + return isDefault; + } render() { return ( -
{ - if (col) { - this._props.setColRef(this._props.columnIndex, col); - } - }}> -
this._props.resizeColumn(e, this._props.columnIndex)} /> +
{ + if (col) { + this._props.setColRef(this._props.columnIndex, col); + } + }}> +
this._props.resizeColumn(e, this._props.columnIndex)} /> -
{this.editableView}
+
{this.editableView}
-
-
this._props.openContextMenu(e.clientX, e.clientY, this._props.columnIndex)}> - -
-
- +
+
this._props.openContextMenu(e.clientX, e.clientY, this._props.columnIndex)}> + +
+
+ +
-
); } } diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index e6660f379..c3a58b505 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -30,7 +30,7 @@ import { Colors } from '../../global/globalEnums'; import { DocumentView } from '../../nodes/DocumentView'; import { FieldViewProps } from '../../nodes/FieldView'; import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; -import { FInfotoColType } from './CollectionSchemaView'; +import { CollectionSchemaView, FInfotoColType } from './CollectionSchemaView'; import './CollectionSchemaView.scss'; export interface SchemaTableCellProps { @@ -149,7 +149,7 @@ export class SchemaTableCell extends ObservableReactComponent Date: Tue, 4 Jun 2024 14:17:50 -0400 Subject: key search on update --- src/client/views/EditableView.tsx | 3 ++- .../collections/collectionSchema/CollectionSchemaView.tsx | 7 ++----- .../views/collections/collectionSchema/SchemaColumnHeader.tsx | 11 +++++++---- 3 files changed, 11 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 5b691c507..c79cabd6a 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -57,6 +57,7 @@ export interface EditableProps { showKeyNotVal?: boolean; updateAlt?: (newAlt: string) => void; + updateSearch?: (value: string) => void; } /** @@ -122,6 +123,7 @@ export class EditableView extends ObservableReactComponent { } else if (!this._overlayDisposer) { this._overlayDisposer = OverlayView.Instance.addElement(, { x: 0, y: 0 }); } + this._props.updateSearch && this._props.updateSearch(targVal); }; @action @@ -183,7 +185,6 @@ export class EditableView extends ObservableReactComponent { @action onClick = (e: React.MouseEvent) => { - if (this._props.GetValue() == 'None' && this._props.updateAlt) this._props.updateAlt('.'); if (this._props.editing !== false) { e.nativeEvent.stopPropagation(); if (this._ref.current && this._props.showMenuOnLoad) { diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 92cc58f54..f5422bce1 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -791,9 +791,8 @@ export class CollectionSchemaView extends CollectionSubView() { }; @action - updateKeySearch = (e: React.ChangeEvent) => { - this._menuValue = e.target.value; - this._menuKeys = this.documentKeys.filter(value => value.toLowerCase().includes(this._menuValue.toLowerCase())); + updateKeySearch = (val: string) => { + this._menuKeys = this.documentKeys.filter(value => value.toLowerCase().includes(val.toLowerCase())); }; getFieldFilters = (field: string) => StrListCast(this.Document._childFilters).filter(filter => filter.split(Doc.FilterSep)[0] === field); @@ -920,7 +919,6 @@ export class CollectionSchemaView extends CollectionSubView() { const x = this._columnMenuIndex! === -1 ? 0 : this.displayColumnWidths.reduce((total, curr, index) => total + (index < this._columnMenuIndex! ? curr : 0), CollectionSchemaView._rowMenuWidth); return (
- e.stopPropagation()} /> {this._makeNewField ? this.newFieldMenu : this.keysDropdown}
); @@ -929,7 +927,6 @@ export class CollectionSchemaView extends CollectionSubView() { get renderKeysMenu() { return (
- e.stopPropagation()} /> {this._makeNewField ? this.newFieldMenu : this.keysDropdown}
); diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index 4f9d53d18..32abc1780 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -61,6 +61,7 @@ export class SchemaColumnHeader extends ObservableReactComponent this._props.schemaView?.fieldInfos.get(fieldKey)); setColumnValues = (field: string, defaultValue: string) => {this._props.schemaView?.setKey(field, defaultValue, this._props.columnIndex);} @action updateAlt = (newAlt: string) => {this._altTitle = newAlt;} + @action updateKeyDropdown = (value: string) => {this._props.schemaView.updateKeySearch(value)} @action sortClicked = (e: React.PointerEvent) => { @@ -76,8 +77,10 @@ export class SchemaColumnHeader extends ObservableReactComponent { - this._props.schemaView.openColumnMenu(this._props.columnIndex, false) - this._displayKeysDropdown = true; + if (this.isDefaultTitle(this.fieldKey)){ + this._props.schemaView.openColumnMenu(this._props.columnIndex, false) + this._displayKeysDropdown = true; + } } @action @@ -122,7 +125,7 @@ export class SchemaColumnHeader extends ObservableReactComponent this._props.schemaView.openColumnMenu(this._props.columnIndex, false)} + return
this.openKeyDropdown()} style={{ color, width: '100%', @@ -136,6 +139,7 @@ export class SchemaColumnHeader extends ObservableReactComponent { if (this.isDefaultTitle(this.fieldKey)) return ''; @@ -149,7 +153,6 @@ export class SchemaColumnHeader extends ObservableReactComponent Date: Wed, 5 Jun 2024 01:42:26 -0400 Subject: adding collection content to schema started --- .../collectionSchema/CollectionSchemaView.tsx | 16 +++++++++++----- .../collections/collectionSchema/SchemaColumnHeader.tsx | 2 +- 2 files changed, 12 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index f5422bce1..6b97cb97c 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -92,6 +92,7 @@ export class CollectionSchemaView extends CollectionSubView() { @observable _colBeingDragged: boolean = false; @observable _colKeysFiltered: boolean = false; @observable _cellTags: ObservableMap = new ObservableMap>(); + @observable _lentDocs: Doc[] = []; // target HTMLelement portal for showing a popup menu to edit cell values. public get MenuTarget() { @@ -1020,17 +1021,22 @@ export class CollectionSchemaView extends CollectionSubView() { } rowHeightFunc = () => (BoolCast(this.layoutDoc._schema_singleLine) ? CollectionSchemaView._rowSingleLineHeight : CollectionSchemaView._rowHeight); - sortedDocsFunc = () => this.sortedDocs; isContentActive = () => this._props.isSelected() || this._props.isContentActive(); screenToLocal = () => this.ScreenToLocalBoxXf().translate(-this.tableWidth, 0); previewWidthFunc = () => this.previewWidth; onPassiveWheel = (e: WheelEvent) => e.stopPropagation(); + displayedDocsFunc = () => { + let docs: Doc[] = this._lentDocs.slice(); + docs = docs.concat(this.sortedDocs.docs); + return docs; + } _oldWheel: any; render() { return (
this.createDashEventsTarget(ele)} onDrop={this.onExternalDrop.bind(this)} - onPointerMove={e => this.onPointerMove(e)} > + onPointerMove={e => this.onPointerMove(e)} + onPointerDown={() => this.closeColumnMenu()}>
{ this._tableContentRef = ref; @@ -1208,7 +1214,7 @@ class CollectionSchemaViewDoc extends ObservableReactComponent void; - childDocs: () => { docs: Doc[] }; + childDocs: () => Doc[]; rowHeight: () => number; } @@ -1217,7 +1223,7 @@ class CollectionSchemaViewDocs extends React.Component - {this.props.childDocs().docs.map((doc: Doc, index: number) => ( + {this.props.childDocs().map((doc: Doc, index: number) => (
diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index 32abc1780..03cf64fc8 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -147,7 +147,7 @@ export class SchemaColumnHeader extends ObservableReactComponent { - if (shiftKey && enterKey) { // if shift & enter, set value of each cell in column + if (enterKey) { // if shift & enter, set value of each cell in column this.setColumnValues(value, ''); this._altTitle = undefined; this._props.finishEdit?.(); -- cgit v1.2.3-70-g09d2 From fed19c3b7e14bc00216b5f91363451a0e9bed93d Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 5 Jun 2024 13:42:04 -0400 Subject: row menu rework, icons mostly good --- .../collectionSchema/CollectionSchemaView.tsx | 34 ++++++---- .../collections/collectionSchema/SchemaRowBox.tsx | 76 ++++++++++------------ 2 files changed, 58 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 6b97cb97c..30daa793a 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -7,11 +7,11 @@ import * as React from 'react'; import { returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../ClientUtils'; import { emptyFunction } from '../../../../Utils'; import { Doc, DocListCast, Field, FieldType, IdToDoc, NumListCast, Opt, StrListCast } from '../../../../fields/Doc'; -import { DocData } from '../../../../fields/DocSymbols'; +import { AclPrivate, DocData } from '../../../../fields/DocSymbols'; import { Id } from '../../../../fields/FieldSymbols'; import { List } from '../../../../fields/List'; import { ColumnType } from '../../../../fields/SchemaHeaderField'; -import { BoolCast, NumCast, StrCast } from '../../../../fields/Types'; +import { BoolCast, Cast, NumCast, StrCast } from '../../../../fields/Types'; import { DocUtils } from '../../../documents/DocUtils'; import { Docs, DocumentOptions, FInfo } from '../../../documents/Documents'; import { DragManager } from '../../../util/DragManager'; @@ -34,6 +34,9 @@ import { SchemaRowBox } from './SchemaRowBox'; import { ActionButton } from '@adobe/react-spectrum'; import { CollectionMasonryViewFieldRow } from '../CollectionMasonryViewFieldRow'; import { Func } from 'mocha'; +import { CollectionView } from '../CollectionView'; +import { listSpec } from '../../../../fields/Schema'; +import { GetEffectiveAcl } from '../../../../fields/util'; const { SCHEMA_NEW_NODE_HEIGHT } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore @@ -635,6 +638,19 @@ export class CollectionSchemaView extends CollectionSubView() { return undefined; }; + addDocsFromChildCollection = (collection: CollectionSchemaView) => { + const childDocs = collection.childDocs.slice(); + console.log(childDocs) + childDocs.forEach((doc: Doc) => {!this.childDocs.includes(doc) && this._lentDocs.push(doc)}); + } + + removeChildCollectionDocs = (collection: CollectionSchemaView) => { + const children = collection.childDocs.slice(); + this._lentDocs.forEach(element => { + + }); + } + @computed get fieldDefaultInput() { switch (this._newFieldType) { case ColumnType.Number: @@ -746,9 +762,7 @@ export class CollectionSchemaView extends CollectionSubView() { this._columnMenuIndex = index; this._menuValue = ''; this._menuKeys = this.documentKeys; - this._makeNewField = false; this._newFieldWarning = ''; - this._makeNewField = false; this._makeNewColumn = newCol; }; @@ -920,7 +934,7 @@ export class CollectionSchemaView extends CollectionSubView() { const x = this._columnMenuIndex! === -1 ? 0 : this.displayColumnWidths.reduce((total, curr, index) => total + (index < this._columnMenuIndex! ? curr : 0), CollectionSchemaView._rowMenuWidth); return (
- {this._makeNewField ? this.newFieldMenu : this.keysDropdown} + {this.keysDropdown}
); } @@ -928,7 +942,7 @@ export class CollectionSchemaView extends CollectionSubView() { get renderKeysMenu() { return (
- {this._makeNewField ? this.newFieldMenu : this.keysDropdown} + {this.keysDropdown}
); } @@ -954,7 +968,7 @@ export class CollectionSchemaView extends CollectionSubView() { } return (
- e.stopPropagation()} onClick={e => e.stopPropagation()} @@ -1025,11 +1039,7 @@ export class CollectionSchemaView extends CollectionSubView() { screenToLocal = () => this.ScreenToLocalBoxXf().translate(-this.tableWidth, 0); previewWidthFunc = () => this.previewWidth; onPassiveWheel = (e: WheelEvent) => e.stopPropagation(); - displayedDocsFunc = () => { - let docs: Doc[] = this._lentDocs.slice(); - docs = docs.concat(this.sortedDocs.docs); - return docs; - } + displayedDocsFunc = () => this._lentDocs.slice().concat(this.sortedDocs.docs); _oldWheel: any; render() { return ( diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index da272cd18..8e4161413 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -1,9 +1,9 @@ import { IconButton, Size } from 'browndash-components'; -import { computed, makeObservable } from 'mobx'; +import { computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; import * as React from 'react'; -import { CgClose, CgLock, CgLockUnlock } from 'react-icons/cg'; +import { CgClose, CgLock, CgLockUnlock, CgMenu } from 'react-icons/cg'; import { FaExternalLinkAlt } from 'react-icons/fa'; import { returnFalse, setupMoveUpEvents } from '../../../../ClientUtils'; import { emptyFunction } from '../../../../Utils'; @@ -18,6 +18,8 @@ import { OpenWhere } from '../../nodes/OpenWhere'; import { CollectionSchemaView } from './CollectionSchemaView'; import './CollectionSchemaView.scss'; import { SchemaTableCell } from './SchemaTableCell'; +import { ContextMenu } from '../../ContextMenu'; +import { CollectionFreeFormView } from '../collectionFreeForm'; interface SchemaRowBoxProps extends FieldViewProps { rowIndex: number; @@ -28,6 +30,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { return FieldView.LayoutString(SchemaRowBox, fieldKey).replace('fieldKey', `rowIndex={${rowIndex}} fieldKey`); } private _ref: HTMLDivElement | null = null; + @observable _childrenAddedToSchema: boolean = false; constructor(props: SchemaRowBoxProps) { super(props); @@ -52,6 +55,33 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { this._props.setContentViewBox?.(this); } + openContextMenu = (x: number, y: number) => { + ContextMenu.Instance.clearItems(); + ContextMenu.Instance.addItem({ + description: `Close doc`, + event: () => this._props.removeDocument?.(this.Document), + icon: 'minus', + }); + ContextMenu.Instance.addItem({ + description: this.Document._lockedPosition ? 'Unlock doc interactions' : 'Lock doc interactions', + event: () => Doc.toggleLockedPosition(this.Document), + icon: this.Document._lockedPosition ? 'lock-open' : 'lock', + }); + ContextMenu.Instance.addItem({ + description: 'Open preview', + event: () => this._props.addDocTab(this.Document, OpenWhere.addRight), + icon: 'magnifying-glass', + }); + if (this.Document['type'] === 'collection') { + ContextMenu.Instance.addItem({ + description: 'Add children to schema', + event: () => this.schemaView.addDocsFromChildCollection(this.Document as unknown as CollectionSchemaView), + icon: 'plus', + }); + } + ContextMenu.Instance.displayMenu(x, y, undefined, false); + } + cleanupField = (field: string) => this.schemaView.cleanupComputedField(field) setCursorIndex = (mouseY: number) => this.schemaView?.setRelCursorIndex(mouseY); selectedCol = () => this.schemaView._selectedCol; @@ -78,42 +108,8 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { pointerEvents: !this._props.isContentActive() ? 'none' : undefined, }}> } - size={Size.XSMALL} - onPointerDown={e => - setupMoveUpEvents( - this, - e, - returnFalse, - emptyFunction, - undoable(clickEv => { - clickEv.stopPropagation(); - this._props.removeDocument?.(this.Document); - }, 'Delete Row') - ) - } - /> - : } - size={Size.XSMALL} - onPointerDown={e => - setupMoveUpEvents( - this, - e, - returnFalse, - emptyFunction, - undoable(clickEv => { - clickEv.stopPropagation(); - Doc.toggleLockedPosition(this.Document); - }, 'toggle document lock') - ) - } - /> - } + tooltip="Open actions menu" + icon={ } size={Size.XSMALL} onPointerDown={e => setupMoveUpEvents( @@ -123,8 +119,8 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { emptyFunction, undoable(clickEv => { clickEv.stopPropagation(); - this._props.addDocTab(this.Document, OpenWhere.addRight); - }, 'Open schema Doc preview') + this.openContextMenu(e.clientX, e.clientY) + }, 'open actions menu') ) } /> -- cgit v1.2.3-70-g09d2 From 9d0576378416b2e4ce7c5eb3c958ec6a650e9f90 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 5 Jun 2024 23:15:35 -0400 Subject: c --- src/client/documents/Documents.ts | 1 + .../collectionSchema/CollectionSchemaView.tsx | 26 +++++++++++----------- .../collections/collectionSchema/SchemaRowBox.tsx | 10 ++++++--- 3 files changed, 21 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index c34a833f8..365af66b7 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -227,6 +227,7 @@ export class DocumentOptions { _header_pointerEvents?: PEVt = new PEInfo('types of events the header of a custom text document can consume'); _lockedPosition?: BOOLt = new BoolInfo("lock the x,y coordinates of the document so that it can't be dragged"); _lockedTransform?: BOOLt = new BoolInfo('lock the freeform_panx,freeform_pany and scale parameters of the document so that it be panned/zoomed'); + _childrenSharedWithSchema?: BOOLt = new BoolInfo("whether this document's children are displayed in its parent schema view"); dataViz_title?: string; dataViz_line?: string; diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 30daa793a..39bde7d37 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -147,7 +147,7 @@ export class CollectionSchemaView extends CollectionSubView() { } @computed get rowHeights() { - return this.childDocs.map(() => this.rowHeightFunc()); + return this.childDocs.concat(this._lentDocs).map(() => this.rowHeightFunc()); } @computed get displayColumnWidths() { @@ -584,7 +584,8 @@ export class CollectionSchemaView extends CollectionSubView() { const draggedDocs = de.complete.docDragData?.draggedDocuments; if (draggedDocs && super.onInternalDrop(e, de) && !this.sortField) { - const map = draggedDocs?.map(doc => this.rowIndex(doc)); + const sortedDocs = this.sortedDocs.docs.slice(); +const filteredChildDocs = sortedDocs.filter((doc: Doc) => !this._lentDocs.includes(doc)); this.dataDoc[this.fieldKey ?? 'data'] = new List([...this.sortedDocs.docs]); this.clearSelection(); draggedDocs.forEach(doc => { @@ -638,17 +639,16 @@ export class CollectionSchemaView extends CollectionSubView() { return undefined; }; - addDocsFromChildCollection = (collection: CollectionSchemaView) => { - const childDocs = collection.childDocs.slice(); - console.log(childDocs) - childDocs.forEach((doc: Doc) => {!this.childDocs.includes(doc) && this._lentDocs.push(doc)}); + addDocsFromChildCollection = (collection: Doc) => { + const childDocs = DocListCast(collection[Doc.LayoutFieldKey(collection)]); + childDocs.forEach((doc: Doc) => {!this.displayedDocsFunc().includes(doc) && this._lentDocs.push(doc)}); } - removeChildCollectionDocs = (collection: CollectionSchemaView) => { - const children = collection.childDocs.slice(); - this._lentDocs.forEach(element => { - - }); + removeChildCollectionDocs = (collection: Doc) => { + const children = DocListCast(collection[Doc.LayoutFieldKey(collection)]); + console.log('before: ' + this._lentDocs) + this._lentDocs.filter((doc: Doc) => !children.includes(doc)); + console.log('after: ' + this._lentDocs) } @computed get fieldDefaultInput() { @@ -1016,7 +1016,7 @@ export class CollectionSchemaView extends CollectionSubView() { const draggedDocs = this.isContentActive() ? DragManager.docsBeingDragged : []; const field = StrCast(this.layoutDoc.sortField); const desc = BoolCast(this.layoutDoc.sortDesc); // is this an ascending or descending sort - const staticDocs = this.childDocs.filter(d => !draggedDocs.includes(d)); + const staticDocs = this.childDocs.filter(d => !draggedDocs.includes(d)).concat(this._lentDocs.filter(d => !draggedDocs.includes(d))); const docs = !field ? staticDocs : [...staticDocs].sort((docA, docB) => { @@ -1039,7 +1039,7 @@ export class CollectionSchemaView extends CollectionSubView() { screenToLocal = () => this.ScreenToLocalBoxXf().translate(-this.tableWidth, 0); previewWidthFunc = () => this.previewWidth; onPassiveWheel = (e: WheelEvent) => e.stopPropagation(); - displayedDocsFunc = () => this._lentDocs.slice().concat(this.sortedDocs.docs); + displayedDocsFunc = () => this.sortedDocs.docs; _oldWheel: any; render() { return ( diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index 8e4161413..8ac2c0314 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -74,9 +74,13 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { }); if (this.Document['type'] === 'collection') { ContextMenu.Instance.addItem({ - description: 'Add children to schema', - event: () => this.schemaView.addDocsFromChildCollection(this.Document as unknown as CollectionSchemaView), - icon: 'plus', + description: this.Document._childrenSharedWithSchema ? 'Remove children from schema' : 'Add children to schema', + event: () => { + this.Document._childrenSharedWithSchema = !this.Document._childrenSharedWithSchema; + this.Document._childrenSharedWithSchema ? + this.schemaView.addDocsFromChildCollection(this.Document) : this.schemaView.removeChildCollectionDocs(this.Document); + }, + icon: this.Document._childrenSharedWithSchema ? 'minus' : 'plus', }); } ContextMenu.Instance.displayMenu(x, y, undefined, false); -- cgit v1.2.3-70-g09d2 From a9ec444d00a02a5e04f3c022fd4d0bea08efe196 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Fri, 7 Jun 2024 02:36:18 -0400 Subject: lots of UI improvements --- src/client/views/EditableView.tsx | 16 +++++++------ .../collectionSchema/CollectionSchemaView.scss | 4 ---- .../collectionSchema/CollectionSchemaView.tsx | 2 ++ .../collectionSchema/SchemaColumnHeader.tsx | 19 ++++++++------- .../collections/collectionSchema/SchemaRowBox.tsx | 3 ++- .../collectionSchema/SchemaTableCell.tsx | 27 ++++++++++++++++++---- 6 files changed, 46 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index c79cabd6a..5b690bf33 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -55,7 +55,7 @@ export interface EditableProps { placeholder?: string; wrap?: string; // nowrap, pre-wrap, etc - showKeyNotVal?: boolean; + schemaHeader?: boolean; updateAlt?: (newAlt: string) => void; updateSearch?: (value: string) => void; } @@ -77,6 +77,7 @@ export class EditableView extends ObservableReactComponent { super(props); makeObservable(this); this._editing = !!this._props.editing; + if (this._props.schemaHeader) this._editing = true; } componentDidMount(): void { @@ -184,9 +185,9 @@ export class EditableView extends ObservableReactComponent { }; @action - onClick = (e: React.MouseEvent) => { + onClick = (e?: React.MouseEvent) => { if (this._props.editing !== false) { - e.nativeEvent.stopPropagation(); + e?.nativeEvent.stopPropagation(); if (this._ref.current && this._props.showMenuOnLoad) { this._props.menuCallback?.(this._ref.current.getBoundingClientRect().x, this._ref.current.getBoundingClientRect().y); } else { @@ -280,12 +281,13 @@ export class EditableView extends ObservableReactComponent { ); } - display = () => { + staticDisplay = () => { let toDisplay; const gval = this._props.GetValue()?.replace(/\n/g, '\\r\\n'); - if (this._props.showKeyNotVal){ + if (this._props.schemaHeader){ toDisplay = { fontSize: this._props.fontSize, }} onClick={this.onClick}> - {this.display()} + {this.staticDisplay()}
); } diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss index 3d89a479a..ceffc7e44 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss @@ -302,7 +302,3 @@ } } -.header-dropdown-container { - height: 0px; - width: 60px; -} diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 39bde7d37..ec1341b14 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -758,6 +758,8 @@ const filteredChildDocs = sortedDocs.filter((doc: Doc) => !this._lentDocs. @action openColumnMenu = (index: number, newCol: boolean) => { + this.closeFilterMenu(); + this._makeNewColumn = false; this._columnMenuIndex = index; this._menuValue = ''; diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index 03cf64fc8..bda9fc9b7 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -57,6 +57,11 @@ export class SchemaColumnHeader extends ObservableReactComponent this._props.schemaView?.fieldInfos.get(fieldKey)); setColumnValues = (field: string, defaultValue: string) => {this._props.schemaView?.setKey(field, defaultValue, this._props.columnIndex);} @@ -77,10 +82,7 @@ export class SchemaColumnHeader extends ObservableReactComponent { - if (this.isDefaultTitle(this.fieldKey)){ - this._props.schemaView.openColumnMenu(this._props.columnIndex, false) - this._displayKeysDropdown = true; - } + this._props.schemaView.openColumnMenu(this._props.columnIndex, false) } @action @@ -125,7 +127,7 @@ export class SchemaColumnHeader extends ObservableReactComponent this.openKeyDropdown()} + return
{SchemaColumnHeader.isDefaultField(this.fieldKey) && this.openKeyDropdown()}} style={{ color, width: '100%', @@ -138,11 +140,12 @@ export class SchemaColumnHeader extends ObservableReactComponent { - if (this.isDefaultTitle(this.fieldKey)) return ''; + if (SchemaColumnHeader.isDefaultField(this.fieldKey)) return ''; else if (this._altTitle) return this._altTitle; else return this.fieldKey; }} @@ -160,7 +163,7 @@ export class SchemaColumnHeader extends ObservableReactComponent } - isDefaultTitle = (key: string) => { + public static isDefaultField = (key: string) => { const defaultPattern = /EmptyColumnKey/; let isDefault: boolean = (defaultPattern.exec(key) != null); return isDefault; diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index 8ac2c0314..8cac302ce 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -113,7 +113,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { }}> } + icon={ } size={Size.XSMALL} onPointerDown={e => setupMoveUpEvents( @@ -133,6 +133,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { {this.schemaView?.columnKeys?.map((key, index) => ( boolean; cleanupField: (field: string) => string; + rowSelected: () => boolean; } function selectedCell(props: SchemaTableCellProps) { return ( props.isRowActive() && - props.selectedCol() === props.col && // + props.selectedCol() === props.col && props.selectedCells()?.filter(d => d === props.Document)?.length ); } @@ -74,6 +76,10 @@ export class SchemaTableCell extends ObservableReactComponent { DocumentView.FocusOrOpen(toList(docs)[0]); return true; @@ -89,9 +95,8 @@ export class SchemaTableCell extends ObservableReactComponent - {this.content} + style={{ padding: this._props.padding, + maxWidth: this._props.maxWidth?.(), + width: this._props.columnWidth() || undefined, + border: selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined, + backgroundColor: this.backgroundColor}}> + {this.defaultKey ? '' : this.content}
); } -- cgit v1.2.3-70-g09d2 From c8dc7104f8a4923bcfc70dcc5ff5f492666487bd Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Fri, 7 Jun 2024 02:56:22 -0400 Subject: add col button tooltip + row menu icon change --- .../collectionSchema/CollectionSchemaView.tsx | 30 ++++++++++++++-------- .../collections/collectionSchema/SchemaRowBox.tsx | 4 ++- 2 files changed, 22 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index ec1341b14..03e7ed5f3 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -1,6 +1,6 @@ /* eslint-disable no-restricted-syntax */ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { Popup, PopupTrigger, Type } from 'browndash-components'; +import { IconButton, Popup, PopupTrigger, Size, Type } from 'browndash-components'; import { ObservableMap, action, autorun, computed, makeObservable, observable, observe, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; @@ -759,7 +759,7 @@ const filteredChildDocs = sortedDocs.filter((doc: Doc) => !this._lentDocs. @action openColumnMenu = (index: number, newCol: boolean) => { this.closeFilterMenu(); - + this._makeNewColumn = false; this._columnMenuIndex = index; this._menuValue = ''; @@ -1061,15 +1061,23 @@ const filteredChildDocs = sortedDocs.filter((doc: Doc) => !this._lentDocs. }}>
- this.addColumn()} icon="plus" />} //here - trigger={PopupTrigger.CLICK} - type={Type.TERT} - isOpen={this._columnMenuIndex !== -1 ? false : undefined} - popup={this.renderKeysMenu} + } + size={Size.XSMALL} + color={'black'} + onPointerDown={e => + setupMoveUpEvents( + this, + e, + returnFalse, + emptyFunction, + undoable(clickEv => { + clickEv.stopPropagation(); + this.addColumn() + }, 'add key to schema') + ) + } />
{this.columnKeys.map((key, index) => ( diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index 8cac302ce..099670022 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -20,6 +20,7 @@ import './CollectionSchemaView.scss'; import { SchemaTableCell } from './SchemaTableCell'; import { ContextMenu } from '../../ContextMenu'; import { CollectionFreeFormView } from '../collectionFreeForm'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; interface SchemaRowBoxProps extends FieldViewProps { rowIndex: number; @@ -113,8 +114,9 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { }}> } + icon={ } size={Size.XSMALL} + color={'black'} onPointerDown={e => setupMoveUpEvents( this, -- cgit v1.2.3-70-g09d2 From 97977e7156eb852c20422fa995bbf96529dfb4e5 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Fri, 7 Jun 2024 19:36:59 -0400 Subject: sort overhaul for columnheader menu cleanup (sort is now a single action, not a persistent toggle; more like google sheets now) --- src/client/views/EditableView.scss | 3 +- src/client/views/EditableView.tsx | 5 +- src/client/views/MainView.tsx | 3 + .../collectionSchema/CollectionSchemaView.tsx | 106 +++++++++++---------- .../collectionSchema/SchemaColumnHeader.tsx | 16 ---- .../collections/collectionSchema/SchemaRowBox.tsx | 7 +- 6 files changed, 69 insertions(+), 71 deletions(-) (limited to 'src') diff --git a/src/client/views/EditableView.scss b/src/client/views/EditableView.scss index e492068c8..d2f11f5e1 100644 --- a/src/client/views/EditableView.scss +++ b/src/client/views/EditableView.scss @@ -34,9 +34,8 @@ pointer-events: all; } - - .editableView-input:focus { border: none; outline: none; } + diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 5b690bf33..1652e6cd7 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -10,6 +10,7 @@ import { DocumentIconContainer } from './nodes/DocumentIcon'; import { FieldView, FieldViewProps } from './nodes/FieldView'; import { ObservableReactComponent } from './ObservableReactComponent'; import { OverlayView } from './OverlayView'; +import { Padding } from 'browndash-components'; export interface EditableProps { /** @@ -293,10 +294,10 @@ export class EditableView extends ObservableReactComponent { // eslint-disable-next-line jsx-a11y/no-autofocus /> } else { - toDisplay = ( { // eslint-disable-next-line react/jsx-props-no-spreading diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 31d88fb87..5fe9332f4 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -278,6 +278,9 @@ export class MainView extends ObservableReactComponent<{}> { library.add( ...[ + fa.faSort, + fa.faArrowUpZA, + fa.faArrowDownAZ, fa.faExclamationCircle, fa.faEdit, fa.faArrowDownShortWide, diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 03e7ed5f3..a2f88eb80 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -37,6 +37,7 @@ import { Func } from 'mocha'; import { CollectionView } from '../CollectionView'; import { listSpec } from '../../../../fields/Schema'; import { GetEffectiveAcl } from '../../../../fields/util'; +import { ContextMenuProps } from '../../ContextMenuItem'; const { SCHEMA_NEW_NODE_HEIGHT } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore @@ -96,6 +97,7 @@ export class CollectionSchemaView extends CollectionSubView() { @observable _colKeysFiltered: boolean = false; @observable _cellTags: ObservableMap = new ObservableMap>(); @observable _lentDocs: Doc[] = []; + @observable _docs: Doc[] = this.childDocs; // target HTMLelement portal for showing a popup menu to edit cell values. public get MenuTarget() { @@ -195,7 +197,7 @@ export class CollectionSchemaView extends CollectionSubView() { // ViewBoxInterface overrides override isUnstyledView = returnTrue; // used by style provider : turns off opacity, animation effects, scaling - rowIndex = (doc: Doc) => this.sortedDocs.docs.indexOf(doc); + rowIndex = (doc: Doc) => this.displayedDocs.docs.indexOf(doc); @action onKeyDown = (e: KeyboardEvent) => { @@ -205,9 +207,9 @@ export class CollectionSchemaView extends CollectionSubView() { { const lastDoc = this._selectedDocs.lastElement(); const lastIndex = this.rowIndex(lastDoc); - const curDoc = this.sortedDocs.docs[lastIndex]; + const curDoc = this.displayedDocs.docs[lastIndex]; if (lastIndex >= 0 && lastIndex < this.childDocs.length - 1) { - const newDoc = this.sortedDocs.docs[lastIndex + 1]; + const newDoc = this.displayedDocs.docs[lastIndex + 1]; if (this._selectedDocs.includes(newDoc)) { DocumentView.DeselectView(DocumentView.getFirstDocumentView(curDoc)); this.deselectCell(curDoc); @@ -224,9 +226,9 @@ export class CollectionSchemaView extends CollectionSubView() { { const firstDoc = this._selectedDocs.lastElement(); const firstIndex = this.rowIndex(firstDoc); - const curDoc = this.sortedDocs.docs[firstIndex]; + const curDoc = this.displayedDocs.docs[firstIndex]; if (firstIndex > 0 && firstIndex < this.childDocs.length) { - const newDoc = this.sortedDocs.docs[firstIndex - 1]; + const newDoc = this.displayedDocs.docs[firstIndex - 1]; if (this._selectedDocs.includes(newDoc)) { DocumentView.DeselectView(DocumentView.getFirstDocumentView(curDoc)); this.deselectCell(curDoc); @@ -269,12 +271,6 @@ export class CollectionSchemaView extends CollectionSubView() { @action changeSelectedCellColumn = () => {}; - @undoBatch - setColumnSort = (field: string | undefined, desc: boolean = false) => { - this.layoutDoc.sortField = field; - this.layoutDoc.sortDesc = desc; - }; - addRow = (doc: Doc | Doc[]) => this.addDocument(doc); @undoBatch @@ -512,7 +508,7 @@ export class CollectionSchemaView extends CollectionSubView() { const startRow = Math.min(lastSelectedRow, index); const endRow = Math.max(lastSelectedRow, index); for (let i = startRow; i <= endRow; i++) { - const currDoc = this.sortedDocs.docs[i]; + const currDoc = this.displayedDocs.docs[i]; if (!this._selectedDocs.includes(currDoc)) { this.selectCell(currDoc, this._selectedCol, false, true); } @@ -552,7 +548,7 @@ export class CollectionSchemaView extends CollectionSubView() { this._lowestSelectedIndex = -1; }; - sortedSelectedDocs = () => this.sortedDocs.docs.filter(doc => this._selectedDocs.includes(doc)); + sortedSelectedDocs = () => this.displayedDocs.docs.filter(doc => this._selectedDocs.includes(doc)); @computed get rowDropIndex() { @@ -584,9 +580,8 @@ export class CollectionSchemaView extends CollectionSubView() { const draggedDocs = de.complete.docDragData?.draggedDocuments; if (draggedDocs && super.onInternalDrop(e, de) && !this.sortField) { - const sortedDocs = this.sortedDocs.docs.slice(); -const filteredChildDocs = sortedDocs.filter((doc: Doc) => !this._lentDocs.includes(doc)); - this.dataDoc[this.fieldKey ?? 'data'] = new List([...this.sortedDocs.docs]); + const docs = this.displayedDocs.docs.slice(); + this._docs = docs; this.clearSelection(); draggedDocs.forEach(doc => { DocumentView.addViewRenderedCb(doc, dv => dv.select(true)); @@ -639,16 +634,13 @@ const filteredChildDocs = sortedDocs.filter((doc: Doc) => !this._lentDocs. return undefined; }; - addDocsFromChildCollection = (collection: Doc) => { - const childDocs = DocListCast(collection[Doc.LayoutFieldKey(collection)]); - childDocs.forEach((doc: Doc) => {!this.displayedDocsFunc().includes(doc) && this._lentDocs.push(doc)}); + addDocsFromOtherCollection = (docs: Doc[]) => { + docs.forEach((doc: Doc) => {!this.displayedDocsFunc().includes(doc) && this._lentDocs.push(doc)}); + this._docs = this.childDocs.slice().concat(this._lentDocs); } - - removeChildCollectionDocs = (collection: Doc) => { - const children = DocListCast(collection[Doc.LayoutFieldKey(collection)]); - console.log('before: ' + this._lentDocs) - this._lentDocs.filter((doc: Doc) => !children.includes(doc)); - console.log('after: ' + this._lentDocs) + removeDocsFromOtherCollection = (docs: Doc[]) => { + this._lentDocs.filter((doc: Doc) => !docs.includes(doc)); + this._docs = this.childDocs.slice().concat(this._lentDocs); } @computed get fieldDefaultInput() { @@ -784,27 +776,46 @@ const filteredChildDocs = sortedDocs.filter((doc: Doc) => !this._lentDocs. this._filterColumnIndex = undefined; }; + @undoBatch + setColumnSort = (field: string | undefined, desc: boolean = false) => { + this.layoutDoc.sortField = field; + this.layoutDoc.sortDesc = desc; + }; + openContextMenu = (x: number, y: number, index: number) => { this.closeColumnMenu(); this.closeFilterMenu(); + const cm = ContextMenu.Instance; + cm.clearItems(); - ContextMenu.Instance.clearItems(); - ContextMenu.Instance.addItem({ + const revealOptions = cm.findByDescription('Sort column') + const sortOptions: ContextMenuProps[] = revealOptions && revealOptions && 'subitems' in revealOptions ? revealOptions.subitems : []; + sortOptions.push({description: 'Sort A-Z', event: () => this.sortDocs(this._docs, this.columnKeys[index], false), icon: 'arrow-down-a-z',}); // prettier-ignore + sortOptions.push({description: 'Sort Z-A', event: () => this.sortDocs(this._docs, this.columnKeys[index], true), icon: 'arrow-up-z-a'}); // prettier-ignore + + cm.addItem({ description: `Change field`, event: () => this.openColumnMenu(index, false), icon: 'pencil-alt', }); - ContextMenu.Instance.addItem({ + cm.addItem({ description: 'Filter field', event: () => this.openFilterMenu(index), icon: 'filter', }); - ContextMenu.Instance.addItem({ + cm.addItem({ + description: 'Sort column', + addDivider: false, + noexpand: true, + subitems: sortOptions, + icon: 'sort' + }); + cm.addItem({ description: 'Delete column', event: () => this.removeColumn(index), icon: 'trash', }); - ContextMenu.Instance.displayMenu(x, y, undefined, false); + cm.displayMenu(x, y, undefined, false); }; @action @@ -1014,34 +1025,33 @@ const filteredChildDocs = sortedDocs.filter((doc: Doc) => !this._lentDocs. } }; - @computed get sortedDocs() { + @computed get displayedDocs() { const draggedDocs = this.isContentActive() ? DragManager.docsBeingDragged : []; - const field = StrCast(this.layoutDoc.sortField); - const desc = BoolCast(this.layoutDoc.sortDesc); // is this an ascending or descending sort - const staticDocs = this.childDocs.filter(d => !draggedDocs.includes(d)).concat(this._lentDocs.filter(d => !draggedDocs.includes(d))); - const docs = !field - ? staticDocs - : [...staticDocs].sort((docA, docB) => { - // this sorts the documents based on the selected field. returning -1 for a before b, 0 for a = b, 1 for a > b - const aStr = Field.toString(docA[field] as FieldType); - const bStr = Field.toString(docB[field] as FieldType); - let out = 0; - if (aStr < bStr) out = -1; - if (aStr > bStr) out = 1; - if (desc) out *= -1; - return out; - }); - + const docs = this._docs.filter(d => !draggedDocs.includes(d)); docs.splice(this.rowDropIndex, 0, ...draggedDocs); return { docs }; } + @action + sortDocs = (docs: Doc[], field: string, desc: boolean) => { + docs = docs.sort((docA, docB) => { + // this sorts the documents based on the selected field. returning -1 for a before b, 0 for a = b, 1 for a > b + const aStr = Field.toString(docA[field] as FieldType); + const bStr = Field.toString(docB[field] as FieldType); + let out = 0; + if (aStr < bStr) out = -1; + if (aStr > bStr) out = 1; + if (desc) out *= -1; + return out; + }); + } + rowHeightFunc = () => (BoolCast(this.layoutDoc._schema_singleLine) ? CollectionSchemaView._rowSingleLineHeight : CollectionSchemaView._rowHeight); isContentActive = () => this._props.isSelected() || this._props.isContentActive(); screenToLocal = () => this.ScreenToLocalBoxXf().translate(-this.tableWidth, 0); previewWidthFunc = () => this.previewWidth; onPassiveWheel = (e: WheelEvent) => e.stopPropagation(); - displayedDocsFunc = () => this.sortedDocs.docs; + displayedDocsFunc = () => this.displayedDocs.docs; _oldWheel: any; render() { return ( diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index bda9fc9b7..dd4a13776 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -68,19 +68,6 @@ export class SchemaColumnHeader extends ObservableReactComponent {this._altTitle = newAlt;} @action updateKeyDropdown = (value: string) => {this._props.schemaView.updateKeySearch(value)} - @action - sortClicked = (e: React.PointerEvent) => { - e.stopPropagation(); - e.preventDefault(); - if (this._props.sortField === this.fieldKey && this._props.sortDesc) { - this._props.setSort(undefined); - } else if (this._props.sortField === this.fieldKey) { - this._props.setSort(this.fieldKey, true); - } else { - this._props.setSort(this.fieldKey, false); - } - }; - openKeyDropdown = () => { this._props.schemaView.openColumnMenu(this._props.columnIndex, false) } @@ -190,9 +177,6 @@ export class SchemaColumnHeader extends ObservableReactComponent this._props.openContextMenu(e.clientX, e.clientY, this._props.columnIndex)}>
-
- -
); diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index 099670022..665704de1 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -7,7 +7,7 @@ import { CgClose, CgLock, CgLockUnlock, CgMenu } from 'react-icons/cg'; import { FaExternalLinkAlt } from 'react-icons/fa'; import { returnFalse, setupMoveUpEvents } from '../../../../ClientUtils'; import { emptyFunction } from '../../../../Utils'; -import { Doc } from '../../../../fields/Doc'; +import { Doc, DocListCast } from '../../../../fields/Doc'; import { BoolCast } from '../../../../fields/Types'; import { Transform } from '../../../util/Transform'; import { undoable } from '../../../util/UndoManager'; @@ -73,13 +73,14 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { event: () => this._props.addDocTab(this.Document, OpenWhere.addRight), icon: 'magnifying-glass', }); - if (this.Document['type'] === 'collection') { + const childDocs = DocListCast(this.Document[Doc.LayoutFieldKey(this.Document)]) + if (this.Document['type'] === 'collection' && childDocs.length) { ContextMenu.Instance.addItem({ description: this.Document._childrenSharedWithSchema ? 'Remove children from schema' : 'Add children to schema', event: () => { this.Document._childrenSharedWithSchema = !this.Document._childrenSharedWithSchema; this.Document._childrenSharedWithSchema ? - this.schemaView.addDocsFromChildCollection(this.Document) : this.schemaView.removeChildCollectionDocs(this.Document); + this.schemaView.addDocsFromOtherCollection(childDocs) : this.schemaView.removeDocsFromOtherCollection(childDocs); }, icon: this.Document._childrenSharedWithSchema ? 'minus' : 'plus', }); -- cgit v1.2.3-70-g09d2 From 99b0ce24e4d56100746016995c20f9bb9c109072 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Mon, 10 Jun 2024 04:01:01 -0400 Subject: adding/removing children from collection works (probably buggy); backspace delete broken --- src/client/documents/Documents.ts | 2 +- .../collectionSchema/CollectionSchemaView.tsx | 34 ++++++++++++++++++---- .../collectionSchema/SchemaColumnHeader.tsx | 23 +++++++++++++-- .../collections/collectionSchema/SchemaRowBox.tsx | 9 +++--- 4 files changed, 53 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 365af66b7..4908d2952 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -227,7 +227,7 @@ export class DocumentOptions { _header_pointerEvents?: PEVt = new PEInfo('types of events the header of a custom text document can consume'); _lockedPosition?: BOOLt = new BoolInfo("lock the x,y coordinates of the document so that it can't be dragged"); _lockedTransform?: BOOLt = new BoolInfo('lock the freeform_panx,freeform_pany and scale parameters of the document so that it be panned/zoomed'); - _childrenSharedWithSchema?: BOOLt = new BoolInfo("whether this document's children are displayed in its parent schema view"); + _childrenSharedWithSchema?: BOOLt = new BoolInfo("whether this document's children are displayed in its parent schema view", false); dataViz_title?: string; dataViz_line?: string; diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index a2f88eb80..f501993b5 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -1,7 +1,7 @@ /* eslint-disable no-restricted-syntax */ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { IconButton, Popup, PopupTrigger, Size, Type } from 'browndash-components'; -import { ObservableMap, action, autorun, computed, makeObservable, observable, observe, runInAction } from 'mobx'; +import { ObservableMap, action, autorun, computed, makeObservable, observable, observe, override, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../ClientUtils'; @@ -65,6 +65,7 @@ export class CollectionSchemaView extends CollectionSubView() { constructor(props: any) { super(props); makeObservable(this); + this.importAddedDocs(); } static _rowHeight: number = 50; @@ -106,7 +107,7 @@ export class CollectionSchemaView extends CollectionSubView() { @computed get _selectedDocs() { // get all selected documents then filter out any whose parent is not this schema document - const selected = DocumentView.SelectedDocs().filter(doc => this.childDocs.includes(doc)); + const selected = DocumentView.SelectedDocs().filter(doc => this._docs.includes(doc)); if (!selected.length) { // if no schema doc is directly selected, test if a child of a schema doc is selected (such as in the preview window) const childOfSchemaDoc = DocumentView.SelectedDocs().find(sel => DocumentView.getContextPath(sel, true).includes(this.Document)); @@ -197,6 +198,22 @@ export class CollectionSchemaView extends CollectionSubView() { // ViewBoxInterface overrides override isUnstyledView = returnTrue; // used by style provider : turns off opacity, animation effects, scaling + importAddedDocs = () => { + const collections = this.childDocs.filter((doc: Doc) => doc.type === 'collection'); + collections.forEach((doc: Doc) => { + const childDocs = DocListCast(doc[Doc.LayoutFieldKey(doc)]); + doc._childrenSharedWithSchema && this.addDocsFromOtherCollection(childDocs); + }); + } + + removeDoc = (doc: Doc) => { + console.log('called') + this.removeDocument(doc); + if (doc instanceof Doc) { + console.log('doc is doc') + this._docs = this._docs.filter(d => d !== doc)}; + } + rowIndex = (doc: Doc) => this.displayedDocs.docs.indexOf(doc); @action @@ -256,13 +273,17 @@ export class CollectionSchemaView extends CollectionSubView() { } break; case 'Backspace': { - undoable(() => this.removeDocument(this._selectedDocs), 'delete schema row'); + undoable(() => {this._selectedDocs.forEach(d => this._docs.includes(d) && this.removeDoc(d));}, 'delete schema row'); break; } case 'Escape': { this.deselectAllCells(); break; } + case 'P': { + this.importAddedDocs(); + break; + } default: } } @@ -635,11 +656,12 @@ export class CollectionSchemaView extends CollectionSubView() { }; addDocsFromOtherCollection = (docs: Doc[]) => { - docs.forEach((doc: Doc) => {!this.displayedDocsFunc().includes(doc) && this._lentDocs.push(doc)}); + docs.forEach((doc: Doc) => !this.displayedDocsFunc().includes(doc) && this._lentDocs.push(doc)); this._docs = this.childDocs.slice().concat(this._lentDocs); } + removeDocsFromOtherCollection = (docs: Doc[]) => { - this._lentDocs.filter((doc: Doc) => !docs.includes(doc)); + this._lentDocs = this._lentDocs.filter((doc: Doc) => !docs.includes(doc)); this._docs = this.childDocs.slice().concat(this._lentDocs); } @@ -1032,7 +1054,7 @@ export class CollectionSchemaView extends CollectionSubView() { return { docs }; } - @action + @action sortDocs = (docs: Doc[], field: string, desc: boolean) => { docs = docs.sort((docA, docB) => { // this sorts the documents based on the selected field. returning -1 for a before b, 0 for a = b, 1 for a > b diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index dd4a13776..dbbf76ea7 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -22,6 +22,7 @@ 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 interface SchemaColumnHeaderProps { Document: Doc; @@ -174,10 +175,26 @@ export class SchemaColumnHeader extends ObservableReactComponent{this.editableView}
-
this._props.openContextMenu(e.clientX, e.clientY, this._props.columnIndex)}> - +
+ } + size={Size.XSMALL} + color={'black'} + onPointerDown={e => + setupMoveUpEvents( + this, + e, + returnFalse, + emptyFunction, + undoable(clickEv => { + clickEv.stopPropagation(); + this._props.openContextMenu(e.clientX, e.clientY, this._props.columnIndex) + }, 'open column menu') + ) + } + />
-
+
); } diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index 665704de1..cdd47f644 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -60,7 +60,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { ContextMenu.Instance.clearItems(); ContextMenu.Instance.addItem({ description: `Close doc`, - event: () => this._props.removeDocument?.(this.Document), + event: () => this.schemaView.removeDoc(this.Document), icon: 'minus', }); ContextMenu.Instance.addItem({ @@ -74,13 +74,12 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { icon: 'magnifying-glass', }); const childDocs = DocListCast(this.Document[Doc.LayoutFieldKey(this.Document)]) - if (this.Document['type'] === 'collection' && childDocs.length) { + if (this.Document.type === 'collection' && childDocs.length) { ContextMenu.Instance.addItem({ description: this.Document._childrenSharedWithSchema ? 'Remove children from schema' : 'Add children to schema', event: () => { this.Document._childrenSharedWithSchema = !this.Document._childrenSharedWithSchema; - this.Document._childrenSharedWithSchema ? - this.schemaView.addDocsFromOtherCollection(childDocs) : this.schemaView.removeDocsFromOtherCollection(childDocs); + this.Document._childrenSharedWithSchema ? this.schemaView.addDocsFromOtherCollection(childDocs) : this.schemaView.removeDocsFromOtherCollection(childDocs); }, icon: this.Document._childrenSharedWithSchema ? 'minus' : 'plus', }); @@ -115,7 +114,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { }}> } + icon={ } size={Size.XSMALL} color={'black'} onPointerDown={e => -- cgit v1.2.3-70-g09d2 From ecea2cb94fa0ea3f9959b3a8f5f43ae7e98aa552 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Mon, 10 Jun 2024 11:19:32 -0400 Subject: lockopen icon --- src/client/views/MainView.tsx | 1 + .../views/collections/collectionSchema/CollectionSchemaView.tsx | 6 +----- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 5fe9332f4..8dc2ce98a 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -278,6 +278,7 @@ export class MainView extends ObservableReactComponent<{}> { library.add( ...[ + fa.faLockOpen, fa.faSort, fa.faArrowUpZA, fa.faArrowDownAZ, diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index f501993b5..7302a7c22 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -207,11 +207,8 @@ export class CollectionSchemaView extends CollectionSubView() { } removeDoc = (doc: Doc) => { - console.log('called') this.removeDocument(doc); - if (doc instanceof Doc) { - console.log('doc is doc') - this._docs = this._docs.filter(d => d !== doc)}; + this._docs = this._docs.filter(d => d !== doc); } rowIndex = (doc: Doc) => this.displayedDocs.docs.indexOf(doc); @@ -353,7 +350,6 @@ export class CollectionSchemaView extends CollectionSubView() { const currKeys = this.columnKeys.slice(); currKeys.splice(index, 1); this.layoutDoc.schema_columnKeys = new List(currKeys); - console.log(...currKeys); }; @action -- cgit v1.2.3-70-g09d2 From 4b604b5118a1aac89d977c832c81495ec2c9aa19 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Mon, 10 Jun 2024 12:56:51 -0400 Subject: lock row editing --- src/client/documents/Documents.ts | 1 + src/client/views/EditableView.tsx | 2 ++ .../collectionSchema/CollectionSchemaView.tsx | 11 ++------ .../collectionSchema/SchemaColumnHeader.tsx | 1 + .../collections/collectionSchema/SchemaRowBox.tsx | 15 ++++++++-- .../collectionSchema/SchemaTableCell.tsx | 33 ++++++++++++---------- 6 files changed, 37 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 4908d2952..dabbf9591 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -228,6 +228,7 @@ export class DocumentOptions { _lockedPosition?: BOOLt = new BoolInfo("lock the x,y coordinates of the document so that it can't be dragged"); _lockedTransform?: BOOLt = new BoolInfo('lock the freeform_panx,freeform_pany and scale parameters of the document so that it be panned/zoomed'); _childrenSharedWithSchema?: BOOLt = new BoolInfo("whether this document's children are displayed in its parent schema view", false); + _lockedSchemaEditing?: BOOLt = new BoolInfo("", false); dataViz_title?: string; dataViz_line?: string; diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 1652e6cd7..c05812e1a 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -57,6 +57,7 @@ export interface EditableProps { wrap?: string; // nowrap, pre-wrap, etc schemaHeader?: boolean; + onClick?: () => void; updateAlt?: (newAlt: string) => void; updateSearch?: (value: string) => void; } @@ -187,6 +188,7 @@ export class EditableView extends ObservableReactComponent { @action onClick = (e?: React.MouseEvent) => { + this._props.onClick && this._props.onClick(); if (this._props.editing !== false) { e?.nativeEvent.stopPropagation(); if (this._ref.current && this._props.showMenuOnLoad) { diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 7302a7c22..48287c3ec 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -208,7 +208,7 @@ export class CollectionSchemaView extends CollectionSubView() { removeDoc = (doc: Doc) => { this.removeDocument(doc); - this._docs = this._docs.filter(d => d !== doc); + this._docs = this._docs.filter(d => d !== doc) } rowIndex = (doc: Doc) => this.displayedDocs.docs.indexOf(doc); @@ -739,13 +739,8 @@ export class CollectionSchemaView extends CollectionSubView() { }; setCellValues = (key: string, value: string) => { - const selectedDocs: Doc[] = []; - this.childDocs.forEach(doc => { - const isSelected = this._selectedCells && !(this._selectedCells?.filter(d => d === doc).length === 0); - isSelected && selectedDocs.push(doc); - }); - if (selectedDocs.length === 1) this.childDocs.forEach(doc => Doc.SetField(doc, key, value)); // if only one cell selected, fill all - else selectedDocs.forEach(doc => Doc.SetField(doc, key, value)); // else only fill selected cells + if (this._selectedCells.length === 1) this.childDocs.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value)); // if only one cell selected, fill all + else this._selectedCells.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value)); // else only fill selected cells return true; }; diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index dbbf76ea7..3719840ff 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -126,6 +126,7 @@ export class SchemaColumnHeader extends ObservableReactComponent() { icon: 'minus', }); ContextMenu.Instance.addItem({ - description: this.Document._lockedPosition ? 'Unlock doc interactions' : 'Lock doc interactions', - event: () => Doc.toggleLockedPosition(this.Document), - icon: this.Document._lockedPosition ? 'lock-open' : 'lock', + description: this.Document._lockedSchemaEditing ? 'Unlock field editing' : 'Lock field editing', + event: () => this.Document._lockedSchemaEditing = !this.Document._lockedSchemaEditing, + icon: this.Document._lockedSchemaEditing ? 'lock-open' : 'lock', }); ContextMenu.Instance.addItem({ description: 'Open preview', @@ -87,6 +87,14 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { ContextMenu.Instance.displayMenu(x, y, undefined, false); } + get menuBackgroundColor(){ + if (this.Document._lockedSchemaEditing){ + if (this._props.isSelected()) return '#B0D1E7' + else return '#F5F5F5' + } + return '' + } + cleanupField = (field: string) => this.schemaView.cleanupComputedField(field) setCursorIndex = (mouseY: number) => this.schemaView?.setRelCursorIndex(mouseY); selectedCol = () => this.schemaView._selectedCol; @@ -111,6 +119,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { style={{ width: CollectionSchemaView._rowMenuWidth, pointerEvents: !this._props.isContentActive() ? 'none' : undefined, + backgroundColor: this.menuBackgroundColor }}> { @@ -89,9 +101,7 @@ export class SchemaTableCell extends ObservableReactComponent selectedCell(this._props) && this._props.autoFocus && r?.setIsFocused(true)} @@ -190,14 +201,6 @@ export class SchemaTableCell extends ObservableReactComponent - {this.defaultKey ? '' : this.content} + {this.isDefault ? '' : this.content}
); } -- cgit v1.2.3-70-g09d2 From 03f9fd4beb2bd3efa8f88c71bdbaf52dbec82e66 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Mon, 10 Jun 2024 14:56:42 -0400 Subject: sub-collection doc adding refactor complete except for small bug --- .../collectionSchema/CollectionSchemaView.tsx | 51 +++++++++--------- .../collectionSchema/SchemaColumnHeader.tsx | 60 +++++++++++++++------- .../collections/collectionSchema/SchemaRowBox.tsx | 1 - 3 files changed, 65 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 48287c3ec..1952f59f5 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -65,7 +65,6 @@ export class CollectionSchemaView extends CollectionSubView() { constructor(props: any) { super(props); makeObservable(this); - this.importAddedDocs(); } static _rowHeight: number = 50; @@ -97,7 +96,6 @@ export class CollectionSchemaView extends CollectionSubView() { @observable _colBeingDragged: boolean = false; @observable _colKeysFiltered: boolean = false; @observable _cellTags: ObservableMap = new ObservableMap>(); - @observable _lentDocs: Doc[] = []; @observable _docs: Doc[] = this.childDocs; // target HTMLelement portal for showing a popup menu to edit cell values. @@ -150,7 +148,7 @@ export class CollectionSchemaView extends CollectionSubView() { } @computed get rowHeights() { - return this.childDocs.concat(this._lentDocs).map(() => this.rowHeightFunc()); + return this.docs.map(() => this.rowHeightFunc()); } @computed get displayColumnWidths() { @@ -198,14 +196,6 @@ export class CollectionSchemaView extends CollectionSubView() { // ViewBoxInterface overrides override isUnstyledView = returnTrue; // used by style provider : turns off opacity, animation effects, scaling - importAddedDocs = () => { - const collections = this.childDocs.filter((doc: Doc) => doc.type === 'collection'); - collections.forEach((doc: Doc) => { - const childDocs = DocListCast(doc[Doc.LayoutFieldKey(doc)]); - doc._childrenSharedWithSchema && this.addDocsFromOtherCollection(childDocs); - }); - } - removeDoc = (doc: Doc) => { this.removeDocument(doc); this._docs = this._docs.filter(d => d !== doc) @@ -278,7 +268,6 @@ export class CollectionSchemaView extends CollectionSubView() { break; } case 'P': { - this.importAddedDocs(); break; } default: @@ -651,16 +640,6 @@ export class CollectionSchemaView extends CollectionSubView() { return undefined; }; - addDocsFromOtherCollection = (docs: Doc[]) => { - docs.forEach((doc: Doc) => !this.displayedDocsFunc().includes(doc) && this._lentDocs.push(doc)); - this._docs = this.childDocs.slice().concat(this._lentDocs); - } - - removeDocsFromOtherCollection = (docs: Doc[]) => { - this._lentDocs = this._lentDocs.filter((doc: Doc) => !docs.includes(doc)); - this._docs = this.childDocs.slice().concat(this._lentDocs); - } - @computed get fieldDefaultInput() { switch (this._newFieldType) { case ColumnType.Number: @@ -739,7 +718,7 @@ export class CollectionSchemaView extends CollectionSubView() { }; setCellValues = (key: string, value: string) => { - if (this._selectedCells.length === 1) this.childDocs.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value)); // if only one cell selected, fill all + if (this._selectedCells.length === 1) this.childDocs.forEach(doc => !doc._lockedSchemaEditing &&Doc.SetField(doc, key, value)); // if only one cell selected, fill all else this._selectedCells.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value)); // else only fill selected cells return true; }; @@ -1038,16 +1017,36 @@ export class CollectionSchemaView extends CollectionSubView() { } }; + displayedSubCollectionDocs = (doc: Doc) => { + const childDocs = DocListCast(doc[Doc.LayoutFieldKey(doc)]); + const displayedCollections = childDocs.filter(d => d.type === 'collection' && d._childrenSharedWithSchema); + let toReturn: Doc[] = [...childDocs]; + displayedCollections.forEach(d => toReturn = toReturn.concat(this.displayedSubCollectionDocs(d))); + return toReturn; + } + + @computed get docs() { + let docsFromChildren: Doc[] = []; + const displayedCollections = this.childDocs.filter(d => d.type === 'collection' && d._childrenSharedWithSchema); + displayedCollections.forEach(d => { + let docsNotAlreadyDisplayed = this.displayedSubCollectionDocs(d).filter(dc => !this._docs.includes(dc)); + docsFromChildren = docsFromChildren.concat(docsNotAlreadyDisplayed); + }); + let docs = this._docs.concat(docsFromChildren); + return docs; + } + @computed get displayedDocs() { const draggedDocs = this.isContentActive() ? DragManager.docsBeingDragged : []; - const docs = this._docs.filter(d => !draggedDocs.includes(d)); + let docs = [...this.docs]; + docs = docs.filter(d => !draggedDocs.includes(d)); docs.splice(this.rowDropIndex, 0, ...draggedDocs); return { docs }; } @action sortDocs = (docs: Doc[], field: string, desc: boolean) => { - docs = docs.sort((docA, docB) => { + this._docs = docs.sort((docA, docB) => { // this sorts the documents based on the selected field. returning -1 for a before b, 0 for a = b, 1 for a > b const aStr = Field.toString(docA[field] as FieldType); const bStr = Field.toString(docB[field] as FieldType); @@ -1115,8 +1114,6 @@ export class CollectionSchemaView extends CollectionSubView() { columnIndex={index} columnKeys={this.columnKeys} columnWidths={this.displayColumnWidths} - sortField={this.sortField} - sortDesc={this.sortDesc} setSort={this.setColumnSort} rowHeight={this.rowHeightFunc} removeColumn={this.removeColumn} diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index 3719840ff..0da186f81 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -30,8 +30,6 @@ export interface SchemaColumnHeaderProps { columnKeys: string[]; columnWidths: number[]; columnIndex: number; - sortField: string; - sortDesc: boolean; schemaView: CollectionSchemaView; keysDropdown: React.JSX.Element; //cleanupField: (s: string) => string; @@ -158,6 +156,46 @@ export class SchemaColumnHeader extends ObservableReactComponent} + size={Size.XSMALL} + color={'black'} + onPointerDown={e => + setupMoveUpEvents( + this, + e, + returnFalse, + emptyFunction, + undoable(clickEv => { + clickEv.stopPropagation(); + this._props.schemaView.removeColumn(this._props.columnIndex); + }, 'open column menu') + ) + } + />) + : (} + size={Size.XSMALL} + color={'black'} + onPointerDown={e => + setupMoveUpEvents( + this, + e, + returnFalse, + emptyFunction, + undoable(clickEv => { + clickEv.stopPropagation(); + this._props.openContextMenu(e.clientX, e.clientY, this._props.columnIndex) + }, 'open column menu') + ) + } + />) + + return toRender; + } + render() { return (
- } - size={Size.XSMALL} - color={'black'} - onPointerDown={e => - setupMoveUpEvents( - this, - e, - returnFalse, - emptyFunction, - undoable(clickEv => { - clickEv.stopPropagation(); - this._props.openContextMenu(e.clientX, e.clientY, this._props.columnIndex) - }, 'open column menu') - ) - } - /> + {this.headerButton}
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index 58964d9fb..a0d3144ce 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -79,7 +79,6 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { description: this.Document._childrenSharedWithSchema ? 'Remove children from schema' : 'Add children to schema', event: () => { this.Document._childrenSharedWithSchema = !this.Document._childrenSharedWithSchema; - this.Document._childrenSharedWithSchema ? this.schemaView.addDocsFromOtherCollection(childDocs) : this.schemaView.removeDocsFromOtherCollection(childDocs); }, icon: this.Document._childrenSharedWithSchema ? 'minus' : 'plus', }); -- cgit v1.2.3-70-g09d2 From 74849a5f9307ca64e2bbafa9eaa77822de18102d Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Mon, 10 Jun 2024 20:41:14 -0400 Subject: bug fixed --- .../views/collections/collectionSchema/CollectionSchemaView.tsx | 5 +++-- src/client/views/collections/collectionSchema/SchemaTableCell.tsx | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 1952f59f5..dc29e7413 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -105,7 +105,7 @@ export class CollectionSchemaView extends CollectionSubView() { @computed get _selectedDocs() { // get all selected documents then filter out any whose parent is not this schema document - const selected = DocumentView.SelectedDocs().filter(doc => this._docs.includes(doc)); + const selected = DocumentView.SelectedDocs().filter(doc => this.docs.includes(doc)); if (!selected.length) { // if no schema doc is directly selected, test if a child of a schema doc is selected (such as in the preview window) const childOfSchemaDoc = DocumentView.SelectedDocs().find(sel => DocumentView.getContextPath(sel, true).includes(this.Document)); @@ -525,7 +525,8 @@ export class CollectionSchemaView extends CollectionSubView() { selectCell = (doc: Doc, col: number, shiftKey: boolean, ctrlKey: boolean) => { if (!shiftKey && !ctrlKey) this.clearSelection(); !this._selectedCells && (this._selectedCells = []); - !shiftKey && this._selectedCells && this._selectedCells.push(doc); + !shiftKey && this._selectedCells.push(doc); + this._selectedCells.forEach(d => console.log(d.title)) const index = this.rowIndex(doc); if (!this) return; diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 49ec70b74..791465741 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -215,6 +215,7 @@ export class SchemaTableCell extends ObservableReactComponent Date: Tue, 11 Jun 2024 01:56:17 -0400 Subject: rowmenu info icons --- src/client/views/MainView.tsx | 1 + .../collectionSchema/CollectionSchemaView.scss | 17 ++++++++++++++--- .../collectionSchema/CollectionSchemaView.tsx | 22 ++++++++++------------ .../collections/collectionSchema/SchemaRowBox.tsx | 13 ++++++++++++- 4 files changed, 37 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 8dc2ce98a..5b9ddbb88 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -278,6 +278,7 @@ export class MainView extends ObservableReactComponent<{}> { library.add( ...[ + fa.faGift, fa.faLockOpen, fa.faSort, fa.faArrowUpZA, diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss index ceffc7e44..d1f1e3a13 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss @@ -259,9 +259,6 @@ flex-direction: row; min-width: 50px; justify-content: center; - .iconButton-container { - min-width: unset !important; - } } .row-cells { @@ -269,6 +266,20 @@ flex-direction: row; justify-content: flex-end; } + + .row-menu-infos { + position: absolute; + top: 3; + left: 3; + z-index: 1; + display: flex; + justify-content: flex-end; + align-items: center; + + .row-infos-icon { + padding-right: 2px; + } + } } .schema-row-button, diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index dc29e7413..4abbc7f51 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -201,7 +201,7 @@ export class CollectionSchemaView extends CollectionSubView() { this._docs = this._docs.filter(d => d !== doc) } - rowIndex = (doc: Doc) => this.displayedDocs.docs.indexOf(doc); + rowIndex = (doc: Doc) => this.draggedSpliceDocs.docs.indexOf(doc); @action onKeyDown = (e: KeyboardEvent) => { @@ -211,9 +211,9 @@ export class CollectionSchemaView extends CollectionSubView() { { const lastDoc = this._selectedDocs.lastElement(); const lastIndex = this.rowIndex(lastDoc); - const curDoc = this.displayedDocs.docs[lastIndex]; + const curDoc = this.docs[lastIndex]; if (lastIndex >= 0 && lastIndex < this.childDocs.length - 1) { - const newDoc = this.displayedDocs.docs[lastIndex + 1]; + const newDoc = this.docs[lastIndex + 1]; if (this._selectedDocs.includes(newDoc)) { DocumentView.DeselectView(DocumentView.getFirstDocumentView(curDoc)); this.deselectCell(curDoc); @@ -230,9 +230,9 @@ export class CollectionSchemaView extends CollectionSubView() { { const firstDoc = this._selectedDocs.lastElement(); const firstIndex = this.rowIndex(firstDoc); - const curDoc = this.displayedDocs.docs[firstIndex]; + const curDoc = this.docs[firstIndex]; if (firstIndex > 0 && firstIndex < this.childDocs.length) { - const newDoc = this.displayedDocs.docs[firstIndex - 1]; + const newDoc = this.docs[firstIndex - 1]; if (this._selectedDocs.includes(newDoc)) { DocumentView.DeselectView(DocumentView.getFirstDocumentView(curDoc)); this.deselectCell(curDoc); @@ -514,7 +514,7 @@ export class CollectionSchemaView extends CollectionSubView() { const startRow = Math.min(lastSelectedRow, index); const endRow = Math.max(lastSelectedRow, index); for (let i = startRow; i <= endRow; i++) { - const currDoc = this.displayedDocs.docs[i]; + const currDoc = this.docs[i]; if (!this._selectedDocs.includes(currDoc)) { this.selectCell(currDoc, this._selectedCol, false, true); } @@ -555,8 +555,6 @@ export class CollectionSchemaView extends CollectionSubView() { this._lowestSelectedIndex = -1; }; - sortedSelectedDocs = () => this.displayedDocs.docs.filter(doc => this._selectedDocs.includes(doc)); - @computed get rowDropIndex() { const mouseY = this.ScreenToLocalBoxXf().transformPoint(this._mouseCoordinates.x, this._mouseCoordinates.y)[1]; @@ -587,7 +585,7 @@ export class CollectionSchemaView extends CollectionSubView() { const draggedDocs = de.complete.docDragData?.draggedDocuments; if (draggedDocs && super.onInternalDrop(e, de) && !this.sortField) { - const docs = this.displayedDocs.docs.slice(); + const docs = this.draggedSpliceDocs.docs.slice(); this._docs = docs; this.clearSelection(); draggedDocs.forEach(doc => { @@ -719,7 +717,7 @@ export class CollectionSchemaView extends CollectionSubView() { }; setCellValues = (key: string, value: string) => { - if (this._selectedCells.length === 1) this.childDocs.forEach(doc => !doc._lockedSchemaEditing &&Doc.SetField(doc, key, value)); // if only one cell selected, fill all + if (this._selectedCells.length === 1) this.docs.forEach(doc => !doc._lockedSchemaEditing &&Doc.SetField(doc, key, value)); // if only one cell selected, fill all else this._selectedCells.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value)); // else only fill selected cells return true; }; @@ -1037,7 +1035,7 @@ export class CollectionSchemaView extends CollectionSubView() { return docs; } - @computed get displayedDocs() { + @computed get draggedSpliceDocs() { const draggedDocs = this.isContentActive() ? DragManager.docsBeingDragged : []; let docs = [...this.docs]; docs = docs.filter(d => !draggedDocs.includes(d)); @@ -1064,7 +1062,7 @@ export class CollectionSchemaView extends CollectionSubView() { screenToLocal = () => this.ScreenToLocalBoxXf().translate(-this.tableWidth, 0); previewWidthFunc = () => this.previewWidth; onPassiveWheel = (e: WheelEvent) => e.stopPropagation(); - displayedDocsFunc = () => this.displayedDocs.docs; + displayedDocsFunc = () => this.draggedSpliceDocs.docs; _oldWheel: any; render() { return ( diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index a0d3144ce..98a16deea 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -7,7 +7,7 @@ import { CgClose, CgLock, CgLockUnlock, CgMenu } from 'react-icons/cg'; import { FaExternalLinkAlt } from 'react-icons/fa'; import { returnFalse, setupMoveUpEvents } from '../../../../ClientUtils'; import { emptyFunction } from '../../../../Utils'; -import { Doc, DocListCast } from '../../../../fields/Doc'; +import { Doc, DocListCast, FieldResult } from '../../../../fields/Doc'; import { BoolCast } from '../../../../fields/Types'; import { Transform } from '../../../util/Transform'; import { undoable } from '../../../util/UndoManager'; @@ -21,6 +21,7 @@ import { SchemaTableCell } from './SchemaTableCell'; import { ContextMenu } from '../../ContextMenu'; import { CollectionFreeFormView } from '../collectionFreeForm'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { IconProp } from '@fortawesome/fontawesome-svg-core'; interface SchemaRowBoxProps extends FieldViewProps { rowIndex: number; @@ -94,6 +95,13 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { return '' } + get menuInfos() { + const infos: Array = []; + if (this.Document._lockedSchemaEditing) infos.push('lock'); + if (this.Document._childrenSharedWithSchema) infos.push('star'); + return infos; + } + cleanupField = (field: string) => this.schemaView.cleanupComputedField(field) setCursorIndex = (mouseY: number) => this.schemaView?.setRelCursorIndex(mouseY); selectedCol = () => this.schemaView._selectedCol; @@ -113,6 +121,9 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { row && this.schemaView?.addRowRef?.(this.Document, row); this._ref = row; }}> +
+ {this.menuInfos.map(icn => )} +
Date: Tue, 11 Jun 2024 12:05:43 -0400 Subject: doninfos --- src/client/views/ScriptingRepl.scss | 2 ++ .../collections/collectionSchema/CollectionSchemaView.tsx | 12 ++++++------ src/client/views/nodes/DocumentIcon.tsx | 7 ++----- 3 files changed, 10 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/client/views/ScriptingRepl.scss b/src/client/views/ScriptingRepl.scss index adc82238e..5fe176920 100644 --- a/src/client/views/ScriptingRepl.scss +++ b/src/client/views/ScriptingRepl.scss @@ -35,6 +35,8 @@ opacity: 0.3; } + + .scriptingObject-icon { padding: 3px; cursor: pointer; diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 4abbc7f51..bdf04f47b 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -260,6 +260,10 @@ export class CollectionSchemaView extends CollectionSubView() { } break; case 'Backspace': { + // this._docs.forEach(doc => { + // if (!this.childDocs.concat(this.displayedSubCollectionDocs(this.Document))) + // }); + // console.log('backspace detected') undoable(() => {this._selectedDocs.forEach(d => this._docs.includes(d) && this.removeDoc(d));}, 'delete schema row'); break; } @@ -319,12 +323,8 @@ export class CollectionSchemaView extends CollectionSubView() { let modField = field.slice(); let matches; let results = new Map(); - while ((matches = idPattern.exec(field)) !== null) { - results.set(matches[0], matches[1].replace(/"/g, '')); - } - results.forEach((id, funcId) => { - modField = modField.replace(funcId, 'd' + (DocumentView.getDocViewIndex(IdToDoc(id))).toString()); - }) + while ((matches = idPattern.exec(field)) !== null) {results.set(matches[0], matches[1].replace(/"/g, '')); } + results.forEach((id, funcId) => {modField = modField.replace(funcId, 'd' + (DocumentView.getDocViewIndex(IdToDoc(id))).toString());}) return modField; } diff --git a/src/client/views/nodes/DocumentIcon.tsx b/src/client/views/nodes/DocumentIcon.tsx index 79fc06279..0b94ae4f7 100644 --- a/src/client/views/nodes/DocumentIcon.tsx +++ b/src/client/views/nodes/DocumentIcon.tsx @@ -25,19 +25,16 @@ export class DocumentIcon extends ObservableReactComponent { render() { const { view } = this._props; - const { left, top, right } = view.getBounds || { left: 0, top: 0, right: 0, bottom: 0 }; + const { left, top, right, bottom } = view.getBounds || { left: 0, top: 0, right: 0, bottom: 0 }; return (
{ this._hovered = true; })} // prettier-ignore - onPointerLeave={action(() => { this._hovered = false; })} // prettier-ignore style={{ pointerEvents: 'all', - opacity: this._hovered ? 0.3 : 1, position: 'absolute', background: SnappingManager.userBackgroundColor, - transform: `translate(${(left + right) / 2}px, ${top}px)`, + transform: `translate(${left}px, ${bottom - (bottom - top)/2}px)`, //**!** }}> {StrCast(this._props.view.Document?.title)}
}>

d{this._props.index}

-- cgit v1.2.3-70-g09d2 From c0afdafa109c377a83ebe4394d63b9fe785fe475 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Tue, 11 Jun 2024 14:33:22 -0400 Subject: added reaction for _docs --- .../collections/collectionSchema/CollectionSchemaView.tsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index bdf04f47b..033bc74d2 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -1,7 +1,7 @@ /* eslint-disable no-restricted-syntax */ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { IconButton, Popup, PopupTrigger, Size, Type } from 'browndash-components'; -import { ObservableMap, action, autorun, computed, makeObservable, observable, observe, override, runInAction } from 'mobx'; +import { IReactionDisposer, ObservableMap, action, autorun, computed, makeObservable, observable, observe, override, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../ClientUtils'; @@ -38,6 +38,7 @@ import { CollectionView } from '../CollectionView'; import { listSpec } from '../../../../fields/Schema'; import { GetEffectiveAcl } from '../../../../fields/util'; import { ContextMenuProps } from '../../ContextMenuItem'; +import { truncate } from 'lodash'; const { SCHEMA_NEW_NODE_HEIGHT } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore @@ -56,6 +57,7 @@ const defaultColumnKeys: string[] = ['title', 'type', 'author', 'author_date', ' @observer export class CollectionSchemaView extends CollectionSubView() { private _keysDisposer: any; + private _disposers: { [name: string]: IReactionDisposer } = {}; private _previewRef: HTMLDivElement | null = null; private _makeNewColumn: boolean = false; private _documentOptions: DocumentOptions = new DocumentOptions(); @@ -96,7 +98,7 @@ export class CollectionSchemaView extends CollectionSubView() { @observable _colBeingDragged: boolean = false; @observable _colKeysFiltered: boolean = false; @observable _cellTags: ObservableMap = new ObservableMap>(); - @observable _docs: Doc[] = this.childDocs; + @observable _docs: Doc[] = []; // target HTMLelement portal for showing a popup menu to edit cell values. public get MenuTarget() { @@ -186,10 +188,16 @@ export class CollectionSchemaView extends CollectionSubView() { }, true ); + this._disposers.docdata = reaction( + () => DocListCast(this.dataDoc[this.fieldKey]), + (docs) => this._docs = docs, + {fireImmediately: true} + ) } componentWillUnmount() { this._keysDisposer?.(); + Object.values(this._disposers).forEach(disposer => disposer?.()); document.removeEventListener('keydown', this.onKeyDown); } -- cgit v1.2.3-70-g09d2 From 571220cb349644efc149b8e13d000a37366db664 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 12 Jun 2024 02:50:19 -0400 Subject: fixed col drag highlight and cleaned up multi-select highlight --- .../collectionSchema/CollectionSchemaView.tsx | 14 +------- .../collections/collectionSchema/SchemaRowBox.tsx | 23 ++++++++---- .../collectionSchema/SchemaTableCell.tsx | 42 +++++++++++++++++++--- 3 files changed, 54 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 033bc74d2..25a1b4819 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -325,17 +325,6 @@ export class CollectionSchemaView extends CollectionSubView() { }); } - // parses a field from the "idToDoc(####)" format to DocumentId (d#) format for readability - cleanupComputedField = (field: string) => { - const idPattern = /idToDoc\((.*?)\)/g; - let modField = field.slice(); - let matches; - let results = new Map(); - while ((matches = idPattern.exec(field)) !== null) {results.set(matches[0], matches[1].replace(/"/g, '')); } - results.forEach((id, funcId) => {modField = modField.replace(funcId, 'd' + (DocumentView.getDocViewIndex(IdToDoc(id))).toString());}) - return modField; - } - @undoBatch removeColumn = (index: number) => { if (this.columnKeys.length === 1) return; @@ -480,7 +469,7 @@ export class CollectionSchemaView extends CollectionSubView() { const edgeStyle = i === index ? `solid 2px ${Colors.MEDIUM_BLUE}` : ''; const cellEles = [ colRef, - ...this.childDocs + ...this.docs .filter(doc => i !== this._selectedCol || !this._selectedDocs.includes(doc)) .map(doc => this._rowEles.get(doc).children[1].children[i]), ]; @@ -534,7 +523,6 @@ export class CollectionSchemaView extends CollectionSubView() { if (!shiftKey && !ctrlKey) this.clearSelection(); !this._selectedCells && (this._selectedCells = []); !shiftKey && this._selectedCells.push(doc); - this._selectedCells.forEach(d => console.log(d.title)) const index = this.rowIndex(doc); if (!this) return; diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index 98a16deea..a8affb0d9 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -87,7 +87,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { ContextMenu.Instance.displayMenu(x, y, undefined, false); } - get menuBackgroundColor(){ + @computed get menuBackgroundColor(){ if (this.Document._lockedSchemaEditing){ if (this._props.isSelected()) return '#B0D1E7' else return '#F5F5F5' @@ -95,14 +95,22 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { return '' } - get menuInfos() { + @computed get menuInfos() { const infos: Array = []; if (this.Document._lockedSchemaEditing) infos.push('lock'); if (this.Document._childrenSharedWithSchema) infos.push('star'); return infos; } - cleanupField = (field: string) => this.schemaView.cleanupComputedField(field) + @computed get isolatedSelection() { + const toReturn: [boolean, boolean] = [true, true]; + const selectedBelow: boolean = this.schemaView?._selectedDocs.includes(this.schemaView.draggedSpliceDocs.docs[this.rowIndex + 1]); + const selectedAbove: boolean = this.schemaView?._selectedDocs.includes(this.schemaView.draggedSpliceDocs.docs[this.rowIndex - 1]); + toReturn[0] = selectedAbove; + toReturn[1] = selectedBelow; + return toReturn; + } + setCursorIndex = (mouseY: number) => this.schemaView?.setRelCursorIndex(mouseY); selectedCol = () => this.schemaView._selectedCol; getFinfo = computedFn((fieldKey: string) => this.schemaView?.fieldInfos.get(fieldKey)); @@ -111,6 +119,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { selectedCells = () => this.schemaView?._selectedDocs; setColumnValues = (field: any, value: any) => this.schemaView?.setCellValues(field, value) ?? false; columnWidth = computedFn((index: number) => () => this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth); + computeRowIndex = () => this.schemaView?.rowIndex(this.Document); render() { return (
() { row && this.schemaView?.addRowRef?.(this.Document, row); this._ref = row; }}> -
- {this.menuInfos.map(icn => )} -
() { ) } /> +
+ {this.menuInfos.map(icn => )} +
{this.schemaView?.columnKeys?.map((key, index) => ( () { setColumnValues={this.setColumnValues} oneLine={BoolCast(this.schemaDoc?._singleLine)} menuTarget={this.schemaView.MenuTarget} - cleanupField={this.cleanupField} transform={() => { const ind = index === this.schemaView.columnKeys.length - 1 ? this.schemaView.columnKeys.length - 3 : index; const x = this.schemaView?.displayColumnWidths.reduce((p, c, i) => (i <= ind ? p + c : p), 0); diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 791465741..c8bd48019 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -13,7 +13,7 @@ import Select from 'react-select'; import { ClientUtils, StopEvent, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnZero } from '../../../../ClientUtils'; import { emptyFunction } from '../../../../Utils'; import { DateField } from '../../../../fields/DateField'; -import { Doc, DocListCast, Field } from '../../../../fields/Doc'; +import { Doc, DocListCast, Field, IdToDoc } from '../../../../fields/Doc'; import { RichTextField } from '../../../../fields/RichTextField'; import { ColumnType } from '../../../../fields/SchemaHeaderField'; import { BoolCast, Cast, DateCast, DocCast, FieldValue, StrCast, toList } from '../../../../fields/Types'; @@ -33,6 +33,7 @@ import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; import { CollectionSchemaView, FInfotoColType } from './CollectionSchemaView'; import './CollectionSchemaView.scss'; import { SchemaColumnHeader } from './SchemaColumnHeader'; +import { ContextMenu } from '../../ContextMenu'; export interface SchemaTableCellProps { Document: Doc; @@ -57,8 +58,8 @@ export interface SchemaTableCellProps { transform: () => Transform; autoFocus?: boolean; // whether to set focus on creation, othwerise wait for a click rootSelected?: () => boolean; - cleanupField: (field: string) => string; rowSelected: () => boolean; + isolatedSelection: [boolean, boolean]; } function selectedCell(props: SchemaTableCellProps) { @@ -137,13 +138,32 @@ export class SchemaTableCell extends ObservableReactComponent { + // const cm = ContextMenu.Instance; + // cm.clearItems(); + + + // } + + // parses a field from the "idToDoc(####)" format to DocumentId (d#) format for readability + cleanupField = (field: string) => { + const idPattern = /idToDoc\((.*?)\)/g; + let modField = field.slice(); + let matches; + let results = new Map(); + while ((matches = idPattern.exec(field)) !== null) {results.set(matches[0], matches[1].replace(/"/g, '')); } + results.forEach((id, funcId) => {modField = modField.replace(funcId, 'd' + (DocumentView.getDocViewIndex(IdToDoc(id))).toString());}) + if (!modField) modField = ''; + return modField; + } + @computed get defaultCellContent() { const { color, textDecoration, fieldProps, pointerEvents } = SchemaTableCell.renderProps(this._props); - return (
this._props.cleanupField(Field.toKeyValueString(fieldProps.Document, this._props.fieldKey, SnappingManager.MetaKey))} //TODO: feed this into parser that handles idToDoc + GetValue={() => this.cleanupField(Field.toKeyValueString(fieldProps.Document, this._props.fieldKey, SnappingManager.MetaKey))} SetValue={undoable((value: string, shiftDown?: boolean, enterKey?: boolean) => { if (shiftDown && enterKey) { this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), value); @@ -201,6 +221,15 @@ export class SchemaTableCell extends ObservableReactComponent = []; + sides[0] = selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // left + sides[1] = selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // right + sides[2] = (!this._props.isolatedSelection[0] && selectedCell(this._props)) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // top + sides[3] = (!this._props.isolatedSelection[1] && selectedCell(this._props)) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // bottom + return sides; + } + render() { return (
{this.isDefault ? '' : this.content}
-- cgit v1.2.3-70-g09d2 From 707a1a4cba9f0af9ee07b487eddf0f4ca85c8a78 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 12 Jun 2024 03:28:07 -0400 Subject: col menu icon now shows only on hover --- .../collections/collectionSchema/CollectionSchemaView.tsx | 8 ++++---- .../collections/collectionSchema/SchemaColumnHeader.tsx | 14 +++++++++++--- .../views/collections/collectionSchema/SchemaRowBox.tsx | 5 +++-- 3 files changed, 18 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 25a1b4819..affa70a62 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -209,7 +209,7 @@ export class CollectionSchemaView extends CollectionSubView() { this._docs = this._docs.filter(d => d !== doc) } - rowIndex = (doc: Doc) => this.draggedSpliceDocs.docs.indexOf(doc); + rowIndex = (doc: Doc) => this.docsWithDrag.docs.indexOf(doc); @action onKeyDown = (e: KeyboardEvent) => { @@ -581,7 +581,7 @@ export class CollectionSchemaView extends CollectionSubView() { const draggedDocs = de.complete.docDragData?.draggedDocuments; if (draggedDocs && super.onInternalDrop(e, de) && !this.sortField) { - const docs = this.draggedSpliceDocs.docs.slice(); + const docs = this.docsWithDrag.docs.slice(); this._docs = docs; this.clearSelection(); draggedDocs.forEach(doc => { @@ -1031,7 +1031,7 @@ export class CollectionSchemaView extends CollectionSubView() { return docs; } - @computed get draggedSpliceDocs() { + @computed get docsWithDrag() { const draggedDocs = this.isContentActive() ? DragManager.docsBeingDragged : []; let docs = [...this.docs]; docs = docs.filter(d => !draggedDocs.includes(d)); @@ -1058,7 +1058,7 @@ export class CollectionSchemaView extends CollectionSubView() { screenToLocal = () => this.ScreenToLocalBoxXf().translate(-this.tableWidth, 0); previewWidthFunc = () => this.previewWidth; onPassiveWheel = (e: WheelEvent) => e.stopPropagation(); - displayedDocsFunc = () => this.draggedSpliceDocs.docs; + displayedDocsFunc = () => this.docsWithDrag.docs; _oldWheel: any; render() { return ( diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index 0da186f81..0fe0033d4 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -1,6 +1,6 @@ /* eslint-disable react/no-unused-prop-types */ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, observable } from 'mobx'; +import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { returnEmptyDoclist, returnEmptyFilter, returnFalse, returnZero, setupMoveUpEvents } from '../../../../ClientUtils'; @@ -51,7 +51,7 @@ export interface SchemaColumnHeaderProps { export class SchemaColumnHeader extends ObservableReactComponent { @observable _altTitle: string | undefined = undefined; - @observable _displayKeysDropdown: boolean = false; + @observable _showMenuIcon: boolean = false; @computed get fieldKey() { return this._props.columnKeys[this._props.columnIndex]; @@ -59,6 +59,7 @@ export class SchemaColumnHeader extends ObservableReactComponent this._showMenuIcon = true; + @action handlePointerLeave = () => this._showMenuIcon = false; + + @computed get displayButton() {return this._showMenuIcon;} + render() { return (
{this.handlePointerEnter()}} + onPointerLeave={() => {this.handlePointerLeave()}} onPointerDown={this.setupDrag} ref={col => { if (col) { @@ -215,7 +223,7 @@ export class SchemaColumnHeader extends ObservableReactComponent
- {this.headerButton} + {this.displayButton ? this.headerButton : null}
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index a8affb0d9..107e29754 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -104,8 +104,9 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { @computed get isolatedSelection() { const toReturn: [boolean, boolean] = [true, true]; - const selectedBelow: boolean = this.schemaView?._selectedDocs.includes(this.schemaView.draggedSpliceDocs.docs[this.rowIndex + 1]); - const selectedAbove: boolean = this.schemaView?._selectedDocs.includes(this.schemaView.draggedSpliceDocs.docs[this.rowIndex - 1]); + const docs = this.schemaView.docsWithDrag.docs; + const selectedBelow: boolean = this.schemaView?._selectedDocs.includes(docs[this.rowIndex + 1]); + const selectedAbove: boolean = this.schemaView?._selectedDocs.includes(docs[this.rowIndex - 1]); toReturn[0] = selectedAbove; toReturn[1] = selectedBelow; return toReturn; -- cgit v1.2.3-70-g09d2 From 60a4ccfe2ab6337c064da8a303336f1872f5e9a6 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 12 Jun 2024 21:16:17 -0400 Subject: cell value parser for highlighting cells used in equation works; need to implement actual VU --- src/client/views/EditableView.tsx | 16 ++++---- .../collectionSchema/CollectionSchemaView.tsx | 48 +++++++++++++++++++--- .../collectionSchema/SchemaColumnHeader.tsx | 6 ++- .../collections/collectionSchema/SchemaRowBox.tsx | 2 + .../collectionSchema/SchemaTableCell.tsx | 5 +++ 5 files changed, 63 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index c05812e1a..f8d6596d8 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -11,6 +11,7 @@ import { FieldView, FieldViewProps } from './nodes/FieldView'; import { ObservableReactComponent } from './ObservableReactComponent'; import { OverlayView } from './OverlayView'; import { Padding } from 'browndash-components'; +import { SchemaFieldType } from './collections/collectionSchema/SchemaColumnHeader'; export interface EditableProps { /** @@ -56,7 +57,7 @@ export interface EditableProps { placeholder?: string; wrap?: string; // nowrap, pre-wrap, etc - schemaHeader?: boolean; + schemaFieldType?: SchemaFieldType; onClick?: () => void; updateAlt?: (newAlt: string) => void; updateSearch?: (value: string) => void; @@ -71,19 +72,18 @@ export interface EditableProps { export class EditableView extends ObservableReactComponent { private _ref = React.createRef(); private _inputref: HTMLInputElement | HTMLTextAreaElement | null = null; + private _disposers: { [name: string]: IReactionDisposer } = {}; _overlayDisposer?: () => void; - _editingDisposer?: IReactionDisposer; + _highlightsDisposer?: () => void; @observable _editing: boolean = false; constructor(props: EditableProps) { super(props); makeObservable(this); - this._editing = !!this._props.editing; - if (this._props.schemaHeader) this._editing = true; } componentDidMount(): void { - this._editingDisposer = reaction( + this._disposers.editing = reaction( () => this._editing, editing => { if (editing) { @@ -91,7 +91,7 @@ export class EditableView extends ObservableReactComponent { if (this._inputref?.value.startsWith('=') || this._inputref?.value.startsWith(':=')) { this._overlayDisposer?.(); this._overlayDisposer = OverlayView.Instance.addElement(, { x: 0, y: 0 }); - } + } }); } else { this._overlayDisposer?.(); @@ -114,7 +114,7 @@ export class EditableView extends ObservableReactComponent { componentWillUnmount() { this._overlayDisposer?.(); - this._editingDisposer?.(); + this._disposers.editing?.(); this._inputref?.value && this.finalizeEdit(this._inputref.value, false, true, false); } @@ -287,7 +287,7 @@ export class EditableView extends ObservableReactComponent { staticDisplay = () => { let toDisplay; const gval = this._props.GetValue()?.replace(/\n/g, '\\r\\n'); - if (this._props.schemaHeader){ + if (this._props.schemaFieldType === SchemaFieldType.Header){ toDisplay = { + const index = this.columnKeys.indexOf(fieldKey); + console.log(doc.title) + const cell = this._rowEles.get(doc).children[1].children[index]; + return cell; + } + + findCellRefs = (text: string) => { + const pattern = /(this|d(\d+))\.(\w+)/g; + interface Match { docRef: string; field: string; } + + const matches: Match[] = []; + let match: RegExpExecArray | null; + + while ((match = pattern.exec(text)) !== null) { + const docRef = match[1] === 'this' ? match[1] : match[2]; + matches.push({ docRef, field: match[3] }); + } + + const cells: Array = []; + matches.forEach((match: Match) => { + const {docRef, field} = match; + const doc = DocumentManager.Instance.DocumentViews[Number(docRef)].Document; + if (this.columnKeys.includes(field)) {cells.push(this.getCellElement(doc, field))} + }) + + console.log(cells); + + return cells; + } + + + @action addRowRef = (doc: Doc, ref: HTMLDivElement) => this._rowEles.set(doc, ref); @@ -1012,22 +1046,26 @@ export class CollectionSchemaView extends CollectionSubView() { } }; - displayedSubCollectionDocs = (doc: Doc) => { + subCollectionDocs = (doc: Doc, displayed: boolean) => { const childDocs = DocListCast(doc[Doc.LayoutFieldKey(doc)]); - const displayedCollections = childDocs.filter(d => d.type === 'collection' && d._childrenSharedWithSchema); + let collections: Array = []; + if (displayed) collections = childDocs.filter(d => d.type === 'collection' && d._childrenSharedWithSchema); + else collections = childDocs.filter(d => d.type === 'collection' && !d._childrenSharedWithSchema); let toReturn: Doc[] = [...childDocs]; - displayedCollections.forEach(d => toReturn = toReturn.concat(this.displayedSubCollectionDocs(d))); + collections.forEach(d => toReturn = toReturn.concat(this.subCollectionDocs(d, displayed))); return toReturn; } - + @computed get docs() { let docsFromChildren: Doc[] = []; + const displayedCollections = this.childDocs.filter(d => d.type === 'collection' && d._childrenSharedWithSchema); displayedCollections.forEach(d => { - let docsNotAlreadyDisplayed = this.displayedSubCollectionDocs(d).filter(dc => !this._docs.includes(dc)); + let docsNotAlreadyDisplayed = this.subCollectionDocs(d, true).filter(dc => !this._docs.includes(dc)); docsFromChildren = docsFromChildren.concat(docsNotAlreadyDisplayed); }); let docs = this._docs.concat(docsFromChildren); + return docs; } diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index 0fe0033d4..f0debaec2 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -24,6 +24,10 @@ import { FInfo } from '../../../documents/Documents'; import { ColumnType } from '../../../../fields/SchemaHeaderField'; import { IconButton, Size } from 'browndash-components'; +export enum SchemaFieldType { + Header, Cell +} + export interface SchemaColumnHeaderProps { Document: Doc; autoFocus?: boolean; @@ -131,7 +135,7 @@ export class SchemaColumnHeader extends ObservableReactComponent { if (SchemaColumnHeader.isDefaultField(this.fieldKey)) return ''; else if (this._altTitle) return this._altTitle; diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index 107e29754..f6d99b47e 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -121,6 +121,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { setColumnValues = (field: any, value: any) => this.schemaView?.setCellValues(field, value) ?? false; columnWidth = computedFn((index: number) => () => this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth); computeRowIndex = () => this.schemaView?.rowIndex(this.Document); + findCellRefs = (text: string) => this.schemaView?.findCellRefs(text); render() { return (
() {
{this.schemaView?.columnKeys?.map((key, index) => ( boolean; rowSelected: () => boolean; isolatedSelection: [boolean, boolean]; + getCellRefs: (text: string) => any; } function selectedCell(props: SchemaTableCellProps) { @@ -72,6 +73,9 @@ function selectedCell(props: SchemaTableCellProps) { @observer export class SchemaTableCell extends ObservableReactComponent { + + @observable _highlighted: boolean = false; + constructor(props: SchemaTableCellProps) { super(props); makeObservable(this); @@ -186,6 +190,7 @@ export class SchemaTableCell extends ObservableReactComponent Date: Thu, 13 Jun 2024 01:19:46 -0400 Subject: cell highlighting from equations WORKS! --- src/client/views/EditableView.tsx | 5 +++- .../collectionSchema/CollectionSchemaView.tsx | 30 ++++++++++++++++++++-- .../collections/collectionSchema/SchemaRowBox.tsx | 4 +-- .../collectionSchema/SchemaTableCell.tsx | 4 +-- 4 files changed, 36 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index f8d6596d8..14af8febb 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -61,6 +61,7 @@ export interface EditableProps { onClick?: () => void; updateAlt?: (newAlt: string) => void; updateSearch?: (value: string) => void; + highlightCells?: (text: string) => void; } /** @@ -74,7 +75,6 @@ export class EditableView extends ObservableReactComponent { private _inputref: HTMLInputElement | HTMLTextAreaElement | null = null; private _disposers: { [name: string]: IReactionDisposer } = {}; _overlayDisposer?: () => void; - _highlightsDisposer?: () => void; @observable _editing: boolean = false; constructor(props: EditableProps) { @@ -91,11 +91,13 @@ export class EditableView extends ObservableReactComponent { if (this._inputref?.value.startsWith('=') || this._inputref?.value.startsWith(':=')) { this._overlayDisposer?.(); this._overlayDisposer = OverlayView.Instance.addElement(, { x: 0, y: 0 }); + this._props.highlightCells?.(this._props.GetValue() ?? ''); } }); } else { this._overlayDisposer?.(); this._overlayDisposer = undefined; + this._props.highlightCells?.(''); } }, { fireImmediately: true } @@ -127,6 +129,7 @@ export class EditableView extends ObservableReactComponent { this._overlayDisposer = OverlayView.Instance.addElement(, { x: 0, y: 0 }); } this._props.updateSearch && this._props.updateSearch(targVal); + this._props.highlightCells?.(targVal); }; @action diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 4d959e42c..4fc89488d 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -40,6 +40,7 @@ import { GetEffectiveAcl } from '../../../../fields/util'; import { ContextMenuProps } from '../../ContextMenuItem'; import { truncate } from 'lodash'; import { DocumentManager } from '../../../util/DocumentManager'; +import { TbHemispherePlus } from 'react-icons/tb'; const { SCHEMA_NEW_NODE_HEIGHT } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore @@ -99,6 +100,8 @@ export class CollectionSchemaView extends CollectionSubView() { @observable _colBeingDragged: boolean = false; @observable _colKeysFiltered: boolean = false; @observable _cellTags: ObservableMap = new ObservableMap>(); + @observable _highlightedCells: Array = []; + @observable _cellHighlightColors: ObservableMap = new ObservableMap(); @observable _docs: Doc[] = []; // target HTMLelement portal for showing a popup menu to edit cell values. @@ -508,12 +511,35 @@ export class CollectionSchemaView extends CollectionSubView() { if (this.columnKeys.includes(field)) {cells.push(this.getCellElement(doc, field))} }) - console.log(cells); - return cells; } + removeCellHighlights = () => { + this._highlightedCells.forEach(cell => cell.style.border = ''); + this._highlightedCells = []; + } + + highlightCells = (text: string) => { + this.removeCellHighlights(); + const randNum = (): number => {return Math.floor(Math.random() * (255 - 1));} + const randomRGBColor = (): string => { + const r = randNum(); const g = randNum(); const b = randNum(); // prettier-ignore + return `rgb(${r}, ${g}, ${b})`; + } + + const cellsToHighlight = this.findCellRefs(text); + this._highlightedCells = [...cellsToHighlight]; + this._highlightedCells.forEach(cell => { + if (!this._cellHighlightColors.has(cell)) {this._cellHighlightColors.set(cell, `solid 2px ${randomRGBColor()}`)} + cell.style.border = this._cellHighlightColors.get(cell); + }); + // const cellsToRemove = []; + // this._highlightedCells.forEach(cell => !cellsToHighlight.includes(cell) && cellsToRemove.push(cell)); + // this._highlightedCells = this._highlightedCells.filter(cell => cellsToHighlight.includes(cell)); + // const cellsToAdd = cellsToHighlight.filter(cell => !this._highlightedCells.includes(cell)); + // this._highlightedCells = this._highlightedCells.concat(cellsToAdd); + } @action addRowRef = (doc: Doc, ref: HTMLDivElement) => this._rowEles.set(doc, ref); diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index f6d99b47e..4902a49ff 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -121,7 +121,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { setColumnValues = (field: any, value: any) => this.schemaView?.setCellValues(field, value) ?? false; columnWidth = computedFn((index: number) => () => this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth); computeRowIndex = () => this.schemaView?.rowIndex(this.Document); - findCellRefs = (text: string) => this.schemaView?.findCellRefs(text); + highlightCells = (text: string) => this.schemaView?.highlightCells(text); render() { return (
() {
{this.schemaView?.columnKeys?.map((key, index) => ( boolean; rowSelected: () => boolean; isolatedSelection: [boolean, boolean]; - getCellRefs: (text: string) => any; + highlightCells: (text: string) => void; } function selectedCell(props: SchemaTableCellProps) { @@ -175,6 +175,7 @@ export class SchemaTableCell extends ObservableReactComponent selectedCell(this._props) && this._props.autoFocus && r?.setIsFocused(true)} oneLine={this._props.oneLine} allowCRs={this._props.allowCRs} @@ -190,7 +191,6 @@ export class SchemaTableCell extends ObservableReactComponent Date: Fri, 14 Jun 2024 14:50:43 -0400 Subject: func parser bug where multiple references to same doc didn't parse correctly fixed --- src/client/views/EditableView.tsx | 4 +++- .../views/collections/collectionSchema/CollectionSchemaView.tsx | 5 ----- src/client/views/collections/collectionSchema/SchemaTableCell.tsx | 8 ++++---- 3 files changed, 7 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 14af8febb..f94f4be86 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -323,7 +323,9 @@ export class EditableView extends ObservableReactComponent { {this.renderEditor()}
) : ( - this.renderEditor() +
+ {this.renderEditor()} +
); } setTimeout(() => this._props.autosuggestProps?.resetValue()); diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 4fc89488d..ba2d2a764 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -534,11 +534,6 @@ export class CollectionSchemaView extends CollectionSubView() { if (!this._cellHighlightColors.has(cell)) {this._cellHighlightColors.set(cell, `solid 2px ${randomRGBColor()}`)} cell.style.border = this._cellHighlightColors.get(cell); }); - // const cellsToRemove = []; - // this._highlightedCells.forEach(cell => !cellsToHighlight.includes(cell) && cellsToRemove.push(cell)); - // this._highlightedCells = this._highlightedCells.filter(cell => cellsToHighlight.includes(cell)); - // const cellsToAdd = cellsToHighlight.filter(cell => !this._highlightedCells.includes(cell)); - // this._highlightedCells = this._highlightedCells.concat(cellsToAdd); } @action diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 50ec2f978..26dc9c3c2 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -154,10 +154,10 @@ export class SchemaTableCell extends ObservableReactComponent(); - while ((matches = idPattern.exec(field)) !== null) {results.set(matches[0], matches[1].replace(/"/g, '')); } - results.forEach((id, funcId) => {modField = modField.replace(funcId, 'd' + (DocumentView.getDocViewIndex(IdToDoc(id))).toString());}) - if (!modField) modField = ''; + let results = new Array<[id: string, func: string]>(); + while ((matches = idPattern.exec(field)) !== null) {results.push([matches[0], matches[1].replace(/"/g, '')]); } + results.forEach((idFuncPair) => {modField = modField.replace(idFuncPair[0], 'd' + (DocumentView.getDocViewIndex(IdToDoc(idFuncPair[1]))).toString());}) + if (modField.charAt(modField.length - 1) === ';') modField = modField.substring(0, modField.length - 1); return modField; } -- cgit v1.2.3-70-g09d2 From 7d4f2c1777f20c47e0f77bd519469ac16a4366b5 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Fri, 14 Jun 2024 16:46:51 -0400 Subject: background color for highlighted cells done (why did this take 2 hours ~_~) --- src/ClientUtils.ts | 20 ++++++++++++++ .../collectionSchema/CollectionSchemaView.tsx | 31 +++++++++++++++------- 2 files changed, 42 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/ClientUtils.ts b/src/ClientUtils.ts index d03ae1486..cd2b9b3a9 100644 --- a/src/ClientUtils.ts +++ b/src/ClientUtils.ts @@ -321,6 +321,26 @@ export namespace ClientUtils { return { h: h, s: s, l: l }; } + export function lightenRGB(rVal: number, gVal: number, bVal: number, percent: number): [number, number, number] { + const amount = 1 + percent/100; + const r = rVal * amount; + const g = gVal * amount; + const b = bVal * amount; + + const threshold = 255.999; + const maxVal = Math.max(r, g, b); + if (maxVal <= threshold) { + return [Math.round(r), Math.round(g), Math.round(b)]; + } + const total = r + g + b; + if (total >= 3 * threshold) { + return [Math.round(threshold), Math.round(threshold), Math.round(threshold)]; + } + const x = (3 * threshold - total) / (3 * maxVal - total); + const gray = threshold - x * maxVal; + return [Math.round(gray + x * r), Math.round(gray + x * g), Math.round(gray + x * b)]; + } + export function scrollIntoView(targetY: number, targetHgt: number, scrollTop: number, contextHgt: number, minSpacing: number, scrollHeight: number) { if (!targetHgt) return targetY; // if there's no height, then assume that if (scrollTop + contextHgt < Math.min(scrollHeight, targetY + minSpacing + targetHgt)) { diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index ba2d2a764..df160a3a4 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -4,7 +4,7 @@ import { IconButton, Popup, PopupTrigger, Size, Type } from 'browndash-component import { IReactionDisposer, ObservableMap, action, autorun, computed, makeObservable, observable, observe, override, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../ClientUtils'; +import { ClientUtils, returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../ClientUtils'; import { emptyFunction } from '../../../../Utils'; import { Doc, DocListCast, Field, FieldType, IdToDoc, NumListCast, Opt, StrListCast } from '../../../../fields/Doc'; import { AclPrivate, DocData } from '../../../../fields/DocSymbols'; @@ -101,7 +101,7 @@ export class CollectionSchemaView extends CollectionSubView() { @observable _colKeysFiltered: boolean = false; @observable _cellTags: ObservableMap = new ObservableMap>(); @observable _highlightedCells: Array = []; - @observable _cellHighlightColors: ObservableMap = new ObservableMap(); + @observable _cellHighlightColors: ObservableMap = new ObservableMap(); @observable _docs: Doc[] = []; // target HTMLelement portal for showing a popup menu to edit cell values. @@ -515,24 +515,37 @@ export class CollectionSchemaView extends CollectionSubView() { } removeCellHighlights = () => { - this._highlightedCells.forEach(cell => cell.style.border = ''); + this._highlightedCells.forEach(cell => {cell.style.border = ''; cell.style.backgroundColor = '';}); this._highlightedCells = []; } highlightCells = (text: string) => { this.removeCellHighlights(); - const randNum = (): number => {return Math.floor(Math.random() * (255 - 1));} - const randomRGBColor = (): string => { - const r = randNum(); const g = randNum(); const b = randNum(); // prettier-ignore - return `rgb(${r}, ${g}, ${b})`; + const randomRGBColor = (): string[] => { + let r; let g; let b; + do { + r = Math.floor(Math.random() * 256); + g = Math.floor(Math.random() * 256); + b = Math.floor(Math.random() * 256); + } while ((r + g + b) < 400 || (r + g + b) > 450); + + const rL = ClientUtils.lightenRGB(r, g, b, 60)[0]; + const gL = ClientUtils.lightenRGB(r, g, b, 60)[1]; + const bL = ClientUtils.lightenRGB(r, g, b, 60)[2]; + const backgroundRGB = {rL, gL, bL}; + + return new Array(`rgb(${r}, ${g}, ${b})`, `rgb(${backgroundRGB.rL}, ${backgroundRGB.gL}, ${backgroundRGB.bL})`); } const cellsToHighlight = this.findCellRefs(text); this._highlightedCells = [...cellsToHighlight]; this._highlightedCells.forEach(cell => { - if (!this._cellHighlightColors.has(cell)) {this._cellHighlightColors.set(cell, `solid 2px ${randomRGBColor()}`)} - cell.style.border = this._cellHighlightColors.get(cell); + const color = randomRGBColor(); + console.log('border: ' + color[0] + ' background: ' + color[1]) + if (!this._cellHighlightColors.has(cell)) {this._cellHighlightColors.set(cell, new Array(`solid 2px ${color[0]}`, color[1]))} + cell.style.border = this._cellHighlightColors.get(cell)[0]; + cell.style.backgroundColor = this._cellHighlightColors.get(cell)[1]; }); } -- cgit v1.2.3-70-g09d2 From 9866828b7b530b3f748509c55e3bb2c76dadce49 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Fri, 14 Jun 2024 17:02:32 -0400 Subject: background color done for real (set consistent brightness level, made background lighter) --- .../collectionSchema/CollectionSchemaView.tsx | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index df160a3a4..ac9b57414 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -524,18 +524,18 @@ export class CollectionSchemaView extends CollectionSubView() { const randomRGBColor = (): string[] => { let r; let g; let b; - do { - r = Math.floor(Math.random() * 256); - g = Math.floor(Math.random() * 256); - b = Math.floor(Math.random() * 256); - } while ((r + g + b) < 400 || (r + g + b) > 450); + const brightness = 450; + r = Math.floor(Math.random() * 256); + g = Math.floor(Math.random() * Math.min(256, brightness - r)); + b = Math.floor(brightness - r - g); - const rL = ClientUtils.lightenRGB(r, g, b, 60)[0]; - const gL = ClientUtils.lightenRGB(r, g, b, 60)[1]; - const bL = ClientUtils.lightenRGB(r, g, b, 60)[2]; - const backgroundRGB = {rL, gL, bL}; + const lightenedRGB = ClientUtils.lightenRGB(r, g, b, 65); + const rL = lightenedRGB[0]; + const gL = lightenedRGB[1]; + const bL = lightenedRGB[2]; + const bgdRGB = {rL, gL, bL}; - return new Array(`rgb(${r}, ${g}, ${b})`, `rgb(${backgroundRGB.rL}, ${backgroundRGB.gL}, ${backgroundRGB.bL})`); + return new Array(`rgb(${r}, ${g}, ${b})`, `rgb(${bgdRGB.rL}, ${bgdRGB.gL}, ${bgdRGB.bL})`); } const cellsToHighlight = this.findCellRefs(text); -- cgit v1.2.3-70-g09d2 From c472f9844ed2806f7965713cf618363210e37de1 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Sat, 15 Jun 2024 00:08:00 -0400 Subject: text highlighting works with 'this.' format --- .../collectionSchema/CollectionSchemaView.tsx | 12 ++++------ .../collectionSchema/SchemaTableCell.tsx | 28 ++++++++++++---------- 2 files changed, 19 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index ac9b57414..d75f076d2 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -523,16 +523,13 @@ export class CollectionSchemaView extends CollectionSubView() { this.removeCellHighlights(); const randomRGBColor = (): string[] => { - let r; let g; let b; const brightness = 450; - r = Math.floor(Math.random() * 256); - g = Math.floor(Math.random() * Math.min(256, brightness - r)); - b = Math.floor(brightness - r - g); + const r = Math.floor(Math.random() * 256); + const g = Math.floor(Math.random() * Math.min(256, brightness - r)); + const b = Math.floor(brightness - r - g); const lightenedRGB = ClientUtils.lightenRGB(r, g, b, 65); - const rL = lightenedRGB[0]; - const gL = lightenedRGB[1]; - const bL = lightenedRGB[2]; + const rL = lightenedRGB[0]; const gL = lightenedRGB[1]; const bL = lightenedRGB[2]; // prettier-ignore const bgdRGB = {rL, gL, bL}; return new Array(`rgb(${r}, ${g}, ${b})`, `rgb(${bgdRGB.rL}, ${bgdRGB.gL}, ${bgdRGB.bL})`); @@ -542,7 +539,6 @@ export class CollectionSchemaView extends CollectionSubView() { this._highlightedCells = [...cellsToHighlight]; this._highlightedCells.forEach(cell => { const color = randomRGBColor(); - console.log('border: ' + color[0] + ' background: ' + color[1]) if (!this._cellHighlightColors.has(cell)) {this._cellHighlightColors.set(cell, new Array(`solid 2px ${color[0]}`, color[1]))} cell.style.border = this._cellHighlightColors.get(cell)[0]; cell.style.backgroundColor = this._cellHighlightColors.get(cell)[1]; diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 26dc9c3c2..69880b280 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -81,13 +81,11 @@ export class SchemaTableCell extends ObservableReactComponent { - // const cm = ContextMenu.Instance; - // cm.clearItems(); - - // } + adjustedHighlight = (field: string) => { + const pattern = /\bthis.\b/g; + const modField = field.replace(pattern, `d${this.docIndex}.`); + this._props.highlightCells(modField); + } // parses a field from the "idToDoc(####)" format to DocumentId (d#) format for readability cleanupField = (field: string) => { @@ -158,6 +155,11 @@ export class SchemaTableCell extends ObservableReactComponent {modField = modField.replace(idFuncPair[0], 'd' + (DocumentView.getDocViewIndex(IdToDoc(idFuncPair[1]))).toString());}) if (modField.charAt(modField.length - 1) === ';') modField = modField.substring(0, modField.length - 1); + + const selfRefPattern = `d${this.docIndex}.${this._props.fieldKey}` + const selfRefRegX = RegExp(selfRefPattern, 'g'); + if (selfRefRegX.exec(modField) !== null) { return 'Invalid'} + return modField; } @@ -175,7 +177,7 @@ export class SchemaTableCell extends ObservableReactComponent selectedCell(this._props) && this._props.autoFocus && r?.setIsFocused(true)} oneLine={this._props.oneLine} allowCRs={this._props.allowCRs} -- cgit v1.2.3-70-g09d2 From 69153ed435cbbc10637563b8bb576a80f8c0693f Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Mon, 17 Jun 2024 12:07:00 -0400 Subject: schema cell editable field class started --- src/client/views/EditableView.tsx | 13 +- .../collectionSchema/SchemaCellField.tsx | 195 +++++++++++++++++++++ .../collectionSchema/SchemaTableCell.tsx | 4 +- 3 files changed, 206 insertions(+), 6 deletions(-) create mode 100644 src/client/views/collections/collectionSchema/SchemaCellField.tsx (limited to 'src') diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index f94f4be86..f5271f749 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -58,6 +58,7 @@ export interface EditableProps { wrap?: string; // nowrap, pre-wrap, etc schemaFieldType?: SchemaFieldType; + prohibitedText?: Array; onClick?: () => void; updateAlt?: (newAlt: string) => void; updateSearch?: (value: string) => void; @@ -203,8 +204,13 @@ export class EditableView extends ObservableReactComponent { } }; + // checkForInvalidText = (text: string) => { + // const regX = new RegExp(new Array(...this._props.prohibitedText), 'g') + // } + @action finalizeEdit(value: string, shiftDown: boolean, lostFocus: boolean, enterKey: boolean) { + //if (invalid) raise error if (this._props.SetValue(value, shiftDown, enterKey)) { this._editing = false; this._props.isEditingCallback?.(false); @@ -252,7 +258,7 @@ export class EditableView extends ObservableReactComponent { onChange: this._props.autosuggestProps.onChange, }} /> - ) : this._props.oneLine !== false && this._props.GetValue()?.toString().indexOf('\n') === -1 ? ( + ) : ( this._props.oneLine !== false && this._props.GetValue()?.toString().indexOf('\n') === -1 ? ( { this._inputref = r; }} // prettier-ignore @@ -284,7 +290,7 @@ export class EditableView extends ObservableReactComponent { onClick={this.stopPropagation} onPointerUp={this.stopPropagation} /> - ); + )); } staticDisplay = () => { @@ -319,8 +325,7 @@ export class EditableView extends ObservableReactComponent { if ((this._editing && gval !== undefined)) { return this._props.sizeToContent ? (
-
{gval}
- {this.renderEditor()} +
{this.renderEditor()}
) : (
diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx new file mode 100644 index 000000000..5f758683d --- /dev/null +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -0,0 +1,195 @@ +import { IReactionDisposer, action, makeObservable, observable, reaction, runInAction } from "mobx"; +import { ObservableReactComponent } from "../../ObservableReactComponent"; +import { observer } from "mobx-react"; +import { OverlayView } from "../../OverlayView"; +import { DocumentIconContainer } from "../../nodes/DocumentIcon"; +import React, { FormEvent } from "react"; +import { FieldView, FieldViewProps } from "../../nodes/FieldView"; +import { ObjectField } from "../../../../fields/ObjectField"; + +export interface SchemaCellFieldProps { + contents: any; + fieldContents?: FieldViewProps; + editing?: boolean; + oneLine?: boolean; + highlightCells?: (text: string) => void; + GetValue(): string | undefined; + SetValue(value: string, shiftDown?: boolean, enterKey?: boolean): boolean; +} + +@observer +export class SchemaCellField extends ObservableReactComponent { + + private _disposers: { [name: string]: IReactionDisposer } = {}; + private _inputref: HTMLDivElement | null = null; + _overlayDisposer?: () => void; + @observable _editing: boolean = false; + + constructor(props: SchemaCellFieldProps) { + super(props); + makeObservable(this); + } + + componentDidMount(): void { + this._disposers.editing = reaction( + () => this._editing, + editing => { + if (editing) { + setTimeout(() => { + if (this._inputref?.innerText.startsWith('=') || this._inputref?.innerText.startsWith(':=')) { + this._overlayDisposer?.(); + this._overlayDisposer = OverlayView.Instance.addElement(, { x: 0, y: 0 }); + this._props.highlightCells?.(this._props.GetValue() ?? ''); + } + }); + } else { + this._overlayDisposer?.(); + this._overlayDisposer = undefined; + this._props.highlightCells?.(''); + } + }, + { fireImmediately: true } + ); + } + + componentDidUpdate(prevProps: Readonly) { + super.componentDidUpdate(prevProps); + if (this._editing && this._props.editing === false) { + this._inputref?.innerText && this.finalizeEdit(this._inputref.innerText, false, true, false); + } else + runInAction(() => { + if (this._props.editing !== undefined) this._editing = this._props.editing; + }); + } + + componentWillUnmount(): void { + this._overlayDisposer?.(); + this._disposers.editing?.(); + this._inputref?.innerText && this.finalizeEdit(this._inputref.innerText, false, true, false); + } + + @action + setIsFocused = (value: boolean) => { + const wasFocused = this._editing; + this._editing = value; + return wasFocused !== this._editing; + }; + + onChange = (e: FormEvent) => { + const targVal = e.currentTarget.innerText; + if (!(targVal.startsWith(':=') || targVal.startsWith('='))) { + this._overlayDisposer?.(); + this._overlayDisposer = undefined; + } else if (!this._overlayDisposer) { + this._overlayDisposer = OverlayView.Instance.addElement(, { x: 0, y: 0 }); + } + this._props.highlightCells?.(targVal); + }; + + @action + onKeyDown = (e: React.KeyboardEvent) => { + if (e.nativeEvent.defaultPrevented) return; // hack .. DashFieldView grabs native events, but react ignores stoppedPropagation and preventDefault, so we need to check it here + switch (e.key) { + case 'Tab': + e.stopPropagation(); + this.finalizeEdit(e.currentTarget.value, e.shiftKey, false, false); + break; + case 'Backspace': + e.stopPropagation(); + break; + case 'Enter': + e.stopPropagation(); + if (!e.ctrlKey) { + this.finalizeEdit(e.currentTarget.value, e.shiftKey, false, true); + } + break; + case 'Escape': + e.stopPropagation(); + this._editing = false; + break; + case 'ArrowUp': case 'ArrowDown': case 'ArrowLeft': case 'ArrowRight': //prettier-ignore + e.stopPropagation(); + break; + case 'Shift': case 'Alt': case 'Meta': case 'Control': case ':': //prettier-ignore + break; + // eslint-disable-next-line no-fallthrough + default: + break; + } + }; + + + @action + onClick = (e?: React.MouseEvent) => { + if (this._props.editing !== false) { + e?.nativeEvent.stopPropagation(); + this._editing = true; + } + }; + + @action + finalizeEdit(value: string, shiftDown: boolean, lostFocus: boolean, enterKey: boolean) { + //if (invalid) raise error + if (this._props.SetValue(value, shiftDown, enterKey)) { + this._editing = false; + } else { + this._editing = false; + !lostFocus && + setTimeout( + action(() => { + this._editing = true; + }), + 0 + ); + } + } + + staticDisplay = () => { + return + { + // eslint-disable-next-line react/jsx-props-no-spreading + this._props.fieldContents ? : this.props.contents ? this._props.contents?.valueOf() : '' + } + + } + + renderEditor = () => { + return ( +
{ this._inputref = r; }} + style={{ overflow: 'auto', minHeight: `min(100%, ${(this._props.GetValue()?.split('\n').length || 1) * 15})`, minWidth: 20, }} + onBlur={e => this.finalizeEdit(this._inputref ? this._inputref.innerText : '', false, true, false)} + autoFocus + onInput={this.onChange} + onKeyDown={this.onKeyDown} + onPointerDown={e => e.stopPropagation} + onClick={e => e.stopPropagation} + onPointerUp={e => e.stopPropagation} + > +
+ ); + } + + render() { + const gval = this._props.GetValue()?.replace(/\n/g, '\\r\\n'); + if ((this._editing && gval !== undefined)) { + return
{this.renderEditor()}
; + } else return ( + this._props.contents instanceof ObjectField ? null : ( +
+ {this.staticDisplay()} +
+ ) + ); + } + +} \ No newline at end of file diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 69880b280..79f9067e2 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -34,6 +34,7 @@ import { CollectionSchemaView, FInfotoColType } from './CollectionSchemaView'; import './CollectionSchemaView.scss'; import { SchemaColumnHeader } from './SchemaColumnHeader'; import { ContextMenu } from '../../ContextMenu'; +import { SchemaCellField } from './SchemaCellField'; export interface SchemaTableCellProps { Document: Doc; @@ -176,11 +177,10 @@ export class SchemaTableCell extends ObservableReactComponent - selectedCell(this._props) && this._props.autoFocus && r?.setIsFocused(true)} oneLine={this._props.oneLine} - allowCRs={this._props.allowCRs} contents={undefined} fieldContents={fieldProps} editing={selectedCell(this._props) ? undefined : false} -- cgit v1.2.3-70-g09d2 From 50021902948840e87da1faf74f6403e25e667580 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Mon, 17 Jun 2024 14:58:18 -0400 Subject: persistent sort option added, still need UI indication; some header bugs/weirdness fixed --- src/client/views/EditableView.tsx | 10 +++- .../collectionSchema/CollectionSchemaView.tsx | 69 +++++++++++++++++----- .../collectionSchema/SchemaColumnHeader.tsx | 20 ++++++- .../collectionSchema/SchemaTableCell.tsx | 2 +- 4 files changed, 80 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index f5271f749..78977bcb8 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -239,6 +239,12 @@ export class EditableView extends ObservableReactComponent { return wasFocused !== this._editing; }; + @action + setIsEditing = (value: boolean) => { + this._editing = value; + return this._editing; + } + renderEditor() { return this._props.autosuggestProps ? ( {
{this.renderEditor()}
) : ( -
- {this.renderEditor()} -
+ this.renderEditor() ); } setTimeout(() => this._props.autosuggestProps?.resetValue()); diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index d75f076d2..c66623bda 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -41,6 +41,7 @@ import { ContextMenuProps } from '../../ContextMenuItem'; import { truncate } from 'lodash'; import { DocumentManager } from '../../../util/DocumentManager'; import { TbHemispherePlus } from 'react-icons/tb'; +import { docs_v1 } from 'googleapis'; const { SCHEMA_NEW_NODE_HEIGHT } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore @@ -400,6 +401,7 @@ export class CollectionSchemaView extends CollectionSubView() { @action dragColumn = (e: PointerEvent, index: number) => { + this.closeColumnMenu(); this._draggedColIndex = index; this._colBeingDragged = true; const dragData = new DragManager.ColumnDragData(index); @@ -584,6 +586,7 @@ export class CollectionSchemaView extends CollectionSubView() { @action selectCell = (doc: Doc, col: number, shiftKey: boolean, ctrlKey: boolean) => { + this.closeColumnMenu(); if (!shiftKey && !ctrlKey) this.clearSelection(); !this._selectedCells && (this._selectedCells = []); !shiftKey && this._selectedCells.push(doc); @@ -839,10 +842,28 @@ export class CollectionSchemaView extends CollectionSubView() { const cm = ContextMenu.Instance; cm.clearItems(); + const fieldSortedAsc = (this.sortField === this.columnKeys[index] && !this.sortDesc); + const fieldSortedDesc = (this.sortField === this.columnKeys[index] && this.sortDesc); const revealOptions = cm.findByDescription('Sort column') const sortOptions: ContextMenuProps[] = revealOptions && revealOptions && 'subitems' in revealOptions ? revealOptions.subitems : []; sortOptions.push({description: 'Sort A-Z', event: () => this.sortDocs(this._docs, this.columnKeys[index], false), icon: 'arrow-down-a-z',}); // prettier-ignore sortOptions.push({description: 'Sort Z-A', event: () => this.sortDocs(this._docs, this.columnKeys[index], true), icon: 'arrow-up-z-a'}); // prettier-ignore + sortOptions.push({ + description: 'Persistent Sort A-Z', + event: () => { + if (fieldSortedAsc){ + this.setColumnSort(undefined) + } else this.setColumnSort(this.columnKeys[index], false) + }, + icon: fieldSortedAsc ? 'lock' : 'lock-open'}); // prettier-ignore + sortOptions.push({ + description: 'Persistent Sort Z-A', + event: () => { + if (fieldSortedDesc){ + this.setColumnSort(undefined) + } else this.setColumnSort(this.columnKeys[index], true) + }, + icon: fieldSortedDesc ? 'lock' : 'lock-open'}); // prettier-ignore cm.addItem({ description: `Change field`, @@ -1100,25 +1121,45 @@ export class CollectionSchemaView extends CollectionSubView() { } @computed get docsWithDrag() { - const draggedDocs = this.isContentActive() ? DragManager.docsBeingDragged : []; - let docs = [...this.docs]; - docs = docs.filter(d => !draggedDocs.includes(d)); - docs.splice(this.rowDropIndex, 0, ...draggedDocs); + let docs = this._docs; + if (this.sortField){ + const field = StrCast(this.layoutDoc.sortField); + const desc = BoolCast(this.layoutDoc.sortDesc); // is this an ascending or descending sort + docs = this._docs.slice().sort((docA, docB) => { + // this sorts the documents based on the selected field. returning -1 for a before b, 0 for a = b, 1 for a > b + const aStr = Field.toString(docA[field] as FieldType); + const bStr = Field.toString(docB[field] as FieldType); + let out = 0; + if (aStr < bStr) out = -1; + if (aStr > bStr) out = 1; + if (desc) out *= -1; + return out; + }); + } else { + const draggedDocs = this.isContentActive() ? DragManager.docsBeingDragged : []; + docs = docs.filter(d => !draggedDocs.includes(d)); + docs.splice(this.rowDropIndex, 0, ...draggedDocs); + } + return { docs }; } @action sortDocs = (docs: Doc[], field: string, desc: boolean) => { - this._docs = docs.sort((docA, docB) => { - // this sorts the documents based on the selected field. returning -1 for a before b, 0 for a = b, 1 for a > b - const aStr = Field.toString(docA[field] as FieldType); - const bStr = Field.toString(docB[field] as FieldType); - let out = 0; - if (aStr < bStr) out = -1; - if (aStr > bStr) out = 1; - if (desc) out *= -1; - return out; - }); + const collator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'}); + this._docs = this._docs.slice().sort((docA, docB) => collator.compare(Field.toString(docA[field] as FieldType), Field.toString(docB[field] as FieldType))); + + + // this._docs = docs.sort((docA, docB) => { + // // this sorts the documents based on the selected field. returning -1 for a before b, 0 for a = b, 1 for a > b + // const aStr = Field.toString(docA[field] as FieldType); + // const bStr = Field.toString(docB[field] as FieldType); + // let out = 0; + // if (aStr < bStr) out = -1; + // if (aStr > bStr) out = 1; + // if (desc) out *= -1; + // return out; + // }); } rowHeightFunc = () => (BoolCast(this.layoutDoc._schema_singleLine) ? CollectionSchemaView._rowSingleLineHeight : CollectionSchemaView._rowHeight); diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index f0debaec2..d16cde1f8 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -54,6 +54,7 @@ export interface SchemaColumnHeaderProps { @observer export class SchemaColumnHeader extends ObservableReactComponent { + private _inputRef: EditableView | null = null; @observable _altTitle: string | undefined = undefined; @observable _showMenuIcon: boolean = false; @@ -118,14 +119,17 @@ export class SchemaColumnHeader extends ObservableReactComponent {SchemaColumnHeader.isDefaultField(this.fieldKey) && this.openKeyDropdown()}} + return
{ + SchemaColumnHeader.isDefaultField(this.fieldKey) && this.openKeyDropdown(); + this._props.schemaView.deselectAllCells(); + }} style={{ color, width: '100%', pointerEvents, }}> this._props.autoFocus && r?.setIsFocused(true)} + ref={r => {this._inputRef = r; this._props.autoFocus && r?.setIsFocused(true)}} oneLine={true} allowCRs={false} contents={undefined} @@ -215,7 +219,17 @@ export class SchemaColumnHeader extends ObservableReactComponent {this.handlePointerEnter()}} onPointerLeave={() => {this.handlePointerLeave()}} - onPointerDown={this.setupDrag} + onPointerDown={e => { + this.setupDrag(e); + setupMoveUpEvents( + this, + e, + e => {return this._inputRef?.setIsEditing(false) ?? false}, + emptyFunction, + emptyFunction, + ); + } + } ref={col => { if (col) { this._props.setColRef(this._props.columnIndex, col); diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 79f9067e2..17fff7bf1 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -177,7 +177,7 @@ export class SchemaTableCell extends ObservableReactComponent - selectedCell(this._props) && this._props.autoFocus && r?.setIsFocused(true)} oneLine={this._props.oneLine} -- cgit v1.2.3-70-g09d2 From 3b838e251d4c626c30ef9fa507e68f6839b5cfd7 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Tue, 18 Jun 2024 00:44:37 -0400 Subject: work on sort --- src/ClientUtils.ts | 2 + .../collectionSchema/CollectionSchemaView.tsx | 56 ++++++++++------------ 2 files changed, 28 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/ClientUtils.ts b/src/ClientUtils.ts index cd2b9b3a9..a72e3ffaa 100644 --- a/src/ClientUtils.ts +++ b/src/ClientUtils.ts @@ -352,6 +352,8 @@ export namespace ClientUtils { return undefined; } + + export function GetClipboardText(): string { const textArea = document.createElement('textarea'); document.body.appendChild(textArea); diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index c66623bda..b1284fe31 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -846,8 +846,8 @@ export class CollectionSchemaView extends CollectionSubView() { const fieldSortedDesc = (this.sortField === this.columnKeys[index] && this.sortDesc); const revealOptions = cm.findByDescription('Sort column') const sortOptions: ContextMenuProps[] = revealOptions && revealOptions && 'subitems' in revealOptions ? revealOptions.subitems : []; - sortOptions.push({description: 'Sort A-Z', event: () => this.sortDocs(this._docs, this.columnKeys[index], false), icon: 'arrow-down-a-z',}); // prettier-ignore - sortOptions.push({description: 'Sort Z-A', event: () => this.sortDocs(this._docs, this.columnKeys[index], true), icon: 'arrow-up-z-a'}); // prettier-ignore + sortOptions.push({description: 'Sort A-Z', event: () => this._docs = this.sortDocs(this.columnKeys[index], false), icon: 'arrow-down-a-z',}); // prettier-ignore + sortOptions.push({description: 'Sort Z-A', event: () => this._docs = this.sortDocs(this.columnKeys[index], true), icon: 'arrow-up-z-a'}); // prettier-ignore sortOptions.push({ description: 'Persistent Sort A-Z', event: () => { @@ -1119,22 +1119,36 @@ export class CollectionSchemaView extends CollectionSubView() { return docs; } + + @action + sortDocs = (field: string, desc: boolean) => { + console.log('called') + const numbers: Doc[] = this.docs.filter(doc => !isNaN(Number(Field.toString(doc[field] as FieldType)))); + const strings = this.docs.filter(doc => !numbers.includes(doc)); + + const sortedNums = numbers.sort((numOne, numTwo) => { + const numA = Number(Field.toString(numOne[field] as FieldType)); + const numB = Number(Field.toString(numTwo[field] as FieldType)); + return desc? numA - numB : numB - numA; + }); + + const collator = new Intl.Collator(undefined, {sensitivity: 'base'}); + let sortedStrings; + if (!desc) {sortedStrings = strings.slice().sort((docA, docB) => collator.compare(Field.toString(docA[field] as FieldType), Field.toString(docB[field] as FieldType))); + } else sortedStrings = strings.slice().sort((docB, docA) => collator.compare(Field.toString(docA[field] as FieldType), Field.toString(docB[field] as FieldType))); + + const sortedDocs = desc ? sortedNums.concat(sortedStrings) : sortedStrings.concat(sortedNums); + return sortedDocs; + } @computed get docsWithDrag() { let docs = this._docs; + console.log('docrender called') if (this.sortField){ + console.log(true) const field = StrCast(this.layoutDoc.sortField); const desc = BoolCast(this.layoutDoc.sortDesc); // is this an ascending or descending sort - docs = this._docs.slice().sort((docA, docB) => { - // this sorts the documents based on the selected field. returning -1 for a before b, 0 for a = b, 1 for a > b - const aStr = Field.toString(docA[field] as FieldType); - const bStr = Field.toString(docB[field] as FieldType); - let out = 0; - if (aStr < bStr) out = -1; - if (aStr > bStr) out = 1; - if (desc) out *= -1; - return out; - }); + docs = this.sortDocs(field, desc); } else { const draggedDocs = this.isContentActive() ? DragManager.docsBeingDragged : []; docs = docs.filter(d => !draggedDocs.includes(d)); @@ -1144,24 +1158,6 @@ export class CollectionSchemaView extends CollectionSubView() { return { docs }; } - @action - sortDocs = (docs: Doc[], field: string, desc: boolean) => { - const collator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'}); - this._docs = this._docs.slice().sort((docA, docB) => collator.compare(Field.toString(docA[field] as FieldType), Field.toString(docB[field] as FieldType))); - - - // this._docs = docs.sort((docA, docB) => { - // // this sorts the documents based on the selected field. returning -1 for a before b, 0 for a = b, 1 for a > b - // const aStr = Field.toString(docA[field] as FieldType); - // const bStr = Field.toString(docB[field] as FieldType); - // let out = 0; - // if (aStr < bStr) out = -1; - // if (aStr > bStr) out = 1; - // if (desc) out *= -1; - // return out; - // }); - } - rowHeightFunc = () => (BoolCast(this.layoutDoc._schema_singleLine) ? CollectionSchemaView._rowSingleLineHeight : CollectionSchemaView._rowHeight); isContentActive = () => this._props.isSelected() || this._props.isContentActive(); screenToLocal = () => this.ScreenToLocalBoxXf().translate(-this.tableWidth, 0); -- cgit v1.2.3-70-g09d2 From eaf5c682662cfac5dd05f776635a347547b4d500 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Tue, 18 Jun 2024 14:24:59 -0400 Subject: colsort persistsent + one-shot hightlight --- .../collectionSchema/CollectionSchemaView.tsx | 101 +++++++++++++++++---- 1 file changed, 83 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index b1284fe31..d8f69b26a 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -104,7 +104,7 @@ export class CollectionSchemaView extends CollectionSubView() { @observable _highlightedCells: Array = []; @observable _cellHighlightColors: ObservableMap = new ObservableMap(); @observable _docs: Doc[] = []; - + // target HTMLelement portal for showing a popup menu to edit cell values. public get MenuTarget() { return this._menuTarget.current; @@ -198,6 +198,11 @@ export class CollectionSchemaView extends CollectionSubView() { (docs) => this._docs = docs, {fireImmediately: true} ) + this._disposers.sortHighlight = reaction( + () => [this.sortField, this._docs], + () => {setTimeout(() => this.highlightSortedColumn(), 5)}, + {fireImmediately: true} + ) } componentWillUnmount() { @@ -285,6 +290,7 @@ export class CollectionSchemaView extends CollectionSubView() { break; } case 'P': { + this.highlightSortedColumn(); break; } default: @@ -475,8 +481,8 @@ export class CollectionSchemaView extends CollectionSubView() { const edgeStyle = i === index ? `solid 2px ${Colors.MEDIUM_BLUE}` : ''; const cellEles = [ colRef, - ...this.docs - .filter(doc => i !== this._selectedCol || !this._selectedDocs.includes(doc)) + ...this.docsWithDrag.docs + .filter(doc => i !== this._selectedCol || !this._selectedDocs.includes(doc) || this.columnKeys.indexOf(this.sortField)) .map(doc => this._rowEles.get(doc).children[1].children[i]), ]; cellEles[0].style.borderTop = edgeStyle; @@ -487,6 +493,43 @@ export class CollectionSchemaView extends CollectionSubView() { cellEles.slice(-1)[0].style.borderBottom = edgeStyle; }); + highlightSortedColumn = (field?: string, descending?: boolean) => { + console.log('field: ' + field + ' desc: ' + descending); + let index = -1; + let highlightColors: string[] = []; + if (field || this.sortField){ + index = this.columnKeys.indexOf(field || this.sortField); + //console.log(index) + const rowCount: number = this._rowEles.size + 1; + const increment: number = 100/rowCount; + for (let i = 0; i < rowCount; ++i){ + const adjColor = ClientUtils.lightenRGB(16, 66, 230, increment * i); + highlightColors.push(`solid 2px rgb(${adjColor[0]}, ${adjColor[1]}, ${adjColor[2]})`); + } + } + + this._colEles.forEach((colRef, i) => { + const highlight: boolean = i === index; + const desc: boolean = descending || this.sortDesc; + //console.log(desc) + const cellEles = [ + colRef, + ...this.docsWithDrag.docs + .filter(doc => i !== this._selectedCol || !this._selectedDocs.includes(doc)) + .map(doc => this._rowEles.get(doc).children[1].children[i]), + ]; + const cellCount = cellEles.length; + for (let ele = 0; ele < cellCount; ++ele){ + const style = highlight ? desc ? `${highlightColors[cellCount - 1 - ele]}` : `${highlightColors[ele]}` : ''; + cellEles[ele].style.borderLeft = style; + cellEles[ele].style.borderRight = style; + } + cellEles[0].style.borderTop = highlight ? desc ? `${highlightColors[cellCount - 1]}` : `${highlightColors[0]}` : ''; + cellEles[cellCount - 1].style.borderBottom = highlight ? desc ? `${highlightColors[0]}` : `${highlightColors[cellCount - 1]}` : ''; + }); + + } + getCellElement = (doc: Doc, fieldKey: string) => { const index = this.columnKeys.indexOf(fieldKey); console.log(doc.title) @@ -545,6 +588,7 @@ export class CollectionSchemaView extends CollectionSubView() { cell.style.border = this._cellHighlightColors.get(cell)[0]; cell.style.backgroundColor = this._cellHighlightColors.get(cell)[1]; }); + } @action @@ -577,7 +621,7 @@ export class CollectionSchemaView extends CollectionSubView() { const startRow = Math.min(lastSelectedRow, index); const endRow = Math.max(lastSelectedRow, index); for (let i = startRow; i <= endRow; i++) { - const currDoc = this.docs[i]; + const currDoc = this.docsWithDrag.docs[i]; if (!this._selectedDocs.includes(currDoc)) { this.selectCell(currDoc, this._selectedCol, false, true); } @@ -846,22 +890,46 @@ export class CollectionSchemaView extends CollectionSubView() { const fieldSortedDesc = (this.sortField === this.columnKeys[index] && this.sortDesc); const revealOptions = cm.findByDescription('Sort column') const sortOptions: ContextMenuProps[] = revealOptions && revealOptions && 'subitems' in revealOptions ? revealOptions.subitems : []; - sortOptions.push({description: 'Sort A-Z', event: () => this._docs = this.sortDocs(this.columnKeys[index], false), icon: 'arrow-down-a-z',}); // prettier-ignore - sortOptions.push({description: 'Sort Z-A', event: () => this._docs = this.sortDocs(this.columnKeys[index], true), icon: 'arrow-up-z-a'}); // prettier-ignore + sortOptions.push({ + description: 'Sort A-Z', + event: () => { + this.setColumnSort(undefined); + const field = this.columnKeys[index]; + this._docs = this.sortDocs(field, false); + setTimeout(() => this.highlightSortedColumn(field, false), 20); + setTimeout(() => this.highlightSortedColumn(), 500); + }, + icon: 'arrow-down-a-z',}); + sortOptions.push({ + description: 'Sort Z-A', + event: () => { + this.setColumnSort(undefined); + const field = this.columnKeys[index]; + this._docs = this.sortDocs(field, true); + setTimeout(() => this.highlightSortedColumn(field, true), 20); + setTimeout(() => this.highlightSortedColumn(), 500); + }, + icon: 'arrow-up-z-a'}); sortOptions.push({ description: 'Persistent Sort A-Z', event: () => { if (fieldSortedAsc){ - this.setColumnSort(undefined) - } else this.setColumnSort(this.columnKeys[index], false) + this.setColumnSort(undefined); + } else { + this.sortDocs(this.columnKeys[index], false); + this.setColumnSort(this.columnKeys[index], false); + } }, icon: fieldSortedAsc ? 'lock' : 'lock-open'}); // prettier-ignore sortOptions.push({ description: 'Persistent Sort Z-A', event: () => { if (fieldSortedDesc){ - this.setColumnSort(undefined) - } else this.setColumnSort(this.columnKeys[index], true) + this.setColumnSort(undefined); + } else { + this.sortDocs(this.columnKeys[index], true); + this.setColumnSort(this.columnKeys[index], true); + } }, icon: fieldSortedDesc ? 'lock' : 'lock-open'}); // prettier-ignore @@ -1120,11 +1188,9 @@ export class CollectionSchemaView extends CollectionSubView() { return docs; } - @action - sortDocs = (field: string, desc: boolean) => { - console.log('called') - const numbers: Doc[] = this.docs.filter(doc => !isNaN(Number(Field.toString(doc[field] as FieldType)))); - const strings = this.docs.filter(doc => !numbers.includes(doc)); + sortDocs = (field: string, desc: boolean, persistent?: boolean) => { + const numbers: Doc[] = this._docs.filter(doc => !isNaN(Number(Field.toString(doc[field] as FieldType)))); + const strings = this._docs.filter(doc => !numbers.includes(doc)); const sortedNums = numbers.sort((numOne, numTwo) => { const numA = Number(Field.toString(numOne[field] as FieldType)); @@ -1138,17 +1204,16 @@ export class CollectionSchemaView extends CollectionSubView() { } else sortedStrings = strings.slice().sort((docB, docA) => collator.compare(Field.toString(docA[field] as FieldType), Field.toString(docB[field] as FieldType))); const sortedDocs = desc ? sortedNums.concat(sortedStrings) : sortedStrings.concat(sortedNums); + if (!persistent) this._docs = sortedDocs; return sortedDocs; } @computed get docsWithDrag() { let docs = this._docs; - console.log('docrender called') if (this.sortField){ - console.log(true) const field = StrCast(this.layoutDoc.sortField); const desc = BoolCast(this.layoutDoc.sortDesc); // is this an ascending or descending sort - docs = this.sortDocs(field, desc); + docs = this.sortDocs(field, desc, true); } else { const draggedDocs = this.isContentActive() ? DragManager.docsBeingDragged : []; docs = docs.filter(d => !draggedDocs.includes(d)); -- cgit v1.2.3-70-g09d2 From 92a9995f7de05df8187a43a38837e38dd60408bf Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 19 Jun 2024 03:05:45 -0400 Subject: ugh --- .../collectionSchema/CollectionSchemaView.tsx | 34 +++++++++++++--------- 1 file changed, 20 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index d8f69b26a..966552cd2 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -199,7 +199,7 @@ export class CollectionSchemaView extends CollectionSubView() { {fireImmediately: true} ) this._disposers.sortHighlight = reaction( - () => [this.sortField, this._docs], + () => [this.sortField, this._docs, this._selectedDocs, this._highlightedCells], () => {setTimeout(() => this.highlightSortedColumn(), 5)}, {fireImmediately: true} ) @@ -401,8 +401,6 @@ export class CollectionSchemaView extends CollectionSubView() { const currWidths = this.storedColumnWidths.slice(); currWidths.splice(toIndex, 0, currWidths.splice(fromIndex, 1)[0]); this.layoutDoc.schema_columnWidths = new List(currWidths); - - this._draggedColIndex = toIndex; }; @action @@ -479,27 +477,28 @@ export class CollectionSchemaView extends CollectionSubView() { highlightDraggedColumn = (index: number) => this._colEles.forEach((colRef, i) => { const edgeStyle = i === index ? `solid 2px ${Colors.MEDIUM_BLUE}` : ''; + const sorted = i === this.columnKeys.indexOf(this.sortField); + console.log(sorted) const cellEles = [ colRef, ...this.docsWithDrag.docs - .filter(doc => i !== this._selectedCol || !this._selectedDocs.includes(doc) || this.columnKeys.indexOf(this.sortField)) + .filter(doc => (i !== this._selectedCol || !this._selectedDocs.includes(doc)) && !sorted) .map(doc => this._rowEles.get(doc).children[1].children[i]), ]; - cellEles[0].style.borderTop = edgeStyle; + !sorted && (cellEles[0].style.borderTop = edgeStyle); cellEles.forEach(ele => { + if (ele === cellEles[0] && sorted) return; ele.style.borderLeft = edgeStyle; ele.style.borderRight = edgeStyle; }); - cellEles.slice(-1)[0].style.borderBottom = edgeStyle; + !sorted && (cellEles.slice(-1)[0].style.borderBottom = edgeStyle); }); highlightSortedColumn = (field?: string, descending?: boolean) => { - console.log('field: ' + field + ' desc: ' + descending); let index = -1; let highlightColors: string[] = []; if (field || this.sortField){ index = this.columnKeys.indexOf(field || this.sortField); - //console.log(index) const rowCount: number = this._rowEles.size + 1; const increment: number = 100/rowCount; for (let i = 0; i < rowCount; ++i){ @@ -511,7 +510,6 @@ export class CollectionSchemaView extends CollectionSubView() { this._colEles.forEach((colRef, i) => { const highlight: boolean = i === index; const desc: boolean = descending || this.sortDesc; - //console.log(desc) const cellEles = [ colRef, ...this.docsWithDrag.docs @@ -546,7 +544,7 @@ export class CollectionSchemaView extends CollectionSubView() { while ((match = pattern.exec(text)) !== null) { const docRef = match[1] === 'this' ? match[1] : match[2]; - matches.push({ docRef, field: match[3] }); + matches.push({ docRef, field: match[3] }); } const cells: Array = []; @@ -674,7 +672,9 @@ export class CollectionSchemaView extends CollectionSubView() { e.stopPropagation(); this._colEles.forEach((colRef, i) => { - // style for menu cell + const sorted = i === this.columnKeys.indexOf(this.sortField); + if (sorted) return; + colRef.style.borderLeft = ''; colRef.style.borderRight = ''; colRef.style.borderTop = ''; @@ -1161,7 +1161,8 @@ export class CollectionSchemaView extends CollectionSubView() { const newIndex = this.findColDropIndex(e.clientX); if (newIndex !== this._draggedColIndex) this.moveColumn(this._draggedColIndex, newIndex ?? this._draggedColIndex); this._draggedColIndex = newIndex || this._draggedColIndex; - this.highlightDraggedColumn(newIndex ?? this._draggedColIndex); + this.highlightSortedColumn(); //TODO: Make this more efficient + !(this.sortField && this._draggedColIndex === this.columnKeys.indexOf(this.sortField)) && this.highlightDraggedColumn(newIndex ?? this._draggedColIndex); } }; @@ -1189,8 +1190,13 @@ export class CollectionSchemaView extends CollectionSubView() { } sortDocs = (field: string, desc: boolean, persistent?: boolean) => { - const numbers: Doc[] = this._docs.filter(doc => !isNaN(Number(Field.toString(doc[field] as FieldType)))); - const strings = this._docs.filter(doc => !numbers.includes(doc)); + const numbers: Doc[] = []; + const strings: Doc[] = []; + + this._docs.forEach(doc => { + if (!isNaN(Number(Field.toString(doc[field] as FieldType)))) numbers.push(doc); + else strings.push(doc); + }); const sortedNums = numbers.sort((numOne, numTwo) => { const numA = Number(Field.toString(numOne[field] as FieldType)); -- cgit v1.2.3-70-g09d2 From 5b81abbba40b8ec3d6fc32a93fa46954139081a5 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 19 Jun 2024 04:50:29 -0400 Subject: it's not pretty but it works --- .../collectionSchema/CollectionSchemaView.tsx | 31 ++++++++++++++++------ 1 file changed, 23 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 966552cd2..c115fd34b 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -104,6 +104,7 @@ export class CollectionSchemaView extends CollectionSubView() { @observable _highlightedCells: Array = []; @observable _cellHighlightColors: ObservableMap = new ObservableMap(); @observable _docs: Doc[] = []; + @observable _pauseSortHighlights: boolean = false; // target HTMLelement portal for showing a popup menu to edit cell values. public get MenuTarget() { @@ -200,7 +201,7 @@ export class CollectionSchemaView extends CollectionSubView() { ) this._disposers.sortHighlight = reaction( () => [this.sortField, this._docs, this._selectedDocs, this._highlightedCells], - () => {setTimeout(() => this.highlightSortedColumn(), 5)}, + () => {this.sortField && setTimeout(() => this.highlightSortedColumn(), 5)}, {fireImmediately: true} ) } @@ -497,9 +498,9 @@ export class CollectionSchemaView extends CollectionSubView() { highlightSortedColumn = (field?: string, descending?: boolean) => { let index = -1; let highlightColors: string[] = []; + const rowCount: number = this._rowEles.size + 1; if (field || this.sortField){ index = this.columnKeys.indexOf(field || this.sortField); - const rowCount: number = this._rowEles.size + 1; const increment: number = 100/rowCount; for (let i = 0; i < rowCount; ++i){ const adjColor = ClientUtils.lightenRGB(16, 66, 230, increment * i); @@ -513,7 +514,7 @@ export class CollectionSchemaView extends CollectionSubView() { const cellEles = [ colRef, ...this.docsWithDrag.docs - .filter(doc => i !== this._selectedCol || !this._selectedDocs.includes(doc)) + .filter(doc => (i !== this._selectedCol || !this._selectedDocs.includes(doc))) .map(doc => this._rowEles.get(doc).children[1].children[i]), ]; const cellCount = cellEles.length; @@ -523,7 +524,7 @@ export class CollectionSchemaView extends CollectionSubView() { cellEles[ele].style.borderRight = style; } cellEles[0].style.borderTop = highlight ? desc ? `${highlightColors[cellCount - 1]}` : `${highlightColors[0]}` : ''; - cellEles[cellCount - 1].style.borderBottom = highlight ? desc ? `${highlightColors[0]}` : `${highlightColors[cellCount - 1]}` : ''; + if (!(cellCount < rowCount)) cellEles[cellCount - 1].style.borderBottom = highlight ? desc ? `${highlightColors[0]}` : `${highlightColors[cellCount - 1]}` : ''; }); } @@ -896,8 +897,14 @@ export class CollectionSchemaView extends CollectionSubView() { this.setColumnSort(undefined); const field = this.columnKeys[index]; this._docs = this.sortDocs(field, false); - setTimeout(() => this.highlightSortedColumn(field, false), 20); - setTimeout(() => this.highlightSortedColumn(), 500); + this._pauseSortHighlights = true; + setTimeout(() => { + this.highlightSortedColumn(field, false); + setTimeout(() => { + this._pauseSortHighlights = false; + this.highlightSortedColumn(); + }, 480); + }, 20); }, icon: 'arrow-down-a-z',}); sortOptions.push({ @@ -906,8 +913,14 @@ export class CollectionSchemaView extends CollectionSubView() { this.setColumnSort(undefined); const field = this.columnKeys[index]; this._docs = this.sortDocs(field, true); - setTimeout(() => this.highlightSortedColumn(field, true), 20); - setTimeout(() => this.highlightSortedColumn(), 500); + this._pauseSortHighlights = true; + setTimeout(() => { + this.highlightSortedColumn(field, true); + setTimeout(() => { + this._pauseSortHighlights = false; + this.highlightSortedColumn(); + }, 480); + }, 20); }, icon: 'arrow-up-z-a'}); sortOptions.push({ @@ -915,6 +928,7 @@ export class CollectionSchemaView extends CollectionSubView() { event: () => { if (fieldSortedAsc){ this.setColumnSort(undefined); + this.highlightSortedColumn(); } else { this.sortDocs(this.columnKeys[index], false); this.setColumnSort(this.columnKeys[index], false); @@ -926,6 +940,7 @@ export class CollectionSchemaView extends CollectionSubView() { event: () => { if (fieldSortedDesc){ this.setColumnSort(undefined); + this.highlightSortedColumn(); } else { this.sortDocs(this.columnKeys[index], true); this.setColumnSort(this.columnKeys[index], true); -- cgit v1.2.3-70-g09d2 From b04015291de1d785ad54c0fad1f66903fb055bf4 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 19 Jun 2024 04:52:26 -0400 Subject: removed unecessary field --- .../collections/collectionSchema/CollectionSchemaView.tsx | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index c115fd34b..1d9245206 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -104,7 +104,6 @@ export class CollectionSchemaView extends CollectionSubView() { @observable _highlightedCells: Array = []; @observable _cellHighlightColors: ObservableMap = new ObservableMap(); @observable _docs: Doc[] = []; - @observable _pauseSortHighlights: boolean = false; // target HTMLelement portal for showing a popup menu to edit cell values. public get MenuTarget() { @@ -897,13 +896,9 @@ export class CollectionSchemaView extends CollectionSubView() { this.setColumnSort(undefined); const field = this.columnKeys[index]; this._docs = this.sortDocs(field, false); - this._pauseSortHighlights = true; setTimeout(() => { this.highlightSortedColumn(field, false); - setTimeout(() => { - this._pauseSortHighlights = false; - this.highlightSortedColumn(); - }, 480); + setTimeout(() => this.highlightSortedColumn(), 480); }, 20); }, icon: 'arrow-down-a-z',}); @@ -913,13 +908,9 @@ export class CollectionSchemaView extends CollectionSubView() { this.setColumnSort(undefined); const field = this.columnKeys[index]; this._docs = this.sortDocs(field, true); - this._pauseSortHighlights = true; setTimeout(() => { this.highlightSortedColumn(field, true); - setTimeout(() => { - this._pauseSortHighlights = false; - this.highlightSortedColumn(); - }, 480); + setTimeout(() => this.highlightSortedColumn(), 480); }, 20); }, icon: 'arrow-up-z-a'}); -- cgit v1.2.3-70-g09d2 From d207cf565968167c59b16baf6ca5ce2543c680ea Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Thu, 20 Jun 2024 01:57:07 -0400 Subject: cursor position consistency for schema cell field --- .../collectionSchema/CollectionSchemaView.tsx | 4 +- .../collectionSchema/SchemaCellField.tsx | 86 ++++++++++++++++++---- .../collectionSchema/SchemaTableCell.tsx | 3 +- 3 files changed, 74 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 1d9245206..c287b7d44 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -478,7 +478,6 @@ export class CollectionSchemaView extends CollectionSubView() { this._colEles.forEach((colRef, i) => { const edgeStyle = i === index ? `solid 2px ${Colors.MEDIUM_BLUE}` : ''; const sorted = i === this.columnKeys.indexOf(this.sortField); - console.log(sorted) const cellEles = [ colRef, ...this.docsWithDrag.docs @@ -497,7 +496,7 @@ export class CollectionSchemaView extends CollectionSubView() { highlightSortedColumn = (field?: string, descending?: boolean) => { let index = -1; let highlightColors: string[] = []; - const rowCount: number = this._rowEles.size + 1; + const rowCount: number = this._docs.length + 1; if (field || this.sortField){ index = this.columnKeys.indexOf(field || this.sortField); const increment: number = 100/rowCount; @@ -530,7 +529,6 @@ export class CollectionSchemaView extends CollectionSubView() { getCellElement = (doc: Doc, fieldKey: string) => { const index = this.columnKeys.indexOf(fieldKey); - console.log(doc.title) const cell = this._rowEles.get(doc).children[1].children[index]; return cell; } diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index 5f758683d..3af3b1d61 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -22,8 +22,10 @@ export class SchemaCellField extends ObservableReactComponent void; @observable _editing: boolean = false; + @observable _displayedContent = ''; constructor(props: SchemaCellFieldProps) { super(props); @@ -50,12 +52,14 @@ export class SchemaCellField extends ObservableReactComponent) { super.componentDidUpdate(prevProps); if (this._editing && this._props.editing === false) { - this._inputref?.innerText && this.finalizeEdit(this._inputref.innerText, false, true, false); + this.finalizeEdit(false, true, false); } else runInAction(() => { if (this._props.editing !== undefined) this._editing = this._props.editing; @@ -65,9 +69,14 @@ export class SchemaCellField extends ObservableReactComponent { + this._displayedContent = content; + }; + @action setIsFocused = (value: boolean) => { const wasFocused = this._editing; @@ -75,7 +84,52 @@ export class SchemaCellField extends ObservableReactComponent) => { + get cursorPosition() { + const selection = window.getSelection(); + if (!selection || selection.rangeCount === 0 || !this._inputref) return null; + + const range = selection.getRangeAt(0); + const adjRange = range.cloneRange(); + + adjRange.selectNodeContents(this._inputref); + adjRange.setEnd(range.startContainer, range.startOffset); + + return adjRange.toString().length; + } + + restoreCursorPosition = (position: number | null) => { + const selection = window.getSelection(); + if (!selection || position === null || !this._inputref) return; + + const range = document.createRange(); + range.setStart(this._inputref, 0); + range.collapse(true); + + let currentPos = 0; + const setRange = (nodes: NodeList) => { + for (let i = 0; i < nodes.length; ++i) { + const node = nodes[i]; + + if (node.nodeType === Node.TEXT_NODE) { + if (!node.textContent) return; + const nextPos = currentPos + node.textContent.length; + if (position <= nextPos) { + range.setStart(node, position - currentPos); + range.collapse(true); + selection.removeAllRanges(); + selection.addRange(range); + return true; + } + currentPos = nextPos; + + } else if ((node.nodeType === Node.ELEMENT_NODE) && (setRange(node.childNodes))) return true; + } + return false; + } + }; + + onChange = (e: FormEvent) => { + const cursorPos = this.cursorPosition; const targVal = e.currentTarget.innerText; if (!(targVal.startsWith(':=') || targVal.startsWith('='))) { this._overlayDisposer?.(); @@ -83,6 +137,9 @@ export class SchemaCellField extends ObservableReactComponent, { x: 0, y: 0 }); } + this._content = targVal; + this.setContent(targVal); + setTimeout(() => this.restoreCursorPosition(cursorPos), 0); this._props.highlightCells?.(targVal); }; @@ -92,7 +149,7 @@ export class SchemaCellField extends ObservableReactComponent : this.props.contents ? this._props.contents?.valueOf() : '' } - } + }; renderEditor = () => { return ( -
{ this._inputref = r; }} style={{ overflow: 'auto', minHeight: `min(100%, ${(this._props.GetValue()?.split('\n').length || 1) * 15})`, minWidth: 20, }} - onBlur={e => this.finalizeEdit(this._inputref ? this._inputref.innerText : '', false, true, false)} + onBlur={e => this.finalizeEdit(false, true, false)} autoFocus onInput={this.onChange} onKeyDown={this.onKeyDown} onPointerDown={e => e.stopPropagation} onClick={e => e.stopPropagation} onPointerUp={e => e.stopPropagation} + dangerouslySetInnerHTML={{ __html: `${this._displayedContent}` }} >
); - } + }; render() { const gval = this._props.GetValue()?.replace(/\n/g, '\\r\\n'); if ((this._editing && gval !== undefined)) { - return
{this.renderEditor()}
; + return
{this.renderEditor()}
; } else return ( this._props.contents instanceof ObjectField ? null : (
- selectedCell(this._props) && this._props.autoFocus && r?.setIsFocused(true)} oneLine={this._props.oneLine} @@ -251,7 +251,6 @@ export class SchemaTableCell extends ObservableReactComponent Date: Thu, 20 Jun 2024 14:33:28 -0400 Subject: some progress on eq text highlighting --- .../collectionSchema/CollectionSchemaView.scss | 5 +++ .../collectionSchema/CollectionSchemaView.tsx | 4 ++- .../collectionSchema/SchemaCellField.tsx | 37 +++++++++++++++++----- .../collections/collectionSchema/SchemaRowBox.tsx | 6 ++++ .../collectionSchema/SchemaTableCell.tsx | 6 +++- 5 files changed, 48 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss index d1f1e3a13..6b53eb1cc 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss @@ -313,3 +313,8 @@ } } +.schemaField-editing { + outline: none; +} + + diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index c287b7d44..5c8a84163 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -533,7 +533,7 @@ export class CollectionSchemaView extends CollectionSubView() { return cell; } - findCellRefs = (text: string) => { + findCellRefs = (text: string, retRawMatches?: boolean) => { const pattern = /(this|d(\d+))\.(\w+)/g; interface Match { docRef: string; field: string; } @@ -545,6 +545,8 @@ export class CollectionSchemaView extends CollectionSubView() { matches.push({ docRef, field: match[3] }); } + if (retRawMatches) return matches; + const cells: Array = []; matches.forEach((match: Match) => { const {docRef, field} = match; diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index 3af3b1d61..4ba8c8469 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -15,6 +15,7 @@ export interface SchemaCellFieldProps { highlightCells?: (text: string) => void; GetValue(): string | undefined; SetValue(value: string, shiftDown?: boolean, enterKey?: boolean): boolean; + func: (text: string, raw: boolean) => HTMLDivElement[] | []; } @observer @@ -72,10 +73,25 @@ export class SchemaCellField extends ObservableReactComponent { + const matches = this._props.func(content, true); + const cells = this._props.func(content, false); + let chunkedText = content; + let matchNum = 0; + matches.forEach((docRef, field) => { + console.log('cell: ' + cells[matchNum] + ' border: ' + cells[matchNum].style.borderTop) + chunkedText = chunkedText.replace(`d5.type`, `d5.type`); + ++matchNum; + }) + return chunkedText; + } + @action setContent = (content: string) => { - this._displayedContent = content; - }; + console.log(this.chunkContent(content)); + this._displayedContent = this.chunkContent(content); + console.log('displayed: ' + this._displayedContent); + } @action setIsFocused = (value: boolean) => { @@ -126,10 +142,13 @@ export class SchemaCellField extends ObservableReactComponent) => { const cursorPos = this.cursorPosition; + const prevVal = this._content; const targVal = e.currentTarget.innerText; if (!(targVal.startsWith(':=') || targVal.startsWith('='))) { this._overlayDisposer?.(); @@ -138,8 +157,10 @@ export class SchemaCellField extends ObservableReactComponent, { x: 0, y: 0 }); } this._content = targVal; - this.setContent(targVal); - setTimeout(() => this.restoreCursorPosition(cursorPos), 0); + if (this._props.func(targVal, true).length > this._props.func(prevVal, true).length) { + this.setContent(targVal); + setTimeout(() => this.restoreCursorPosition(cursorPos), 0); + } this._props.highlightCells?.(targVal); }; @@ -208,15 +229,15 @@ export class SchemaCellField extends ObservableReactComponent : this.props.contents ? this._props.contents?.valueOf() : '' } - }; + } renderEditor = () => { return (
{ this._inputref = r; }} - style={{ overflow: 'auto', minHeight: `min(100%, ${(this._props.GetValue()?.split('\n').length || 1) * 15})`, minWidth: 20, }} + style={{ outline: 'none', overflow: 'auto', minHeight: `min(100%, ${(this._props.GetValue()?.split('\n').length || 1) * 15})`, minWidth: 20, }} onBlur={e => this.finalizeEdit(false, true, false)} autoFocus onInput={this.onChange} @@ -228,7 +249,7 @@ export class SchemaCellField extends ObservableReactComponent
); - }; + } render() { const gval = this._props.GetValue()?.replace(/\n/g, '\\r\\n'); diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index 4902a49ff..121605a2b 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -122,6 +122,10 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { columnWidth = computedFn((index: number) => () => this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth); computeRowIndex = () => this.schemaView?.rowIndex(this.Document); highlightCells = (text: string) => this.schemaView?.highlightCells(text); + equationHighlightRef = (text: string) => { + + } + eqHighlightFunc = (text: string, raw: boolean) => {return this.schemaView.findCellRefs(text, raw)}; render() { return (
() {
{this.schemaView?.columnKeys?.map((key, index) => ( boolean; isolatedSelection: [boolean, boolean]; highlightCells: (text: string) => void; + equationHighlightRef: ObservableMap; + func: (text: string, raw: boolean) => HTMLDivElement[] | []; + } function selectedCell(props: SchemaTableCellProps) { @@ -179,6 +182,7 @@ export class SchemaTableCell extends ObservableReactComponent selectedCell(this._props) && this._props.autoFocus && r?.setIsFocused(true)} oneLine={this._props.oneLine} contents={undefined} -- cgit v1.2.3-70-g09d2 From 83a2f119bf908d07e08ac89171e73d2211e1eb8f Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Thu, 20 Jun 2024 17:50:00 -0400 Subject: eq highlight working 70% --- .../collectionSchema/SchemaCellField.tsx | 35 +++++++++++++++------- .../collections/collectionSchema/SchemaRowBox.tsx | 2 +- .../collectionSchema/SchemaTableCell.tsx | 1 + 3 files changed, 27 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index 4ba8c8469..6663fb68f 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -6,12 +6,15 @@ import { DocumentIconContainer } from "../../nodes/DocumentIcon"; import React, { FormEvent } from "react"; import { FieldView, FieldViewProps } from "../../nodes/FieldView"; import { ObjectField } from "../../../../fields/ObjectField"; +import { Doc } from "../../../../fields/Doc"; +import { DocumentView } from "../../nodes/DocumentView"; export interface SchemaCellFieldProps { contents: any; fieldContents?: FieldViewProps; editing?: boolean; oneLine?: boolean; + Document: Doc; highlightCells?: (text: string) => void; GetValue(): string | undefined; SetValue(value: string, shiftDown?: boolean, enterKey?: boolean): boolean; @@ -33,7 +36,11 @@ export class SchemaCellField extends ObservableReactComponent this._editing, editing => { @@ -43,6 +50,7 @@ export class SchemaCellField extends ObservableReactComponent, { x: 0, y: 0 }); this._props.highlightCells?.(this._props.GetValue() ?? ''); + this.setContent(this._content); } }); } else { @@ -53,8 +61,6 @@ export class SchemaCellField extends ObservableReactComponent) { @@ -74,13 +80,24 @@ export class SchemaCellField extends ObservableReactComponent { - const matches = this._props.func(content, true); + const pattern = /(this|d(\d+))\.(\w+)/g; + interface Match { docRef: string; field: string; } + + const matches: Match[] = []; + let match: RegExpExecArray | null; + + while ((match = pattern.exec(content)) !== null) { + const docRef = match[1] === 'this' ? match[1] : match[2]; + matches.push({ docRef, field: match[3] }); + } + const cells = this._props.func(content, false); let chunkedText = content; let matchNum = 0; - matches.forEach((docRef, field) => { - console.log('cell: ' + cells[matchNum] + ' border: ' + cells[matchNum].style.borderTop) - chunkedText = chunkedText.replace(`d5.type`, `d5.type`); + matches.forEach((match: Match) => { + const {docRef, field} = match; + // const refToUse = docRef === 'this' ? `${this.docIndex}` : docRef; + chunkedText = chunkedText.replace(`d${docRef}.${field}`, `d${docRef}.${field}`); ++matchNum; }) return chunkedText; @@ -88,9 +105,7 @@ export class SchemaCellField extends ObservableReactComponent { - console.log(this.chunkContent(content)); this._displayedContent = this.chunkContent(content); - console.log('displayed: ' + this._displayedContent); } @action @@ -157,11 +172,11 @@ export class SchemaCellField extends ObservableReactComponent, { x: 0, y: 0 }); } this._content = targVal; + this._props.highlightCells?.(targVal); if (this._props.func(targVal, true).length > this._props.func(prevVal, true).length) { this.setContent(targVal); setTimeout(() => this.restoreCursorPosition(cursorPos), 0); } - this._props.highlightCells?.(targVal); }; @action @@ -245,7 +260,7 @@ export class SchemaCellField extends ObservableReactComponent e.stopPropagation} onClick={e => e.stopPropagation} onPointerUp={e => e.stopPropagation} - dangerouslySetInnerHTML={{ __html: `${this._displayedContent}` }} + dangerouslySetInnerHTML={{ __html: this._displayedContent }} >
); diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index 121605a2b..c0ad95141 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -131,7 +131,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() {
this.setCursorIndex(e.clientY)} - style={{ height: this._props.PanelHeight(), backgroundColor: this._props.isSelected() ? Colors.LIGHT_BLUE : undefined }} + style={{ height: this._props.PanelHeight()}} ref={(row: HTMLDivElement | null) => { row && this.schemaView?.addRowRef?.(this.Document, row); this._ref = row; diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 74ee46065..3233e363a 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -181,6 +181,7 @@ export class SchemaTableCell extends ObservableReactComponent selectedCell(this._props) && this._props.autoFocus && r?.setIsFocused(true)} -- cgit v1.2.3-70-g09d2 From 22152c38c3e1485c107b321f1ce3894e87c0226f Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Fri, 21 Jun 2024 01:57:54 -0400 Subject: refactor --- .../collectionSchema/CollectionSchemaView.tsx | 16 ++++++++++------ .../views/collections/collectionSchema/SchemaRowBox.tsx | 8 +++++++- 2 files changed, 17 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 5c8a84163..992ee2ec9 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -101,8 +101,8 @@ export class CollectionSchemaView extends CollectionSubView() { @observable _colBeingDragged: boolean = false; @observable _colKeysFiltered: boolean = false; @observable _cellTags: ObservableMap = new ObservableMap>(); - @observable _highlightedCells: Array = []; - @observable _cellHighlightColors: ObservableMap = new ObservableMap(); + @observable _highlightedCells: Array<[doc: Doc, field: string]> = []; + @observable _cellHighlightColors: ObservableMap = new ObservableMap<[doc: Doc, field: string], string[]>(); @observable _docs: Doc[] = []; // target HTMLelement portal for showing a popup menu to edit cell values. @@ -290,7 +290,7 @@ export class CollectionSchemaView extends CollectionSubView() { break; } case 'P': { - this.highlightSortedColumn(); + console.log(this._cellHighlightColors) break; } default: @@ -551,14 +551,17 @@ export class CollectionSchemaView extends CollectionSubView() { matches.forEach((match: Match) => { const {docRef, field} = match; const doc = DocumentManager.Instance.DocumentViews[Number(docRef)].Document; - if (this.columnKeys.includes(field)) {cells.push(this.getCellElement(doc, field))} + if (this.columnKeys.includes(field)) {cells.push([doc, field])} }) return cells; } removeCellHighlights = () => { - this._highlightedCells.forEach(cell => {cell.style.border = ''; cell.style.backgroundColor = '';}); + this._highlightedCells.forEach(info => { + const cell = this.getCellElement(info[0], info[1]); + cell.style.border = ''; cell.style.backgroundColor = ''; + }); this._highlightedCells = []; } @@ -580,8 +583,9 @@ export class CollectionSchemaView extends CollectionSubView() { const cellsToHighlight = this.findCellRefs(text); this._highlightedCells = [...cellsToHighlight]; - this._highlightedCells.forEach(cell => { + this._highlightedCells.forEach(info => { const color = randomRGBColor(); + const cell = this.getCellElement(info[0], info[1]); if (!this._cellHighlightColors.has(cell)) {this._cellHighlightColors.set(cell, new Array(`solid 2px ${color[0]}`, color[1]))} cell.style.border = this._cellHighlightColors.get(cell)[0]; cell.style.backgroundColor = this._cellHighlightColors.get(cell)[1]; diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index c0ad95141..6f6b6decf 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -125,7 +125,13 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { equationHighlightRef = (text: string) => { } - eqHighlightFunc = (text: string, raw: boolean) => {return this.schemaView.findCellRefs(text, raw)}; + eqHighlightFunc = (text: string, raw: boolean) => { + const info = this.schemaView.findCellRefs(text, raw); + if (raw) return info; + const cells: HTMLDivElement[] = []; + info.forEach(info => {cells.push(this.schemaView.getCellElement(info[0], info[1]))}) + return cells; + }; render() { return (
Date: Fri, 21 Jun 2024 02:17:46 -0400 Subject: cell highlights consistsent on row moving --- .../collections/collectionSchema/CollectionSchemaView.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 992ee2ec9..6838662c7 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -585,10 +585,13 @@ export class CollectionSchemaView extends CollectionSubView() { this._highlightedCells = [...cellsToHighlight]; this._highlightedCells.forEach(info => { const color = randomRGBColor(); - const cell = this.getCellElement(info[0], info[1]); - if (!this._cellHighlightColors.has(cell)) {this._cellHighlightColors.set(cell, new Array(`solid 2px ${color[0]}`, color[1]))} - cell.style.border = this._cellHighlightColors.get(cell)[0]; - cell.style.backgroundColor = this._cellHighlightColors.get(cell)[1]; + const doc = info[0]; + const field = info[1]; + const key = `${doc}_${field}`; + const cell = this.getCellElement(doc, field); + if (!this._cellHighlightColors.has(key)) {this._cellHighlightColors.set(key, new Array(`solid 2px ${color[0]}`, color[1]))} + cell.style.border = this._cellHighlightColors.get(key)[0]; + cell.style.backgroundColor = this._cellHighlightColors.get(key)[1]; }); } -- cgit v1.2.3-70-g09d2 From 24fad06cbd2e273bb6729f21956e35243e602bb7 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Fri, 21 Jun 2024 12:37:47 -0400 Subject: fixed bug where equation didn't save in cell field on reloading (batching issue) --- .../views/collections/collectionSchema/CollectionSchemaView.tsx | 2 +- src/client/views/collections/collectionSchema/SchemaCellField.tsx | 7 +++++-- src/client/views/collections/collectionSchema/SchemaTableCell.tsx | 1 + 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 6838662c7..308520154 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -587,7 +587,7 @@ export class CollectionSchemaView extends CollectionSubView() { const color = randomRGBColor(); const doc = info[0]; const field = info[1]; - const key = `${doc}_${field}`; + const key = `${doc[Id]}_${field}`; const cell = this.getCellElement(doc, field); if (!this._cellHighlightColors.has(key)) {this._cellHighlightColors.set(key, new Array(`solid 2px ${color[0]}`, color[1]))} cell.style.border = this._cellHighlightColors.get(key)[0]; diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index 6663fb68f..dcfa4f6f2 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -39,8 +39,10 @@ export class SchemaCellField extends ObservableReactComponent { + this._content = this._props.GetValue() ?? ''; + this.setContent(this._content); + }, 0); //must be moved to end of batch or else other docs aren't loaded, so render as d-1 in function this._disposers.editing = reaction( () => this._editing, editing => { @@ -50,6 +52,7 @@ export class SchemaCellField extends ObservableReactComponent, { x: 0, y: 0 }); this._props.highlightCells?.(this._props.GetValue() ?? ''); + if (this._props.Document.type === 'collection') console.log('highlight: ' + this._props.GetValue()) this.setContent(this._content); } }); diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 3233e363a..94fd9ec7d 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -152,6 +152,7 @@ export class SchemaTableCell extends ObservableReactComponent { + if (field === ':=d6.type + d4.type + d3.type') console.log(true) const idPattern = /idToDoc\((.*?)\)/g; let modField = field.slice(); let matches; -- cgit v1.2.3-70-g09d2 From 7f9d92b3e1d0ca433c732936eae767095c9a5e7f Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Sat, 22 Jun 2024 15:47:12 -0400 Subject: work on cell field (numerous bugs fixed: spaces now make new divs, invalid refs no longer break things, valid->invalid ref causes update properly) --- .../collectionSchema/CollectionSchemaView.tsx | 9 ++- .../collectionSchema/SchemaCellField.tsx | 79 ++++++++++++++-------- .../collections/collectionSchema/SchemaRowBox.tsx | 5 +- .../collectionSchema/SchemaTableCell.tsx | 4 +- 4 files changed, 59 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 308520154..9c4eda3b8 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -533,7 +533,7 @@ export class CollectionSchemaView extends CollectionSubView() { return cell; } - findCellRefs = (text: string, retRawMatches?: boolean) => { + findCellRefs = (text: string) => { const pattern = /(this|d(\d+))\.(\w+)/g; interface Match { docRef: string; field: string; } @@ -545,13 +545,12 @@ export class CollectionSchemaView extends CollectionSubView() { matches.push({ docRef, field: match[3] }); } - if (retRawMatches) return matches; - const cells: Array = []; matches.forEach((match: Match) => { const {docRef, field} = match; - const doc = DocumentManager.Instance.DocumentViews[Number(docRef)].Document; - if (this.columnKeys.includes(field)) {cells.push([doc, field])} + const docView = DocumentManager.Instance.DocumentViews[Number(docRef)]; + const doc = docView?.Document ?? undefined; + if (this.columnKeys.includes(field) && this._docs.includes(doc)) {cells.push([doc, field])} }) return cells; diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index dcfa4f6f2..e2aa27a95 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -18,7 +18,7 @@ export interface SchemaCellFieldProps { highlightCells?: (text: string) => void; GetValue(): string | undefined; SetValue(value: string, shiftDown?: boolean, enterKey?: boolean): boolean; - func: (text: string, raw: boolean) => HTMLDivElement[] | []; + getCells: (text: string) => HTMLDivElement[] | []; } @observer @@ -26,7 +26,7 @@ export class SchemaCellField extends ObservableReactComponent void; @observable _editing: boolean = false; @observable _displayedContent = ''; @@ -40,8 +40,8 @@ export class SchemaCellField extends ObservableReactComponent { - this._content = this._props.GetValue() ?? ''; - this.setContent(this._content); + this._unrenderedContent = this._props.GetValue() ?? ''; + this.setContent(this._unrenderedContent, true); }, 0); //must be moved to end of batch or else other docs aren't loaded, so render as d-1 in function this._disposers.editing = reaction( () => this._editing, @@ -52,8 +52,7 @@ export class SchemaCellField extends ObservableReactComponent, { x: 0, y: 0 }); this._props.highlightCells?.(this._props.GetValue() ?? ''); - if (this._props.Document.type === 'collection') console.log('highlight: ' + this._props.GetValue()) - this.setContent(this._content); + this.setContent(this._unrenderedContent, true); } }); } else { @@ -82,33 +81,44 @@ export class SchemaCellField extends ObservableReactComponent { - const pattern = /(this|d(\d+))\.(\w+)/g; - interface Match { docRef: string; field: string; } + makeSpans = (content: string) => { + let chunkedText = content; + chunkedText = chunkedText.replace(/ +/g, (match) => { + const spanSpaces = ' '.repeat(match.length); + return `${spanSpaces}`; + }); - const matches: Match[] = []; + const pattern = /(this|d(\d+))\.(\w+)/g; + const matches: string[] = []; let match: RegExpExecArray | null; + const cells: Map = new Map(); + while ((match = pattern.exec(content)) !== null) { - const docRef = match[1] === 'this' ? match[1] : match[2]; - matches.push({ docRef, field: match[3] }); + const cell = this._props.getCells(match[0]); + if (cell.length) { + matches.push(match[0]); + cells.set(match[0], cell[0]) + } } - const cells = this._props.func(content, false); - let chunkedText = content; let matchNum = 0; - matches.forEach((match: Match) => { - const {docRef, field} = match; + matches.forEach((match: string) => { // const refToUse = docRef === 'this' ? `${this.docIndex}` : docRef; - chunkedText = chunkedText.replace(`d${docRef}.${field}`, `d${docRef}.${field}`); + chunkedText = chunkedText.replace(match, `${match}`); ++matchNum; }) + return chunkedText; } @action - setContent = (content: string) => { - this._displayedContent = this.chunkContent(content); + setContent = (content: string, restoreCursorPos?: boolean) => { + this._displayedContent = this.makeSpans(content); + if (restoreCursorPos) { + const cursorPos = this.cursorPosition; + setTimeout(() => this.restoreCursorPosition(cursorPos), 0); + } } @action @@ -164,9 +174,13 @@ export class SchemaCellField extends ObservableReactComponent { + if (this._props.getCells(currVal).length !== this._props.getCells(prevVal).length) return true; + //if (contains self-ref pattern) + }; + onChange = (e: FormEvent) => { - const cursorPos = this.cursorPosition; - const prevVal = this._content; + const prevVal = this._unrenderedContent; const targVal = e.currentTarget.innerText; if (!(targVal.startsWith(':=') || targVal.startsWith('='))) { this._overlayDisposer?.(); @@ -174,12 +188,9 @@ export class SchemaCellField extends ObservableReactComponent, { x: 0, y: 0 }); } - this._content = targVal; + this._unrenderedContent = targVal; this._props.highlightCells?.(targVal); - if (this._props.func(targVal, true).length > this._props.func(prevVal, true).length) { - this.setContent(targVal); - setTimeout(() => this.restoreCursorPosition(cursorPos), 0); - } + if (this.shouldUpdate(prevVal, targVal)) {this.setContent(targVal, true)}; }; @action @@ -206,6 +217,18 @@ export class SchemaCellField extends ObservableReactComponent { + this.setContent(this._unrenderedContent); + const cursorPos = this.cursorPosition; + setTimeout(() => this.restoreCursorPosition(cursorPos), 0); + } + , 0); + break; + case 'u': // for some reason 'u' otherwise exits the editor + e.stopPropagation(); + break; case 'Shift': case 'Alt': case 'Meta': case 'Control': case ':': //prettier-ignore break; // eslint-disable-next-line no-fallthrough @@ -225,8 +248,8 @@ export class SchemaCellField extends ObservableReactComponent() { equationHighlightRef = (text: string) => { } - eqHighlightFunc = (text: string, raw: boolean) => { - const info = this.schemaView.findCellRefs(text, raw); - if (raw) return info; + eqHighlightFunc = (text: string) => { + const info = this.schemaView.findCellRefs(text); const cells: HTMLDivElement[] = []; info.forEach(info => {cells.push(this.schemaView.getCellElement(info[0], info[1]))}) return cells; diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 94fd9ec7d..ab384a487 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -63,7 +63,7 @@ export interface SchemaTableCellProps { isolatedSelection: [boolean, boolean]; highlightCells: (text: string) => void; equationHighlightRef: ObservableMap; - func: (text: string, raw: boolean) => HTMLDivElement[] | []; + func: (text: string) => HTMLDivElement[] | []; } @@ -184,7 +184,7 @@ export class SchemaTableCell extends ObservableReactComponent selectedCell(this._props) && this._props.autoFocus && r?.setIsFocused(true)} oneLine={this._props.oneLine} contents={undefined} -- cgit v1.2.3-70-g09d2 From fc1fd8902b090b75c81347a37cce15145322b4e2 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Sat, 22 Jun 2024 23:55:38 -0400 Subject: moving row no longer messes up cell field (of course it was batching...) --- src/client/views/EditableView.tsx | 2 +- .../views/collections/collectionSchema/SchemaCellField.tsx | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 78977bcb8..8e48b4c11 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -193,7 +193,7 @@ export class EditableView extends ObservableReactComponent { @action onClick = (e?: React.MouseEvent) => { this._props.onClick && this._props.onClick(); - if (this._props.editing !== false) { + if (this._props.editing) { e?.nativeEvent.stopPropagation(); if (this._ref.current && this._props.showMenuOnLoad) { this._props.menuCallback?.(this._ref.current.getBoundingClientRect().x, this._ref.current.getBoundingClientRect().y); diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index e2aa27a95..ffda334ec 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -34,15 +34,17 @@ export class SchemaCellField extends ObservableReactComponent { + this._unrenderedContent = this._props.GetValue() ?? ''; + this.setContent(this._unrenderedContent, true); + }, 0); //must be moved to end of batch or else other docs aren't loaded, so render as d-1 in function } get docIndex(){return DocumentView.getDocViewIndex(this._props.Document);} // prettier-ignore componentDidMount(): void { - setTimeout(() => { - this._unrenderedContent = this._props.GetValue() ?? ''; - this.setContent(this._unrenderedContent, true); - }, 0); //must be moved to end of batch or else other docs aren't loaded, so render as d-1 in function + this._unrenderedContent = this._props.GetValue() ?? ''; + this.setContent(this._unrenderedContent, true); this._disposers.editing = reaction( () => this._editing, editing => { -- cgit v1.2.3-70-g09d2 From 4c56da7db9feb018e004354bb6bf333d3890d91b Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Sun, 23 Jun 2024 00:12:31 -0400 Subject: text cursor icon in cell --- src/client/views/collections/collectionSchema/SchemaCellField.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index ffda334ec..08231dd91 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -280,7 +280,7 @@ export class SchemaCellField extends ObservableReactComponent { this._inputref = r; }} - style={{ outline: 'none', overflow: 'auto', minHeight: `min(100%, ${(this._props.GetValue()?.split('\n').length || 1) * 15})`, minWidth: 20, }} + style={{ cursor: 'text', outline: 'none', overflow: 'auto', minHeight: `min(100%, ${(this._props.GetValue()?.split('\n').length || 1) * 15})`, minWidth: 20, }} onBlur={e => this.finalizeEdit(false, true, false)} autoFocus onInput={this.onChange} -- cgit v1.2.3-70-g09d2 From 1775ceb9b840ab73194eb84e673ef692c1fef454 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Sun, 23 Jun 2024 00:25:19 -0400 Subject: drag text highlighting --- src/client/views/collections/collectionSchema/SchemaCellField.tsx | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index 08231dd91..fc191014c 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -288,6 +288,7 @@ export class SchemaCellField extends ObservableReactComponent e.stopPropagation} onClick={e => e.stopPropagation} onPointerUp={e => e.stopPropagation} + onPointerMove={e => {e.stopPropagation(); e.preventDefault()}} dangerouslySetInnerHTML={{ __html: this._displayedContent }} >
-- cgit v1.2.3-70-g09d2 From 9fab1b3ac096138fba3a99a2515ec44b526a3956 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Sun, 23 Jun 2024 02:54:24 -0400 Subject: text highlight works with 'this.' format --- src/client/views/collections/collectionSchema/SchemaCellField.tsx | 7 +++++-- src/client/views/collections/collectionSchema/SchemaRowBox.tsx | 2 ++ src/client/views/collections/collectionSchema/SchemaTableCell.tsx | 8 ++++---- 3 files changed, 11 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index fc191014c..aa6c382ef 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -53,7 +53,7 @@ export class SchemaCellField extends ObservableReactComponent { - // const refToUse = docRef === 'this' ? `${this.docIndex}` : docRef; + const adjMatch = match.replace('this.', `d${this.docIndex}`) chunkedText = chunkedText.replace(match, `${match}`); ++matchNum; }) diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index f4320dc09..45f178815 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -22,6 +22,7 @@ import { ContextMenu } from '../../ContextMenu'; import { CollectionFreeFormView } from '../collectionFreeForm'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { IconProp } from '@fortawesome/fontawesome-svg-core'; +import { infoState } from '../collectionFreeForm/CollectionFreeFormInfoState'; interface SchemaRowBoxProps extends FieldViewProps { rowIndex: number; @@ -129,6 +130,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { const info = this.schemaView.findCellRefs(text); const cells: HTMLDivElement[] = []; info.forEach(info => {cells.push(this.schemaView.getCellElement(info[0], info[1]))}) + console.log('info: ' + info + ' cells: ' + cells); return cells; }; render() { diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index ab384a487..6ccada48c 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -144,10 +144,10 @@ export class SchemaTableCell extends ObservableReactComponent { + adjustSelfReference = (field: string) => { const pattern = /\bthis.\b/g; const modField = field.replace(pattern, `d${this.docIndex}.`); - this._props.highlightCells(modField); + return modField; } // parses a field from the "idToDoc(####)" format to DocumentId (d#) format for readability @@ -183,8 +183,8 @@ export class SchemaTableCell extends ObservableReactComponent this._props.highlightCells(this.adjustSelfReference(text))} + getCells={(text: string) => this._props.func(this.adjustSelfReference(text))} ref={r => selectedCell(this._props) && this._props.autoFocus && r?.setIsFocused(true)} oneLine={this._props.oneLine} contents={undefined} -- cgit v1.2.3-70-g09d2 From b2691d6119dfa1f192ac6eb19650f44742b253f5 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Sun, 23 Jun 2024 03:36:21 -0400 Subject: col filling (really external setting of cell fieldval) works properly (reaction); moved 'remove doc' option to bottom of row menu --- .../collectionSchema/CollectionSchemaView.tsx | 6 +++--- .../collections/collectionSchema/SchemaCellField.tsx | 17 +++++++++++------ .../views/collections/collectionSchema/SchemaRowBox.tsx | 13 ++++++------- .../collections/collectionSchema/SchemaTableCell.tsx | 4 +--- 4 files changed, 21 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 9c4eda3b8..2a84efa7c 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -829,9 +829,9 @@ export class CollectionSchemaView extends CollectionSubView() { this.closeColumnMenu(); }; - setCellValues = (key: string, value: string) => { - if (this._selectedCells.length === 1) this.docs.forEach(doc => !doc._lockedSchemaEditing &&Doc.SetField(doc, key, value)); // if only one cell selected, fill all - else this._selectedCells.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value)); // else only fill selected cells + setColumnValues = (key: string, value: string) => { + if (this._selectedCells.length === 1) this.docs.forEach(doc => !doc._lockedSchemaEditing &&Doc.SetField(doc, key, value)); + else this._selectedCells.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value)); return true; }; diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index aa6c382ef..e85bf75e6 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -36,7 +36,7 @@ export class SchemaCellField extends ObservableReactComponent { this._unrenderedContent = this._props.GetValue() ?? ''; - this.setContent(this._unrenderedContent, true); + this.setContent(this._unrenderedContent); }, 0); //must be moved to end of batch or else other docs aren't loaded, so render as d-1 in function } @@ -65,6 +65,13 @@ export class SchemaCellField extends ObservableReactComponent this._props.GetValue(), + fieldVal => { + this._unrenderedContent = fieldVal ?? ''; + this.setContent(this._unrenderedContent); + } + ) } componentDidUpdate(prevProps: Readonly) { @@ -79,7 +86,7 @@ export class SchemaCellField extends ObservableReactComponent disposer?.()); this.finalizeEdit(false, true, false); } @@ -98,15 +105,12 @@ export class SchemaCellField extends ObservableReactComponent { const adjMatch = match.replace('this.', `d${this.docIndex}`) @@ -237,6 +241,8 @@ export class SchemaCellField extends ObservableReactComponent() { openContextMenu = (x: number, y: number) => { ContextMenu.Instance.clearItems(); - ContextMenu.Instance.addItem({ - description: `Close doc`, - event: () => this.schemaView.removeDoc(this.Document), - icon: 'minus', - }); ContextMenu.Instance.addItem({ description: this.Document._lockedSchemaEditing ? 'Unlock field editing' : 'Lock field editing', event: () => this.Document._lockedSchemaEditing = !this.Document._lockedSchemaEditing, @@ -75,6 +70,11 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { event: () => this._props.addDocTab(this.Document, OpenWhere.addRight), icon: 'magnifying-glass', }); + ContextMenu.Instance.addItem({ + description: `Close doc`, + event: () => this.schemaView.removeDoc(this.Document), + icon: 'minus', + }); const childDocs = DocListCast(this.Document[Doc.LayoutFieldKey(this.Document)]) if (this.Document.type === 'collection' && childDocs.length) { ContextMenu.Instance.addItem({ @@ -119,7 +119,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { selectCell = (doc: Doc, col: number, shift: boolean, ctrl: boolean) => this.schemaView?.selectCell(doc, col, shift, ctrl); deselectCell = () => this.schemaView?.deselectAllCells(); selectedCells = () => this.schemaView?._selectedDocs; - setColumnValues = (field: any, value: any) => this.schemaView?.setCellValues(field, value) ?? false; + setColumnValues = (field: any, value: any) => this.schemaView?.setColumnValues(field, value) ?? false; columnWidth = computedFn((index: number) => () => this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth); computeRowIndex = () => this.schemaView?.rowIndex(this.Document); highlightCells = (text: string) => this.schemaView?.highlightCells(text); @@ -130,7 +130,6 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { const info = this.schemaView.findCellRefs(text); const cells: HTMLDivElement[] = []; info.forEach(info => {cells.push(this.schemaView.getCellElement(info[0], info[1]))}) - console.log('info: ' + info + ' cells: ' + cells); return cells; }; render() { diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 6ccada48c..aa8401502 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -145,14 +145,12 @@ export class SchemaTableCell extends ObservableReactComponent { - const pattern = /\bthis.\b/g; - const modField = field.replace(pattern, `d${this.docIndex}.`); + const modField = field.replace(/\bthis.\b/g, `d${this.docIndex}.`); return modField; } // parses a field from the "idToDoc(####)" format to DocumentId (d#) format for readability cleanupField = (field: string) => { - if (field === ':=d6.type + d4.type + d3.type') console.log(true) const idPattern = /idToDoc\((.*?)\)/g; let modField = field.slice(); let matches; -- cgit v1.2.3-70-g09d2 From 9197630d59f4ae4624e3b47b794e0a5fa7bc080d Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Mon, 24 Jun 2024 12:14:51 -0400 Subject: Work on persistent sort highlight + equation highlight inteeraction --- .../collectionSchema/CollectionSchemaView.tsx | 30 ++++++++++++---------- .../collectionSchema/SchemaCellField.tsx | 11 ++++---- 2 files changed, 23 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 2a84efa7c..018fd35b5 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -101,7 +101,7 @@ export class CollectionSchemaView extends CollectionSubView() { @observable _colBeingDragged: boolean = false; @observable _colKeysFiltered: boolean = false; @observable _cellTags: ObservableMap = new ObservableMap>(); - @observable _highlightedCells: Array<[doc: Doc, field: string]> = []; + @observable _highlightedCellsInfo: Array<[doc: Doc, field: string]> = []; @observable _cellHighlightColors: ObservableMap = new ObservableMap<[doc: Doc, field: string], string[]>(); @observable _docs: Doc[] = []; @@ -124,6 +124,10 @@ export class CollectionSchemaView extends CollectionSubView() { return selected; } + @computed get highlightedCells() { + return this._highlightedCellsInfo.map(info => this.getCellElement(info[0], info[1])); + } + @computed get documentKeys() { return Array.from(this.fieldInfos.keys()); } @@ -199,8 +203,8 @@ export class CollectionSchemaView extends CollectionSubView() { {fireImmediately: true} ) this._disposers.sortHighlight = reaction( - () => [this.sortField, this._docs, this._selectedDocs, this._highlightedCells], - () => {this.sortField && setTimeout(() => this.highlightSortedColumn(), 5)}, + () => [this.sortField, this._docs, this._selectedDocs, this._highlightedCellsInfo], + () => {this.sortField && setTimeout(() => this.highlightSortedColumn(), 0)}, {fireImmediately: true} ) } @@ -517,12 +521,15 @@ export class CollectionSchemaView extends CollectionSubView() { ]; const cellCount = cellEles.length; for (let ele = 0; ele < cellCount; ++ele){ + const toHighlight = cellEles[ele]; + if (!this.highlightedCells.includes(toHighlight)){ const style = highlight ? desc ? `${highlightColors[cellCount - 1 - ele]}` : `${highlightColors[ele]}` : ''; - cellEles[ele].style.borderLeft = style; - cellEles[ele].style.borderRight = style; + toHighlight.style.borderLeft = style; + toHighlight.style.borderRight = style; + } } cellEles[0].style.borderTop = highlight ? desc ? `${highlightColors[cellCount - 1]}` : `${highlightColors[0]}` : ''; - if (!(cellCount < rowCount)) cellEles[cellCount - 1].style.borderBottom = highlight ? desc ? `${highlightColors[0]}` : `${highlightColors[cellCount - 1]}` : ''; + if (!(this._selectedDocs.includes(this.docsWithDrag.docs[this.docsWithDrag.docs.length - 1]) && this._selectedCol === index)) cellEles[cellCount - 1].style.borderBottom = highlight ? desc ? `${highlightColors[0]}` : `${highlightColors[cellCount - 1]}` : ''; }); } @@ -557,11 +564,8 @@ export class CollectionSchemaView extends CollectionSubView() { } removeCellHighlights = () => { - this._highlightedCells.forEach(info => { - const cell = this.getCellElement(info[0], info[1]); - cell.style.border = ''; cell.style.backgroundColor = ''; - }); - this._highlightedCells = []; + this.highlightedCells.forEach(cell => {cell.style.border = ''; cell.style.backgroundColor = '';}); + this._highlightedCellsInfo = []; } highlightCells = (text: string) => { @@ -581,8 +585,8 @@ export class CollectionSchemaView extends CollectionSubView() { } const cellsToHighlight = this.findCellRefs(text); - this._highlightedCells = [...cellsToHighlight]; - this._highlightedCells.forEach(info => { + this._highlightedCellsInfo = [...cellsToHighlight]; + this._highlightedCellsInfo.forEach(info => { const color = randomRGBColor(); const doc = info[0]; const field = info[1]; diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index e85bf75e6..ccd15cbd0 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -92,10 +92,6 @@ export class SchemaCellField extends ObservableReactComponent { let chunkedText = content; - chunkedText = chunkedText.replace(/ +/g, (match) => { - const spanSpaces = ' '.repeat(match.length); - return `${spanSpaces}`; - }); const pattern = /(this|d(\d+))\.(\w+)/g; const matches: string[] = []; @@ -123,6 +119,7 @@ export class SchemaCellField extends ObservableReactComponent { + console.log('content: ' + content) this._displayedContent = this.makeSpans(content); if (restoreCursorPos) { const cursorPos = this.cursorPosition; @@ -147,6 +144,8 @@ export class SchemaCellField extends ObservableReactComponent { this.setContent(this._unrenderedContent); - const cursorPos = this.cursorPosition; setTimeout(() => this.restoreCursorPosition(cursorPos), 0); } , 0); -- cgit v1.2.3-70-g09d2 From 227a289e49019ad1e9f634b098bb564bd4a8e743 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Mon, 24 Jun 2024 13:49:43 -0400 Subject: cell/column highlight interactions (maybe some minor bugs left but at least 95%) --- src/client/views/EditableView.tsx | 8 +--- .../collectionSchema/CollectionSchemaView.tsx | 44 +++++++++++++++------- .../collectionSchema/SchemaCellField.tsx | 24 ++++++++---- 3 files changed, 49 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 8e48b4c11..0c09e12de 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -193,7 +193,7 @@ export class EditableView extends ObservableReactComponent { @action onClick = (e?: React.MouseEvent) => { this._props.onClick && this._props.onClick(); - if (this._props.editing) { + if (this._props.editing !== false) { e?.nativeEvent.stopPropagation(); if (this._ref.current && this._props.showMenuOnLoad) { this._props.menuCallback?.(this._ref.current.getBoundingClientRect().x, this._ref.current.getBoundingClientRect().y); @@ -203,11 +203,7 @@ export class EditableView extends ObservableReactComponent { } } }; - - // checkForInvalidText = (text: string) => { - // const regX = new RegExp(new Array(...this._props.prohibitedText), 'g') - // } - + @action finalizeEdit(value: string, shiftDown: boolean, lostFocus: boolean, enterKey: boolean) { //if (invalid) raise error diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 018fd35b5..48c34c647 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -102,8 +102,9 @@ export class CollectionSchemaView extends CollectionSubView() { @observable _colKeysFiltered: boolean = false; @observable _cellTags: ObservableMap = new ObservableMap>(); @observable _highlightedCellsInfo: Array<[doc: Doc, field: string]> = []; - @observable _cellHighlightColors: ObservableMap = new ObservableMap<[doc: Doc, field: string], string[]>(); + @observable _cellHighlightColors: ObservableMap = new ObservableMap(); @observable _docs: Doc[] = []; + @observable _inCellSelectMode: boolean = false; // target HTMLelement portal for showing a popup menu to edit cell values. public get MenuTarget() { @@ -488,13 +489,13 @@ export class CollectionSchemaView extends CollectionSubView() { .filter(doc => (i !== this._selectedCol || !this._selectedDocs.includes(doc)) && !sorted) .map(doc => this._rowEles.get(doc).children[1].children[i]), ]; - !sorted && (cellEles[0].style.borderTop = edgeStyle); cellEles.forEach(ele => { - if (ele === cellEles[0] && sorted) return; + if (sorted || this.highlightedCells.includes(ele)) return; + ele.style.borderTop = ele === cellEles[0] ? edgeStyle : ''; ele.style.borderLeft = edgeStyle; ele.style.borderRight = edgeStyle; + ele.style.borderBottom = ele === cellEles.slice(-1)[0] ? edgeStyle : ''; }); - !sorted && (cellEles.slice(-1)[0].style.borderBottom = edgeStyle); }); highlightSortedColumn = (field?: string, descending?: boolean) => { @@ -521,15 +522,14 @@ export class CollectionSchemaView extends CollectionSubView() { ]; const cellCount = cellEles.length; for (let ele = 0; ele < cellCount; ++ele){ - const toHighlight = cellEles[ele]; - if (!this.highlightedCells.includes(toHighlight)){ + const currCell = cellEles[ele]; + if (this.highlightedCells.includes(currCell)) continue; const style = highlight ? desc ? `${highlightColors[cellCount - 1 - ele]}` : `${highlightColors[ele]}` : ''; - toHighlight.style.borderLeft = style; - toHighlight.style.borderRight = style; - } + currCell.style.borderLeft = style; + currCell.style.borderRight = style; } cellEles[0].style.borderTop = highlight ? desc ? `${highlightColors[cellCount - 1]}` : `${highlightColors[0]}` : ''; - if (!(this._selectedDocs.includes(this.docsWithDrag.docs[this.docsWithDrag.docs.length - 1]) && this._selectedCol === index)) cellEles[cellCount - 1].style.borderBottom = highlight ? desc ? `${highlightColors[0]}` : `${highlightColors[cellCount - 1]}` : ''; + if (!(this._selectedDocs.includes(this.docsWithDrag.docs[this.docsWithDrag.docs.length - 1]) && this._selectedCol === index) && !this.highlightedCells.includes(cellEles[cellCount - 1])) cellEles[cellCount - 1].style.borderBottom = highlight ? desc ? `${highlightColors[0]}` : `${highlightColors[cellCount - 1]}` : ''; }); } @@ -568,6 +568,20 @@ export class CollectionSchemaView extends CollectionSubView() { this._highlightedCellsInfo = []; } + restoreCellHighlights = () => { + this._highlightedCellsInfo.forEach(info => { + const doc = info[0]; + const field = info[1]; + const key = `${doc[Id]}_${field}`; + const cell = this.getCellElement(doc, field); + const color = this._cellHighlightColors.get(key)[0]; + cell.style.borderTop = color; + cell.style.borderLeft = color; + cell.style.borderRight = color; + cell.style.borderBottom = color; + }); + } + highlightCells = (text: string) => { this.removeCellHighlights(); @@ -690,10 +704,11 @@ export class CollectionSchemaView extends CollectionSubView() { colRef.style.borderTop = ''; this.childDocs.forEach(doc => { - if (!(this._selectedDocs.includes(doc) && i === this._selectedCol)) { - this._rowEles.get(doc).children[1].children[i].style.borderLeft = ''; - this._rowEles.get(doc).children[1].children[i].style.borderRight = ''; - this._rowEles.get(doc).children[1].children[i].style.borderBottom = ''; + const cell = this._rowEles.get(doc).children[1].children[i]; + if (!(this._selectedDocs.includes(doc) && i === this._selectedCol) && !(this.highlightedCells.includes(cell))) { + cell.style.borderLeft = ''; + cell.style.borderRight = ''; + cell.style.borderBottom = ''; } }); }); @@ -1178,6 +1193,7 @@ export class CollectionSchemaView extends CollectionSubView() { if (newIndex !== this._draggedColIndex) this.moveColumn(this._draggedColIndex, newIndex ?? this._draggedColIndex); this._draggedColIndex = newIndex || this._draggedColIndex; this.highlightSortedColumn(); //TODO: Make this more efficient + this.restoreCellHighlights(); !(this.sortField && this._draggedColIndex === this.columnKeys.indexOf(this.sortField)) && this.highlightDraggedColumn(newIndex ?? this._draggedColIndex); } }; diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index ccd15cbd0..e13763b45 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -1,4 +1,4 @@ -import { IReactionDisposer, action, makeObservable, observable, reaction, runInAction } from "mobx"; +import { IReactionDisposer, action, computed, makeObservable, observable, reaction, runInAction } from "mobx"; import { ObservableReactComponent } from "../../ObservableReactComponent"; import { observer } from "mobx-react"; import { OverlayView } from "../../OverlayView"; @@ -30,6 +30,7 @@ export class SchemaCellField extends ObservableReactComponent void; @observable _editing: boolean = false; @observable _displayedContent = ''; + @observable _inCellSelectMode: boolean = false; constructor(props: SchemaCellFieldProps) { super(props); @@ -40,6 +41,10 @@ export class SchemaCellField extends ObservableReactComponent { + return `${text}` + } + makeSpans = (content: string) => { let chunkedText = content; @@ -109,8 +118,7 @@ export class SchemaCellField extends ObservableReactComponent { - const adjMatch = match.replace('this.', `d${this.docIndex}`) - chunkedText = chunkedText.replace(match, `${match}`); + chunkedText = chunkedText.replace(match, this.generateSpan(match, cells.get(match))); ++matchNum; }) @@ -222,8 +230,11 @@ export class SchemaCellField extends ObservableReactComponent Date: Tue, 25 Jun 2024 01:14:06 -0400 Subject: progress on refSelect (single click to add cell to equation) --- .../collectionSchema/CollectionSchemaView.tsx | 135 +++++++++++---------- .../collectionSchema/SchemaCellField.tsx | 25 ++-- .../collections/collectionSchema/SchemaRowBox.tsx | 8 +- .../collectionSchema/SchemaTableCell.tsx | 11 +- 4 files changed, 106 insertions(+), 73 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 48c34c647..c3dc4bad6 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -42,6 +42,7 @@ import { truncate } from 'lodash'; import { DocumentManager } from '../../../util/DocumentManager'; import { TbHemispherePlus } from 'react-icons/tb'; import { docs_v1 } from 'googleapis'; +import { SchemaCellField } from './SchemaCellField'; const { SCHEMA_NEW_NODE_HEIGHT } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore @@ -104,7 +105,7 @@ export class CollectionSchemaView extends CollectionSubView() { @observable _highlightedCellsInfo: Array<[doc: Doc, field: string]> = []; @observable _cellHighlightColors: ObservableMap = new ObservableMap(); @observable _docs: Doc[] = []; - @observable _inCellSelectMode: boolean = false; + @observable _referenceSelectMode = {enabled: false, currEditing: undefined} // target HTMLelement portal for showing a popup menu to edit cell values. public get MenuTarget() { @@ -113,7 +114,7 @@ export class CollectionSchemaView extends CollectionSubView() { @computed get _selectedDocs() { // get all selected documents then filter out any whose parent is not this schema document - const selected = DocumentView.SelectedDocs().filter(doc => this.docs.includes(doc)); + const selected = DocumentView.SelectedDocs().filter(doc => this.docs.includes(doc) && this._selectedCells.includes(doc)); if (!selected.length) { // if no schema doc is directly selected, test if a child of a schema doc is selected (such as in the preview window) const childOfSchemaDoc = DocumentView.SelectedDocs().find(sel => DocumentView.getContextPath(sel, true).includes(this.Document)); @@ -651,7 +652,19 @@ export class CollectionSchemaView extends CollectionSubView() { }; @action - selectCell = (doc: Doc, col: number, shiftKey: boolean, ctrlKey: boolean) => { + selectCell = (doc: Doc | undefined, col: number, shiftKey: boolean, ctrlKey: boolean) => { + if (!doc) return; + + if (this._referenceSelectMode.enabled) { + const docIndex = DocumentView.getDocViewIndex(doc); + const field = this.columnKeys[col]; + const refToAdd = `d${docIndex}.${field}` + const editedField = this._referenceSelectMode.currEditing ? this._referenceSelectMode.currEditing as SchemaCellField : null; + editedField?.appendText(refToAdd); + editedField?.setupRefSelect(false); + return; + } + this.closeColumnMenu(); if (!shiftKey && !ctrlKey) this.clearSelection(); !this._selectedCells && (this._selectedCells = []); @@ -1015,64 +1028,64 @@ export class CollectionSchemaView extends CollectionSubView() { this._filterSearchValue = e.target.value; }; - @computed get newFieldMenu() { - return ( -
-
- { - this._newFieldType = ColumnType.Number; - this._newFieldDefault = 0; - })} - /> - number -
-
- { - this._newFieldType = ColumnType.Boolean; - this._newFieldDefault = false; - })} - /> - boolean -
-
- { - this._newFieldType = ColumnType.String; - this._newFieldDefault = ''; - })} - /> - string -
-
value: {this.fieldDefaultInput}
-
{this._newFieldWarning}
-
{ - if (this.documentKeys.includes(this._menuValue)) { - this._newFieldWarning = 'Field already exists'; - } else if (this._menuValue.length === 0) { - this._newFieldWarning = 'Field cannot be an empty string'; - } else { - this.setKey(this._menuValue, this._newFieldDefault); - } - this._columnMenuIndex = undefined; - })}> - done -
-
- ); - } + // @computed get newFieldMenu() { + // return ( + //
+ //
+ // { + // this._newFieldType = ColumnType.Number; + // this._newFieldDefault = 0; + // })} + // /> + // number + //
+ //
+ // { + // this._newFieldType = ColumnType.Boolean; + // this._newFieldDefault = false; + // })} + // /> + // boolean + //
+ //
+ // { + // this._newFieldType = ColumnType.String; + // this._newFieldDefault = ''; + // })} + // /> + // string + //
+ //
value: {this.fieldDefaultInput}
+ //
{this._newFieldWarning}
+ //
{ + // if (this.documentKeys.includes(this._menuValue)) { + // this._newFieldWarning = 'Field already exists'; + // } else if (this._menuValue.length === 0) { + // this._newFieldWarning = 'Field cannot be an empty string'; + // } else { + // this.setKey(this._menuValue, this._newFieldDefault); + // } + // this._columnMenuIndex = undefined; + // })}> + // done + //
+ //
+ // ); + // } onKeysPassiveWheel = (e: WheelEvent) => { // if scrollTop is 0, then don't let wheel trigger scroll on any container (which it would since onScroll won't be triggered on this) diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index e13763b45..ea46fb432 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -15,6 +15,8 @@ export interface SchemaCellFieldProps { editing?: boolean; oneLine?: boolean; Document: Doc; + fieldKey: string; + refSelectModeInfo: {enabled: boolean, currEditing: SchemaCellField | undefined}; highlightCells?: (text: string) => void; GetValue(): string | undefined; SetValue(value: string, shiftDown?: boolean, enterKey?: boolean): boolean; @@ -41,10 +43,6 @@ export class SchemaCellField extends ObservableReactComponent { - console.log('content: ' + content) this._displayedContent = this.makeSpans(content); if (restoreCursorPos) { const cursorPos = this.cursorPosition; @@ -135,6 +133,12 @@ export class SchemaCellField extends ObservableReactComponent { + this._unrenderedContent += text; + this.setContent(this._unrenderedContent); + } + @action setIsFocused = (value: boolean) => { const wasFocused = this._editing; @@ -209,6 +213,12 @@ export class SchemaCellField extends ObservableReactComponent { + const properties = this._props.refSelectModeInfo; + properties.enabled = enabled; + properties.currEditing = enabled ? this : undefined; + } + @action onKeyDown = (e: React.KeyboardEvent) => { if (e.nativeEvent.defaultPrevented) return; // hack .. DashFieldView grabs native events, but react ignores stoppedPropagation and preventDefault, so we need to check it here @@ -234,7 +244,7 @@ export class SchemaCellField extends ObservableReactComponent() { return '' } + @computed get refSelectModeInfo() { + return this.schemaView._referenceSelectMode; + } + @computed get menuInfos() { const infos: Array = []; if (this.Document._lockedSchemaEditing) infos.push('lock'); @@ -123,9 +127,6 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { columnWidth = computedFn((index: number) => () => this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth); computeRowIndex = () => this.schemaView?.rowIndex(this.Document); highlightCells = (text: string) => this.schemaView?.highlightCells(text); - equationHighlightRef = (text: string) => { - - } eqHighlightFunc = (text: string) => { const info = this.schemaView.findCellRefs(text); const cells: HTMLDivElement[] = []; @@ -174,6 +175,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() {
{this.schemaView?.columnKeys?.map((key, index) => ( void; equationHighlightRef: ObservableMap; func: (text: string) => HTMLDivElement[] | []; - + refSelectModeInfo: {enabled: boolean, currEditing: SchemaCellField | undefined}; } function selectedCell(props: SchemaTableCellProps) { @@ -78,7 +78,7 @@ function selectedCell(props: SchemaTableCellProps) { @observer export class SchemaTableCell extends ObservableReactComponent { - @observable _highlighted: boolean = false; + // private _fieldRef: SchemaCellField | null = null; constructor(props: SchemaTableCellProps) { super(props); @@ -143,6 +143,11 @@ export class SchemaTableCell extends ObservableReactComponent { + // this._fieldRef?.appendText(text); + // } adjustSelfReference = (field: string) => { const modField = field.replace(/\bthis.\b/g, `d${this.docIndex}.`); @@ -180,6 +185,8 @@ export class SchemaTableCell extends ObservableReactComponent this._props.highlightCells(this.adjustSelfReference(text))} getCells={(text: string) => this._props.func(this.adjustSelfReference(text))} -- cgit v1.2.3-70-g09d2 From 434fe9b5f27a14dc7bddeea9628abe4aaa62ce21 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Tue, 25 Jun 2024 01:56:34 -0400 Subject: scrolling for field text --- src/client/views/EditableView.scss | 8 +++++++- src/client/views/collections/collectionSchema/SchemaCellField.tsx | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/EditableView.scss b/src/client/views/EditableView.scss index d2f11f5e1..fa4542ac4 100644 --- a/src/client/views/EditableView.scss +++ b/src/client/views/EditableView.scss @@ -3,11 +3,17 @@ overflow-wrap: break-word; word-wrap: break-word; hyphens: auto; - overflow: hidden; + overflow-y: auto; height: 100%; width: 100%; min-width: 20; text-overflow: ellipsis; + -ms-overflow-style: none; + scrollbar-width: none; +} + +.editableView-container-editing::-webkit-scrollbar { + display: none; } .editableView-container-editing-oneLine { diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index ea46fb432..9d9fcbd1f 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -94,6 +94,10 @@ export class SchemaCellField extends ObservableReactComponent { return `${text}` } -- cgit v1.2.3-70-g09d2 From 3809bb004617a20fd631388d9cf404fa34c3ad52 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Tue, 25 Jun 2024 02:57:44 -0400 Subject: refselect consistency --- .../collectionSchema/SchemaCellField.tsx | 24 +++++++++++++--------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index 9d9fcbd1f..84b4d3462 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -45,6 +45,16 @@ export class SchemaCellField extends ObservableReactComponent 0; --i) { + if (text.charCodeAt(i) !== 160 && text.charCodeAt(i) !== 32) { + return text[i]; + } + } + return null; + } + componentDidMount(): void { this._unrenderedContent = this._props.GetValue() ?? ''; this.setContent(this._unrenderedContent, true); @@ -94,10 +104,6 @@ export class SchemaCellField extends ObservableReactComponent { return `${text}` } @@ -215,6 +221,9 @@ export class SchemaCellField extends ObservableReactComponent { @@ -247,12 +256,8 @@ export class SchemaCellField extends ObservableReactComponent { @@ -263,13 +268,11 @@ export class SchemaCellField extends ObservableReactComponent Date: Tue, 25 Jun 2024 12:10:05 -0400 Subject: focus is no longer lost --- src/client/util/SelectionManager.ts | 1 + .../collectionSchema/CollectionSchemaView.tsx | 26 ++++++++++++---------- .../collectionSchema/SchemaCellField.tsx | 11 ++++----- .../collections/collectionSchema/SchemaRowBox.tsx | 3 +++ .../collectionSchema/SchemaTableCell.tsx | 8 +++++++ 5 files changed, 32 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 0b942116c..fc494583f 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -58,6 +58,7 @@ export class SelectionManager { }); public static DeselectAll = (except?: Doc): void => { + const found = this.Instance.SelectedViews.find(dv => dv.Document === except); runInAction(() => { if (LinkManager.Instance) { diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index c3dc4bad6..3b5a32ca7 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -634,6 +634,7 @@ export class CollectionSchemaView extends CollectionSubView() { @action clearSelection = () => { + if (this._referenceSelectMode.enabled) return; DocumentView.DeselectAll(); this.deselectAllCells(); }; @@ -651,20 +652,19 @@ export class CollectionSchemaView extends CollectionSubView() { } }; - @action - selectCell = (doc: Doc | undefined, col: number, shiftKey: boolean, ctrlKey: boolean) => { + selectReference = (doc: Doc | undefined, col: number) => { if (!doc) return; + const docIndex = DocumentView.getDocViewIndex(doc); + const field = this.columnKeys[col]; + const refToAdd = `d${docIndex}.${field}` + const editedField = this._referenceSelectMode.currEditing ? this._referenceSelectMode.currEditing as SchemaCellField : null; + editedField?.appendText(refToAdd); + editedField?.setupRefSelect(false); + return; + } - if (this._referenceSelectMode.enabled) { - const docIndex = DocumentView.getDocViewIndex(doc); - const field = this.columnKeys[col]; - const refToAdd = `d${docIndex}.${field}` - const editedField = this._referenceSelectMode.currEditing ? this._referenceSelectMode.currEditing as SchemaCellField : null; - editedField?.appendText(refToAdd); - editedField?.setupRefSelect(false); - return; - } - + @action + selectCell = (doc: Doc, col: number, shiftKey: boolean, ctrlKey: boolean) => { this.closeColumnMenu(); if (!shiftKey && !ctrlKey) this.clearSelection(); !this._selectedCells && (this._selectedCells = []); @@ -687,12 +687,14 @@ export class CollectionSchemaView extends CollectionSubView() { @action deselectCell = (doc: Doc) => { + console.log('single deselect called') this._selectedCells && (this._selectedCells = this._selectedCells.filter(d => d !== doc)); if (this.rowIndex(doc) === this._lowestSelectedIndex) this._lowestSelectedIndex = Math.min(...this._selectedDocs.map(d => this.rowIndex(d))); }; @action deselectAllCells = () => { + console.log('deselectall called') this._selectedCells = []; this._lowestSelectedIndex = -1; }; diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index 84b4d3462..06d3926a8 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -62,6 +62,7 @@ export class SchemaCellField extends ObservableReactComponent this._editing, editing => { if (editing) { + if (this.lastChar !== '+') this.setupRefSelect(false); setTimeout(() => { if (this._inputref?.innerText.startsWith('=') || this._inputref?.innerText.startsWith(':=')) { this._overlayDisposer?.(); @@ -145,8 +146,8 @@ export class SchemaCellField extends ObservableReactComponent { - this._unrenderedContent += text; - this.setContent(this._unrenderedContent); + const newText = this._unrenderedContent.concat(text); + this.onChange(undefined, newText); } @action @@ -209,9 +210,9 @@ export class SchemaCellField extends ObservableReactComponent) => { + onChange = (e: FormEvent | undefined, newText?: string) => { const prevVal = this._unrenderedContent; - const targVal = e.currentTarget.innerText; + const targVal = newText ?? e!.currentTarget.innerText; // TODO: bang if (!(targVal.startsWith(':=') || targVal.startsWith('='))) { this._overlayDisposer?.(); this._overlayDisposer = undefined; @@ -319,7 +320,7 @@ export class SchemaCellField extends ObservableReactComponent { this._inputref = r; }} style={{ cursor: 'text', outline: 'none', overflow: 'auto', minHeight: `min(100%, ${(this._props.GetValue()?.split('\n').length || 1) * 15})`, minWidth: 20, }} - onBlur={e => this.finalizeEdit(false, true, false)} + onBlur={e => {this._props.refSelectModeInfo.enabled ? setTimeout(() => {this.setIsFocused(true)}, 1000) : this.finalizeEdit(false, true, false)}} autoFocus onInput={this.onChange} onKeyDown={this.onKeyDown} diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index b15804d41..3f5c2a90e 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -23,6 +23,7 @@ import { CollectionFreeFormView } from '../collectionFreeForm'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { infoState } from '../collectionFreeForm/CollectionFreeFormInfoState'; +import { TbShieldX } from 'react-icons/tb'; interface SchemaRowBoxProps extends FieldViewProps { rowIndex: number; @@ -127,6 +128,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { columnWidth = computedFn((index: number) => () => this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth); computeRowIndex = () => this.schemaView?.rowIndex(this.Document); highlightCells = (text: string) => this.schemaView?.highlightCells(text); + selectReference = (doc: Doc, col: number) => {this.schemaView.selectReference(doc, col)} eqHighlightFunc = (text: string) => { const info = this.schemaView.findCellRefs(text); const cells: HTMLDivElement[] = []; @@ -175,6 +177,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() {
{this.schemaView?.columnKeys?.map((key, index) => ( ; func: (text: string) => HTMLDivElement[] | []; refSelectModeInfo: {enabled: boolean, currEditing: SchemaCellField | undefined}; + selectReference: (doc: Doc, col: number) => void; } function selectedCell(props: SchemaTableCellProps) { @@ -254,6 +255,13 @@ export class SchemaTableCell extends ObservableReactComponent StopEvent(e)} onPointerDown={action(e => { + if (this._props.refSelectModeInfo.enabled && !selectedCell(this._props)){ + e.stopPropagation(); + e.preventDefault(); + this._props.selectReference(this._props.Document, this._props.col); + return; + } + const shift: boolean = e.shiftKey; const ctrl: boolean = e.ctrlKey; if (this._props.isRowActive?.()) { -- cgit v1.2.3-70-g09d2 From aad1ca740bcbad129dc23a5d8f71e3caae787d43 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Tue, 25 Jun 2024 12:26:00 -0400 Subject: cursor position reset properly, appendtext has atCursor option --- .../collectionSchema/CollectionSchemaView.tsx | 2 +- .../collections/collectionSchema/SchemaCellField.tsx | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 3b5a32ca7..32106e3be 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -658,7 +658,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); + editedField?.appendText(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 06d3926a8..8c4c1cd76 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -45,8 +45,10 @@ export class SchemaCellField extends ObservableReactComponent 0; --i) { if (text.charCodeAt(i) !== 160 && text.charCodeAt(i) !== 32) { return text[i]; @@ -62,7 +64,7 @@ export class SchemaCellField extends ObservableReactComponent this._editing, editing => { if (editing) { - if (this.lastChar !== '+') this.setupRefSelect(false); + if (this.lastCharBeforeCursor !== '+') this.setupRefSelect(false); setTimeout(() => { if (this._inputref?.innerText.startsWith('=') || this._inputref?.innerText.startsWith(':=')) { this._overlayDisposer?.(); @@ -145,9 +147,13 @@ export class SchemaCellField extends ObservableReactComponent { - const newText = this._unrenderedContent.concat(text); + appendText = (text: string, atCursorPos?: 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); this.onChange(undefined, newText); + setTimeout(() => this.restoreCursorPosition(robustPos + text.length), 0); } @action @@ -222,8 +228,8 @@ export class SchemaCellField extends ObservableReactComponent Date: Tue, 25 Jun 2024 13:17:54 -0400 Subject: enhanced refselect logic --- .../collectionSchema/CollectionSchemaView.tsx | 3 --- .../collectionSchema/SchemaCellField.tsx | 28 +++++++++++----------- 2 files changed, 14 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 32106e3be..583829d6c 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -296,7 +296,6 @@ export class CollectionSchemaView extends CollectionSubView() { break; } case 'P': { - console.log(this._cellHighlightColors) break; } default: @@ -687,14 +686,12 @@ export class CollectionSchemaView extends CollectionSubView() { @action deselectCell = (doc: Doc) => { - console.log('single deselect called') this._selectedCells && (this._selectedCells = this._selectedCells.filter(d => d !== doc)); if (this.rowIndex(doc) === this._lowestSelectedIndex) this._lowestSelectedIndex = Math.min(...this._selectedDocs.map(d => this.rowIndex(d))); }; @action deselectAllCells = () => { - console.log('deselectall called') this._selectedCells = []; this._lowestSelectedIndex = -1; }; diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index 8c4c1cd76..72d89adc3 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -57,6 +57,11 @@ export class SchemaCellField extends ObservableReactComponent this._editing, editing => { if (editing) { - if (this.lastCharBeforeCursor !== '+') this.setupRefSelect(false); + this.setupRefSelect(this.refSelectConditionMet); setTimeout(() => { if (this._inputref?.innerText.startsWith('=') || this._inputref?.innerText.startsWith(':=')) { this._overlayDisposer?.(); this._overlayDisposer = OverlayView.Instance.addElement(, { x: 0, y: 0 }); this._props.highlightCells?.(this._unrenderedContent); - this.setContent(this._unrenderedContent, true); + this.setContent(this._unrenderedContent); + setTimeout(() => this.setCursorPosition(this._unrenderedContent.length), 0); } }); } else { @@ -139,11 +145,9 @@ export class SchemaCellField extends ObservableReactComponent { + const pos = this.cursorPosition; this._displayedContent = this.makeSpans(content); - if (restoreCursorPos) { - const cursorPos = this.cursorPosition; - setTimeout(() => this.restoreCursorPosition(cursorPos), 0); - } + restoreCursorPos && setTimeout(() => this.setCursorPosition(pos), 0); } @action @@ -153,7 +157,7 @@ export class SchemaCellField extends ObservableReactComponent this.restoreCursorPosition(robustPos + text.length), 0); + setTimeout(() => this.setCursorPosition(robustPos + text.length), 0); } @action @@ -173,12 +177,10 @@ export class SchemaCellField extends ObservableReactComponent { + setCursorPosition = (position: number | null) => { const selection = window.getSelection(); if (!selection || position === null || !this._inputref) return; @@ -228,9 +230,7 @@ export class SchemaCellField extends ObservableReactComponent { @@ -269,7 +269,7 @@ export class SchemaCellField extends ObservableReactComponent { this.setContent(this._unrenderedContent); - setTimeout(() => this.restoreCursorPosition(cursorPos), 0); + setTimeout(() => this.setCursorPosition(cursorPos), 0); } , 0); break; -- cgit v1.2.3-70-g09d2 From a9494a1959430ffb3f501ef59f699aabc3748c7d Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Tue, 25 Jun 2024 13:49:35 -0400 Subject: changing cursor position updates refselectmode --- src/client/views/collections/collectionSchema/SchemaCellField.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index 72d89adc3..7bdfaa587 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -219,6 +219,7 @@ export class SchemaCellField extends ObservableReactComponent | undefined, newText?: string) => { + console.log('onchange called') const prevVal = this._unrenderedContent; const targVal = newText ?? e!.currentTarget.innerText; // TODO: bang if (!(targVal.startsWith(':=') || targVal.startsWith('='))) { @@ -230,6 +231,7 @@ export class SchemaCellField extends ObservableReactComponent this.setupRefSelect(this.refSelectConditionMet), 0) break; case ' ': e.stopPropagation(); @@ -330,7 +333,7 @@ export class SchemaCellField extends ObservableReactComponent e.stopPropagation} + onPointerDown={e => {e.stopPropagation(); setTimeout(() => this.setupRefSelect(this.refSelectConditionMet), 0)}} //timeout callback ensures that refSelectMode is properly set onClick={e => e.stopPropagation} onPointerUp={e => e.stopPropagation} onPointerMove={e => {e.stopPropagation(); e.preventDefault()}} -- cgit v1.2.3-70-g09d2 From 830121ffc5d3d7ba9c5bd48771b6927d24dfce59 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 26 Jun 2024 13:10:47 -0400 Subject: removing 0s from settimeut + minor sorted col highlight color change --- .../collectionSchema/CollectionSchemaView.tsx | 4 ++-- .../collectionSchema/SchemaCellField.tsx | 22 +++++++++++++--------- 2 files changed, 15 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 583829d6c..57327a008 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -206,7 +206,7 @@ export class CollectionSchemaView extends CollectionSubView() { ) this._disposers.sortHighlight = reaction( () => [this.sortField, this._docs, this._selectedDocs, this._highlightedCellsInfo], - () => {this.sortField && setTimeout(() => this.highlightSortedColumn(), 0)}, + () => {this.sortField && setTimeout(() => this.highlightSortedColumn())}, {fireImmediately: true} ) } @@ -505,7 +505,7 @@ export class CollectionSchemaView extends CollectionSubView() { if (field || this.sortField){ index = this.columnKeys.indexOf(field || this.sortField); const increment: number = 100/rowCount; - for (let i = 0; i < rowCount; ++i){ + for (let i = 1; i <= rowCount; ++i){ const adjColor = ClientUtils.lightenRGB(16, 66, 230, increment * i); highlightColors.push(`solid 2px rgb(${adjColor[0]}, ${adjColor[1]}, ${adjColor[2]})`); } diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index 7bdfaa587..8e751f4ba 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -40,11 +40,13 @@ export class SchemaCellField extends ObservableReactComponent { this._unrenderedContent = this._props.GetValue() ?? ''; this.setContent(this._unrenderedContent); - }, 0); //must be moved to end of batch or else other docs aren't loaded, so render as d-1 in function + }); //must be moved to end of batch or else other docs aren't loaded, so render as d-1 in function } get docIndex(){return DocumentView.getDocViewIndex(this._props.Document);} // prettier-ignore + get selfRefPattern() {return `d${this.docIndex}.${this._props.fieldKey}`}; + @computed get lastCharBeforeCursor(){ const pos = this.cursorPosition; const content = this._unrenderedContent; @@ -76,7 +78,7 @@ export class SchemaCellField extends ObservableReactComponent, { x: 0, y: 0 }); this._props.highlightCells?.(this._unrenderedContent); this.setContent(this._unrenderedContent); - setTimeout(() => this.setCursorPosition(this._unrenderedContent.length), 0); + setTimeout(() => this.setCursorPosition(this._unrenderedContent.length)); } }); } else { @@ -114,7 +116,8 @@ export class SchemaCellField extends ObservableReactComponent { - return `${text}` + const selfRef = text === this.selfRefPattern; + return `${text}`; } makeSpans = (content: string) => { @@ -147,7 +150,7 @@ export class SchemaCellField extends ObservableReactComponent { const pos = this.cursorPosition; this._displayedContent = this.makeSpans(content); - restoreCursorPos && setTimeout(() => this.setCursorPosition(pos), 0); + restoreCursorPos && setTimeout(() => this.setCursorPosition(pos)); } @action @@ -157,7 +160,7 @@ export class SchemaCellField extends ObservableReactComponent this.setCursorPosition(robustPos + text.length), 0); + setTimeout(() => this.setCursorPosition(robustPos + text.length)); } @action @@ -219,7 +222,6 @@ export class SchemaCellField extends ObservableReactComponent | undefined, newText?: string) => { - console.log('onchange called') const prevVal = this._unrenderedContent; const targVal = newText ?? e!.currentTarget.innerText; // TODO: bang if (!(targVal.startsWith(':=') || targVal.startsWith('='))) { @@ -231,7 +233,6 @@ export class SchemaCellField extends ObservableReactComponent { this.setContent(this._unrenderedContent); - setTimeout(() => this.setCursorPosition(cursorPos), 0); + setTimeout(() => this.setCursorPosition(cursorPos)); } , 0); break; @@ -298,7 +299,10 @@ export class SchemaCellField extends ObservableReactComponent Date: Wed, 26 Jun 2024 13:48:25 -0400 Subject: self-reference warning added --- src/client/views/collections/collectionSchema/SchemaCellField.tsx | 6 +++++- src/client/views/collections/collectionSchema/SchemaRowBox.tsx | 2 +- src/client/views/collections/collectionSchema/SchemaTableCell.tsx | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index 8e751f4ba..27ca37c2b 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -33,6 +33,7 @@ export class SchemaCellField extends ObservableReactComponent() { void; equationHighlightRef: ObservableMap; - func: (text: string) => HTMLDivElement[] | []; + eqHighlightFunc: (text: string) => HTMLDivElement[] | []; refSelectModeInfo: {enabled: boolean, currEditing: SchemaCellField | undefined}; selectReference: (doc: Doc, col: number) => void; } @@ -190,7 +190,7 @@ export class SchemaTableCell extends ObservableReactComponent this._props.highlightCells(this.adjustSelfReference(text))} - getCells={(text: string) => this._props.func(this.adjustSelfReference(text))} + getCells={(text: string) => this._props.eqHighlightFunc(this.adjustSelfReference(text))} ref={r => selectedCell(this._props) && this._props.autoFocus && r?.setIsFocused(true)} oneLine={this._props.oneLine} contents={undefined} -- cgit v1.2.3-70-g09d2 From 22760f7f9d79511862851a0d8289b9a6ff9956e7 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 26 Jun 2024 14:22:39 -0400 Subject: freeze fixed (revisit why this change was needed?) --- .../views/collections/collectionSchema/CollectionSchemaView.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 57327a008..497c781fd 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -105,7 +105,7 @@ export class CollectionSchemaView extends CollectionSubView() { @observable _highlightedCellsInfo: Array<[doc: Doc, field: string]> = []; @observable _cellHighlightColors: ObservableMap = new ObservableMap(); @observable _docs: Doc[] = []; - @observable _referenceSelectMode = {enabled: false, currEditing: undefined} + @observable _referenceSelectMode: {enabled: boolean, currEditing: SchemaCellField | undefined} = {enabled: false, currEditing: undefined} // target HTMLelement portal for showing a popup menu to edit cell values. public get MenuTarget() { @@ -114,7 +114,8 @@ export class CollectionSchemaView extends CollectionSubView() { @computed get _selectedDocs() { // get all selected documents then filter out any whose parent is not this schema document - const selected = DocumentView.SelectedDocs().filter(doc => this.docs.includes(doc) && this._selectedCells.includes(doc)); + const selected = DocumentView.SelectedDocs().filter(doc => this.docs.includes(doc)); + //&& this._selectedCells.includes(doc) if (!selected.length) { // if no schema doc is directly selected, test if a child of a schema doc is selected (such as in the preview window) const childOfSchemaDoc = DocumentView.SelectedDocs().find(sel => DocumentView.getContextPath(sel, true).includes(this.Document)); -- cgit v1.2.3-70-g09d2 From 8ceaba8b8264f5519de732cc603dcd276b4b4f4d Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Fri, 28 Jun 2024 01:49:10 -0400 Subject: header text no longer shifts left on hover --- src/client/documents/Documents.ts | 6 +++++ src/client/util/Scripting.ts | 9 ++++++-- .../collectionSchema/CollectionSchemaView.scss | 1 - .../collectionSchema/SchemaCellField.tsx | 4 +++- .../collectionSchema/SchemaColumnHeader.tsx | 6 ++--- .../collections/collectionSchema/SchemaRowBox.tsx | 6 +---- .../collectionSchema/SchemaTableCell.tsx | 26 +++++++++++++++++----- src/client/views/nodes/FieldView.tsx | 2 +- src/client/views/nodes/KeyValueBox.tsx | 2 +- 9 files changed, 43 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index dabbf9591..1b1608cd5 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -143,7 +143,12 @@ class ListInfo extends FInfo { fieldType? = FInfoFieldType.list; values?: List[] = []; } +class MapInfo extends FInfo { + fieldType? = FInfoFieldType.list; + values?: List[] = []; +} type BOOLt = BoolInfo | boolean; +type MAPt = MapInfo | Map; type NUMt = NumInfo | number; type STRt = StrInfo | string; type LISTt = ListInfo | List; @@ -229,6 +234,7 @@ export class DocumentOptions { _lockedTransform?: BOOLt = new BoolInfo('lock the freeform_panx,freeform_pany and scale parameters of the document so that it be panned/zoomed'); _childrenSharedWithSchema?: BOOLt = new BoolInfo("whether this document's children are displayed in its parent schema view", false); _lockedSchemaEditing?: BOOLt = new BoolInfo("", false); + _schemaInputs?: LISTt = new ListInfo('user inputs to schema field', false) dataViz_title?: string; dataViz_line?: string; diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index 6ef592ef2..c7aa56c1e 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -183,14 +183,19 @@ function forEachNode(node: ts.Node, onEnter: Traverser, onExit?: Traverser, inde ); } +ScriptField.CompileScript(value, {}, true, undefined, DocumentIconContainer.getTransformer()); +//addreturn = true +//capturedvariables = undefined +// + export function CompileScript(script: string, options: ScriptOptions = {}): CompileResult { - const captured = options.capturedVariables ?? {}; + const captured = options.capturedVariables ?? {}; const signature = Object.keys(captured).reduce((p, v) => { const formatCapture = (obj: any) => `${v}=${obj instanceof RefField ? 'XXX' : obj.toString()}`; if (captured[v] instanceof Array) return p + (captured[v] as any).map(formatCapture); return p + formatCapture(captured[v]); }, ''); - const found = ScriptField.GetScriptFieldCache(script + ':' + signature); + const found = ScriptField.GetScriptFieldCache(script + ':' + signature); // if already compiled, found is the result; cache set below if (found) return found as CompiledScript; const { requiredType = '', addReturn = false, params = {}, capturedVariables = {}, typecheck = true } = options; if (options.params && !options.params.this) options.params.this = Doc.name; diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss index 6b53eb1cc..425b67fa9 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss @@ -155,7 +155,6 @@ padding: 0; z-index: 1; border: 1px solid $medium-gray; - //overflow: hidden; .schema-column-title { flex-grow: 2; diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index 27ca37c2b..c7c483df8 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -321,11 +321,13 @@ export class SchemaCellField extends ObservableReactComponent + staticDisplay = () => { return { // eslint-disable-next-line react/jsx-props-no-spreading - this._props.fieldContents ? : this.props.contents ? this._props.contents?.valueOf() : '' + this._props.fieldContents ? : '' } } diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index d16cde1f8..83a136737 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -237,11 +237,11 @@ export class SchemaColumnHeader extends ObservableReactComponent
this._props.resizeColumn(e, this._props.columnIndex)} /> -
{this.editableView}
+
{this.editableView}
-
- {this.displayButton ? this.headerButton : null} +
+ {this.headerButton}
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index c9feeac6b..077d95c57 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -97,10 +97,6 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { return '' } - @computed get refSelectModeInfo() { - return this.schemaView._referenceSelectMode; - } - @computed get menuInfos() { const infos: Array = []; if (this.Document._lockedSchemaEditing) infos.push('lock'); @@ -178,7 +174,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { {this.schemaView?.columnKeys?.map((key, index) => ( { // private _fieldRef: SchemaCellField | null = null; + private _submittedValue: string = ''; constructor(props: SchemaTableCellProps) { super(props); @@ -157,19 +159,31 @@ export class SchemaTableCell extends ObservableReactComponent { - const idPattern = /idToDoc\((.*?)\)/g; let modField = field.slice(); + let eqSymbol: string = ''; + if (modField.startsWith('=')) {modField = modField.substring(1); eqSymbol += '=';} + if (modField.startsWith(':=')) {modField = modField.substring(2); eqSymbol += ':=';} + + const idPattern = /idToDoc\((.*?)\)/g; let matches; let results = new Array<[id: string, func: string]>(); while ((matches = idPattern.exec(field)) !== null) {results.push([matches[0], matches[1].replace(/"/g, '')]); } results.forEach((idFuncPair) => {modField = modField.replace(idFuncPair[0], 'd' + (DocumentView.getDocViewIndex(IdToDoc(idFuncPair[1]))).toString());}) - if (modField.charAt(modField.length - 1) === ';') modField = modField.substring(0, modField.length - 1); + + for (let i = 0; i < modField.length; ++i){ + + } + + if (modField.endsWith(';')) modField = modField.substring(0, modField.length - 1); + + const inQuotes = (field: string) => {return ((field.startsWith('`') && field.endsWith('`')) || (field.startsWith("'") && field.endsWith("'")) || (field.startsWith('"') && field.endsWith('"')))} + if (!inQuotes(this._submittedValue) && inQuotes(modField)) modField = modField.substring(1, modField.length - 1); const selfRefPattern = `d${this.docIndex}.${this._props.fieldKey}` const selfRefRegX = RegExp(selfRefPattern, 'g'); if (selfRefRegX.exec(modField) !== null) { return 'Invalid'} - return modField; + return eqSymbol + modField; } @computed get defaultCellContent() { @@ -196,7 +210,8 @@ export class SchemaTableCell extends ObservableReactComponent this.cleanupField(Field.toKeyValueString(fieldProps.Document, this._props.fieldKey, SnappingManager.MetaKey))} + ////const script = ScriptCast(fieldProps.Document[this._props.fieldKey]).rawscript; + GetValue={() => ScriptCast(fieldProps.Document[this._props.fieldKey])?.rawscript ?? ''} SetValue={undoable((value: string, shiftDown?: boolean, enterKey?: boolean) => { if (shiftDown && enterKey) { this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), value); @@ -205,6 +220,7 @@ export class SchemaTableCell extends ObservableReactComponent { const field = this.fieldval; // prettier-ignore if (field instanceof Doc) return

{field.title?.toString()}

; - if (field === undefined) return

{''}

; + if (field === undefined) return

{''}

; if (field instanceof DateField) return

{field.date.toLocaleString()}

; if (field instanceof List) return
{field.map(f => Field.toString(f)).join(', ')}
; if (field instanceof WebField) return

{Field.toString(field.url.href)}

; diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 66e210c03..bc6633f23 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -88,7 +88,7 @@ export class KeyValueBox extends ViewBoxBaseComponent() { const type: 'computed' | 'script' | false = rawvalue.startsWith(':=') ? 'computed' : rawvalue.startsWith('$=') ? 'script' : false; rawvalue = type ? rawvalue.substring(2) : rawvalue; rawvalue = rawvalue.replace(/.*\(\((.*)\)\)/, 'dashCallChat(_setCacheResult_, this, `$1`)'); - const value = ["'", '"', '`'].includes(rawvalue.length ? rawvalue[0] : '') || !isNaN(rawvalue as any) ? rawvalue : '`' + rawvalue + '`'; + const value = (["'", '"', '`'].includes(rawvalue.length ? rawvalue[0] : '') || !isNaN(rawvalue as any)) ? rawvalue : '`' + rawvalue + '`'; let script = ScriptField.CompileScript(rawvalue, {}, true, undefined, DocumentIconContainer.getTransformer()); if (!script.compiled) { -- cgit v1.2.3-70-g09d2 From 21a9278abe3bab3a7da7eef079a27169cc2cd49c Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Fri, 28 Jun 2024 13:24:40 -0400 Subject: col drag stutter fixed --- src/client/util/Scripting.ts | 8 +-- .../collectionSchema/CollectionSchemaView.tsx | 70 ++++++++++++++-------- .../collectionSchema/SchemaColumnHeader.tsx | 2 + .../collectionSchema/SchemaTableCell.tsx | 6 +- 4 files changed, 52 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index c7aa56c1e..5202e62a3 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -183,10 +183,10 @@ function forEachNode(node: ts.Node, onEnter: Traverser, onExit?: Traverser, inde ); } -ScriptField.CompileScript(value, {}, true, undefined, DocumentIconContainer.getTransformer()); -//addreturn = true -//capturedvariables = undefined -// +// ScriptField.CompileScript(value, {}, true, undefined, DocumentIconContainer.getTransformer()); +// //addreturn = true +// //capturedvariables = undefined +// // export function CompileScript(script: string, options: ScriptOptions = {}): CompileResult { const captured = options.capturedVariables ?? {}; diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 497c781fd..93347f067 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -95,7 +95,7 @@ export class CollectionSchemaView extends CollectionSubView() { @observable _filterSearchValue: string = ''; @observable _selectedCol: number = 0; @observable _selectedCells: Array = []; - @observable _mouseCoordinates = { x: 0, y: 0 }; + @observable _mouseCoordinates = { x: 0, y: 0, prevX: 0, prevY: 0 }; @observable _lowestSelectedIndex: number = -1; //lowest index among selected rows; used to properly sync dragged docs with cursor position @observable _relCursorIndex: number = -1; //cursor index relative to the current selected cells @observable _draggedColIndex: number = 0; @@ -413,7 +413,7 @@ export class CollectionSchemaView extends CollectionSubView() { dragColumn = (e: PointerEvent, index: number) => { this.closeColumnMenu(); this._draggedColIndex = index; - this._colBeingDragged = true; + this.setColDrag(true); const dragData = new DragManager.ColumnDragData(index); const dragEles = [this._colEles[index]]; this.childDocs.forEach(doc => dragEles.push(this._rowEles.get(doc).children[1].children[index])); @@ -499,6 +499,26 @@ export class CollectionSchemaView extends CollectionSubView() { }); }); + removeDragHighlight = () => { + this._colEles.forEach((colRef, i) => { + const sorted = i === this.columnKeys.indexOf(this.sortField); + if (sorted) return; + + colRef.style.borderLeft = ''; + colRef.style.borderRight = ''; + colRef.style.borderTop = ''; + + this.childDocs.forEach(doc => { + const cell = this._rowEles.get(doc).children[1].children[i]; + if (!(this._selectedDocs.includes(doc) && i === this._selectedCol) && !(this.highlightedCells.includes(cell))) { + cell.style.borderLeft = ''; + cell.style.borderRight = ''; + cell.style.borderBottom = ''; + } + }); + }); + } + highlightSortedColumn = (field?: string, descending?: boolean) => { let index = -1; let highlightColors: string[] = []; @@ -703,28 +723,11 @@ export class CollectionSchemaView extends CollectionSubView() { return this.findRowDropIndex(mouseY); } + @action onInternalDrop = (e: Event, de: DragManager.DropEvent) => { if (de.complete.columnDragData) { - this._colBeingDragged = false; + this.setColDrag(false); e.stopPropagation(); - - this._colEles.forEach((colRef, i) => { - const sorted = i === this.columnKeys.indexOf(this.sortField); - if (sorted) return; - - colRef.style.borderLeft = ''; - colRef.style.borderRight = ''; - colRef.style.borderTop = ''; - - this.childDocs.forEach(doc => { - const cell = this._rowEles.get(doc).children[1].children[i]; - if (!(this._selectedDocs.includes(doc) && i === this._selectedCol) && !(this.highlightedCells.includes(cell))) { - cell.style.borderLeft = ''; - cell.style.borderRight = ''; - cell.style.borderBottom = ''; - } - }); - }); return true; } @@ -1196,18 +1199,33 @@ export class CollectionSchemaView extends CollectionSubView() { ); } + @action setColDrag = (beingDragged: boolean) => { + this._colBeingDragged = beingDragged; + !beingDragged && this.removeDragHighlight(); + } + + @action updateMouseCoordinates = (e: React.PointerEvent) => { + const prevX = this._mouseCoordinates.x; + const prevY = this._mouseCoordinates.y; + this._mouseCoordinates = { x: e.clientX, y: e.clientY, prevX: prevX, prevY: prevY }; + } + @action onPointerMove = (e: React.PointerEvent) => { if (DragManager.docsBeingDragged.length) { - this._mouseCoordinates = { x: e.clientX, y: e.clientY }; + this.updateMouseCoordinates(e); } if (this._colBeingDragged) { + this.updateMouseCoordinates(e); const newIndex = this.findColDropIndex(e.clientX); - if (newIndex !== this._draggedColIndex) this.moveColumn(this._draggedColIndex, newIndex ?? this._draggedColIndex); - this._draggedColIndex = newIndex || this._draggedColIndex; + const direction: number = this._mouseCoordinates.x > this._mouseCoordinates.prevX ? 1 : 0; + if (newIndex !== undefined && ((newIndex > this._draggedColIndex && direction === 1) || (newIndex < this._draggedColIndex && direction === 0))) { + this.moveColumn(this._draggedColIndex, newIndex ?? this._draggedColIndex); + this._draggedColIndex = newIndex !== undefined ? newIndex : this._draggedColIndex; + } this.highlightSortedColumn(); //TODO: Make this more efficient this.restoreCellHighlights(); - !(this.sortField && this._draggedColIndex === this.columnKeys.indexOf(this.sortField)) && this.highlightDraggedColumn(newIndex ?? this._draggedColIndex); + !(this.sortField && this._draggedColIndex === this.columnKeys.indexOf(this.sortField)) && this.highlightDraggedColumn(this._draggedColIndex); } }; @@ -1286,7 +1304,7 @@ export class CollectionSchemaView extends CollectionSubView() {
this.createDashEventsTarget(ele)} onDrop={this.onExternalDrop.bind(this)} onPointerMove={e => this.onPointerMove(e)} - onPointerDown={() => this.closeColumnMenu()}> + onPointerDown={() => {this.closeColumnMenu(); this.setColDrag(false)}}>
+ +
this._props.resizeColumn(e, this._props.columnIndex)} />
); } diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index c0e1743a5..d06e2a147 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -16,7 +16,7 @@ import { DateField } from '../../../../fields/DateField'; import { Doc, DocListCast, Field, IdToDoc } from '../../../../fields/Doc'; import { RichTextField } from '../../../../fields/RichTextField'; import { ColumnType } from '../../../../fields/SchemaHeaderField'; -import { BoolCast, Cast, DateCast, DocCast, FieldValue, ScriptCast, StrCast, toList } from '../../../../fields/Types'; +import { BoolCast, Cast, DateCast, DocCast, FieldValue, StrCast, toList } from '../../../../fields/Types'; import { ImageField } from '../../../../fields/URLField'; import { FInfo, FInfoFieldType } from '../../../documents/Documents'; import { dropActionType } from '../../../util/DropActionTypes'; @@ -35,7 +35,6 @@ import './CollectionSchemaView.scss'; import { SchemaColumnHeader } from './SchemaColumnHeader'; import { ContextMenu } from '../../ContextMenu'; import { SchemaCellField } from './SchemaCellField'; -import { ComputedField } from '../../../../fields/ScriptField'; export interface SchemaTableCellProps { Document: Doc; @@ -210,8 +209,7 @@ export class SchemaTableCell extends ObservableReactComponent ScriptCast(fieldProps.Document[this._props.fieldKey])?.rawscript ?? ''} + GetValue={() => this.cleanupField(Field.toKeyValueString(fieldProps.Document, this._props.fieldKey, SnappingManager.MetaKey))} SetValue={undoable((value: string, shiftDown?: boolean, enterKey?: boolean) => { if (shiftDown && enterKey) { this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), value); -- cgit v1.2.3-70-g09d2 From b01f8732034396114c6a37665054de1617ccda1b Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Fri, 28 Jun 2024 14:32:27 -0400 Subject: fixed selected row highlight on new col --- src/client/views/collections/collectionSchema/SchemaRowBox.tsx | 5 +---- src/client/views/collections/collectionSchema/SchemaTableCell.tsx | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index 077d95c57..9ac7a24b2 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -90,10 +90,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { } @computed get menuBackgroundColor(){ - if (this.Document._lockedSchemaEditing){ - if (this._props.isSelected()) return '#B0D1E7' - else return '#F5F5F5' - } + if (this.Document._lockedSchemaEditing) {return '#F5F5F5'} return '' } diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index d06e2a147..084306c4a 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -94,10 +94,7 @@ export class SchemaTableCell extends ObservableReactComponent Date: Fri, 28 Jun 2024 14:44:00 -0400 Subject: row drag changes saved through reload --- src/client/views/collections/collectionSchema/CollectionSchemaView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 93347f067..ee693078f 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -734,7 +734,7 @@ export class CollectionSchemaView extends CollectionSubView() { const draggedDocs = de.complete.docDragData?.draggedDocuments; if (draggedDocs && super.onInternalDrop(e, de) && !this.sortField) { const docs = this.docsWithDrag.docs.slice(); - this._docs = docs; + this.dataDoc[this.fieldKey ?? 'data'] = new List([...docs]); this.clearSelection(); draggedDocs.forEach(doc => { DocumentView.addViewRenderedCb(doc, dv => dv.select(true)); -- cgit v1.2.3-70-g09d2 From db7e5ed3ac36f05787b809e2ae03c94f310ef3e4 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Fri, 28 Jun 2024 19:26:23 -0400 Subject: colkeys menu width conforms to column with --- .../collections/collectionSchema/CollectionSchemaView.scss | 9 +-------- .../collections/collectionSchema/CollectionSchemaView.tsx | 13 ++----------- 2 files changed, 3 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss index 425b67fa9..e3f3dafab 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss @@ -51,8 +51,6 @@ .schema-filter-menu { background: $light-gray; position: absolute; - min-width: 150px; - max-width: 300px; max-height: 300px; display: flex; overflow: hidden; @@ -60,11 +58,6 @@ align-items: flex-start; z-index: 5; - .schema-key-search-input { - width: calc(100% - 20px); - margin: 10px; - } - .schema-search-result { cursor: pointer; padding: 5px 10px; @@ -106,7 +99,7 @@ .schema-key-list { width: 100%; - max-height: 300px; + max-height: 250px; overflow-y: auto; } diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index ee693078f..a3bc537d2 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -154,7 +154,6 @@ export class CollectionSchemaView extends CollectionSubView() { ); const totalWidth = widths.reduce((sum, width) => sum + width, 0); - // If the total width of all columns is not the width of the schema table minus the width of the row menu, resize them appropriately if (totalWidth !== this.tableWidth - CollectionSchemaView._rowMenuWidth) { return widths.map(w => (w / totalWidth) * (this.tableWidth - CollectionSchemaView._rowMenuWidth)); } @@ -1133,15 +1132,7 @@ export class CollectionSchemaView extends CollectionSubView() { @computed get renderColumnMenu() { const x = this._columnMenuIndex! === -1 ? 0 : this.displayColumnWidths.reduce((total, curr, index) => total + (index < this._columnMenuIndex! ? curr : 0), CollectionSchemaView._rowMenuWidth); return ( -
- {this.keysDropdown} -
- ); - } - - get renderKeysMenu() { - return ( -
+
{this.keysDropdown}
); @@ -1184,7 +1175,7 @@ export class CollectionSchemaView extends CollectionSubView() { @computed get renderFilterMenu() { const x = this.displayColumnWidths.reduce((total, curr, index) => total + (index < this._filterColumnIndex! ? curr : 0), CollectionSchemaView._rowMenuWidth); return ( -
+
e.stopPropagation()} /> {this.renderFilterOptions}
Date: Fri, 28 Jun 2024 19:36:44 -0400 Subject: dragging col stops editing of schema header --- .../views/collections/collectionSchema/CollectionSchemaView.tsx | 3 +++ src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx | 5 +++++ 2 files changed, 8 insertions(+) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index a3bc537d2..e4ffc5b13 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -67,6 +67,7 @@ export class CollectionSchemaView extends CollectionSubView() { private _documentOptions: DocumentOptions = new DocumentOptions(); private _tableContentRef: HTMLDivElement | null = null; private _menuTarget = React.createRef(); + private _headerRefs: SchemaColumnHeader[] = []; constructor(props: any) { super(props); @@ -411,6 +412,7 @@ export class CollectionSchemaView extends CollectionSubView() { @action dragColumn = (e: PointerEvent, index: number) => { this.closeColumnMenu(); + this._headerRefs.forEach(ref => ref.stopEditing()); this._draggedColIndex = index; this.setColDrag(true); const dragData = new DragManager.ColumnDragData(index); @@ -1331,6 +1333,7 @@ export class CollectionSchemaView extends CollectionSubView() { r && this._headerRefs.push(r)} keysDropdown={(this.keysDropdown)} schemaView={this} columnWidth={() => CollectionSchemaView._minColWidth} //TODO: update diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index e98a2c778..382d7487b 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -23,6 +23,7 @@ import { undoable } from '../../../util/UndoManager'; import { FInfo } from '../../../documents/Documents'; import { ColumnType } from '../../../../fields/SchemaHeaderField'; import { IconButton, Size } from 'browndash-components'; +import { TbHospital } from 'react-icons/tb'; export enum SchemaFieldType { Header, Cell @@ -72,6 +73,10 @@ export class SchemaColumnHeader extends ObservableReactComponent {this._props.schemaView?.setKey(field, defaultValue, this._props.columnIndex);} @action updateAlt = (newAlt: string) => {this._altTitle = newAlt;} @action updateKeyDropdown = (value: string) => {this._props.schemaView.updateKeySearch(value)} + @action stopEditing = () => { + this._inputRef?.setIsEditing(false); + this._inputRef?.setIsFocused(false); + } openKeyDropdown = () => { this._props.schemaView.openColumnMenu(this._props.columnIndex, false) -- cgit v1.2.3-70-g09d2 From 25e69f18cf38587853771be8080035ab8a460e7e Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Sat, 29 Jun 2024 05:39:44 -0400 Subject: cyclic preset colors for eqhighlights --- .../collectionSchema/CollectionSchemaView.tsx | 42 ++++++++++++---------- 1 file changed, 24 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index e4ffc5b13..d3259d42e 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -68,10 +68,26 @@ export class CollectionSchemaView extends CollectionSubView() { private _tableContentRef: HTMLDivElement | null = null; private _menuTarget = React.createRef(); private _headerRefs: SchemaColumnHeader[] = []; + private _eqHighlightColors: Array<[{r: number, g: number, b: number}, {r: number, g: number, b: number}]> = []; constructor(props: any) { super(props); makeObservable(this); + const lightenedColor = (r: number, g: number, b:number) => { + const lightened = ClientUtils.lightenRGB(r, g, b, 165); + return {r: lightened[0], g: lightened[1], b: lightened[2]} + } + const colors = (r: number, g: number, b: number): [any, any] => {return [{r: r, g: g, b: b}, lightenedColor(r, g, b)]} + this._eqHighlightColors.push(colors(70, 150, 50)); + this._eqHighlightColors.push(colors(180, 70, 20)); + this._eqHighlightColors.push(colors(70, 50, 150)); + this._eqHighlightColors.push(colors(0, 140, 140)); + this._eqHighlightColors.push(colors(140, 30, 110)); + this._eqHighlightColors.push(colors(20, 50, 200)); + this._eqHighlightColors.push(colors(210, 30, 40)); + this._eqHighlightColors.push(colors(120, 130, 30)); + this._eqHighlightColors.push(colors(50, 150, 70)); + this._eqHighlightColors.push(colors(10, 90, 180)); } static _rowHeight: number = 50; @@ -607,32 +623,22 @@ export class CollectionSchemaView extends CollectionSubView() { highlightCells = (text: string) => { this.removeCellHighlights(); - const randomRGBColor = (): string[] => { - const brightness = 450; - const r = Math.floor(Math.random() * 256); - const g = Math.floor(Math.random() * Math.min(256, brightness - r)); - const b = Math.floor(brightness - r - g); - - const lightenedRGB = ClientUtils.lightenRGB(r, g, b, 65); - const rL = lightenedRGB[0]; const gL = lightenedRGB[1]; const bL = lightenedRGB[2]; // prettier-ignore - const bgdRGB = {rL, gL, bL}; - - return new Array(`rgb(${r}, ${g}, ${b})`, `rgb(${bgdRGB.rL}, ${bgdRGB.gL}, ${bgdRGB.bL})`); - } - const cellsToHighlight = this.findCellRefs(text); + console.log(cellsToHighlight); this._highlightedCellsInfo = [...cellsToHighlight]; - this._highlightedCellsInfo.forEach(info => { - const color = randomRGBColor(); + + for (let i = 0; i < this._highlightedCellsInfo.length; ++i) { + const info = this._highlightedCellsInfo[i]; + const color = this._eqHighlightColors[i % 10]; + const colorStrings = [`solid 2px rgb(${color[0].r}, ${color[0].g}, ${color[0].b})`, `rgb(${color[1].r}, ${color[1].g}, ${color[1].b})`]; const doc = info[0]; const field = info[1]; const key = `${doc[Id]}_${field}`; const cell = this.getCellElement(doc, field); - if (!this._cellHighlightColors.has(key)) {this._cellHighlightColors.set(key, new Array(`solid 2px ${color[0]}`, color[1]))} + if (!this._cellHighlightColors.has(key)) {this._cellHighlightColors.set(key, [colorStrings[0], colorStrings[1]])} cell.style.border = this._cellHighlightColors.get(key)[0]; cell.style.backgroundColor = this._cellHighlightColors.get(key)[1]; - }); - + } } @action -- cgit v1.2.3-70-g09d2 From 6d8c85aacba7d9ccdedfb85b838e84ad914e6081 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Sat, 29 Jun 2024 19:07:27 -0400 Subject: highlight updates properly when highlighted cell is selected; no longer possible to add EmptyKey to equation --- .../collections/collectionSchema/CollectionSchemaView.tsx | 13 +++++++------ .../views/collections/collectionSchema/SchemaTableCell.tsx | 2 ++ 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index d3259d42e..bcb94e10d 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -73,11 +73,8 @@ export class CollectionSchemaView extends CollectionSubView() { constructor(props: any) { super(props); makeObservable(this); - const lightenedColor = (r: number, g: number, b:number) => { - const lightened = ClientUtils.lightenRGB(r, g, b, 165); - return {r: lightened[0], g: lightened[1], b: lightened[2]} - } - const colors = (r: number, g: number, b: number): [any, any] => {return [{r: r, g: g, b: b}, lightenedColor(r, g, b)]} + const lightenedColor = (r: number, g: number, b:number) => { const lightened = ClientUtils.lightenRGB(r, g, b, 165); return {r: lightened[0], g: lightened[1], b: lightened[2]}} // prettier-ignore + const colors = (r: number, g: number, b: number): [any, any] => {return [{r: r, g: g, b: b}, lightenedColor(r, g, b)]} // prettier-ignore this._eqHighlightColors.push(colors(70, 150, 50)); this._eqHighlightColors.push(colors(180, 70, 20)); this._eqHighlightColors.push(colors(70, 50, 150)); @@ -602,7 +599,11 @@ export class CollectionSchemaView extends CollectionSubView() { } removeCellHighlights = () => { - this.highlightedCells.forEach(cell => {cell.style.border = ''; cell.style.backgroundColor = '';}); + this._highlightedCellsInfo.forEach(info => { + const doc = info[0]; + const cell = this.getCellElement(doc, info[1]); + if (!this._selectedDocs.includes(doc)) cell.style.border = ''; + cell.style.backgroundColor = '';}); this._highlightedCellsInfo = []; } diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 084306c4a..1f5684151 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -266,6 +266,8 @@ export class SchemaTableCell extends ObservableReactComponent StopEvent(e)} onPointerDown={action(e => { + if (this.lockedInteraction) { e.stopPropagation(); e.preventDefault(); return; } + if (this._props.refSelectModeInfo.enabled && !selectedCell(this._props)){ e.stopPropagation(); e.preventDefault(); -- cgit v1.2.3-70-g09d2 From 821e10405c13e125ea439450b7a66090f0c118fa Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Sun, 30 Jun 2024 18:47:20 -0400 Subject: adding columns to left/right of other column --- .../collectionSchema/CollectionSchemaView.tsx | 30 ++++++++++++++-------- .../collectionSchema/SchemaColumnHeader.tsx | 1 - 2 files changed, 20 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index bcb94e10d..49cb86732 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -332,19 +332,19 @@ export class CollectionSchemaView extends CollectionSubView() { }; @undoBatch - addColumn = (key?: string, defaultVal?: any) => { + addColumn = (index: number = 0, key?: string, defaultVal?: any) => { if (key && !this.documentKeys.includes(key)) this.addNewKey(key, defaultVal); const newColWidth = this.tableWidth / (this.storedColumnWidths.length + 1); const currWidths = this.storedColumnWidths.slice(); - currWidths.splice(0, 0, newColWidth); + currWidths.splice(index, 0, newColWidth); const newDesiredTableWidth = currWidths.reduce((w, cw) => w + cw, 0); this.layoutDoc.schema_columnWidths = new List(currWidths.map(w => (w / newDesiredTableWidth) * (this.tableWidth - CollectionSchemaView._rowMenuWidth))); const currKeys = this.columnKeys.slice(); if (!key) key = 'EmptyColumnKey' + Math.floor(Math.random() * 1000000000000000).toString(); - currKeys.splice(0, 0, key); - this.changeColumnKey(0, 'EmptyColumnKey' + Math.floor(Math.random() * 1000000000000000).toString()); + currKeys.splice(index, 0, key); + this.changeColumnKey(index, 'EmptyColumnKey' + Math.floor(Math.random() * 1000000000000000).toString()); this.layoutDoc.schema_columnKeys = new List(currKeys); }; @@ -524,7 +524,7 @@ export class CollectionSchemaView extends CollectionSubView() { this.childDocs.forEach(doc => { const cell = this._rowEles.get(doc).children[1].children[i]; - if (!(this._selectedDocs.includes(doc) && i === this._selectedCol) && !(this.highlightedCells.includes(cell))) { + if (!(this._selectedDocs.includes(doc) && i === this._selectedCol) && !(this.highlightedCells.includes(cell)) && cell) { cell.style.borderLeft = ''; cell.style.borderRight = ''; cell.style.borderBottom = ''; @@ -539,7 +539,7 @@ export class CollectionSchemaView extends CollectionSubView() { const rowCount: number = this._docs.length + 1; if (field || this.sortField){ index = this.columnKeys.indexOf(field || this.sortField); - const increment: number = 100/rowCount; + const increment: number = 110/rowCount; for (let i = 1; i <= rowCount; ++i){ const adjColor = ClientUtils.lightenRGB(16, 66, 230, increment * i); highlightColors.push(`solid 2px rgb(${adjColor[0]}, ${adjColor[1]}, ${adjColor[2]})`); @@ -601,8 +601,9 @@ export class CollectionSchemaView extends CollectionSubView() { removeCellHighlights = () => { this._highlightedCellsInfo.forEach(info => { const doc = info[0]; - const cell = this.getCellElement(doc, info[1]); - if (!this._selectedDocs.includes(doc)) cell.style.border = ''; + const field = info[1]; + const cell = this.getCellElement(doc, field); + if (!(this._selectedDocs.includes(doc) && this._selectedCol === this.columnKeys.indexOf(field))) cell.style.border = ''; cell.style.backgroundColor = '';}); this._highlightedCellsInfo = []; } @@ -625,7 +626,6 @@ export class CollectionSchemaView extends CollectionSubView() { this.removeCellHighlights(); const cellsToHighlight = this.findCellRefs(text); - console.log(cellsToHighlight); this._highlightedCellsInfo = [...cellsToHighlight]; for (let i = 0; i < this._highlightedCellsInfo.length; ++i) { @@ -865,7 +865,7 @@ export class CollectionSchemaView extends CollectionSubView() { if (this.columnKeys.includes(key)) return; if (this._makeNewColumn) { - this.addColumn(key, defaultVal); + this.addColumn(this.columnKeys.indexOf(key), key, defaultVal); this._makeNewColumn = false; } else this.changeColumnKey(this._columnMenuIndex! | index!, key, defaultVal); @@ -1005,6 +1005,16 @@ export class CollectionSchemaView extends CollectionSubView() { subitems: sortOptions, icon: 'sort' }); + cm.addItem({ + description: 'Add column to left', + event: () => this.addColumn(index), + icon: 'plus', + }); + cm.addItem({ + description: 'Add column to right', + event: () => this.addColumn(index + 1), + icon: 'plus', + }); cm.addItem({ description: 'Delete column', event: () => this.removeColumn(index), diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index 382d7487b..70db3d1f5 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -66,7 +66,6 @@ export class SchemaColumnHeader extends ObservableReactComponent this._props.schemaView?.fieldInfos.get(fieldKey)); -- cgit v1.2.3-70-g09d2 From c528298bf2375daff4ba8de170870eddf331aa4e Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Sun, 30 Jun 2024 19:08:37 -0400 Subject: removing column closes menu and stops editing --- .../collections/collectionSchema/CollectionSchemaView.tsx | 6 +++++- .../collections/collectionSchema/SchemaColumnHeader.tsx | 14 ++++---------- 2 files changed, 9 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 49cb86732..1b23e3c40 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -358,6 +358,10 @@ export class CollectionSchemaView extends CollectionSubView() { @undoBatch removeColumn = (index: number) => { if (this.columnKeys.length === 1) return; + if (this._columnMenuIndex === index) { + this._headerRefs[index].toggleEditing(false); + this.closeColumnMenu(); + } const currWidths = this.storedColumnWidths.slice(); currWidths.splice(index, 1); const newDesiredTableWidth = currWidths.reduce((w, cw) => w + cw, 0); @@ -425,7 +429,7 @@ export class CollectionSchemaView extends CollectionSubView() { @action dragColumn = (e: PointerEvent, index: number) => { this.closeColumnMenu(); - this._headerRefs.forEach(ref => ref.stopEditing()); + this._headerRefs.forEach(ref => ref.toggleEditing(false)); this._draggedColIndex = index; this.setColDrag(true); const dragData = new DragManager.ColumnDragData(index); diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index 70db3d1f5..2b56ae881 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -71,15 +71,9 @@ export class SchemaColumnHeader extends ObservableReactComponent this._props.schemaView?.fieldInfos.get(fieldKey)); setColumnValues = (field: string, defaultValue: string) => {this._props.schemaView?.setKey(field, defaultValue, this._props.columnIndex);} @action updateAlt = (newAlt: string) => {this._altTitle = newAlt;} - @action updateKeyDropdown = (value: string) => {this._props.schemaView.updateKeySearch(value)} - @action stopEditing = () => { - this._inputRef?.setIsEditing(false); - this._inputRef?.setIsFocused(false); - } - - openKeyDropdown = () => { - this._props.schemaView.openColumnMenu(this._props.columnIndex, false) - } + updateKeyDropdown = (value: string) => {this._props.schemaView.updateKeySearch(value)} + toggleEditing = (editing: boolean) => {this._inputRef?.setIsEditing(editing); this._inputRef?.setIsFocused(editing);} + openKeyDropdown = () => {this._props.schemaView.openColumnMenu(this._props.columnIndex, false)} @action setupDrag = (e: React.PointerEvent) => { @@ -89,7 +83,7 @@ export class SchemaColumnHeader extends ObservableReactComponent { const { columnKeys, columnWidth, Document } = props; const fieldKey = columnKeys[props.columnIndex]; - const color = 'black'; // color of text in cells + const color = 'black'; const fieldProps: FieldViewProps = { childFilters: returnEmptyFilter, childFiltersByRanges: returnEmptyFilter, -- cgit v1.2.3-70-g09d2 From fc4b71f2623fe1602d911b71828b8b3f6c0ce0cd Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Sun, 30 Jun 2024 19:42:18 -0400 Subject: deleting column no longer messes up drag highlight; removed unecessary documents.ts changes --- src/client/documents/Documents.ts | 6 ------ .../views/collections/collectionSchema/CollectionSchemaView.tsx | 3 +++ 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 1b1608cd5..dabbf9591 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -143,12 +143,7 @@ class ListInfo extends FInfo { fieldType? = FInfoFieldType.list; values?: List[] = []; } -class MapInfo extends FInfo { - fieldType? = FInfoFieldType.list; - values?: List[] = []; -} type BOOLt = BoolInfo | boolean; -type MAPt = MapInfo | Map; type NUMt = NumInfo | number; type STRt = StrInfo | string; type LISTt = ListInfo | List; @@ -234,7 +229,6 @@ export class DocumentOptions { _lockedTransform?: BOOLt = new BoolInfo('lock the freeform_panx,freeform_pany and scale parameters of the document so that it be panned/zoomed'); _childrenSharedWithSchema?: BOOLt = new BoolInfo("whether this document's children are displayed in its parent schema view", false); _lockedSchemaEditing?: BOOLt = new BoolInfo("", false); - _schemaInputs?: LISTt = new ListInfo('user inputs to schema field', false) dataViz_title?: string; dataViz_line?: string; diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 1b23e3c40..2f62b1c8d 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -43,6 +43,7 @@ import { DocumentManager } from '../../../util/DocumentManager'; import { TbHemispherePlus } from 'react-icons/tb'; import { docs_v1 } from 'googleapis'; import { SchemaCellField } from './SchemaCellField'; +import { threadId } from 'worker_threads'; const { SCHEMA_NEW_NODE_HEIGHT } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore @@ -370,6 +371,8 @@ export class CollectionSchemaView extends CollectionSubView() { const currKeys = this.columnKeys.slice(); currKeys.splice(index, 1); this.layoutDoc.schema_columnKeys = new List(currKeys); + + this._colEles.splice(index, 1); }; @action -- cgit v1.2.3-70-g09d2 From c9e3b7679247b615b1821d913b2648a0c1560c5a Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Mon, 1 Jul 2024 13:18:22 -0400 Subject: keymenu no longer opened on dragged col drop --- .../collections/collectionSchema/CollectionSchemaView.tsx | 4 ++-- .../collections/collectionSchema/SchemaColumnHeader.tsx | 12 +++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 2f62b1c8d..d0b531ad6 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -434,7 +434,7 @@ export class CollectionSchemaView extends CollectionSubView() { this.closeColumnMenu(); this._headerRefs.forEach(ref => ref.toggleEditing(false)); this._draggedColIndex = index; - this.setColDrag(true); + this.setColDrag(true); const dragData = new DragManager.ColumnDragData(index); const dragEles = [this._colEles[index]]; this.childDocs.forEach(doc => dragEles.push(this._rowEles.get(doc).children[1].children[index])); @@ -741,7 +741,7 @@ export class CollectionSchemaView extends CollectionSubView() { @action onInternalDrop = (e: Event, de: DragManager.DropEvent) => { if (de.complete.columnDragData) { - this.setColDrag(false); + setTimeout(() => {this.setColDrag(false);}); e.stopPropagation(); return true; } diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index 2b56ae881..22237f448 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -23,7 +23,6 @@ import { undoable } from '../../../util/UndoManager'; import { FInfo } from '../../../documents/Documents'; import { ColumnType } from '../../../../fields/SchemaHeaderField'; import { IconButton, Size } from 'browndash-components'; -import { TbHospital } from 'react-icons/tb'; export enum SchemaFieldType { Header, Cell @@ -70,10 +69,13 @@ export class SchemaColumnHeader extends ObservableReactComponent this._props.schemaView?.fieldInfos.get(fieldKey)); setColumnValues = (field: string, defaultValue: string) => {this._props.schemaView?.setKey(field, defaultValue, this._props.columnIndex);} - @action updateAlt = (newAlt: string) => {this._altTitle = newAlt;} - updateKeyDropdown = (value: string) => {this._props.schemaView.updateKeySearch(value)} - toggleEditing = (editing: boolean) => {this._inputRef?.setIsEditing(editing); this._inputRef?.setIsFocused(editing);} - openKeyDropdown = () => {this._props.schemaView.openColumnMenu(this._props.columnIndex, false)} + @action updateAlt = (newAlt: string) => {this._altTitle = newAlt}; + updateKeyDropdown = (value: string) => {this._props.schemaView.updateKeySearch(value)}; + openKeyDropdown = () => {console.log('caled'); console.log(this._props.schemaView._colBeingDragged); !this._props.schemaView._colBeingDragged && this._props.schemaView.openColumnMenu(this._props.columnIndex, false)}; + toggleEditing = (editing: boolean) => { + this._inputRef?.setIsEditing(editing); + this._inputRef?.setIsFocused(editing); + }; @action setupDrag = (e: React.PointerEvent) => { -- cgit v1.2.3-70-g09d2 From a4199d30b81c464fd7ff15eee1fc56f432ee53a3 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Mon, 1 Jul 2024 14:52:35 -0400 Subject: fonticonbox no longer added when dragged from tools menu --- .../views/collections/collectionSchema/CollectionSchemaView.tsx | 4 +++- src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index d0b531ad6..7a90b3505 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -44,6 +44,7 @@ import { TbHemispherePlus } from 'react-icons/tb'; import { docs_v1 } from 'googleapis'; import { SchemaCellField } from './SchemaCellField'; import { threadId } from 'worker_threads'; +import { FontIconBox } from '../../nodes/FontIconBox/FontIconBox'; const { SCHEMA_NEW_NODE_HEIGHT } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore @@ -740,6 +741,7 @@ export class CollectionSchemaView extends CollectionSubView() { @action onInternalDrop = (e: Event, de: DragManager.DropEvent) => { + console.log('called') if (de.complete.columnDragData) { setTimeout(() => {this.setColDrag(false);}); e.stopPropagation(); @@ -1301,7 +1303,7 @@ export class CollectionSchemaView extends CollectionSubView() { const desc = BoolCast(this.layoutDoc.sortDesc); // is this an ascending or descending sort docs = this.sortDocs(field, desc, true); } else { - const draggedDocs = this.isContentActive() ? DragManager.docsBeingDragged : []; + const draggedDocs = this.isContentActive() ? DragManager.docsBeingDragged.filter(doc => !(doc.type === 'fonticonbox')) : []; docs = docs.filter(d => !draggedDocs.includes(d)); docs.splice(this.rowDropIndex, 0, ...draggedDocs); } diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index 22237f448..4f5b3005d 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -71,7 +71,7 @@ export class SchemaColumnHeader extends ObservableReactComponent {this._props.schemaView?.setKey(field, defaultValue, this._props.columnIndex);} @action updateAlt = (newAlt: string) => {this._altTitle = newAlt}; updateKeyDropdown = (value: string) => {this._props.schemaView.updateKeySearch(value)}; - openKeyDropdown = () => {console.log('caled'); console.log(this._props.schemaView._colBeingDragged); !this._props.schemaView._colBeingDragged && this._props.schemaView.openColumnMenu(this._props.columnIndex, false)}; + openKeyDropdown = () => {!this._props.schemaView._colBeingDragged && this._props.schemaView.openColumnMenu(this._props.columnIndex, false)}; toggleEditing = (editing: boolean) => { this._inputRef?.setIsEditing(editing); this._inputRef?.setIsFocused(editing); -- cgit v1.2.3-70-g09d2 From 3dd0a92767972736f415341c0b6e06e6e3a242b1 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Mon, 1 Jul 2024 16:38:24 -0400 Subject: highlighting then un-highlighting a selected cell with equations now properly maintains original select highlight --- src/client/views/EditableView.tsx | 1 - .../collectionSchema/CollectionSchemaView.tsx | 19 +++++++++++++++---- .../collections/collectionSchema/SchemaCellField.tsx | 8 ++++++-- .../collections/collectionSchema/SchemaRowBox.tsx | 13 ++----------- .../collections/collectionSchema/SchemaTableCell.tsx | 10 +++------- 5 files changed, 26 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 0c09e12de..af6a43555 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -206,7 +206,6 @@ export class EditableView extends ObservableReactComponent { @action finalizeEdit(value: string, shiftDown: boolean, lostFocus: boolean, enterKey: boolean) { - //if (invalid) raise error if (this._props.SetValue(value, shiftDown, enterKey)) { this._editing = false; this._props.isEditingCallback?.(false); diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 7a90b3505..b81cfa821 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -606,12 +606,24 @@ export class CollectionSchemaView extends CollectionSubView() { return cells; } + selectionOverlap = (doc: Doc): [boolean, boolean] => { + const docs = this.docsWithDrag.docs; + const index = this.rowIndex(doc); + const selectedBelow: boolean = this._selectedDocs.includes(docs[index + 1]); + const selectedAbove: boolean = this._selectedDocs.includes(docs[index - 1]); + return [selectedAbove, selectedBelow]; + } + removeCellHighlights = () => { this._highlightedCellsInfo.forEach(info => { const doc = info[0]; const field = info[1]; const cell = this.getCellElement(doc, field); - if (!(this._selectedDocs.includes(doc) && this._selectedCol === this.columnKeys.indexOf(field))) cell.style.border = ''; + if (this._selectedDocs.includes(doc) && this._selectedCol === this.columnKeys.indexOf(field)) { + cell.style.border = `solid 2px ${Colors.MEDIUM_BLUE}`; + if (this.selectionOverlap(doc)[0]) cell.style.borderTop = ''; + if (this.selectionOverlap(doc)[1]) cell.style.borderBottom = ''; + } else cell.style.border = ''; cell.style.backgroundColor = '';}); this._highlightedCellsInfo = []; } @@ -741,7 +753,6 @@ export class CollectionSchemaView extends CollectionSubView() { @action onInternalDrop = (e: Event, de: DragManager.DropEvent) => { - console.log('called') if (de.complete.columnDragData) { setTimeout(() => {this.setColDrag(false);}); e.stopPropagation(); @@ -881,8 +892,8 @@ export class CollectionSchemaView extends CollectionSubView() { this.closeColumnMenu(); }; - setColumnValues = (key: string, value: string) => { - if (this._selectedCells.length === 1) this.docs.forEach(doc => !doc._lockedSchemaEditing &&Doc.SetField(doc, key, value)); + setCellValues = (key: string, value: string) => { + if (this._selectedCells.length === 1) this.docs.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value)); else this._selectedCells.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value)); return true; }; diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index c7c483df8..e1059b8fc 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -95,7 +95,7 @@ export class SchemaCellField extends ObservableReactComponent this._props.GetValue(), fieldVal => { this._unrenderedContent = fieldVal ?? ''; - this.setContent(this._unrenderedContent); + this.finalizeEdit(false, false, false); } ) } @@ -246,6 +246,10 @@ export class SchemaCellField extends ObservableReactComponent) => { 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(); @@ -302,7 +306,7 @@ export class SchemaCellField extends ObservableReactComponent() { return infos; } - @computed get isolatedSelection() { - const toReturn: [boolean, boolean] = [true, true]; - const docs = this.schemaView.docsWithDrag.docs; - const selectedBelow: boolean = this.schemaView?._selectedDocs.includes(docs[this.rowIndex + 1]); - const selectedAbove: boolean = this.schemaView?._selectedDocs.includes(docs[this.rowIndex - 1]); - toReturn[0] = selectedAbove; - toReturn[1] = selectedBelow; - return toReturn; - } - + isolatedSelection = (doc: Doc) => {return this.schemaView?.selectionOverlap(doc)}; setCursorIndex = (mouseY: number) => this.schemaView?.setRelCursorIndex(mouseY); selectedCol = () => this.schemaView._selectedCol; getFinfo = computedFn((fieldKey: string) => this.schemaView?.fieldInfos.get(fieldKey)); selectCell = (doc: Doc, col: number, shift: boolean, ctrl: boolean) => this.schemaView?.selectCell(doc, col, shift, ctrl); deselectCell = () => this.schemaView?.deselectAllCells(); selectedCells = () => this.schemaView?._selectedDocs; - setColumnValues = (field: any, value: any) => this.schemaView?.setColumnValues(field, value) ?? false; + setColumnValues = (field: any, value: any) => this.schemaView?.setCellValues(field, value) ?? false; columnWidth = computedFn((index: number) => () => this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth); computeRowIndex = () => this.schemaView?.rowIndex(this.Document); highlightCells = (text: string) => this.schemaView?.highlightCells(text); diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 1f5684151..e2a05da7f 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -60,7 +60,7 @@ export interface SchemaTableCellProps { autoFocus?: boolean; // whether to set focus on creation, othwerise wait for a click rootSelected?: () => boolean; rowSelected: () => boolean; - isolatedSelection: [boolean, boolean]; + isolatedSelection: (doc: Doc) => [boolean, boolean]; highlightCells: (text: string) => void; equationHighlightRef: ObservableMap; eqHighlightFunc: (text: string) => HTMLDivElement[] | []; @@ -174,10 +174,6 @@ export class SchemaTableCell extends ObservableReactComponent {return ((field.startsWith('`') && field.endsWith('`')) || (field.startsWith("'") && field.endsWith("'")) || (field.startsWith('"') && field.endsWith('"')))} if (!inQuotes(this._submittedValue) && inQuotes(modField)) modField = modField.substring(1, modField.length - 1); - - const selfRefPattern = `d${this.docIndex}.${this._props.fieldKey}` - const selfRefRegX = RegExp(selfRefPattern, 'g'); - if (selfRefRegX.exec(modField) !== null) { return 'Invalid'} return eqSymbol + modField; } @@ -255,8 +251,8 @@ export class SchemaTableCell extends ObservableReactComponent = []; sides[0] = selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // left sides[1] = selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // right - sides[2] = (!this._props.isolatedSelection[0] && selectedCell(this._props)) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // top - sides[3] = (!this._props.isolatedSelection[1] && selectedCell(this._props)) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // bottom + sides[2] = (!this._props.isolatedSelection(this._props.Document)[0] && selectedCell(this._props)) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // top + sides[3] = (!this._props.isolatedSelection(this._props.Document)[1] && selectedCell(this._props)) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // bottom return sides; } -- cgit v1.2.3-70-g09d2 From da10c63823f7bc5e90c3f397c9ff06431d2ee027 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Tue, 2 Jul 2024 00:55:45 -0400 Subject: eq highlight cycling inconsistency fixed --- .../views/collections/collectionSchema/CollectionSchemaView.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index b81cfa821..a6a5df4b9 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -614,6 +614,7 @@ export class CollectionSchemaView extends CollectionSubView() { return [selectedAbove, selectedBelow]; } + @action removeCellHighlights = () => { this._highlightedCellsInfo.forEach(info => { const doc = info[0]; @@ -655,10 +656,11 @@ export class CollectionSchemaView extends CollectionSubView() { const doc = info[0]; const field = info[1]; const key = `${doc[Id]}_${field}`; + console.log(key + ' ' + i % 10 + ' color: ' + color[0].r + color[0].g + color[0].b); const cell = this.getCellElement(doc, field); - if (!this._cellHighlightColors.has(key)) {this._cellHighlightColors.set(key, [colorStrings[0], colorStrings[1]])} - cell.style.border = this._cellHighlightColors.get(key)[0]; - cell.style.backgroundColor = this._cellHighlightColors.get(key)[1]; + this._cellHighlightColors.set(key, [colorStrings[0], colorStrings[1]]); + cell.style.border = colorStrings[0]; + cell.style.backgroundColor = colorStrings[1]; } } -- cgit v1.2.3-70-g09d2 From c69f325a6640d5843fabce5488a49e74d3efbba1 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Tue, 2 Jul 2024 01:20:15 -0400 Subject: resizer right working --- .../collections/collectionSchema/CollectionSchemaView.tsx | 11 +++++++---- .../views/collections/collectionSchema/SchemaColumnHeader.tsx | 6 +++--- 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index a6a5df4b9..ef3efea39 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -377,20 +377,23 @@ export class CollectionSchemaView extends CollectionSubView() { }; @action - startResize = (e: any, index: number) => { + startResize = (e: any, index: number, rightSide: boolean) => { this._displayColumnWidths = this.storedColumnWidths; - setupMoveUpEvents(this, e, moveEv => this.resizeColumn(moveEv, index), this.finishResize, emptyFunction); + setupMoveUpEvents(this, e, moveEv => this.resizeColumn(moveEv, index, rightSide), this.finishResize, emptyFunction); }; @action - resizeColumn = (e: PointerEvent, index: number) => { + resizeColumn = (e: PointerEvent, index: number, rightSide: boolean) => { if (this._displayColumnWidths) { let shrinking; let growing; let change = e.movementX; - if (index !== 0) { + if (rightSide && (index !== this._displayColumnWidths.length - 1)) { + growing = change < 0 ? index + 1: index; + shrinking = change < 0 ? index : index + 1; + } else if (index !== 0) { growing = change < 0 ? index : index - 1; shrinking = change < 0 ? index - 1 : index; } diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index 4f5b3005d..40509c41b 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -41,7 +41,7 @@ export interface SchemaColumnHeaderProps { setSort: (field: string | undefined, desc?: boolean) => void; removeColumn: (index: number) => void; rowHeight: () => number; - resizeColumn: (e: any, index: number) => void; + resizeColumn: (e: any, index: number, isRight: boolean) => void; dragColumn: (e: any, index: number) => boolean; openContextMenu: (x: number, y: number, index: number) => void; setColRef: (index: number, ref: HTMLDivElement) => void; @@ -235,7 +235,7 @@ export class SchemaColumnHeader extends ObservableReactComponent -
this._props.resizeColumn(e, this._props.columnIndex)} /> +
this._props.resizeColumn(e, this._props.columnIndex, false)} />
{this.editableView}
@@ -245,7 +245,7 @@ export class SchemaColumnHeader extends ObservableReactComponent
-
this._props.resizeColumn(e, this._props.columnIndex)} /> +
this._props.resizeColumn(e, this._props.columnIndex, true)} />
); } -- cgit v1.2.3-70-g09d2 From 8c48d4d489e0fd670ba46953dca3a435220d00f4 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Tue, 2 Jul 2024 13:58:10 -0400 Subject: keymenu changes --- .../views/collections/collectionSchema/CollectionSchemaView.scss | 4 +++- .../views/collections/collectionSchema/CollectionSchemaView.tsx | 7 ++----- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss index e3f3dafab..c32661214 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss @@ -51,7 +51,9 @@ .schema-filter-menu { background: $light-gray; position: absolute; - max-height: 300px; + border: 1px solid $medium-gray; + border-bottom: 2px solid $medium-gray; + max-height: 201px; display: flex; overflow: hidden; flex-direction: column; diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index ef3efea39..cc8b0fc7e 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -1159,11 +1159,8 @@ export class CollectionSchemaView extends CollectionSubView() {

{key} - {this.fieldInfos.get(key)!.fieldType ? ':' : ''} - - - {this.fieldInfos.get(key)!.fieldType} + :   {this.fieldInfos.get(key)!.description}

@@ -1313,7 +1310,7 @@ export class CollectionSchemaView extends CollectionSubView() { } @computed get docsWithDrag() { - let docs = this._docs; + let docs = this.docs.slice(); if (this.sortField){ const field = StrCast(this.layoutDoc.sortField); const desc = BoolCast(this.layoutDoc.sortDesc); // is this an ascending or descending sort -- cgit v1.2.3-70-g09d2 From 32771d4b202a8552815c7f4459d5ac5142401292 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 3 Jul 2024 04:40:55 -0400 Subject: schemacell refactor started --- .../collectionSchema/SchemaCellField.tsx | 119 ++++++++++++++++++++- .../collectionSchema/SchemaTableCell.tsx | 2 +- 2 files changed, 116 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index e1059b8fc..5048bf899 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -8,6 +8,15 @@ import { FieldView, FieldViewProps } from "../../nodes/FieldView"; import { ObjectField } from "../../../../fields/ObjectField"; import { Doc } from "../../../../fields/Doc"; import { DocumentView } from "../../nodes/DocumentView"; +import { date } from "serializr"; +import { createRoot } from "react-dom/client"; +import DatePicker from "react-datepicker"; +import { emptyFunction } from "../../../../Utils"; +import { DateField } from "../../../../fields/DateField"; + +enum EleType { + plainText, fieldReference, date, boolean +} export interface SchemaCellFieldProps { contents: any; @@ -34,6 +43,7 @@ export class SchemaCellField extends ObservableReactComponent) { + this.addReactComponents(); super.componentDidUpdate(prevProps); if (this._editing && this._props.editing === false) { this.finalizeEdit(false, true, false); @@ -116,12 +127,31 @@ export class SchemaCellField extends ObservableReactComponent { + addReactComponents = () => { + if (!this._inputref) return; + + const dateRefs = Array.from(this._inputref.querySelectorAll('.date-placeholder')); + + dateRefs.forEach(ref => { + const root = createRoot(ref); + root.render(); + }) + } + + generateSpan = (text: string, cell: HTMLDivElement | undefined): JSX.Element => { const selfRef = text === this.selfRefPattern; - return `${text}`; + return ( + + {text} + + ); } makeSpans = (content: string) => { + const spans: JSX.Element[] = []; let chunkedText = content; const pattern = /(this|d(\d+))\.(\w+)/g; @@ -140,13 +170,89 @@ export class SchemaCellField extends ObservableReactComponent { - chunkedText = chunkedText.replace(match, this.generateSpan(match, cells.get(match))); + chunkedText = chunkedText.replace(match, ''); + spans.push(this.generateSpan(match, cells.get(match))); ++matchNum; }) + chunkedText = chunkedText.replace(/{{date}}/g, `placeholder text`); + console.log(chunkedText) + return chunkedText; } + verifyCellRef = (text: string): [string, HTMLDivElement | undefined] | undefined => { + const pattern = /(this|d(\d+))\.(\w+)/g; + let matchedText: string = ''; + let matchedCell: HTMLDivElement | undefined = undefined; + let match: RegExpExecArray | null; + + while ((match = pattern.exec(text)) !== null) { + const cells = this._props.getCells(match[0]); + if (cells.length) { + matchedText = match[0]; + matchedCell = cells[0]; + } + } + + if (!matchedText && !matchedCell) return undefined; + else return [matchedText, matchedCell]; + } + + elementsFromText = (chunks: string[]): JSX.Element[] => { + const eles: any[] = []; + + chunks.forEach(text => { + const cellRef = this.verifyCellRef(text); + if (cellRef) { + eles.push(this.generateSpan(cellRef[0], cellRef[1])); + } else if (!text.replace('{{date}}', '')){ + eles.push(); + } else if (!text.replace('{{boolean}}', '')) { + eles.push(
boolean thing
); + } else { + eles.push({text}); + } + }); + + return eles; + } + + parseElements = () => { + let string: string = this._unrenderedContent; + if (string.startsWith(':')) string = string.slice(1); + if (string.startsWith('=')) string = string.slice(1); + + const chunks: string[] = []; + + let subStr: string = ''; + let currChar = ''; + for (let i = 0; i < string.length; i++){ + currChar = string[i]; + if ((currChar === ' ' && subStr.trim()) || (currChar !== ' ' && !subStr.trim())) { + chunks.push(subStr); + subStr = currChar; + } else { + subStr += currChar; + } + } + + if (subStr) {chunks.push(subStr)}; + + return this.elementsFromText(chunks); + } + + // ` | undefined) => { + // if ((value?.nativeEvent as any).shiftKey) { + // this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), (color === 'black' ? '=' : '') + (value?.target?.checked.toString() ?? '')); + // } else Doc.SetField(this._props.Document, this._props.fieldKey.replace(/^_/, ''), (color === 'black' ? '=' : '') + (value?.target?.checked.toString() ?? '')); + // })} + // />` + @action setContent = (content: string, restoreCursorPos?: boolean) => { const pos = this.cursorPosition; @@ -235,6 +341,7 @@ export class SchemaCellField extends ObservableReactComponent { @@ -351,8 +458,12 @@ export class SchemaCellField extends ObservableReactComponent e.stopPropagation} onPointerUp={e => e.stopPropagation} onPointerMove={e => {e.stopPropagation(); e.preventDefault()}} - dangerouslySetInnerHTML={{ __html: this._displayedContent }} + suppressContentEditableWarning={true} + //dangerouslySetInnerHTML={{ __html: this._displayedContent }} > + {this.parseElements().map((ele, index) => { + return
{ele}
+ })}
); } diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index e2a05da7f..7d29e40cc 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -389,7 +389,7 @@ export class SchemaDateCell extends ObservableReactComponent -
+
{pointerEvents === 'none' ? null : ( -- cgit v1.2.3-70-g09d2 From bb890c23b367374d9da7eb10d879ebbf48dc4e77 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Sat, 6 Jul 2024 02:31:27 -0400 Subject: wheel spinning --- .../collectionSchema/SchemaCellField.tsx | 44 +++++++++++----------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index 5048bf899..3be9167fe 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -111,7 +111,6 @@ export class SchemaCellField extends ObservableReactComponent) { - this.addReactComponents(); super.componentDidUpdate(prevProps); if (this._editing && this._props.editing === false) { this.finalizeEdit(false, true, false); @@ -127,24 +126,25 @@ export class SchemaCellField extends ObservableReactComponent { - if (!this._inputref) return; + // addReactComponents = () => { + // if (!this._inputref) return; - const dateRefs = Array.from(this._inputref.querySelectorAll('.date-placeholder')); + // const dateRefs = Array.from(this._inputref.querySelectorAll('.date-placeholder')); - dateRefs.forEach(ref => { - const root = createRoot(ref); - root.render(); - }) - } + // dateRefs.forEach(ref => { + // const root = createRoot(ref); + // root.render(); + // }) + // } generateSpan = (text: string, cell: HTMLDivElement | undefined): JSX.Element => { const selfRef = text === this.selfRefPattern; + const color: string | undefined = cell?.style.borderTop.replace('2px solid', ''); return ( + color: selfRef ? 'gray' : color}}> {text} ); @@ -176,7 +176,6 @@ export class SchemaCellField extends ObservableReactComponentplaceholder text`); - console.log(chunkedText) return chunkedText; } @@ -206,10 +205,10 @@ export class SchemaCellField extends ObservableReactComponent); - } else if (!text.replace('{{boolean}}', '')) { - eles.push(
boolean thing
); + } else if (text && !text.replace('{{boolean}}', '')) { + eles.push(boolean thing); } else { eles.push({text}); } @@ -218,8 +217,8 @@ export class SchemaCellField extends ObservableReactComponent { - let string: string = this._unrenderedContent; + parseElements = (content: string) => { + let string: string = content; if (string.startsWith(':')) string = string.slice(1); if (string.startsWith('=')) string = string.slice(1); @@ -229,7 +228,7 @@ export class SchemaCellField extends ObservableReactComponent { const pos = this.cursorPosition; - this._displayedContent = this.makeSpans(content); + this._displayedContent = content; + this._displayedElements = this.parseElements(content); restoreCursorPos && setTimeout(() => this.setCursorPosition(pos)); } @@ -339,9 +339,9 @@ export class SchemaCellField extends ObservableReactComponent this.parseElements(this._displayedContent).length) this.setContent(targVal, true); this.setupRefSelect(this.refSelectConditionMet); - console.log(this.parseElements()); + console.log(this.parseElements(targVal)); }; setupRefSelect = (enabled: boolean) => { @@ -461,8 +461,8 @@ export class SchemaCellField extends ObservableReactComponent - {this.parseElements().map((ele, index) => { - return
{ele}
+ {this._displayedElements.map((ele, index) => { + return {ele}; })}
); -- cgit v1.2.3-70-g09d2 From 77d76c1a7e88b3ad4b72c4cd6aa4d4772042b65d Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Mon, 8 Jul 2024 14:07:26 -0400 Subject: method in dataviz for identifying valid templates (WIP); option added to contextmenu to create docs from dataViz --- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index 4d5f15a3e..1cb1ad6af 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -32,6 +32,8 @@ import { Histogram } from './components/Histogram'; import { LineChart } from './components/LineChart'; import { PieChart } from './components/PieChart'; import { TableBox } from './components/TableBox'; +import { LinkManager } from '../../../util/LinkManager'; +import { Collection } from 'mongoose'; export enum DataVizView { TABLE = 'table', @@ -431,6 +433,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { const options = cm.findByDescription('Options...'); const optionItems = options && 'subitems' in options ? options.subitems : []; optionItems.push({ description: `Analyze with AI`, event: () => this.askGPT(), icon: 'lightbulb' }); + optionItems.push({ description: `Create documents`, event: () => this.askGPT(), icon: 'table-cells' }); !options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'eye' }); }; @@ -445,6 +448,26 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { GPTPopup.Instance.generateDataAnalysis(); }); + getPossibleTemplates = (): Doc[] => { + const linkedDocs: Doc[] = LinkManager.Instance.getAllRelatedLinks(this.Document).map(d => DocCast(LinkManager.getOppositeAnchor(d, this.Document))); + const linkedCollections: Doc[] = linkedDocs.filter(doc => doc.type === 'collection'); + const isColumnTitle = (title: string): boolean => { + const colTitles: string[] = Object.keys(this.records[0]); + for (let i = 0; i < colTitles.length; ++i){ + if (colTitles[i] === title) return true; + } + return false; + } + const isValidTemplate = (collection: Doc) => { + const childDocs = DocListCast(collection[Doc.LayoutFieldKey(collection)]); + for (let i = 0; i < childDocs.length; ++i){ + if (isColumnTitle(String(childDocs[i].title))) return true; + } + return false; + } + return linkedCollections.filter(col => isValidTemplate(col)); + } + /** * creates a new dataviz document filter from this one * it appears to the right of this document, with the -- cgit v1.2.3-70-g09d2 From 0c68bfcf4041558edf94f2898fc0531f24433351 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Tue, 9 Jul 2024 03:12:28 -0400 Subject: started doccreatormenu for dataviz --- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 16 ++- .../views/nodes/DataVizBox/DocCreatorMenu.scss | 12 +++ .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 113 +++++++++++++++++++++ 3 files changed, 138 insertions(+), 3 deletions(-) create mode 100644 src/client/views/nodes/DataVizBox/DocCreatorMenu.scss create mode 100644 src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index 1cb1ad6af..dae535ba6 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -34,6 +34,7 @@ import { PieChart } from './components/PieChart'; import { TableBox } from './components/TableBox'; import { LinkManager } from '../../../util/LinkManager'; import { Collection } from 'mongoose'; +import { DocCreatorMenu } from './DocCreatorMenu'; export enum DataVizView { TABLE = 'table', @@ -433,7 +434,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { const options = cm.findByDescription('Options...'); const optionItems = options && 'subitems' in options ? options.subitems : []; optionItems.push({ description: `Analyze with AI`, event: () => this.askGPT(), icon: 'lightbulb' }); - optionItems.push({ description: `Create documents`, event: () => this.askGPT(), icon: 'table-cells' }); + optionItems.push({ description: `Create documents`, event: () => DocCreatorMenu.Instance.displayMenu(200, 200), icon: 'table-cells' }); !options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'eye' }); }; @@ -450,16 +451,22 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { getPossibleTemplates = (): Doc[] => { const linkedDocs: Doc[] = LinkManager.Instance.getAllRelatedLinks(this.Document).map(d => DocCast(LinkManager.getOppositeAnchor(d, this.Document))); - const linkedCollections: Doc[] = linkedDocs.filter(doc => doc.type === 'collection'); + const linkedCollections: Doc[] = linkedDocs.filter(doc => doc.type === 'config').filter(doc => DocCast(doc.annotationOn).type === 'collection'); + console.log('cols: ' + linkedCollections) const isColumnTitle = (title: string): boolean => { const colTitles: string[] = Object.keys(this.records[0]); + console.log('titles: ' + colTitles) for (let i = 0; i < colTitles.length; ++i){ - if (colTitles[i] === title) return true; + if (colTitles[i] === title) { + console.log(true); + return true; + } } return false; } const isValidTemplate = (collection: Doc) => { const childDocs = DocListCast(collection[Doc.LayoutFieldKey(collection)]); + console.log('childDocs of col: ' + childDocs) for (let i = 0; i < childDocs.length; ++i){ if (isColumnTitle(String(childDocs[i].title))) return true; } @@ -511,6 +518,8 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { // displays how to get data into the DataVizBox if its empty
To create a DataViz box, either import / drag a CSV file into your canvas or copy a data table and use the command (ctrl + p) to bring the data table to your canvas.
) : ( +
+
() { /> )}
+
); } } diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss new file mode 100644 index 000000000..fea5a6f59 --- /dev/null +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -0,0 +1,12 @@ +.docCreatorMenu-cont { + position: absolute; + display: flex; + min-width: 300px; + min-height: 400px; + z-index: 6; + box-shadow: 0px 3px 4px rgba(0, 0, 0, 30%); + flex-direction: column; + background: whitesmoke; + color: black; + border-radius: 3px; +} \ No newline at end of file diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx new file mode 100644 index 000000000..d5c2bc227 --- /dev/null +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -0,0 +1,113 @@ +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { action, computed, IReactionDisposer, makeObservable, observable } from 'mobx'; +import { observer } from 'mobx-react'; +import * as React from 'react'; +import { SnappingManager } from '../../../util/SnappingManager'; +import './DocCreatorMenu.scss'; +import { ObservableReactComponent } from '../../ObservableReactComponent'; + +@observer +export class DocCreatorMenu extends ObservableReactComponent<{}> { + + static Instance: DocCreatorMenu; + + private _reactionDisposer?: IReactionDisposer; + + @observable _pageX: number = 0; + @observable _pageY: number = 0; + @observable _display: boolean = false; + + @observable _yRelativeToTop: boolean = true; + @observable _selectedIndex = -1; + + @observable _mouseX: number = -1; + @observable _mouseY: number = -1; + @observable _shouldDisplay: boolean = false; + + constructor(props: any) { + super(props); + makeObservable(this); + DocCreatorMenu.Instance = this; + } + + @action + onPointerDown = (e: PointerEvent) => { + this._mouseX = e.clientX; + this._mouseY = e.clientY; + }; + @action + onPointerUp = (e: PointerEvent) => { + if (e.button !== 2 && !e.ctrlKey) return; + const curX = e.clientX; + const curY = e.clientY; + if (Math.abs(this._mouseX - curX) > 1 || Math.abs(this._mouseY - curY) > 1) { + this._shouldDisplay = false; + } + + if (this._shouldDisplay) { + this._display = true; + } + }; + + componentDidMount() { + document.addEventListener('pointerdown', this.onPointerDown, true); + document.addEventListener('pointerup', this.onPointerUp); + } + + componentWillUnmount() { + document.removeEventListener('pointerdown', this.onPointerDown, true); + document.removeEventListener('pointerup', this.onPointerUp); + this._reactionDisposer?.(); + } + + static readonly buffer = 20; + static readonly width = 300; + static readonly height = 400; + get pageX() { + return this._pageX + DocCreatorMenu.width > window.innerWidth - DocCreatorMenu.buffer ? window.innerWidth - DocCreatorMenu.buffer - DocCreatorMenu.width : Math.max(0, this._pageX); + } + + get pageY() { + return this._pageY + DocCreatorMenu.height > window.innerHeight - DocCreatorMenu.buffer ? window.innerHeight - DocCreatorMenu.buffer - DocCreatorMenu.height : Math.max(0, this._pageY); + } + + @action + displayMenu = (x: number, y: number) => { + // maxX and maxY will change if the UI/font size changes, but will work for any amount + // of items added to the menu + + this._pageX = x; + this._pageY = y; + this._shouldDisplay = true; + }; + + @action + closeMenu = () => { + const wasOpen = this._display; + this._display = false; + this._shouldDisplay = false; + return wasOpen; + }; + + render() { + return ( +
+ {!this._shouldDisplay ? undefined : +
hi hi
+ + + } +
+ ) + } + + +} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From b669b8c82efa9217cf065e670c7f6111b096f20d Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 10 Jul 2024 02:11:46 -0400 Subject: docCreatorMenu progress --- src/client/views/ContextMenu.tsx | 1 - src/client/views/MainView.tsx | 3 + src/client/views/nodes/DataVizBox/DataVizBox.tsx | 9 +- .../views/nodes/DataVizBox/DocCreatorMenu.scss | 59 ++++++++-- .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 119 +++++++++++++++++---- 5 files changed, 157 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index d784a14b8..de985263d 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -269,7 +269,6 @@ export class ContextMenu extends ObservableReactComponent<{}> { // if (this._searchString.startsWith(this._defaultPrefix)) { this._defaultItem?.(this._searchString.substring(this._defaultPrefix.length)); } - this.closeMenu(); e.preventDefault(); e.stopPropagation(); } diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 5b9ddbb88..926e5fd55 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -76,6 +76,7 @@ import { PresBox } from './nodes/trails'; import { AnchorMenu } from './pdf/AnchorMenu'; import { GPTPopup } from './pdf/GPTPopup/GPTPopup'; import { TopBar } from './topbar/TopBar'; +import { DocCreatorMenu } from './nodes/DataVizBox/DocCreatorMenu'; const { LEFT_MENU_WIDTH, TOPBAR_HEIGHT } = require('./global/globalCssVariables.module.scss'); // prettier-ignore const _global = (window /* browser */ || global) /* node */ as any; @@ -278,6 +279,7 @@ export class MainView extends ObservableReactComponent<{}> { library.add( ...[ + fa.faWindowMaximize, fa.faGift, fa.faLockOpen, fa.faSort, @@ -1093,6 +1095,7 @@ export class MainView extends ObservableReactComponent<{}> { + diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index dae535ba6..1e0a72a91 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -429,12 +429,12 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { this.layoutDoc.dataViz_filterSelection = !this.layoutDoc.dataViz_filterSelection; }; - specificContextMenu = (): void => { + specificContextMenu = (x: number, y: number): void => { const cm = ContextMenu.Instance; const options = cm.findByDescription('Options...'); const optionItems = options && 'subitems' in options ? options.subitems : []; optionItems.push({ description: `Analyze with AI`, event: () => this.askGPT(), icon: 'lightbulb' }); - optionItems.push({ description: `Create documents`, event: () => DocCreatorMenu.Instance.displayMenu(200, 200), icon: 'table-cells' }); + optionItems.push({ description: `Create documents`, event: () => DocCreatorMenu.Instance.toggleDisplay(x, y), icon: 'table-cells' }); !options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'eye' }); }; @@ -518,8 +518,6 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { // displays how to get data into the DataVizBox if its empty
To create a DataViz box, either import / drag a CSV file into your canvas or copy a data table and use the command (ctrl + p) to bring the data table to your canvas.
) : ( -
-
() { transform: `scale(${scale})`, position: 'absolute', }} - onContextMenu={this.specificContextMenu} + onContextMenu={(e) => this.specificContextMenu(e.pageX, e.pageY)} onWheel={e => e.stopPropagation()} ref={this._mainCont}>
@@ -596,7 +594,6 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { /> )}
-
); } } diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index fea5a6f59..43053ee34 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -1,12 +1,55 @@ .docCreatorMenu-cont { position: absolute; - display: flex; - min-width: 300px; - min-height: 400px; - z-index: 6; - box-shadow: 0px 3px 4px rgba(0, 0, 0, 30%); - flex-direction: column; - background: whitesmoke; - color: black; + z-index: 100000; + // box-shadow: 0px 3px 4px rgba(0, 0, 0, 30%); + // background: whitesmoke; + // color: black; border-radius: 3px; +} + +.docCreatorMenu-menu { + display: flex; + flex-direction: row; +} + +.docCreatorMenu-menu-button { + width: 30px; + height: 30px; + background: whitesmoke; + background-color: rgb(34, 34, 37); + border-radius: 5px; + border: 1px solid whitesmoke; + padding: 0px; + font-size: 14px; + + &.right{ + margin-left: auto; + font-size: 12px; + } + + &.close-menu { + margin-left: 0px; + font-size: 12px; + } + + &.options { + margin-left: 0px; + } + + &:hover { + background-color: rgb(60, 60, 65); + } +} + +.docCreatorMenu-menu-hr{ + margin-top: 0px; + margin-bottom: 0px; +} + +.docCreatorMenu-content { + margin: 5px; + width: calc(100% - 10px); + height: calc(100% - 51px); + border: 1px solid whitesmoke; + border-radius: 5px; } \ No newline at end of file diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index d5c2bc227..dbd385047 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -1,16 +1,25 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, IReactionDisposer, makeObservable, observable } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { SnappingManager } from '../../../util/SnappingManager'; import './DocCreatorMenu.scss'; import { ObservableReactComponent } from '../../ObservableReactComponent'; +import { IconButton, Size } from 'browndash-components'; +import { returnFalse, setupMoveUpEvents } from '../../../../ClientUtils'; +import { emptyFunction } from '../../../../Utils'; +import { undoable } from '../../../util/UndoManager'; +import { DragManager } from '../../../util/DragManager'; +import { DocumentView } from '../DocumentView'; +import { dropActionType } from '../../../util/DropActionTypes'; @observer export class DocCreatorMenu extends ObservableReactComponent<{}> { static Instance: DocCreatorMenu; + private _ref: HTMLDivElement | null = null; + private _reactionDisposer?: IReactionDisposer; @observable _pageX: number = 0; @@ -22,8 +31,12 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @observable _mouseX: number = -1; @observable _mouseY: number = -1; + @observable _startPos: {x: number, y: number} | undefined = undefined; @observable _shouldDisplay: boolean = false; + @observable _menuContent: 'templates' | 'options' = 'templates'; + @observable _dragging: boolean = false; + constructor(props: any) { super(props); makeObservable(this); @@ -35,6 +48,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { this._mouseX = e.clientX; this._mouseY = e.clientY; }; + @action onPointerUp = (e: PointerEvent) => { if (e.button !== 2 && !e.ctrlKey) return; @@ -43,10 +57,6 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { if (Math.abs(this._mouseX - curX) > 1 || Math.abs(this._mouseY - curY) > 1) { this._shouldDisplay = false; } - - if (this._shouldDisplay) { - this._display = true; - } }; componentDidMount() { @@ -67,18 +77,18 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { return this._pageX + DocCreatorMenu.width > window.innerWidth - DocCreatorMenu.buffer ? window.innerWidth - DocCreatorMenu.buffer - DocCreatorMenu.width : Math.max(0, this._pageX); } - get pageY() { - return this._pageY + DocCreatorMenu.height > window.innerHeight - DocCreatorMenu.buffer ? window.innerHeight - DocCreatorMenu.buffer - DocCreatorMenu.height : Math.max(0, this._pageY); - } - @action - displayMenu = (x: number, y: number) => { + toggleDisplay = (x: number, y: number) => { // maxX and maxY will change if the UI/font size changes, but will work for any amount // of items added to the menu - - this._pageX = x; - this._pageY = y; - this._shouldDisplay = true; + if (this._shouldDisplay) { + this._shouldDisplay = false; + } else { + this._pageX = x; + console.log(y); + this._pageY = y; + this._shouldDisplay = true; + } }; @action @@ -89,21 +99,92 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { return wasOpen; }; + @action + onPointerMove = (e: any) => { + if (this._dragging){ + this._pageX = e.pageX - (this._startPos?.x ?? 0); + this._pageY = e.pageY - (this._startPos?.y ?? 0); + } + } + + setDragStart = () => { + + } + render() { return (
this._ref = r} style={{ display: '', - left: this.pageX, - ...(this._yRelativeToTop ? { top: Math.max(0, this.pageY) } : { bottom: this.pageY }), + left: this._pageX, + top: this._pageY, + width: this._shouldDisplay ? 300 : 0, + height: this._shouldDisplay ? 400 : 0, background: SnappingManager.userBackgroundColor, color: SnappingManager.userColor, }}> {!this._shouldDisplay ? undefined : -
hi hi
- - + <> +
+ setupMoveUpEvents( + this, + e, + (e) => { + this._dragging = true; + this._startPos = {x: 0, y: 0}; + this._startPos.x = e.pageX - (this._ref?.getBoundingClientRect().left ?? 0); + this._startPos.y = e.pageY - (this._ref?.getBoundingClientRect().top ?? 0); + return true; + }, + emptyFunction, + undoable(clickEv => { + clickEv.stopPropagation(); + }, 'open actions menu') + ) + + } + onPointerMove={e => this.onPointerMove(e)} + onPointerUp={() => this._dragging = false} + > + + + +
+
+
+ {this._menuContent === 'templates' ? +
+
+ : +
+
+ } +
+ }
) -- cgit v1.2.3-70-g09d2 From 3db8305f45233850031eaee1f19436ee7034df59 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 10 Jul 2024 03:15:43 -0400 Subject: menu progress --- .../views/nodes/DataVizBox/DocCreatorMenu.scss | 14 ++++++- .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 46 ++++++++++++++++------ 2 files changed, 46 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index 43053ee34..dc0f99cbd 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -46,10 +46,22 @@ margin-bottom: 0px; } -.docCreatorMenu-content { +.docCreatorMenu-preview-content { + display: grid; + grid-template-columns: repeat(2, 1fr); + overflow-y: scroll; margin: 5px; width: calc(100% - 10px); height: calc(100% - 51px); border: 1px solid whitesmoke; border-radius: 5px; + + .docCreatorMenu-preview-window { + width: 125px; + height: 125px; + margin-top: 10px; + margin-left: 10px; + border: 1px solid whitesmoke; + border-radius: 5px; + } } \ No newline at end of file diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index dbd385047..520dd9c2d 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -79,8 +79,6 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @action toggleDisplay = (x: number, y: number) => { - // maxX and maxY will change if the UI/font size changes, but will work for any amount - // of items added to the menu if (this._shouldDisplay) { this._shouldDisplay = false; } else { @@ -107,8 +105,24 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { } } - setDragStart = () => { + get templatesPreviewContents(){ + const tempArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + return ( +
+ {tempArray.map(i => +
+ +
)} +
+ ); + } + get optionsMenuContents(){ + return ( +
+ ); } render() { @@ -167,7 +181,21 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { > -

-
- {this._menuContent === 'templates' ? -
-
- : -
-
- } -
+ {this._menuContent === 'templates' ? this.templatesPreviewContents : this.optionsMenuContents} }
-- cgit v1.2.3-70-g09d2 From 77bf838bebc813d476788fabed6bc7bcbf8197b0 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 10 Jul 2024 14:36:39 -0400 Subject: images displaying --- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 13 ++-- .../views/nodes/DataVizBox/DocCreatorMenu.scss | 54 +++++++++++++-- .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 80 +++++++++++++--------- 3 files changed, 107 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index 1e0a72a91..f75ba9700 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -429,12 +429,18 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { this.layoutDoc.dataViz_filterSelection = !this.layoutDoc.dataViz_filterSelection; }; + openDocCreatorMenu = (x: number, y: number) => { + DocCreatorMenu.Instance.toggleDisplay(x, y); + DocCreatorMenu.Instance.setDataViz(this); + DocCreatorMenu.Instance.setTemplateDocs(this.getPossibleTemplates()); + } + specificContextMenu = (x: number, y: number): void => { const cm = ContextMenu.Instance; const options = cm.findByDescription('Options...'); const optionItems = options && 'subitems' in options ? options.subitems : []; optionItems.push({ description: `Analyze with AI`, event: () => this.askGPT(), icon: 'lightbulb' }); - optionItems.push({ description: `Create documents`, event: () => DocCreatorMenu.Instance.toggleDisplay(x, y), icon: 'table-cells' }); + optionItems.push({ description: `Create documents`, event: () => this.openDocCreatorMenu(x, y), icon: 'table-cells' }); !options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'eye' }); }; @@ -452,13 +458,12 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { getPossibleTemplates = (): Doc[] => { const linkedDocs: Doc[] = LinkManager.Instance.getAllRelatedLinks(this.Document).map(d => DocCast(LinkManager.getOppositeAnchor(d, this.Document))); const linkedCollections: Doc[] = linkedDocs.filter(doc => doc.type === 'config').filter(doc => DocCast(doc.annotationOn).type === 'collection'); - console.log('cols: ' + linkedCollections) const isColumnTitle = (title: string): boolean => { const colTitles: string[] = Object.keys(this.records[0]); console.log('titles: ' + colTitles) for (let i = 0; i < colTitles.length; ++i){ if (colTitles[i] === title) { - console.log(true); + console.log(true); return true; } } @@ -472,7 +477,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { } return false; } - return linkedCollections.filter(col => isValidTemplate(col)); + return linkedDocs; } /** diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index dc0f99cbd..43d4ed7e5 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -23,13 +23,13 @@ font-size: 14px; &.right{ - margin-left: auto; + margin-left: 0px; font-size: 12px; } &.close-menu { - margin-left: 0px; font-size: 12px; + margin-left: auto; } &.options { @@ -46,7 +46,7 @@ margin-bottom: 0px; } -.docCreatorMenu-preview-content { +.docCreatorMenu-preview-container { display: grid; grid-template-columns: repeat(2, 1fr); overflow-y: scroll; @@ -64,4 +64,50 @@ border: 1px solid whitesmoke; border-radius: 5px; } -} \ No newline at end of file +} + +.docCreatorMenu-options-container { + display: flex; + overflow-y: scroll; + margin: 5px; + width: calc(100% - 10px); + height: calc(100% - 51px); + border: 1px solid whitesmoke; + border-radius: 5px; + + .docCreatorMenu-dropdown-button{ + display: flex; + width: 120px; + height: 30px; + background: whitesmoke; + background-color: rgb(34, 34, 37); + border-radius: 5px; + border: 1px solid whitesmoke; + padding: 0px; + font-size: 13px; + margin: 10px; + align-content: center; + justify-content: center; + text-transform: uppercase; + + // &:hover .docCreatorMenu-dropdown-content{ + // display: block; + // } + } + + .docCreatorMenu-dropdown-content { + display: none; + position: absolute; + min-width: 100px; + z-index: 1; + + .docCreatorMenu-dropdown-option{ + display: block; + } + + } + + + +} + diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index 520dd9c2d..1976ecad2 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -1,17 +1,18 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, IReactionDisposer, makeObservable, observable, runInAction } from 'mobx'; +import { IReactionDisposer, action, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { SnappingManager } from '../../../util/SnappingManager'; -import './DocCreatorMenu.scss'; -import { ObservableReactComponent } from '../../ObservableReactComponent'; -import { IconButton, Size } from 'browndash-components'; import { returnFalse, setupMoveUpEvents } from '../../../../ClientUtils'; +import { Doc } from '../../../../fields/Doc'; +import { DocCast, ImageCast } from '../../../../fields/Types'; +import { ImageField } from '../../../../fields/URLField'; import { emptyFunction } from '../../../../Utils'; +import { SnappingManager } from '../../../util/SnappingManager'; import { undoable } from '../../../util/UndoManager'; -import { DragManager } from '../../../util/DragManager'; +import { ObservableReactComponent } from '../../ObservableReactComponent'; import { DocumentView } from '../DocumentView'; -import { dropActionType } from '../../../util/DropActionTypes'; +import { DataVizBox } from './DataVizBox'; +import './DocCreatorMenu.scss'; @observer export class DocCreatorMenu extends ObservableReactComponent<{}> { @@ -20,22 +21,21 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { private _ref: HTMLDivElement | null = null; - private _reactionDisposer?: IReactionDisposer; + @observable _templateDocs: Doc[] = []; + @observable _icons : (ImageField|undefined)[] = []; @observable _pageX: number = 0; @observable _pageY: number = 0; @observable _display: boolean = false; - @observable _yRelativeToTop: boolean = true; - @observable _selectedIndex = -1; - @observable _mouseX: number = -1; @observable _mouseY: number = -1; - @observable _startPos: {x: number, y: number} | undefined = undefined; + @observable _startPos?: {x: number, y: number}; @observable _shouldDisplay: boolean = false; @observable _menuContent: 'templates' | 'options' = 'templates'; @observable _dragging: boolean = false; + @observable _dataViz?: DataVizBox; constructor(props: any) { super(props); @@ -43,6 +43,11 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { DocCreatorMenu.Instance = this; } + @action setDataViz = (dataViz: DataVizBox) => { this._dataViz = dataViz }; + @action setTemplateDocs = (docs: Doc[]) => { + this._templateDocs = docs.map(doc => doc.annotationOn ? DocCast(doc.annotationOn):doc); + }; + @action onPointerDown = (e: PointerEvent) => { this._mouseX = e.clientX; @@ -59,22 +64,19 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { } }; + _disposer: IReactionDisposer|undefined; componentDidMount() { document.addEventListener('pointerdown', this.onPointerDown, true); document.addEventListener('pointerup', this.onPointerUp); + this._disposer = reaction(() => this._templateDocs.slice(), + async(docs) => this._icons = (await Promise.all(docs.map(doc => this.getIcon(doc)))) + , {fireImmediately: true}); } componentWillUnmount() { + this._disposer?.(); document.removeEventListener('pointerdown', this.onPointerDown, true); document.removeEventListener('pointerup', this.onPointerUp); - this._reactionDisposer?.(); - } - - static readonly buffer = 20; - static readonly width = 300; - static readonly height = 400; - get pageX() { - return this._pageX + DocCreatorMenu.width > window.innerWidth - DocCreatorMenu.buffer ? window.innerWidth - DocCreatorMenu.buffer - DocCreatorMenu.width : Math.max(0, this._pageX); } @action @@ -105,23 +107,37 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { } } + async getIcon(doc: Doc) { + const docView = DocumentView.getDocumentView(doc); + if (docView) { + docView.ComponentView?.updateIcon?.(); + return new Promise(res => setTimeout(() => res(ImageCast(docView.Document.icon)), 500)); + } + return undefined; + } + get templatesPreviewContents(){ - const tempArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; return ( -
- {tempArray.map(i => -
- -
)} +
+ {this._icons.filter(url => url).map(url => +
+ +
) + }
); } get optionsMenuContents(){ return ( -
+
+
Dropdown
+
+
Link 1
+
Link 1
+
Link 1
+
+
); } @@ -181,6 +197,9 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { > + -

{this._menuContent === 'templates' ? this.templatesPreviewContents : this.optionsMenuContents} -- cgit v1.2.3-70-g09d2 From 6e65af16347169a9932c9e8ba737a2c76e684c5f Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Thu, 11 Jul 2024 01:53:02 -0400 Subject: menu --- .../views/nodes/DataVizBox/DocCreatorMenu.scss | 33 +++++++++++--- .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 53 +++++++++++++++------- 2 files changed, 63 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index 43d4ed7e5..452d9b354 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -49,6 +49,8 @@ .docCreatorMenu-preview-container { display: grid; grid-template-columns: repeat(2, 1fr); + grid-template-rows: 140px; + grid-auto-rows: 141px; overflow-y: scroll; margin: 5px; width: calc(100% - 10px); @@ -57,17 +59,33 @@ border-radius: 5px; .docCreatorMenu-preview-window { + display: flex; + justify-content: center; + align-items: center; width: 125px; height: 125px; margin-top: 10px; margin-left: 10px; border: 1px solid whitesmoke; border-radius: 5px; + box-shadow: 5px 5px rgb(34, 34, 37); + + &:hover{ + background-color: rgb(72, 72, 73); + } + + .docCreatorMenu-preview-image{ + width: 105px; + height: 105px; + border-radius: 5px; + } + } } .docCreatorMenu-options-container { display: flex; + justify-content: center; overflow-y: scroll; margin: 5px; width: calc(100% - 10px); @@ -77,22 +95,23 @@ .docCreatorMenu-dropdown-button{ display: flex; - width: 120px; - height: 30px; + width: 140px; + height: 25px; background: whitesmoke; background-color: rgb(34, 34, 37); border-radius: 5px; border: 1px solid whitesmoke; padding: 0px; - font-size: 13px; + font-size: 12px; margin: 10px; - align-content: center; + align-items: center; justify-content: center; text-transform: uppercase; + cursor: pointer; - // &:hover .docCreatorMenu-dropdown-content{ - // display: block; - // } + &:hover .docCreatorMenu-dropdown-content{ + display: block; + } } .docCreatorMenu-dropdown-content { diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index 1976ecad2..7859ec60a 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -1,5 +1,5 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { IReactionDisposer, action, makeObservable, observable, reaction, runInAction } from 'mobx'; +import { IReactionDisposer, ObservableMap, action, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { returnFalse, setupMoveUpEvents } from '../../../../ClientUtils'; @@ -13,6 +13,8 @@ import { ObservableReactComponent } from '../../ObservableReactComponent'; import { DocumentView } from '../DocumentView'; import { DataVizBox } from './DataVizBox'; import './DocCreatorMenu.scss'; +import { Id } from '../../../../fields/FieldSymbols'; +import { Colors } from 'browndash-components'; @observer export class DocCreatorMenu extends ObservableReactComponent<{}> { @@ -22,7 +24,8 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { private _ref: HTMLDivElement | null = null; @observable _templateDocs: Doc[] = []; - @observable _icons : (ImageField|undefined)[] = []; + @observable _templateRefToDoc?: ObservableMap; + @observable _selectedTemplateID?: Doc; @observable _pageX: number = 0; @observable _pageY: number = 0; @@ -64,13 +67,11 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { } }; - _disposer: IReactionDisposer|undefined; + _disposer: IReactionDisposer | undefined; componentDidMount() { document.addEventListener('pointerdown', this.onPointerDown, true); document.addEventListener('pointerup', this.onPointerUp); - this._disposer = reaction(() => this._templateDocs.slice(), - async(docs) => this._icons = (await Promise.all(docs.map(doc => this.getIcon(doc)))) - , {fireImmediately: true}); + this._disposer = reaction(() => this._templateDocs.slice(), (docs) => docs.map(this.getIcon)); } componentWillUnmount() { @@ -117,13 +118,34 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { } get templatesPreviewContents(){ + const renderedTemplates: Doc[] = []; return (
- {this._icons.filter(url => url).map(url => -
- -
) - } + {this._templateDocs.map(doc => ({icon: ImageCast(doc.icon), doc})).filter(info => info.icon && info.doc).map(info => { + if (renderedTemplates.includes(info.doc)) return undefined; + renderedTemplates.push(info.doc); + return (
+ setupMoveUpEvents( + this, + e, + returnFalse, + emptyFunction, + undoable(clickEv => { + clickEv.stopPropagation(); + this._selectedTemplateID = info.doc; + this.forceUpdate(); + }, 'open actions menu') + ) + }> + +
+ )})}
); } @@ -131,7 +153,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { get optionsMenuContents(){ return (
-
Dropdown
+
Choose Layout
Link 1
Link 1
@@ -173,9 +195,8 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { emptyFunction, undoable(clickEv => { clickEv.stopPropagation(); - }, 'open actions menu') + }, 'drag menu') ) - } onPointerMove={e => this.onPointerMove(e)} onPointerUp={() => this._dragging = false} @@ -191,7 +212,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { undoable(clickEv => { clickEv.stopPropagation(); runInAction(() => this._menuContent = this._menuContent === 'templates' ? 'options' : 'templates'); - }, 'open actions menu') + }, 'create docs') ) } > @@ -211,7 +232,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { undoable(clickEv => { clickEv.stopPropagation(); this.closeMenu(); - }, 'open actions menu') + }, 'close menu') ) } > -- cgit v1.2.3-70-g09d2 From 31bfb5e8b5e40322572252e1d823aebe48b27788 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Thu, 11 Jul 2024 02:54:35 -0400 Subject: menu --- .../views/nodes/DataVizBox/DocCreatorMenu.scss | 86 +++++++++++++++------- .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 43 ++++++++--- 2 files changed, 93 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index 452d9b354..ba20c9179 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -85,7 +85,9 @@ .docCreatorMenu-options-container { display: flex; - justify-content: center; + flex-direction: column; + justify-content: flex-start; + align-items: center; overflow-y: scroll; margin: 5px; width: calc(100% - 10px); @@ -93,40 +95,72 @@ border: 1px solid whitesmoke; border-radius: 5px; - .docCreatorMenu-dropdown-button{ - display: flex; + .docCreatorMenu-dropdown-hoverable { width: 140px; height: 25px; - background: whitesmoke; - background-color: rgb(34, 34, 37); - border-radius: 5px; - border: 1px solid whitesmoke; - padding: 0px; - font-size: 12px; - margin: 10px; - align-items: center; - justify-content: center; - text-transform: uppercase; - cursor: pointer; + margin-bottom: 17px; + z-index: 5; - &:hover .docCreatorMenu-dropdown-content{ + &:hover .docCreatorMenu-dropdown-content { display: block; } - } - - .docCreatorMenu-dropdown-content { - display: none; - position: absolute; - min-width: 100px; - z-index: 1; - .docCreatorMenu-dropdown-option{ - display: block; + &:hover .docCreatorMenu-dropdown-title { + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; } + .docCreatorMenu-dropdown-title{ + display: flex; + width: 140px; + height: 25px; + background: whitesmoke; + background-color: rgb(34, 34, 37); + border-radius: 5px; + border: 1px solid whitesmoke; + padding: 0px; + font-size: 12px; + margin-top: 10px; + align-items: center; + justify-content: center; + text-transform: uppercase; + cursor: pointer; + } + + .docCreatorMenu-dropdown-content { + display: none; + min-width: 100px; + height: 75px; + overflow-y: scroll; + -ms-overflow-style: none; + scrollbar-width: none; + + .docCreatorMenu-dropdown-option{ + display: flex; + background-color: rgb(42, 42, 46); + border-left: 1px solid whitesmoke; + border-right: 1px solid whitesmoke; + border-bottom: 1px solid whitesmoke; + width: 140px; + height: 25px; + justify-content: center; + justify-items: center; + padding-top: 3px; + + &:hover { + background-color: rgb(68, 68, 74); + cursor: pointer; + } + } + } } - - + .docCreatorMenu-layout-preview-window { + width: 85%; + height: 100px; + border: 1px solid whitesmoke; + border-radius: 5px; + background-color: rgb(34, 34, 37); + } } diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index 7859ec60a..356172b6a 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -27,6 +27,8 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @observable _templateRefToDoc?: ObservableMap; @observable _selectedTemplateID?: Doc; + @observable _selectedLayout?: 'stacked' | 'grid' | 'row' | 'column' | 'custom'; + @observable _pageX: number = 0; @observable _pageY: number = 0; @observable _display: boolean = false; @@ -131,11 +133,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { boxShadow: this._selectedTemplateID === info.doc ? `0 0 15px rgba(68, 118, 247, .8)` : '' }} onPointerDown={e => - setupMoveUpEvents( - this, - e, - returnFalse, - emptyFunction, + setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoable(clickEv => { clickEv.stopPropagation(); this._selectedTemplateID = info.doc; @@ -151,13 +149,38 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { } get optionsMenuContents(){ + + const layoutOption = (option: 'stacked' | 'grid' | 'row' | 'column' | 'custom') => { + return ( +
+ setupMoveUpEvents(this, e, returnFalse, emptyFunction, + undoable(clickEv => { + clickEv.stopPropagation(); + runInAction(() => this._selectedLayout = option); + }, 'open actions menu') + ) + }> + {option} +
+ ); + } + return (
-
Choose Layout
-
-
Link 1
-
Link 1
-
Link 1
+
+
Choose Layout
+
+ {layoutOption('stacked')} + {layoutOption('grid')} + {layoutOption('row')} + {layoutOption('column')} + {layoutOption('custom')} +
+
+
+
); -- cgit v1.2.3-70-g09d2 From 54fbd0815e93da8aff7a601676a90aa0faf87de8 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Thu, 11 Jul 2024 13:19:04 -0400 Subject: collection filtering works --- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 5 ++--- src/client/views/nodes/DataVizBox/DocCreatorMenu.scss | 5 +++-- src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx | 7 ++++--- 3 files changed, 9 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index f75ba9700..c43177c51 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -457,10 +457,9 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { getPossibleTemplates = (): Doc[] => { const linkedDocs: Doc[] = LinkManager.Instance.getAllRelatedLinks(this.Document).map(d => DocCast(LinkManager.getOppositeAnchor(d, this.Document))); - const linkedCollections: Doc[] = linkedDocs.filter(doc => doc.type === 'config').filter(doc => DocCast(doc.annotationOn).type === 'collection'); + const linkedCollections: Doc[] = linkedDocs.filter(doc => doc.type === 'config').filter(doc => DocCast(doc.annotationOn).type === 'collection').map(doc => DocCast(doc.annotationOn)); const isColumnTitle = (title: string): boolean => { const colTitles: string[] = Object.keys(this.records[0]); - console.log('titles: ' + colTitles) for (let i = 0; i < colTitles.length; ++i){ if (colTitles[i] === title) { console.log(true); @@ -477,7 +476,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { } return false; } - return linkedDocs; + return linkedCollections.filter(col => isValidTemplate(col)); } /** diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index ba20c9179..4944f3071 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -66,9 +66,9 @@ height: 125px; margin-top: 10px; margin-left: 10px; - border: 1px solid whitesmoke; + border: 1px solid rgb(163, 163, 163); border-radius: 5px; - box-shadow: 5px 5px rgb(34, 34, 37); + box-shadow: 5px 5px rgb(29, 29, 31); &:hover{ background-color: rgb(72, 72, 73); @@ -134,6 +134,7 @@ overflow-y: scroll; -ms-overflow-style: none; scrollbar-width: none; + border-bottom: solid 1px whitesmoke; .docCreatorMenu-dropdown-option{ display: flex; diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index 356172b6a..3ebf97570 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -150,10 +150,11 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { get optionsMenuContents(){ - const layoutOption = (option: 'stacked' | 'grid' | 'row' | 'column' | 'custom') => { + const layoutOption = (option: 'stacked' | 'grid' | 'row' | 'column' | 'custom', optStyle?: {}) => { return (
setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoable(clickEv => { @@ -176,7 +177,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { {layoutOption('grid')} {layoutOption('row')} {layoutOption('column')} - {layoutOption('custom')} + {layoutOption('custom', {borderBottom: `0px`})}
@@ -239,7 +240,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { ) } > - + -
@@ -270,6 +297,9 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
) } - +} +export interface DataVizTemplateInfo { + doc: Doc; + layout?: LayoutType; } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From c09ccb23ee490b5c1060f734665fd85668a62659 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Fri, 12 Jul 2024 18:25:26 -0400 Subject: repeat option added to menu; css refactoring --- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 5 +- .../views/nodes/DataVizBox/DocCreatorMenu.scss | 166 ++++++++++++++------- .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 72 ++++++--- 3 files changed, 168 insertions(+), 75 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index 86a9db79c..283288013 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -496,6 +496,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { @action createDocsFromTemplate = (templateInfo: DataVizTemplateInfo) => { + if (!templateInfo.doc) return; const mainCollection = this.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView; const fields: string[] = Array.from(Object.keys(this.records[0])); const selectedRows = NumListCast(this.layoutDoc.dataViz_selectedRows); @@ -508,8 +509,8 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { values.forEach((val, i) => {proto[fields[i]] = val as FieldType}); const target = Doc.MakeDelegate(proto); - const targetKey = StrCast(templateInfo.doc.layout_fieldKey, 'layout'); - const applied = this.ApplyTemplateTo(templateInfo.doc, target, targetKey, templateInfo.doc.title + `${row}`); + const targetKey = StrCast(templateInfo.doc!.layout_fieldKey, 'layout'); + const applied = this.ApplyTemplateTo(templateInfo.doc!, target, targetKey, templateInfo.doc!.title + `${row}`); target.layout_fieldKey = targetKey; return applied; }); diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index 4944f3071..243954873 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -46,6 +46,11 @@ margin-bottom: 0px; } +//------------------------------------------------------------------------------------------------------------------------------------------ +//DocCreatorMenu templates preview CSS +//-------------------------------------------------------------------------------------------------------------------------------------------- + + .docCreatorMenu-preview-container { display: grid; grid-template-columns: repeat(2, 1fr); @@ -83,7 +88,66 @@ } } -.docCreatorMenu-options-container { +//------------------------------------------------------------------------------------------------------------------------------------------ +//DocCreatorMenu options CSS +//-------------------------------------------------------------------------------------------------------------------------------------------- + +.docCreatorMenu-option-container{ + display: flex; + width: 180px; + height: 30px; + flex-direction: row; + justify-content: center; + align-items: center; + margin-top: 10px; + + &.layout{ + z-index: 5; + } +} + +.docCreatorMenu-option-title{ + display: flex; + width: 140px; + height: 30px; + background: whitesmoke; + background-color: rgb(34, 34, 37); + border-radius: 5px; + border: 1px solid whitesmoke; + padding: 0px; + font-size: 12px; + align-items: center; + justify-content: center; + text-transform: uppercase; + cursor: pointer; + + &.repeat { + border-top-right-radius: 0px; + border-bottom-right-radius: 0px; + width: 60px; + border-right: 0px; + } +} + +.docCreatorMenu-input { + display: flex; + height: 30px; + background-color: rgb(34, 34, 37); + border-radius: 5px; + border: 1px solid whitesmoke; + align-items: center; + justify-content: center; + + &.repeat { + margin: 0px; + border-top-left-radius: 0px; + border-bottom-left-radius: 0px; + border-left: 0px; + width: 40px; + } +} + +.docCreatorMenu-menu-container { display: flex; flex-direction: column; justify-content: flex-start; @@ -95,73 +159,63 @@ border: 1px solid whitesmoke; border-radius: 5px; - .docCreatorMenu-dropdown-hoverable { - width: 140px; - height: 25px; - margin-bottom: 17px; - z-index: 5; - - &:hover .docCreatorMenu-dropdown-content { - display: block; - } + .docCreatorMenu-option-container{ + width: 180px; + height: 30px; - &:hover .docCreatorMenu-dropdown-title { - border-bottom-left-radius: 0px; - border-bottom-right-radius: 0px; - } - - .docCreatorMenu-dropdown-title{ - display: flex; + .docCreatorMenu-dropdown-hoverable { width: 140px; - height: 25px; - background: whitesmoke; - background-color: rgb(34, 34, 37); - border-radius: 5px; - border: 1px solid whitesmoke; - padding: 0px; - font-size: 12px; - margin-top: 10px; - align-items: center; - justify-content: center; - text-transform: uppercase; - cursor: pointer; - } + height: 30px; - .docCreatorMenu-dropdown-content { - display: none; - min-width: 100px; - height: 75px; - overflow-y: scroll; - -ms-overflow-style: none; - scrollbar-width: none; - border-bottom: solid 1px whitesmoke; + &:hover .docCreatorMenu-dropdown-content { + display: block; + } - .docCreatorMenu-dropdown-option{ - display: flex; - background-color: rgb(42, 42, 46); - border-left: 1px solid whitesmoke; - border-right: 1px solid whitesmoke; - border-bottom: 1px solid whitesmoke; - width: 140px; - height: 25px; - justify-content: center; - justify-items: center; - padding-top: 3px; - - &:hover { - background-color: rgb(68, 68, 74); - cursor: pointer; - } + &:hover .docCreatorMenu-option-title { + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; } - } + + .docCreatorMenu-dropdown-content { + display: none; + min-width: 100px; + height: 75px; + overflow-y: scroll; + -ms-overflow-style: none; + scrollbar-width: none; + border-bottom: solid 1px whitesmoke; + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; + + .docCreatorMenu-dropdown-option{ + display: flex; + background-color: rgb(42, 42, 46); + border-left: 1px solid whitesmoke; + border-right: 1px solid whitesmoke; + border-bottom: 1px solid whitesmoke; + width: 140px; + height: 25px; + justify-content: center; + justify-items: center; + padding-top: 3px; + + &:hover { + background-color: rgb(68, 68, 74); + cursor: pointer; + } + } + } + } + } .docCreatorMenu-layout-preview-window { + aspect-ratio: 1 / 1; width: 85%; - height: 100px; border: 1px solid whitesmoke; border-radius: 5px; background-color: rgb(34, 34, 37); + margin-top: 10px; } } diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index 88308c226..1b4fe0879 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -31,12 +31,14 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { static Instance: DocCreatorMenu; private _ref: HTMLDivElement | null = null; + private _templateInfo: DataVizTemplateInfo = {}; @observable _templateDocs: Doc[] = []; @observable _templateRefToDoc?: ObservableMap; - @observable _selectedTemplate?: Doc; + @observable _selectedTemplate: Doc | undefined = undefined; - @observable _selectedLayout?: LayoutType; + @observable _selectedLayout: LayoutType | undefined = undefined; + @observable _layoutPreview: boolean = false; @observable _pageX: number = 0; @observable _pageY: number = 0; @@ -150,7 +152,6 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { MakeTemplate(info.doc); // ref.style.background = Colors.MEDIUM_BLUE; // ref.style.boxShadow = `0 0 15px rgba(68, 118, 247, .8)`; - this.forceUpdate(); }, 'open actions menu') ) }> @@ -161,8 +162,15 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { ); } - get optionsMenuContents(){ + get layoutPreviewContents() { + return ( +
+ +
+ ); + } + get optionsMenuContents(){ const layoutOption = (option: LayoutType, optStyle?: {}) => { return (
{ ); } + const repeatOption = (num: number) => { + return (); + } + + const repeatOptions = [0, 1, 2, 3, 4, 5]; + return ( -
-
-
Choose Layout
-
- {layoutOption(LayoutType.Stacked)} - {layoutOption(LayoutType.Grid)} - {layoutOption(LayoutType.Row)} - {layoutOption(LayoutType.Column)} - {layoutOption(LayoutType.Custom, {borderBottom: `0px`})} +
+
+
+
{this._selectedLayout ? this._selectedLayout.toUpperCase() : 'Choose Layout'}
+
+ {layoutOption(LayoutType.Stacked)} + {layoutOption(LayoutType.Grid)} + {layoutOption(LayoutType.Row)} + {layoutOption(LayoutType.Column)} + {layoutOption(LayoutType.Custom, {borderBottom: `0px`})} +
+
-
- + {this._layoutPreview ? this.layoutPreviewContents : null} +
+
Repeat
+
); @@ -253,7 +290,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { ) } > - +
+ {this._selectedLayout ? this.layoutConfigOptions: null} {this._layoutPreview ? this.layoutPreviewContents : null} -
-
Repeat
- -
+ {selectionBox(100, 30, 'Repeat:', undefined, repeatOptions.map(num => ))}
); } -- cgit v1.2.3-70-g09d2 From e0dbe3a59d2e1e61fda951c250ef8d43cc0ccd3d Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Mon, 15 Jul 2024 01:38:38 -0400 Subject: layout options/preview progress --- .../views/nodes/DataVizBox/DocCreatorMenu.scss | 14 ++ .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 250 +++++++++++++-------- 2 files changed, 174 insertions(+), 90 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index 71ad9e105..e3530c0ef 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -271,12 +271,26 @@ } .docCreatorMenu-layout-preview-window { + padding: 5px; + overflow: scroll; aspect-ratio: 1 / 1; + display: grid; width: 85%; border: 1px solid whitesmoke; border-radius: 5px; background-color: rgb(34, 34, 37); margin-top: 10px; + -ms-overflow-style: none; + scrollbar-width: none; + + .docCreatorMenu-layout-preview-item { + display: flex; + justify-content: center; + align-items: center; + border-radius: 3px; + border: solid 1px lightblue; + } } } + diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index a45234a79..c8b414c59 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -1,9 +1,9 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { IReactionDisposer, ObservableMap, action, makeObservable, observable, reaction, runInAction } from 'mobx'; +import { IReactionDisposer, ObservableMap, action, computed, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { returnAll, returnFalse, setupMoveUpEvents } from '../../../../ClientUtils'; -import { Doc } from '../../../../fields/Doc'; +import { Doc, NumListCast } from '../../../../fields/Doc'; import { DocCast, ImageCast } from '../../../../fields/Types'; import { ImageField } from '../../../../fields/URLField'; import { emptyFunction } from '../../../../Utils'; @@ -16,6 +16,7 @@ import './DocCreatorMenu.scss'; import { Id } from '../../../../fields/FieldSymbols'; import { Colors } from 'browndash-components'; import { MakeTemplate } from '../../../util/DropConverter'; +import { threadId } from 'worker_threads'; export enum LayoutType { Stacked = 'stacked', @@ -37,7 +38,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @observable _templateRefToDoc?: ObservableMap; @observable _selectedTemplate: Doc | undefined = undefined; - @observable _selectedLayout: LayoutType | undefined = undefined; + @observable _layout: {type?: LayoutType, yMargin: number, xMargin: number, rows?:number, columns?: number} = {yMargin: 0, xMargin: 0}; @observable _layoutPreview: boolean = false; @observable _pageX: number = 0; @@ -62,6 +63,35 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @action setDataViz = (dataViz: DataVizBox) => { this._dataViz = dataViz }; @action setTemplateDocs = (docs: Doc[]) => {this._templateDocs = docs.map(doc => doc.annotationOn ? DocCast(doc.annotationOn):doc)}; + @computed get docsToRender() { + return NumListCast(this._dataViz?.layoutDoc.dataViz_selectedRows); + } + + @computed get rowsCount(){ + switch (this._layout.type) { + case LayoutType.Row: case LayoutType.Stacked: + return 1; + case LayoutType.Column: + return this.docsToRender.length; + case LayoutType.Grid: + return this._layout.rows ?? 0; + default: + return 0; + } + } + + @computed get columnsCount(){ + switch (this._layout.type) { + case LayoutType.Row: + return this.docsToRender.length; + case LayoutType.Column: case LayoutType.Stacked: + return 1; + case LayoutType.Grid: + return this._layout.columns ?? 0; + default: + return 0; + } + } @action onPointerDown = (e: PointerEvent) => { @@ -158,40 +188,50 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { ); } + @action updateXMargin = (input: string) => { this._layout.xMargin = Number(input) }; + @action updateYMargin = (input: string) => { this._layout.yMargin = Number(input) }; + @action updateDimensions = (dimension: 'x' | 'y', input: string) => { + if (dimension === 'x') { + this._layout.rows = Number(input); + } else { + this._layout.columns = Number(input); + } + }; + get layoutConfigOptions() { - const optionInput = (title: string) => { + const optionInput = (title: string, func: Function) => { return (
{title}
- + func(e.currentTarget.value)} className='docCreatorMenu-input config layout-config'/>
); } - switch (this._selectedLayout) { + switch (this._layout.type) { case LayoutType.Row: case LayoutType.Column: return (
- {optionInput('Y Margin:')} - {optionInput('X Margin:')} + {optionInput('Y Margin:', this.updateYMargin)} + {optionInput('X Margin:', this.updateXMargin)}
); case LayoutType.Grid: return ( <>
- {optionInput('Y Margin:')} - {optionInput('X Margin:')} + {optionInput('Y Margin:', this.updateYMargin)} + {optionInput('X Margin:', this.updateXMargin)}
Dimensions:
- + {this.updateDimensions('x', e.currentTarget.value); this.forceUpdate()}}/>
x
- + this.updateDimensions('y', e.currentTarget.value)}/>
); @@ -203,8 +243,38 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { } get layoutPreviewContents() { + const docWidth = Number(this._selectedTemplate?._width); + const docHeight = Number(this._selectedTemplate?._height); + const horizontalSpan: number = (docWidth + this._layout.xMargin) * this.columnsCount - this._layout.xMargin; + const verticalSpan: number = (docHeight + this._layout.yMargin) * this.rowsCount - this._layout.yMargin; + const largerSpan: number = horizontalSpan > verticalSpan ? horizontalSpan : verticalSpan; + const scaleDownFactor: number = largerSpan / 235; + const scaledWidth = docWidth / scaleDownFactor; + const scaledHeight = docHeight / scaleDownFactor; + + console.log(this.rowsCount); + console.log(this.columnsCount) + return ( -
+
+ {this.docsToRender.map(num => +
+ {num} +
+ )}
); @@ -220,7 +290,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoable(clickEv => { clickEv.stopPropagation(); - runInAction(() => this._selectedLayout = option); + runInAction(() => this._layout.type = option); }, 'open actions menu') ) }> @@ -248,7 +318,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
-
{this._selectedLayout ? this._selectedLayout.toUpperCase() : 'Choose Layout'}
+
{this._layout.type ? this._layout.type.toUpperCase() : 'Choose Layout'}
{layoutOption(LayoutType.Stacked)} {layoutOption(LayoutType.Grid)} @@ -270,7 +340,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
- {this._selectedLayout ? this.layoutConfigOptions: null} + {this._layout.type ? this.layoutConfigOptions: null} {this._layoutPreview ? this.layoutPreviewContents : null} {selectionBox(100, 30, 'Repeat:', undefined, repeatOptions.map(num => ))}
@@ -279,79 +349,61 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { render() { return ( -
this._ref = r} - style={{ - display: '', - left: this._pageX, - top: this._pageY, - width: this._shouldDisplay ? 300 : 0, - height: this._shouldDisplay ? 400 : 0, - background: SnappingManager.userBackgroundColor, - color: SnappingManager.userColor, - }}> - {!this._shouldDisplay ? undefined : - <> -
- setupMoveUpEvents( - this, - e, - (e) => { - this._dragging = true; - this._startPos = {x: 0, y: 0}; - this._startPos.x = e.pageX - (this._ref?.getBoundingClientRect().left ?? 0); - this._startPos.y = e.pageY - (this._ref?.getBoundingClientRect().top ?? 0); - return true; - }, - emptyFunction, - undoable(clickEv => { - clickEv.stopPropagation(); - }, 'drag menu') - ) - } - onPointerMove={e => this.onPointerMove(e)} - onPointerUp={() => this._dragging = false} - > - - - + -
-
- {this._menuContent === 'templates' ? this.templatesPreviewContents : this.optionsMenuContents} - - } + + + +
+
+ {this._menuContent === 'templates' ? this.templatesPreviewContents : this.optionsMenuContents} +
+ }
) } -- cgit v1.2.3-70-g09d2 From f992fbeed6c523985e5ee6c851217a0dc38358d4 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Mon, 15 Jul 2024 19:42:08 -0400 Subject: working on layout preview window --- .../views/nodes/DataVizBox/DocCreatorMenu.scss | 7 ++- .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 63 +++++++++++----------- 2 files changed, 33 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index e3530c0ef..bfc1c1216 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -211,7 +211,6 @@ .docCreatorMenu-menu-container { display: flex; flex-direction: column; - justify-content: flex-start; align-items: center; overflow-y: scroll; margin: 5px; @@ -272,14 +271,14 @@ .docCreatorMenu-layout-preview-window { padding: 5px; + flex: 0 0 auto; overflow: scroll; - aspect-ratio: 1 / 1; display: grid; - width: 85%; + width: 240; + height: 240; border: 1px solid whitesmoke; border-radius: 5px; background-color: rgb(34, 34, 37); - margin-top: 10px; -ms-overflow-style: none; scrollbar-width: none; diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index c8b414c59..9da9f5aa8 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -17,6 +17,7 @@ import { Id } from '../../../../fields/FieldSymbols'; import { Colors } from 'browndash-components'; import { MakeTemplate } from '../../../util/DropConverter'; import { threadId } from 'worker_threads'; +import { ideahub } from 'googleapis/build/src/apis/ideahub'; export enum LayoutType { Stacked = 'stacked', @@ -40,6 +41,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @observable _layout: {type?: LayoutType, yMargin: number, xMargin: number, rows?:number, columns?: number} = {yMargin: 0, xMargin: 0}; @observable _layoutPreview: boolean = false; + @observable _layoutPreviewScale: number = 1; @observable _pageX: number = 0; @observable _pageY: number = 0; @@ -190,48 +192,42 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @action updateXMargin = (input: string) => { this._layout.xMargin = Number(input) }; @action updateYMargin = (input: string) => { this._layout.yMargin = Number(input) }; - @action updateDimensions = (dimension: 'x' | 'y', input: string) => { - if (dimension === 'x') { - this._layout.rows = Number(input); - } else { - this._layout.columns = Number(input); - } - }; + @action updateColumns = (input: string) => { this._layout.columns = Number(input) }; get layoutConfigOptions() { - const optionInput = (title: string, func: Function) => { + const optionInput = (title: string, func: Function, def?: number, key?: string) => { return ( -
+
{title}
- func(e.currentTarget.value)} className='docCreatorMenu-input config layout-config'/> + func(e.currentTarget.value)} className='docCreatorMenu-input config layout-config'/>
); } switch (this._layout.type) { - case LayoutType.Row: case LayoutType.Column: + case LayoutType.Row: + return ( +
+ {optionInput('Margin:', this.updateXMargin, this._layout.xMargin, '0')} +
+ ); + case LayoutType.Column: return (
- {optionInput('Y Margin:', this.updateYMargin)} - {optionInput('X Margin:', this.updateXMargin)} + {optionInput('Margin:', this.updateYMargin, this._layout.yMargin, '1')}
); case LayoutType.Grid: return ( <>
- {optionInput('Y Margin:', this.updateYMargin)} - {optionInput('X Margin:', this.updateXMargin)} + {optionInput('Y Margin:', this.updateYMargin, this._layout.xMargin, '2')} + {optionInput('X Margin:', this.updateXMargin, this._layout.xMargin, '3')}
-
- Dimensions: -
- {this.updateDimensions('x', e.currentTarget.value); this.forceUpdate()}}/> -
x
- this.updateDimensions('y', e.currentTarget.value)}/> + {optionInput('Columns:', this.updateColumns, this._layout.columns, '3')}
); @@ -248,28 +244,29 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { const horizontalSpan: number = (docWidth + this._layout.xMargin) * this.columnsCount - this._layout.xMargin; const verticalSpan: number = (docHeight + this._layout.yMargin) * this.rowsCount - this._layout.yMargin; const largerSpan: number = horizontalSpan > verticalSpan ? horizontalSpan : verticalSpan; - const scaleDownFactor: number = largerSpan / 235; - const scaledWidth = docWidth / scaleDownFactor; - const scaledHeight = docHeight / scaleDownFactor; - - console.log(this.rowsCount); - console.log(this.columnsCount) + const scaledDown = (input: number) => {return input / (largerSpan / 225 * this._layoutPreviewScale)} + const fontSize = Math.min(scaledDown(docWidth / 3), scaledDown(docHeight / 3)); return (
+ {/* */} {this.docsToRender.map(num =>
{num} -- cgit v1.2.3-70-g09d2 From bcbbfc670b95530b4dd9bd258e726fe75c47cfa8 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Tue, 16 Jul 2024 03:17:11 -0400 Subject: refactored click events; zoom in/out option --- .../views/nodes/DataVizBox/DocCreatorMenu.scss | 82 ++++++++--- .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 150 +++++++++------------ 2 files changed, 125 insertions(+), 107 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index bfc1c1216..a9b4e2501 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -1,3 +1,10 @@ +.no-margin { + margin-top: 0px !important; + margin-bottom: 0px !important; + margin-left: 0px !important; + margin-right: 0px !important; +} + .docCreatorMenu-cont { position: absolute; z-index: 100000; @@ -269,25 +276,64 @@ } - .docCreatorMenu-layout-preview-window { - padding: 5px; - flex: 0 0 auto; - overflow: scroll; - display: grid; - width: 240; - height: 240; - border: 1px solid whitesmoke; - border-radius: 5px; - background-color: rgb(34, 34, 37); - -ms-overflow-style: none; - scrollbar-width: none; - - .docCreatorMenu-layout-preview-item { - display: flex; - justify-content: center; - align-items: center; + .docCreatorMenu-layout-preview-window-wrapper { + display: flex; + justify-content: center; + align-items: center; + width: 85%; + height: auto; + position: relative; + padding: 0px; + + &:hover .docCreatorMenu-zoom-button { + display: block; + } + + .docCreatorMenu-layout-preview-window { + padding: 5px; + flex: 0 0 auto; + overflow: scroll; + display: grid; + width: auto; + height: auto; + max-width: 240; + max-height: 240; + border: 1px solid whitesmoke; + border-radius: 5px; + background-color: rgb(34, 34, 37); + -ms-overflow-style: none; + scrollbar-width: none; + + .docCreatorMenu-layout-preview-item { + display: flex; + justify-content: center; + align-items: center; + border-radius: 3px; + border: solid 1px lightblue; + } + } + + .docCreatorMenu-zoom-button{ + display: none; + width: 15px; + height: 15px; + background: whitesmoke; + background-color: rgb(34, 34, 37); border-radius: 3px; - border: solid 1px lightblue; + border: 1px solid whitesmoke; + padding: 0px; + font-size: 10px; + position: absolute; + top: 0px; + z-index: 6; + margin-left: 0px; + margin-top: 0px; + margin-right: 225px; + margin-bottom: 0px; + + &.zoom-in{ + top: 15px; + } } } } diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index 9da9f5aa8..bae2d2000 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -39,7 +39,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @observable _templateRefToDoc?: ObservableMap; @observable _selectedTemplate: Doc | undefined = undefined; - @observable _layout: {type?: LayoutType, yMargin: number, xMargin: number, rows?:number, columns?: number} = {yMargin: 0, xMargin: 0}; + @observable _layout: {type?: LayoutType, yMargin: number, xMargin: number, rows?:number, columns: number} = {yMargin: 0, xMargin: 0, columns: 1}; @observable _layoutPreview: boolean = false; @observable _layoutPreviewScale: number = 1; @@ -76,7 +76,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { case LayoutType.Column: return this.docsToRender.length; case LayoutType.Grid: - return this._layout.rows ?? 0; + return Math.ceil(this.docsToRender.length / (this._layout.columns ?? 1)) ?? 0; default: return 0; } @@ -95,6 +95,19 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { } } + setUpButtonClick = (e: any, func: Function) => { + setupMoveUpEvents( + this, + e, + returnFalse, + emptyFunction, + undoable(clickEv => { + clickEv.stopPropagation(); + func(); + }, 'create docs') + ) + } + @action onPointerDown = (e: PointerEvent) => { this._mouseX = e.clientX; @@ -130,7 +143,6 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { this._shouldDisplay = false; } else { this._pageX = x; - console.log(y); this._pageY = y; this._shouldDisplay = true; } @@ -174,15 +186,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { background: this._selectedTemplate === info.doc ? Colors.MEDIUM_BLUE : '', boxShadow: this._selectedTemplate === info.doc ? `0 0 15px rgba(68, 118, 247, .8)` : '' }} - onPointerDown={e => - setupMoveUpEvents(this, e, returnFalse, emptyFunction, - undoable(clickEv => { - clickEv.stopPropagation(); - this._selectedTemplate = info.doc; - MakeTemplate(info.doc); - }, 'open actions menu') - ) - }> + onPointerDown={e => this.setUpButtonClick(e, () => runInAction(() => {this._selectedTemplate = info.doc; MakeTemplate(info.doc);}))}>
)})} @@ -195,9 +199,10 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @action updateColumns = (input: string) => { this._layout.columns = Number(input) }; get layoutConfigOptions() { - const optionInput = (title: string, func: Function, def?: number, key?: string) => { + const optionInput = (title: string, func: Function, def?: number, key?: string, noMargin?: boolean) => { return ( -
+
{title}
@@ -226,8 +231,8 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { {optionInput('Y Margin:', this.updateYMargin, this._layout.xMargin, '2')} {optionInput('X Margin:', this.updateXMargin, this._layout.xMargin, '3')}
-
- {optionInput('Columns:', this.updateColumns, this._layout.columns, '3')} +
+ {optionInput('Columns:', this.updateColumns, this._layout.columns, '3', true)}
); @@ -248,49 +253,51 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { const fontSize = Math.min(scaledDown(docWidth / 3), scaledDown(docHeight / 3)); return ( -
- {/* */} - {this.docsToRender.map(num => -
- {num} -
- )} +
+ + +
+ {this.docsToRender.map(num => +
+ {num} +
+ )} +
); } get optionsMenuContents(){ - const layoutOption = (option: LayoutType, optStyle?: {}) => { + const layoutOption = (option: LayoutType, optStyle?: {}, specialFunc?: Function) => { return (
- setupMoveUpEvents(this, e, returnFalse, emptyFunction, - undoable(clickEv => { - clickEv.stopPropagation(); - runInAction(() => this._layout.type = option); - }, 'open actions menu') - ) - }> + onPointerDown={e => this.setUpButtonClick(e, () => {specialFunc?.(); runInAction(() => this._layout.type = option)})}> {option}
); @@ -318,7 +325,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
{this._layout.type ? this._layout.type.toUpperCase() : 'Choose Layout'}
{layoutOption(LayoutType.Stacked)} - {layoutOption(LayoutType.Grid)} + {layoutOption(LayoutType.Grid, undefined, () => {this._layout.columns = Math.ceil(Math.sqrt(this.docsToRender.length))})} {layoutOption(LayoutType.Row)} {layoutOption(LayoutType.Column)} {layoutOption(LayoutType.Custom, {borderBottom: `0px`})} @@ -326,14 +333,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
@@ -384,29 +384,12 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { >
-- cgit v1.2.3-70-g09d2 From dcbc6f5657109b19b623f946a1e86e1940a5c60c Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Tue, 16 Jul 2024 14:10:05 -0400 Subject: work on menu (mostly UI improvements) --- src/client/views/MainView.tsx | 3 + .../views/nodes/DataVizBox/DocCreatorMenu.scss | 37 +++++++----- .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 68 +++++++++++++--------- 3 files changed, 68 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 926e5fd55..d337aae68 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -279,6 +279,9 @@ export class MainView extends ObservableReactComponent<{}> { library.add( ...[ + fa.faRepeat, + fa.faArrowsUpDown, + fa.faArrowsLeftRight, fa.faWindowMaximize, fa.faGift, fa.faLockOpen, diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index a9b4e2501..d2f8f13d1 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -25,9 +25,14 @@ background: whitesmoke; background-color: rgb(34, 34, 37); border-radius: 5px; - border: 1px solid whitesmoke; + border: 1px solid rgb(180, 180, 180); padding: 0px; font-size: 14px; + //box-shadow: 3px 3px rgb(29, 29, 31); + + &:hover { + box-shadow: none; + } &.right{ margin-left: 0px; @@ -51,6 +56,7 @@ .docCreatorMenu-menu-hr{ margin-top: 0px; margin-bottom: 0px; + color: rgb(180, 180, 180); } //------------------------------------------------------------------------------------------------------------------------------------------ @@ -67,7 +73,7 @@ margin: 5px; width: calc(100% - 10px); height: calc(100% - 51px); - border: 1px solid whitesmoke; + border: 1px solid rgb(180, 180, 180); border-radius: 5px; .docCreatorMenu-preview-window { @@ -107,6 +113,7 @@ justify-content: center; align-items: center; margin-top: 10px; + margin-bottom: 10px; &.layout{ z-index: 5; @@ -120,7 +127,7 @@ background: whitesmoke; background-color: rgb(34, 34, 37); border-radius: 5px; - border: 1px solid whitesmoke; + border: 1px solid rgb(180, 180, 180); padding: 0px; font-size: 12px; align-items: center; @@ -142,10 +149,12 @@ } &.config { + border-radius: 4px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; - width: 60px; + width: 30px; border-right: 0px; + gap: 3px; &.layout-config { height: 20px; @@ -167,17 +176,17 @@ display: flex; height: 30px; background-color: rgb(34, 34, 37); - border-radius: 5px; - border: 1px solid whitesmoke; + border: 1px solid rgb(180, 180, 180); align-items: center; justify-content: center; &.config { + border-radius: 4px; margin: 0px; border-top-left-radius: 0px; border-bottom-left-radius: 0px; border-left: 0px; - width: 40px; + width: 25px; &.layout-config { height: 20px; @@ -223,7 +232,7 @@ margin: 5px; width: calc(100% - 10px); height: calc(100% - 51px); - border: 1px solid whitesmoke; + border: 1px solid rgb(180, 180, 180); border-radius: 5px; .docCreatorMenu-option-container{ @@ -250,16 +259,16 @@ overflow-y: scroll; -ms-overflow-style: none; scrollbar-width: none; - border-bottom: solid 1px whitesmoke; + border-bottom: 1px solid rgb(180, 180, 180); border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; .docCreatorMenu-dropdown-option{ display: flex; background-color: rgb(42, 42, 46); - border-left: 1px solid whitesmoke; - border-right: 1px solid whitesmoke; - border-bottom: 1px solid whitesmoke; + border-left: 1px solid rgb(180, 180, 180); + border-right: 1px solid rgb(180, 180, 180); + border-bottom: 1px solid rgb(180, 180, 180); width: 140px; height: 25px; justify-content: center; @@ -298,7 +307,7 @@ height: auto; max-width: 240; max-height: 240; - border: 1px solid whitesmoke; + border: 1px solid rgb(180, 180, 180); border-radius: 5px; background-color: rgb(34, 34, 37); -ms-overflow-style: none; @@ -320,7 +329,7 @@ background: whitesmoke; background-color: rgb(34, 34, 37); border-radius: 3px; - border: 1px solid whitesmoke; + border: 1px solid rgb(180, 180, 180); padding: 0px; font-size: 10px; position: absolute; diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index bae2d2000..3eda2c891 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -14,7 +14,7 @@ import { DocumentView } from '../DocumentView'; import { DataVizBox } from './DataVizBox'; import './DocCreatorMenu.scss'; import { Id } from '../../../../fields/FieldSymbols'; -import { Colors } from 'browndash-components'; +import { Colors, IconButton, Size } from 'browndash-components'; import { MakeTemplate } from '../../../util/DropConverter'; import { threadId } from 'worker_threads'; import { ideahub } from 'googleapis/build/src/apis/ideahub'; @@ -39,8 +39,8 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @observable _templateRefToDoc?: ObservableMap; @observable _selectedTemplate: Doc | undefined = undefined; - @observable _layout: {type?: LayoutType, yMargin: number, xMargin: number, rows?:number, columns: number} = {yMargin: 0, xMargin: 0, columns: 1}; - @observable _layoutPreview: boolean = false; + @observable _layout: {type: LayoutType, yMargin: number, xMargin: number, columns: number} = {type: LayoutType.Grid, yMargin: 0, xMargin: 0, columns: 1}; + @observable _layoutPreview: boolean = true; @observable _layoutPreviewScale: number = 1; @observable _pageX: number = 0; @@ -173,6 +173,16 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { return undefined; } + @action updateSelectedTemplate = (template: Doc) => { + if (this._selectedTemplate === template) { + this._selectedTemplate = undefined; + return; + } else { + this._selectedTemplate = template; + MakeTemplate(template); + } + } + get templatesPreviewContents(){ const renderedTemplates: Doc[] = []; return ( @@ -186,7 +196,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { background: this._selectedTemplate === info.doc ? Colors.MEDIUM_BLUE : '', boxShadow: this._selectedTemplate === info.doc ? `0 0 15px rgba(68, 118, 247, .8)` : '' }} - onPointerDown={e => this.setUpButtonClick(e, () => runInAction(() => {this._selectedTemplate = info.doc; MakeTemplate(info.doc);}))}> + onPointerDown={e => this.setUpButtonClick(e, () => runInAction(() => this.updateSelectedTemplate(info.doc)))}>
)})} @@ -199,12 +209,12 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @action updateColumns = (input: string) => { this._layout.columns = Number(input) }; get layoutConfigOptions() { - const optionInput = (title: string, func: Function, def?: number, key?: string, noMargin?: boolean) => { + const optionInput = (icon: string, func: Function, def?: number, key?: string, noMargin?: boolean) => { return ( -
- {title} +
func(e.currentTarget.value)} className='docCreatorMenu-input config layout-config'/>
@@ -215,26 +225,22 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { case LayoutType.Row: return (
- {optionInput('Margin:', this.updateXMargin, this._layout.xMargin, '0')} + {optionInput('arrows-left-right', this.updateXMargin, this._layout.xMargin, '0')}
); case LayoutType.Column: return (
- {optionInput('Margin:', this.updateYMargin, this._layout.yMargin, '1')} + {optionInput('arrows-up-down', this.updateYMargin, this._layout.yMargin, '1')}
); case LayoutType.Grid: return ( - <>
- {optionInput('Y Margin:', this.updateYMargin, this._layout.xMargin, '2')} - {optionInput('X Margin:', this.updateXMargin, this._layout.xMargin, '3')} + {optionInput('arrows-up-down', this.updateYMargin, this._layout.xMargin, '2')} + {optionInput('arrows-left-right', this.updateXMargin, this._layout.xMargin, '3')} + {optionInput('table-columns', this.updateColumns, this._layout.columns, '4', true)}
-
- {optionInput('Columns:', this.updateColumns, this._layout.columns, '3', true)} -
- ); case LayoutType.Stacked: return null; @@ -273,7 +279,18 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { rowGap: `${scaledDown(this._layout.yMargin)}px`, columnGap: `${scaledDown(this._layout.xMargin)}px` }}> - {this.docsToRender.map(num => + {this._layout.type === LayoutType.Stacked ? +
+ All +
: + this.docsToRender.map(num =>
{ ); } - const selectionBox = (width: number, height: number, title: string, specClass?: string, options?: JSX.Element[], manual?: boolean): JSX.Element => { + const selectionBox = (width: number, height: number, icon: string, specClass?: string, options?: JSX.Element[], manual?: boolean): JSX.Element => { return (
-
- {title} +
+
- {manual ? : - : + } @@ -339,7 +356,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
{this._layout.type ? this.layoutConfigOptions: null} {this._layoutPreview ? this.layoutPreviewContents : null} - {selectionBox(100, 30, 'Repeat:', undefined, repeatOptions.map(num => ))} + {selectionBox(60, 20, 'repeat', undefined, repeatOptions.map(num => ))}
); } @@ -381,7 +398,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { } onPointerMove={e => this.onPointerMove(e)} onPointerUp={() => this._dragging = false} - > + >
-
{this._menuContent === 'templates' ? this.templatesPreviewContents : this.optionsMenuContents}
} @@ -417,6 +433,6 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { export interface DataVizTemplateInfo { doc?: Doc; - layout?: LayoutType; + layout?: {}; repeat?: number; } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 58d3eeb6e45555e5eeaf172f571b500ca3b564c0 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 17 Jul 2024 00:54:22 -0400 Subject: creation with layout works --- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 38 ++++++++++++++++- .../views/nodes/DataVizBox/DocCreatorMenu.scss | 10 +++++ .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 48 ++++++++++++++++++---- 3 files changed, 88 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index 283288013..e03da8e7b 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -33,10 +33,11 @@ import { LineChart } from './components/LineChart'; import { PieChart } from './components/PieChart'; import { TableBox } from './components/TableBox'; import { LinkManager } from '../../../util/LinkManager'; -import { DataVizTemplateInfo, DocCreatorMenu } from './DocCreatorMenu'; +import { DataVizTemplateInfo, DocCreatorMenu, LayoutType } from './DocCreatorMenu'; import { CollectionFreeFormView } from '../../collections/collectionFreeForm'; import { PrefetchProxy } from '../../../../fields/Proxy'; import { AclAdmin, AclAugment, AclEdit } from '../../../../fields/DocSymbols'; +import { template } from 'lodash'; export enum DataVizView { TABLE = 'table', @@ -494,6 +495,38 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { return target; } + applyLayout = (templateInfo: DataVizTemplateInfo, docs: Doc[]) => { + if (templateInfo.layout.type === LayoutType.Stacked) return; + const columns: number = templateInfo.columns; + const xGap: number = templateInfo.layout.xMargin; + const yGap: number = templateInfo.layout.yMargin; + const repeat: number = templateInfo.layout.repeat; + const startX: number = templateInfo.referencePos.x; + const startY: number = templateInfo.referencePos.y; + const templWidth = Number(templateInfo.doc._width); + const templHeight = Number(templateInfo.doc._height); + + let i: number = 0; + let docsChanged: number = 0; + let curX: number = startX; + let curY: number = startY; + + while (docsChanged < docs.length){ + while (i < columns && docsChanged < docs.length){ + docs[docsChanged].x = curX; + docs[docsChanged].y = curY; + console.log('x: ' + docs[i].x + ' y: ' + docs[i].y); + curX += templWidth + xGap; + ++docsChanged; + ++i; + } + + i = 0; + curX = startX; + curY += templHeight + yGap; + } + } + @action createDocsFromTemplate = (templateInfo: DataVizTemplateInfo) => { if (!templateInfo.doc) return; @@ -514,7 +547,10 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { target.layout_fieldKey = targetKey; return applied; }); + docs.forEach(doc => mainCollection.addDocument(doc)); + + this.applyLayout(templateInfo, docs); } /** diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index d2f8f13d1..8b17f1ed4 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -59,6 +59,16 @@ color: rgb(180, 180, 180); } + +.docCreatorMenu-placement-indicator { + position: absolute; + z-index: 100000; + border-left: solid 3px #9fd7fb; + border-top: solid 3px #9fd7fb; + width: 25px; + height: 25px; +} + //------------------------------------------------------------------------------------------------------------------------------------------ //DocCreatorMenu templates preview CSS //-------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index 3eda2c891..b1488679f 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -33,18 +33,19 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { static Instance: DocCreatorMenu; private _ref: HTMLDivElement | null = null; - private _templateInfo: DataVizTemplateInfo = {}; @observable _templateDocs: Doc[] = []; @observable _templateRefToDoc?: ObservableMap; @observable _selectedTemplate: Doc | undefined = undefined; - @observable _layout: {type: LayoutType, yMargin: number, xMargin: number, columns: number} = {type: LayoutType.Grid, yMargin: 0, xMargin: 0, columns: 1}; + @observable _layout: {type: LayoutType, yMargin: number, xMargin: number, columns: number, repeat: number} = {type: LayoutType.Grid, yMargin: 0, xMargin: 0, columns: 1, repeat: 0}; @observable _layoutPreview: boolean = true; @observable _layoutPreviewScale: number = 1; @observable _pageX: number = 0; @observable _pageY: number = 0; + @observable _indicatorX: number | undefined = undefined; + @observable _indicatorY: number | undefined = undefined; @observable _display: boolean = false; @observable _mouseX: number = -1; @@ -54,6 +55,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @observable _menuContent: 'templates' | 'options' = 'templates'; @observable _dragging: boolean = false; + @observable _draggingIndicator: boolean = false; @observable _dataViz?: DataVizBox; constructor(props: any) { @@ -158,6 +160,10 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @action onPointerMove = (e: any) => { + // if (this._draggingIndicator) { + // this._indicatorX = e.pageX - (this._startPos?.x ?? 0) + this._pageX; + // this._indicatorY = e.pageY - (this._startPos?.y ?? 0) + this._pageY; + // } else if (this._dragging){ this._pageX = e.pageX - (this._startPos?.x ?? 0); this._pageY = e.pageY - (this._startPos?.y ?? 0); @@ -356,7 +362,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
{this._layout.type ? this.layoutConfigOptions: null} {this._layoutPreview ? this.layoutPreviewContents : null} - {selectionBox(60, 20, 'repeat', undefined, repeatOptions.map(num => ))} + {selectionBox(60, 20, 'repeat', undefined, repeatOptions.map(num => ))}
); } @@ -365,6 +371,31 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { return (
{!this._shouldDisplay ? undefined : + <> + {/*
this.onPointerMove(e)} + onPointerDown={e => + setupMoveUpEvents( + this, + e, + (e) => { + this._draggingIndicator = true; + this._startPos = {x: 0, y: 0}; + this._startPos.x = e.pageX - (this._ref?.getBoundingClientRect().left ?? 0); + this._startPos.y = e.pageY - (this._ref?.getBoundingClientRect().top ?? 0); + return true; + }, + emptyFunction, + undoable(clickEv => { + clickEv.stopPropagation(); + }, 'drag menu') + ) + }/> */}
this._ref = r} @@ -410,7 +441,8 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { undoable(clickEv => { clickEv.stopPropagation(); if (!this._selectedTemplate) return; - const templateInfo: DataVizTemplateInfo = {doc: this._selectedTemplate}; + const templateInfo: DataVizTemplateInfo = {doc: this._selectedTemplate, layout: this._layout, referencePos: {x: this._pageX + 450, y: this._pageY}, columns: this.columnsCount}; + this._dataViz?.createDocsFromTemplate(templateInfo); }, 'make docs') ) @@ -425,6 +457,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
{this._menuContent === 'templates' ? this.templatesPreviewContents : this.optionsMenuContents}
+ }
) @@ -432,7 +465,8 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { } export interface DataVizTemplateInfo { - doc?: Doc; - layout?: {}; - repeat?: number; + doc: Doc; + layout: {type: LayoutType, xMargin: number, yMargin: number, repeat: number}; + columns: number; + referencePos: {x: number, y: number}; } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From ded7673796965e9cb9239cfd483a2f1e35abd38b Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 17 Jul 2024 18:28:05 -0400 Subject: highlighting rows based on layoutpreview hover --- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 20 ++++++++++++++++++-- .../views/nodes/DataVizBox/DocCreatorMenu.scss | 11 +++++++++-- src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx | 18 +++++++++++++----- .../views/nodes/DataVizBox/components/TableBox.tsx | 6 ++++-- src/client/views/nodes/ImageBox.tsx | 2 +- 5 files changed, 45 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index e03da8e7b..765642891 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -38,6 +38,7 @@ import { CollectionFreeFormView } from '../../collections/collectionFreeForm'; import { PrefetchProxy } from '../../../../fields/Proxy'; import { AclAdmin, AclAugment, AclEdit } from '../../../../fields/DocSymbols'; import { template } from 'lodash'; +import { data } from 'jquery'; export enum DataVizView { TABLE = 'table', @@ -57,6 +58,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { crop: ((region: Doc | undefined, addCrop?: boolean) => Doc | undefined) | undefined; @observable _marqueeing: number[] | undefined = undefined; @observable _savedAnnotations = new ObservableMap(); + @observable _specialHighlightedRow: number | undefined = undefined; constructor(props: FieldViewProps) { super(props); @@ -131,6 +133,10 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { this.layoutDoc._dataViz_titleCol = titleCol; }; + @action setSpecialHighlightedRow = (row: number | undefined) => { + this._specialHighlightedRow = row; + } + @action // pinned / linked anchor doc includes selected rows, graph titles, and graph colors restoreView = (data: Doc) => { // const changedView = data.config_dataViz && this.dataVizView !== data.config_dataViz && (this.layoutDoc._dataViz = data.config_dataViz); @@ -366,7 +372,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { }; if (!this.records.length) return 'no data/visualization'; switch (this.dataVizView) { - case DataVizView.TABLE: return ; + case DataVizView.TABLE: return ; case DataVizView.LINECHART: return {this._vizRenderer = r ?? undefined;}} vizBox={this} />; case DataVizView.HISTOGRAM: return {this._vizRenderer = r ?? undefined;}} />; case DataVizView.PIECHART: return {this._vizRenderer = r ?? undefined;}} @@ -515,7 +521,6 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { while (i < columns && docsChanged < docs.length){ docs[docsChanged].x = curX; docs[docsChanged].y = curY; - console.log('x: ' + docs[i].x + ' y: ' + docs[i].y); curX += templWidth + xGap; ++docsChanged; ++i; @@ -527,6 +532,16 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { } } + // applyImagesTo = (doc: Doc, cols: string[]) => { + // const childDocs = DocListCast(doc[Doc.LayoutFieldKey(doc)]); + // const imageFields = childDocs.filter(doc => doc.type === 'image'); + // const imageToKey: Map = new Map(); + // imageFields.forEach(img => cols.forEach(col => {if (img[col]) imageToKey.set(img, col)})); + + // imageFields.forEach(doc => doc['data'] = String(doc[String(imageToKey.get(doc))]).replace(/"/g, '')); + + // } + @action createDocsFromTemplate = (templateInfo: DataVizTemplateInfo) => { if (!templateInfo.doc) return; @@ -545,6 +560,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { const targetKey = StrCast(templateInfo.doc!.layout_fieldKey, 'layout'); const applied = this.ApplyTemplateTo(templateInfo.doc!, target, targetKey, templateInfo.doc!.title + `${row}`); target.layout_fieldKey = targetKey; + //this.applyImagesTo(target, fields); return applied; }); diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index 8b17f1ed4..328cbbaf1 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -81,8 +81,9 @@ grid-auto-rows: 141px; overflow-y: scroll; margin: 5px; + margin-top: 0px; width: calc(100% - 10px); - height: calc(100% - 51px); + height: calc(100% - 45px); border: 1px solid rgb(180, 180, 180); border-radius: 5px; @@ -240,8 +241,9 @@ align-items: center; overflow-y: scroll; margin: 5px; + margin-top: 0px; width: calc(100% - 10px); - height: calc(100% - 51px); + height: calc(100% - 45px); border: 1px solid rgb(180, 180, 180); border-radius: 5px; @@ -329,6 +331,11 @@ align-items: center; border-radius: 3px; border: solid 1px lightblue; + + &:hover { + border: solid 2px rgb(68, 153, 233); + z-index: 2; + } } } diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index b1488679f..48b87fae7 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -38,7 +38,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @observable _templateRefToDoc?: ObservableMap; @observable _selectedTemplate: Doc | undefined = undefined; - @observable _layout: {type: LayoutType, yMargin: number, xMargin: number, columns: number, repeat: number} = {type: LayoutType.Grid, yMargin: 0, xMargin: 0, columns: 1, repeat: 0}; + @observable _layout: {type: LayoutType, yMargin: number, xMargin: number, columns?: number, repeat: number} = {type: LayoutType.Grid, yMargin: 0, xMargin: 0, repeat: 0}; @observable _layoutPreview: boolean = true; @observable _layoutPreviewScale: number = 1; @@ -48,6 +48,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @observable _indicatorY: number | undefined = undefined; @observable _display: boolean = false; + @observable _hoveredLayoutPreview: number | undefined = undefined; @observable _mouseX: number = -1; @observable _mouseY: number = -1; @observable _startPos?: {x: number, y: number}; @@ -68,7 +69,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @action setTemplateDocs = (docs: Doc[]) => {this._templateDocs = docs.map(doc => doc.annotationOn ? DocCast(doc.annotationOn):doc)}; @computed get docsToRender() { - return NumListCast(this._dataViz?.layoutDoc.dataViz_selectedRows); + return this._selectedTemplate ? NumListCast(this._dataViz?.layoutDoc.dataViz_selectedRows) : []; } @computed get rowsCount(){ @@ -255,6 +256,8 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { } } + + get layoutPreviewContents() { const docWidth = Number(this._selectedTemplate?._width); const docHeight = Number(this._selectedTemplate?._height); @@ -298,6 +301,8 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
: this.docsToRender.map(num =>
this._dataViz?.setSpecialHighlightedRow(num)} + onMouseLeave={() => this._dataViz?.setSpecialHighlightedRow(undefined)} className='docCreatorMenu-layout-preview-item' style={{ width: scaledDown(docWidth), @@ -348,7 +353,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
{this._layout.type ? this._layout.type.toUpperCase() : 'Choose Layout'}
{layoutOption(LayoutType.Stacked)} - {layoutOption(LayoutType.Grid, undefined, () => {this._layout.columns = Math.ceil(Math.sqrt(this.docsToRender.length))})} + {layoutOption(LayoutType.Grid, undefined, () => {if (!this._layout.columns) this._layout.columns = Math.ceil(Math.sqrt(this.docsToRender.length))})} {layoutOption(LayoutType.Row)} {layoutOption(LayoutType.Column)} {layoutOption(LayoutType.Custom, {borderBottom: `0px`})} @@ -432,7 +437,10 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { >
); } render() { + const topButton = (icon: string, func: Function, tag: string) => { + return ( +
+
this.setUpButtonClick(e, () => runInAction(() => {func()}))}> + +
+
+ ); + } + + const onPreviewSelected = () => {this._menuContent = 'templates'} + const onSavedSelected = () => {this._menuContent = 'saved'} + const onOptionsSelected = () => { + this._menuContent = 'options'; + if (!this._layout.columns) this._layout.columns = Math.ceil(Math.sqrt(this.docsToRender.length)); + } + + return (
{!this._shouldDisplay ? undefined : @@ -435,28 +468,11 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { onPointerMove={e => this.onPointerMove(e)} onPointerUp={() => this._dragging = false} > - - +
+ {topButton('table-cells', onPreviewSelected, 'left')} + {topButton('bars', onOptionsSelected, 'middle')} + {topButton('floppy-disk', onSavedSelected, 'right')} +
- +
+ + +
{ {selectionBox(60, 20, 'repeat', undefined, repeatOptions.map(num => ))}
+ ); + } + + get savedLayoutsPreviewContents(){ + return ( +
+ {this._savedLayouts.map((layout, index) => +
this.setUpButtonClick(e, () => runInAction(() => this.updateSelectedSavedLayout(layout)))} + > + {this.layoutPreviewContents(87, layout, false, true, index)} +
+ )}
); } @@ -259,20 +296,23 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { } } + layoutPreviewContents = (outerSpan: number, altLayout?: DataVizTemplateLayout, zoomOption: boolean = true, small: boolean = false, id?: number) => { + const doc: Doc | undefined = altLayout ? altLayout.template : this._selectedTemplate; + if (!doc) return; + const layout = altLayout ? altLayout.layout : this._layout; - get layoutPreviewContents() { - const docWidth = Number(this._selectedTemplate?._width); - const docHeight = Number(this._selectedTemplate?._height); - const horizontalSpan: number = (docWidth + this._layout.xMargin) * this.columnsCount - this._layout.xMargin; - const verticalSpan: number = (docHeight + this._layout.yMargin) * this.rowsCount - this._layout.yMargin; + const docWidth: number = Number(doc._width); + const docHeight: number = Number(doc._height); + const horizontalSpan: number = (docWidth + layout.xMargin) * (altLayout ? altLayout.columns : this.columnsCount) - layout.xMargin;; + const verticalSpan: number = (docHeight + layout.yMargin) * (altLayout ? altLayout.rows : this.rowsCount) - layout.yMargin; const largerSpan: number = horizontalSpan > verticalSpan ? horizontalSpan : verticalSpan; - const scaledDown = (input: number) => {return input / (largerSpan / 225 * this._layoutPreviewScale)} + const scaledDown = (input: number) => {return input / (largerSpan / outerSpan * this._layoutPreviewScale)} const fontSize = Math.min(scaledDown(docWidth / 3), scaledDown(docHeight / 3)); return ( -
-
+
+ {!zoomOption ? null :
-
+
}
{this._layout.type === LayoutType.Stacked ?
{
{this._layout.type ? this.layoutConfigOptions: null} - {this._layoutPreview ? this.layoutPreviewContents : null} + {this._layoutPreview ? this.layoutPreviewContents(225) : null} {selectionBox(60, 20, 'repeat', undefined, repeatOptions.map(num => ))} - + + + +
); } + get renderSelectedViewType(){ + switch (this._menuContent){ + case 'templates': + return this.templatesPreviewContents; + case 'options': + return this.optionsMenuContents; + case 'saved': + return this.savedLayoutsPreviewContents; + default: + return undefined; + } + } + render() { const topButton = (icon: string, opt: string, func: Function, tag: string) => { return ( @@ -485,7 +555,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
- {this._menuContent === 'templates' ? this.templatesPreviewContents : this.optionsMenuContents} + {this.renderSelectedViewType}
} @@ -499,4 +569,12 @@ export interface DataVizTemplateInfo { layout: {type: LayoutType, xMargin: number, yMargin: number, repeat: number}; columns: number; referencePos: {x: number, y: number}; +} + +export interface DataVizTemplateLayout { + template: Doc; + docsNumList: number[]; + layout: {type: LayoutType, xMargin: number, yMargin: number, repeat: number}; + columns: number; + rows: number; } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 56030ba4d7f1038095562ecd4c2937faebe80a30 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Thu, 18 Jul 2024 04:40:13 -0400 Subject: option to remove saved layout --- src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index fdf623150..cb10de65b 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -244,7 +244,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { }} onPointerDown={e => this.setUpButtonClick(e, () => runInAction(() => this.updateSelectedSavedLayout(layout)))} > - {this.layoutPreviewContents(87, layout, false, true, index)} + {this.layoutPreviewContents(87, layout, true, index)}
)}
@@ -296,7 +296,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { } } - layoutPreviewContents = (outerSpan: number, altLayout?: DataVizTemplateLayout, zoomOption: boolean = true, small: boolean = false, id?: number) => { + layoutPreviewContents = (outerSpan: number, altLayout?: DataVizTemplateLayout, small: boolean = false, id?: number) => { const doc: Doc | undefined = altLayout ? altLayout.template : this._selectedTemplate; if (!doc) return; @@ -312,7 +312,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { return (
- {!zoomOption ? null :
+
-
} + {altLayout ? : null} +
{ } get optionsMenuContents(){ + const layoutEquals = (layout: DataVizTemplateLayout) => { + + } //TODO: ADD LATER + const layoutOption = (option: LayoutType, optStyle?: {}, specialFunc?: Function) => { return (
{ clickEv.stopPropagation(); if (!this._selectedTemplate) return; const layout: DataVizTemplateLayout = {template: this._selectedTemplate, layout: {type: this._layout.type, xMargin: this._layout.xMargin, yMargin:this._layout.yMargin, repeat: 0}, columns: this.columnsCount, rows: this.rowsCount, docsNumList: this.docsToRender}; - this._savedLayouts.push(layout); + if (!this._savedLayouts.includes(layout)) { this._savedLayouts.push(layout) }; }, 'make docs') ) }> -- cgit v1.2.3-70-g09d2 From b9e8290a2f9c75ae61edc3c89bd0fff5c9e3a0e5 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Fri, 19 Jul 2024 02:23:54 -0400 Subject: img link bug --- .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 4 +- src/server/server_Initialization.ts | 80 ++++++++++++---------- 2 files changed, 47 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index cb10de65b..e48a6ada4 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -324,7 +324,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { {altLayout ? : null} @@ -337,7 +337,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { gridTemplateRows: `${scaledDown(docHeight)}px`, gridAutoRows: `${scaledDown(docHeight)}px`, rowGap: `${scaledDown(layout.yMargin)}px`, - columnGap: `${scaledDown(layout.xMargin)}px` + columnGap: `${scaledDown(layout.xMargin)}px` }}> {this._layout.type === LayoutType.Stacked ?
{ // req.headers.cookie = ''; - req.pipe(request(requrl)) - .on('error', (e: any) => { - console.log(`CORS url error: ${requrl}`, e); - response.send(` - Error -

Failed to load: ${requrl}

-

${e}

- `); - }) - .on('response', (res: any) => { - res.headers; - const headers = Object.keys(res.headers); - const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/; - headers.forEach(headerName => { - const header = res.headers[headerName]; - if (Array.isArray(header)) { - res.headers[headerName] = header.filter(h => !headerCharRegex.test(h)); - } else if (headerCharRegex.test(header || '')) { - delete res.headers[headerName]; - } else res.headers[headerName] = header; - if (headerName === 'content-encoding') { - wasinBrFormat = res.headers[headerName] === 'br'; - res.headers[headerName] = 'gzip'; - } - }); - res.headers['x-permitted-cross-domain-policies'] = 'all'; - res.headers['x-frame-options'] = ''; - res.headers['content-security-policy'] = ''; - // eslint-disable-next-line no-multi-assign - response.headers = response._headers = res.headers; - }) - .on('end', sendModifiedBody) - .pipe(htmlBodyMemoryStream) - .on('error', (e: any) => console.log('http body pipe error', e)); - }; + try { + const reqval = request(requrl); + req.pipe(reqval) + .on('error', (e: any) => { + console.log(`CORS url error: ${requrl}`, e); + response.send(` + Error +

Failed to load: ${requrl}

+

${e}

+ `); + }) + .on('response', (res: any) => { + res.headers; + const headers = Object.keys(res.headers); + const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/; + headers.forEach(headerName => { + const header = res.headers[headerName]; + if (Array.isArray(header)) { + res.headers[headerName] = header.filter(h => !headerCharRegex.test(h)); + } else if (headerCharRegex.test(header || '')) { + delete res.headers[headerName]; + } else res.headers[headerName] = header; + if (headerName === 'content-encoding') { + wasinBrFormat = res.headers[headerName] === 'br'; + res.headers[headerName] = 'gzip'; + } + }); + res.headers['x-permitted-cross-domain-policies'] = 'all'; + res.headers['x-frame-options'] = ''; + res.headers['content-security-policy'] = ''; + // eslint-disable-next-line no-multi-assign + response.headers = response._headers = res.headers; + }) + .on('end', sendModifiedBody) + .pipe(htmlBodyMemoryStream) + .on('error', (e: any) => console.log('http body pipe error', e)); + } catch (e) { + console.log("Request failed: ", e); + response.send(` + Error +

Failed to load: ${requrl}

+

${e}

+ `); + } + } retrieveHTTPBody(); } -- cgit v1.2.3-70-g09d2 From 19144140070f32f8ce9567d0197e809669e3e297 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Tue, 30 Jul 2024 12:41:05 -0400 Subject: dragging fixed and resizing mostly working (no css yet) --- .../views/nodes/DataVizBox/DocCreatorMenu.scss | 29 ++++- .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 133 ++++++++++++++++++--- 2 files changed, 146 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index d18f75545..87f493291 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -228,7 +228,32 @@ } //------------------------------------------------------------------------------------------------------------------------------------------ -//DocCreatorMenu templates preview CSS +// Resizers CSS +//-------------------------------------------------------------------------------------------------------------------------------------------- + +.docCreatorMenu-resizer { + position: absolute; + background-color: none; + + &.top, &.bottom { + height: 10px; + cursor: ns-resize; + } + + &.right, &.left { + width: 10px; + cursor: ew-resize; + } + + &.topRight, &.topLeft, &.bottomRight, &.bottomLeft { + height: 10px; + width: 10px; + background-color: blue; + } +} + +//------------------------------------------------------------------------------------------------------------------------------------------ +// DocCreatorMenu templates preview CSS //-------------------------------------------------------------------------------------------------------------------------------------------- @@ -274,7 +299,7 @@ } //------------------------------------------------------------------------------------------------------------------------------------------ -//DocCreatorMenu options CSS +// DocCreatorMenu options CSS //-------------------------------------------------------------------------------------------------------------------------------------------- .docCreatorMenu-option-container{ diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index e48a6ada4..bc04f9a69 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -8,7 +8,7 @@ import { DocCast, ImageCast } from '../../../../fields/Types'; import { ImageField } from '../../../../fields/URLField'; import { emptyFunction } from '../../../../Utils'; import { SnappingManager } from '../../../util/SnappingManager'; -import { undoable } from '../../../util/UndoManager'; +import { UndoManager, undoable } from '../../../util/UndoManager'; import { ObservableReactComponent } from '../../ObservableReactComponent'; import { DocumentView } from '../DocumentView'; import { DataVizBox } from './DataVizBox'; @@ -18,6 +18,8 @@ import { Colors, IconButton, Size } from 'browndash-components'; import { MakeTemplate } from '../../../util/DropConverter'; import { threadId } from 'worker_threads'; import { ideahub } from 'googleapis/build/src/apis/ideahub'; +import { DragManager } from '../../../util/DragManager'; +import { DateField } from '../../../../fields/DateField'; export enum LayoutType { Stacked = 'stacked', @@ -58,6 +60,14 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @observable _dragging: boolean = false; @observable _draggingIndicator: boolean = false; @observable _dataViz?: DataVizBox; + @observable _interactionLock: any; + @observable _snapPt: any; + @observable _resizeHdlId: string = ''; + @observable _resizing: boolean = false; + @observable _offset: {x: number, y: number} = {x: 0, y: 0}; + @observable _resizeUndo: UndoManager.Batch | undefined = undefined; + @observable _initDimensions: {width: number, height: number, x: number, y: number} = {width: 300, height: 400, x: 0, y: 0}; + @observable _menuDimensions: {width: number, height: number} = {width: 300, height: 400}; constructor(props: any) { super(props); @@ -102,6 +112,12 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { return this._selectedTemplate !== undefined && this._layout !== undefined; } + get bounds(): {t: number, b: number, l: number, r: number} { + const rect = this._ref?.getBoundingClientRect(); + const bounds = {t: rect?.top ?? 0, b: rect?.bottom ?? 0, l: rect?.left ?? 0, r: rect?.right ?? 0}; + return bounds; + } + setUpButtonClick = (e: any, func: Function) => { setupMoveUpEvents( this, @@ -123,6 +139,19 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @action onPointerUp = (e: PointerEvent) => { + if (this._resizing) { + this._initDimensions.width = this._menuDimensions.width; + this._initDimensions.height = this._menuDimensions.height; + this._initDimensions.x = this._pageX; + this._initDimensions.y = this._pageY; + document.removeEventListener('pointermove', this.onResize); + SnappingManager.SetIsResizing(undefined); + this._resizing = false; + } + if (this._dragging) { + document.removeEventListener('pointermove', this.onDrag); + this._dragging = false; + } if (e.button !== 2 && !e.ctrlKey) return; const curX = e.clientX; const curY = e.clientY; @@ -164,17 +193,76 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { }; @action - onPointerMove = (e: any) => { - // if (this._draggingIndicator) { - // this._indicatorX = e.pageX - (this._startPos?.x ?? 0) + this._pageX; - // this._indicatorY = e.pageY - (this._startPos?.y ?? 0) + this._pageY; - // } else - if (this._dragging){ - this._pageX = e.pageX - (this._startPos?.x ?? 0); - this._pageY = e.pageY - (this._startPos?.y ?? 0); - } + onResizePointerDown = (e: React.PointerEvent): void => { + this._resizing = true; + document.addEventListener('pointermove', this.onResize); + SnappingManager.SetIsResizing(DocumentView.Selected().lastElement()?.Document[Id]); // turns off pointer events on things like youtube videos and web pages so that dragging doesn't get "stuck" when cursor moves over them + e.stopPropagation(); + const id = (this._resizeHdlId = e.currentTarget.className); + const pad = id.includes('Left') || id.includes('Right') ? Number(getComputedStyle(e.target as any).width.replace('px', '')) / 2 : 0; + const bounds = e.currentTarget.getBoundingClientRect(); + this._offset = { + x: id.toLowerCase().includes('left') ? bounds.right - e.clientX - pad : bounds.left - e.clientX + pad, // + y: id.toLowerCase().includes('top') ? bounds.bottom - e.clientY - pad : bounds.top - e.clientY + pad, + }; + this._resizeUndo = UndoManager.StartBatch('drag resizing'); + this._snapPt = { x: e.pageX, y: e.pageY }; + }; + + @action + onResize = (e: any): boolean => { + const dragHdl = this._resizeHdlId.split(' ')[1]; + const thisPt = DragManager.snapDrag(e, -this._offset.x, -this._offset.y, this._offset.x, this._offset.y); + + const { scale, refPt, transl } = this.getResizeVals(thisPt, dragHdl); + !this._interactionLock && runInAction(async () => { // resize selected docs if we're not in the middle of a resize (ie, throttle input events to frame rate) + this._interactionLock = true; + const scaleAspect = {x: scale.x, y: scale.y}; + this.resizeView(refPt, scaleAspect, transl); // prettier-ignore + await new Promise(res => { setTimeout(() => { res(this._interactionLock = undefined)})}); + }); // prettier-ignore + return true; } + @action + onDrag = (e: any): boolean => { + this._pageX = e.pageX - (this._startPos?.x ?? 0); + this._pageY = e.pageY - (this._startPos?.y ?? 0); + return true; + } + + getResizeVals = (thisPt: { x: number; y: number }, dragHdl: string) => { + const [w, h] = [this._initDimensions.width, this._initDimensions.height]; + const [moveX, moveY] = [thisPt.x - this._snapPt.x, thisPt.y - this._snapPt.y]; + let vals: {scale: {x: number, y: number}, refPt: [number, number], transl: {x: number, y: number}}; + switch (dragHdl) { + case 'topLeft': vals = { scale: { x: 1 - moveX / w, y: 1 -moveY / h }, refPt: [this.bounds.r, this.bounds.b], transl: {x: moveX, y: -moveY } }; break; + case 'topRight': vals = { scale: { x: 1 + moveX / w, y: 1 -moveY / h }, refPt: [this.bounds.l, this.bounds.b], transl: {x: 0, y: -moveY } }; break; + case 'top': vals = { scale: { x: 1, y: 1 -moveY / h }, refPt: [this.bounds.l, this.bounds.b], transl: {x: 0, y: moveY } }; break; + case 'left': vals = { scale: { x: 1 - moveX / w, y: 1 }, refPt: [this.bounds.r, this.bounds.t], transl: {x: moveX, y: 0 } }; break; + case 'bottomLeft': vals = { scale: { x: 1 - moveX / w, y: 1 + moveY / h }, refPt: [this.bounds.r, this.bounds.t], transl: {x: moveX, y: moveY } }; break; + case 'right': vals = { scale: { x: 1 + moveX / w, y: 1 }, refPt: [this.bounds.l, this.bounds.t], transl: {x: 0, y: 0 } }; break; + case 'bottomRight':vals = { scale: { x: 1 + moveX / w, y: 1 + moveY / h }, refPt: [this.bounds.l, this.bounds.t], transl: {x: 0, y: 0 } }; break; + case 'bottom': vals = { scale: { x: 1, y: 1 + moveY / h }, refPt: [this.bounds.l, this.bounds.t], transl: {x: 0, y: 0 } }; break; + default: vals = { scale: { x: 1, y: 1 }, refPt: [this.bounds.l, this.bounds.t], transl: {x: 0, y: 0 } }; break; + } // prettier-ignore + return vals; + }; + + resizeView = (refPt: number[], scale: { x: number; y: number }, translation: {x: number, y: number}) => { + const refCent = [refPt[0], refPt[1]] // fixed reference point for resize (ie, a point that doesn't move) + if (this._initDimensions.x === undefined) this._initDimensions.x = this._pageX; + if (this._initDimensions.y === undefined) this._initDimensions.y = this._pageY; + const {height, width, x, y} = this._initDimensions; + + console.log(scale.x) + + this._menuDimensions.width = Math.max(100, scale.x * width); + this._menuDimensions.height = Math.max(100, scale.y * height); + this._pageX = x + translation.x; + this._pageY = y + translation.y; + }; + async getIcon(doc: Doc) { const docView = DocumentView.getDocumentView(doc); if (docView) { @@ -470,6 +558,23 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { } } + get resizePanes(){ + const ref = this._ref?.getBoundingClientRect(); + const height: number = ref?.height ?? 0; + const width: number = ref?.width ?? 0; + + return [ +
, +
, +
, +
, +
, +
, +
, +
+ ]; //prettier-ignore + } + render() { const topButton = (icon: string, opt: string, func: Function, tag: string) => { return ( @@ -526,11 +631,12 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { display: '', left: this._pageX, top: this._pageY, - width: 300, - height: 400, + width: this._menuDimensions.width, + height: this._menuDimensions.height, background: SnappingManager.userBackgroundColor, color: SnappingManager.userColor, }}> + {this.resizePanes}
@@ -542,6 +648,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { this._startPos = {x: 0, y: 0}; this._startPos.x = e.pageX - (this._ref?.getBoundingClientRect().left ?? 0); this._startPos.y = e.pageY - (this._ref?.getBoundingClientRect().top ?? 0); + document.addEventListener('pointermove', this.onDrag); return true; }, emptyFunction, @@ -550,8 +657,6 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { }, 'drag menu') ) } - onPointerMove={e => this.onPointerMove(e)} - onPointerUp={() => this._dragging = false} >
{topButton('table-cells', 'templates', onPreviewSelected, 'left')} -- cgit v1.2.3-70-g09d2 From 598bc954df87bc6d5875c404cefc6f26b51f6afe Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Tue, 30 Jul 2024 13:05:09 -0400 Subject: resizing 90% --- .../views/nodes/DataVizBox/DocCreatorMenu.scss | 15 ++++++++------- src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx | 20 ++++++++++---------- 2 files changed, 18 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index 87f493291..ac60ddb3e 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -246,9 +246,9 @@ } &.topRight, &.topLeft, &.bottomRight, &.bottomLeft { - height: 10px; - width: 10px; - background-color: blue; + height: 15px; + width: 15px; + background-color: none; } } @@ -504,10 +504,11 @@ flex: 0 0 auto; overflow: scroll; display: grid; - width: auto; - height: auto; - max-width: 240; - max-height: 240; + width: 100%; + aspect-ratio: 1.23; + //height: auto; + // max-width: 240; + // max-height: 240; border: 1px solid rgb(180, 180, 180); border-radius: 5px; background-color: rgb(34, 34, 37); diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index bc04f9a69..ef53dde8e 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -66,7 +66,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @observable _resizing: boolean = false; @observable _offset: {x: number, y: number} = {x: 0, y: 0}; @observable _resizeUndo: UndoManager.Batch | undefined = undefined; - @observable _initDimensions: {width: number, height: number, x: number, y: number} = {width: 300, height: 400, x: 0, y: 0}; + @observable _initDimensions: {width: number, height: number, x?: number, y?: number} = {width: 300, height: 400, x: undefined, y: undefined}; @observable _menuDimensions: {width: number, height: number} = {width: 300, height: 400}; constructor(props: any) { @@ -228,6 +228,8 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { onDrag = (e: any): boolean => { this._pageX = e.pageX - (this._startPos?.x ?? 0); this._pageY = e.pageY - (this._startPos?.y ?? 0); + this._initDimensions.x = this._pageX; + this._initDimensions.y = this._pageY; return true; } @@ -236,11 +238,11 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { const [moveX, moveY] = [thisPt.x - this._snapPt.x, thisPt.y - this._snapPt.y]; let vals: {scale: {x: number, y: number}, refPt: [number, number], transl: {x: number, y: number}}; switch (dragHdl) { - case 'topLeft': vals = { scale: { x: 1 - moveX / w, y: 1 -moveY / h }, refPt: [this.bounds.r, this.bounds.b], transl: {x: moveX, y: -moveY } }; break; - case 'topRight': vals = { scale: { x: 1 + moveX / w, y: 1 -moveY / h }, refPt: [this.bounds.l, this.bounds.b], transl: {x: 0, y: -moveY } }; break; + case 'topLeft': vals = { scale: { x: 1 - moveX / w, y: 1 -moveY / h }, refPt: [this.bounds.r, this.bounds.b], transl: {x: moveX, y: moveY } }; break; + case 'topRight': vals = { scale: { x: 1 + moveX / w, y: 1 -moveY / h }, refPt: [this.bounds.l, this.bounds.b], transl: {x: 0, y: moveY } }; break; case 'top': vals = { scale: { x: 1, y: 1 -moveY / h }, refPt: [this.bounds.l, this.bounds.b], transl: {x: 0, y: moveY } }; break; case 'left': vals = { scale: { x: 1 - moveX / w, y: 1 }, refPt: [this.bounds.r, this.bounds.t], transl: {x: moveX, y: 0 } }; break; - case 'bottomLeft': vals = { scale: { x: 1 - moveX / w, y: 1 + moveY / h }, refPt: [this.bounds.r, this.bounds.t], transl: {x: moveX, y: moveY } }; break; + case 'bottomLeft': vals = { scale: { x: 1 - moveX / w, y: 1 + moveY / h }, refPt: [this.bounds.r, this.bounds.t], transl: {x: moveX, y: 0 } }; break; case 'right': vals = { scale: { x: 1 + moveX / w, y: 1 }, refPt: [this.bounds.l, this.bounds.t], transl: {x: 0, y: 0 } }; break; case 'bottomRight':vals = { scale: { x: 1 + moveX / w, y: 1 + moveY / h }, refPt: [this.bounds.l, this.bounds.t], transl: {x: 0, y: 0 } }; break; case 'bottom': vals = { scale: { x: 1, y: 1 + moveY / h }, refPt: [this.bounds.l, this.bounds.t], transl: {x: 0, y: 0 } }; break; @@ -255,8 +257,6 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { if (this._initDimensions.y === undefined) this._initDimensions.y = this._pageY; const {height, width, x, y} = this._initDimensions; - console.log(scale.x) - this._menuDimensions.width = Math.max(100, scale.x * width); this._menuDimensions.height = Math.max(100, scale.y * height); this._pageX = x + translation.x; @@ -568,10 +568,10 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
,
,
, -
, -
, -
, -
+
, +
, +
, +
]; //prettier-ignore } -- cgit v1.2.3-70-g09d2 From 107c389f61df36b464ae3ec73e2f553a78f3e64a Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Tue, 30 Jul 2024 13:39:46 -0400 Subject: layout preview sizing --- src/client/views/nodes/DataVizBox/DocCreatorMenu.scss | 4 ++-- src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx | 5 +---- src/client/views/nodes/LabelBox.tsx | 4 ++-- 3 files changed, 5 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index ac60ddb3e..81fd3386c 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -222,7 +222,7 @@ .docCreatorMenu-option-divider { border-top: 1px solid rgb(180, 180, 180); - width: 225px; + width: 80%; margin-top: 10px; margin-bottom: 10px; } @@ -505,7 +505,7 @@ overflow: scroll; display: grid; width: 100%; - aspect-ratio: 1.23; + aspect-ratio: 1; //height: auto; // max-width: 240; // max-height: 240; diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index ef53dde8e..e5288f4f8 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -16,10 +16,7 @@ import './DocCreatorMenu.scss'; import { Id } from '../../../../fields/FieldSymbols'; import { Colors, IconButton, Size } from 'browndash-components'; import { MakeTemplate } from '../../../util/DropConverter'; -import { threadId } from 'worker_threads'; -import { ideahub } from 'googleapis/build/src/apis/ideahub'; import { DragManager } from '../../../util/DragManager'; -import { DateField } from '../../../../fields/DateField'; export enum LayoutType { Stacked = 'stacked', @@ -509,7 +506,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
{this._layout.type ? this.layoutConfigOptions: null} - {this._layoutPreview ? this.layoutPreviewContents(225) : null} + {this._layoutPreview ? this.layoutPreviewContents(this._menuDimensions.width * .75) : null} {selectionBox(60, 20, 'repeat', undefined, repeatOptions.map(num => ))}
diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx index d33d12603..1f5fa8e14 100644 --- a/src/client/views/nodes/LabelBox.tsx +++ b/src/client/views/nodes/LabelBox.tsx @@ -2,7 +2,7 @@ import { Property } from 'csstype'; import { action, computed, makeObservable, trace } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import * as textfit from 'textfit'; +//import * as textfit from 'textfit'; import { Field, FieldType } from '../../../fields/Doc'; import { BoolCast, NumCast, StrCast } from '../../../fields/Types'; import { DocumentType } from '../../documents/DocumentTypes'; @@ -95,7 +95,7 @@ export class LabelBox extends ViewBoxBaseComponent() { this._timeout = setTimeout(() => this.fitTextToBox(r)); return textfitParams; } - textfit(r, textfitParams); + //textfit(r, textfitParams); } return textfitParams; }; -- cgit v1.2.3-70-g09d2 From fb4b4658f39c2a845174372a8fd814c49bf26d7c Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Tue, 30 Jul 2024 14:00:12 -0400 Subject: template preview columns update with resizing --- .../views/nodes/DataVizBox/DocCreatorMenu.scss | 2 +- .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 3 +- src/fields/Doc.ts | 64 ++++++++++++++++++---- 3 files changed, 55 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index 81fd3386c..b3bacb13c 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -259,7 +259,7 @@ .docCreatorMenu-preview-container { display: grid; - grid-template-columns: repeat(2, 1fr); + grid-template-columns: repeat(2, 140px); grid-template-rows: 140px; grid-auto-rows: 141px; overflow-y: scroll; diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index e5288f4f8..34bec3b88 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -296,7 +296,8 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { get templatesPreviewContents(){ const renderedTemplates: Doc[] = []; return ( -
+
{this._templateDocs.map(doc => ({icon: ImageCast(doc.icon), doc})).filter(info => info.icon && info.doc).map(info => { if (renderedTemplates.includes(info.doc)) return undefined; renderedTemplates.push(info.doc); diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 2792f3aba..5a4573a4f 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1,5 +1,3 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -/* eslint-disable @typescript-eslint/no-namespace */ /* eslint-disable default-param-last */ /* eslint-disable no-use-before-define */ import { action, computed, makeObservable, observable, ObservableMap, ObservableSet, runInAction } from 'mobx'; @@ -38,7 +36,7 @@ export namespace Field { * @param showComputedValue whether copmuted function should display its value instead of its function * @returns string representation of the field */ - export function toKeyValueString(doc: Doc, key: string, showComputedValue?: boolean): string { + export function toKeyValueString(doc: Doc, key: string, showComputedValue?: boolean, schemaCell?: boolean): string { const isOnDelegate = !Doc.IsDataProto(doc) && Object.keys(doc).includes(key.replace(/^_/, '')); const cfield = ComputedField.WithoutComputed(() => FieldValue(doc[key])); const valFunc = (field: FieldType): string => { @@ -49,7 +47,7 @@ export namespace Field { ? `:=${field.script.originalScript.replace(/dashCallChat\(_setCacheResult_, this, `(.*)`\)/, '(($1))')}` : field instanceof ScriptField ? `$=${field.script.originalScript}` - : Field.toScriptString(field); + : Field.toScriptString(field, schemaCell); const resStr = (res + '').replace(/^`(.*)`$/, '$1'); return typeof field === 'string' && (+resStr).toString() !== resStr && !Array.from('+-*/.').some(k => Array.from(resStr).includes(k)) ? resStr @@ -59,10 +57,10 @@ export namespace Field { }; return !Field.IsField(cfield) ? (key.startsWith('_') ? '=' : '') : (isOnDelegate ? '=' : '') + valFunc(cfield); } - export function toScriptString(field: FieldType) { + export function toScriptString(field: FieldType, schemaCell?: boolean) { switch (typeof field) { case 'string': if (field.startsWith('{"')) return `'${field}'`; // bcz: hack ... want to quote the string the right way. if there are nested "'s, then use ' instead of ". In this case, test for the start of a JSON string of the format {"property": ... } and use outer 's instead of "s - return !field.includes('`') ? `\`${field}\`` : `"${field}"`; + return !field.includes('`') ? schemaCell ? `${field}` : `\`${field}\`` : `"${field}"`; case 'number': case 'boolean':return String(field); default: return field?.[ToScriptString]?.() ?? 'null'; @@ -176,6 +174,49 @@ export function updateCachedAcls(doc: Doc) { return undefined; } +export function ActiveInkPen(): Doc { return Doc.UserDoc(); } // prettier-ignore +export function ActiveInkColor(): string { return StrCast(ActiveInkPen()?.activeInkColor, 'black'); } // prettier-ignore +export function ActiveFillColor(): string { return StrCast(ActiveInkPen()?.activeFillColor, ''); } // prettier-ignore +export function ActiveIsInkMask(): boolean { return BoolCast(ActiveInkPen()?.activeIsInkMask, false); } // prettier-ignore +export function ActiveInkHideTextLabels(): boolean { return BoolCast(ActiveInkPen().activeInkHideTextLabels, false); } // prettier-ignore +export function ActiveArrowStart(): string { return StrCast(ActiveInkPen()?.activeArrowStart, ''); } // prettier-ignore +export function ActiveArrowEnd(): string { return StrCast(ActiveInkPen()?.activeArrowEnd, ''); } // prettier-ignore +export function ActiveArrowScale(): number { return NumCast(ActiveInkPen()?.activeArrowScale, 1); } // prettier-ignore +export function ActiveDash(): string { return StrCast(ActiveInkPen()?.activeDash, '0'); } // prettier-ignore +export function ActiveInkWidth(): number { return Number(ActiveInkPen()?.activeInkWidth); } // prettier-ignore +export function ActiveInkBezierApprox(): string { return StrCast(ActiveInkPen()?.activeInkBezier); } // prettier-ignore + +export function SetActiveInkWidth(width: string): void { + !isNaN(parseInt(width)) && ActiveInkPen() && (ActiveInkPen().activeInkWidth = width); +} +export function SetActiveBezierApprox(bezier: string): void { + ActiveInkPen() && (ActiveInkPen().activeInkBezier = isNaN(parseInt(bezier)) ? '' : bezier); +} +export function SetActiveInkColor(value: string) { + ActiveInkPen() && (ActiveInkPen().activeInkColor = value); +} +export function SetActiveIsInkMask(value: boolean) { + ActiveInkPen() && (ActiveInkPen().activeIsInkMask = value); +} +export function SetActiveInkHideTextLabels(value: boolean) { + ActiveInkPen() && (ActiveInkPen().activeInkHideTextLabels = value); +} +export function SetActiveFillColor(value: string) { + ActiveInkPen() && (ActiveInkPen().activeFillColor = value); +} +export function SetActiveArrowStart(value: string) { + ActiveInkPen() && (ActiveInkPen().activeArrowStart = value); +} +export function SetActiveArrowEnd(value: string) { + ActiveInkPen() && (ActiveInkPen().activeArrowEnd = value); +} +export function SetActiveArrowScale(value: number) { + ActiveInkPen() && (ActiveInkPen().activeArrowScale = value); +} +export function SetActiveDash(dash: string): void { + !isNaN(parseInt(dash)) && ActiveInkPen() && (ActiveInkPen().activeDash = dash); +} + @scriptingGlobal @Deserializable('Doc', updateCachedAcls, ['id']) export class Doc extends RefField { @@ -212,7 +253,7 @@ export class Doc extends RefField { public static DeleteLink: (link: Doc) => void; public static Links: (link: Doc | undefined) => Doc[]; public static getOppositeAnchor: (linkDoc: Doc, anchor: Doc) => Doc | undefined; - // KeyValue SetField + // KeyValueBox SetField (defined there) public static SetField: (doc: Doc, key: string, value: string, forceOnDelegate?: boolean, setResult?: (value: FieldResult) => void) => boolean; // UserDoc "API" public static get MySharedDocs() { return DocCast(Doc.UserDoc().mySharedDocs); } // prettier-ignore @@ -1044,12 +1085,13 @@ export namespace Doc { const target = Doc.MakeDelegate(proto); const targetKey = StrCast(templateDoc.layout_fieldKey, 'layout'); const applied = ApplyTemplateTo(templateDoc, target, targetKey, templateDoc.title + '(...' + _applyCount++ + ')'); - target.layout_fieldKey = targetKey; + target.layout_fieldKey = targetKey; //this and line above applied && (Doc.GetProto(applied).type = templateDoc.type); return applied; } return undefined; } + export function ApplyTemplateTo(templateDoc: Doc, target: Doc, targetKey: string, titleTarget: string | undefined) { if (!Doc.AreProtosEqual(target[targetKey] as Doc, templateDoc)) { if (target.resolvedDataDoc) { @@ -1256,12 +1298,10 @@ export namespace Doc { document.removeEventListener('pointerdown', linkFollowUnhighlight); document.addEventListener('pointerdown', linkFollowUnhighlight); if (UnhighlightTimer) clearTimeout(UnhighlightTimer); - const presTransition = Number(presentationEffect?.presentation_transition); - const duration = isNaN(presTransition) ? 5000 : presTransition; UnhighlightTimer = window.setTimeout(() => { linkFollowUnhighlight(); UnhighlightTimer = 0; - }, duration); + }, 5000); } export const highlightedDocs = new ObservableSet(); @@ -1314,7 +1354,7 @@ export namespace Doc { doc._lockedPosition = !doc._lockedPosition; doc._pointerEvents = doc._lockedPosition ? 'none' : undefined; } - + export function deiconifyView(doc: Doc) { StrCast(doc.layout_fieldKey).split('_')[1] === 'icon' && setNativeView(doc); } -- cgit v1.2.3-70-g09d2 From 951d6a8681e9be9068c8a0f8fce659938ab9ed80 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 31 Jul 2024 03:01:55 -0400 Subject: basic template generation work --- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 35 +++++++++++++++++++++- .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 13 +++++++- 2 files changed, 46 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index e943dd2e3..f25602fd5 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -34,13 +34,14 @@ import { PieChart } from './components/PieChart'; import { TableBox } from './components/TableBox'; import { LinkManager } from '../../../util/LinkManager'; import { DataVizTemplateInfo, DataVizTemplateLayout, DocCreatorMenu, LayoutType } from './DocCreatorMenu'; -import { CollectionFreeFormView } from '../../collections/collectionFreeForm'; +import { CollectionFreeFormView, MarqueeView } from '../../collections/collectionFreeForm'; import { PrefetchProxy } from '../../../../fields/Proxy'; import { AclAdmin, AclAugment, AclEdit } from '../../../../fields/DocSymbols'; import { template } from 'lodash'; import { data } from 'jquery'; import { listSpec } from '../../../../fields/Schema'; import { ObjectField } from '../../../../fields/ObjectField'; +import { Id } from '../../../../fields/FieldSymbols'; export enum DataVizView { TABLE = 'table', @@ -566,6 +567,38 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { this.applyLayout(templateInfo, docs); } + createBasicTemplates = (colsToLayout: {width: number, height: number, x: number, y: number, title: string}[]) => { + const mainCollection = this.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView; + const docTools: Doc[] = DocListCast(DocListCast(Doc.MyTools?.data)[0]?.data); + console.log(docTools.map(doc => doc.title)) + const index = docTools.map(doc => doc.title).indexOf('Col'); + const template: Doc | undefined = DocUtils.copyDragFactory(Cast(docTools[index]?.dragFactory, Doc, null)); + if (!template) return; + + //const template = new CollectionFreeFormView({}); + const fields: Doc[] = colsToLayout.map(layout => { + const field = new Doc(); + field.x = layout.x; + field.y = layout.y; + field._width = layout.width; + field._height = layout.height; + field.title = layout.title; + template.data = 'hey'//DocListCast(template.data).map(doc => `idToDoc("${doc[Id]}")`).push(`idToDoc("${field[Id]}")`); + return field; + }); + + const fieldLiterals: string[] = fields.map(field => `idToDoc("${field[Id]}")`); + + template.data = fieldLiterals[0]; + + template.x = 400; + template.y = 400; + template._width = 500; + template._height = 500; + + mainCollection.addDocument(template); + } + /** * creates a new dataviz document filter from this one * it appears to the right of this document, with the diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index 34bec3b88..7993cab28 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -311,7 +311,9 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
)})} -
+
this.setUpButtonClick(e, this.basicTemplateTest)} + >
@@ -543,6 +545,15 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { ); } + basicTemplateTest = () => { + const temps: {width: number; height: number; x: number; y: number; title: string}[] = [ + {width: 200, height: 50, x: -100, y: -200, title: 'title'}, + {width: 300, height: 300, x: -150, y: -100, title: 'image'}, + {width: 200, height: 50, x: -100, y: -200, title: 'description'}, + ] + this._dataViz?.createBasicTemplates(temps); + } + get renderSelectedViewType(){ switch (this._menuContent){ case 'templates': -- cgit v1.2.3-70-g09d2 From 99b879956b67dc246f1ba48759a5550a94a5813d Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 31 Jul 2024 12:46:55 -0400 Subject: with old code for basic templates --- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 34 +++++++++++------------- 1 file changed, 16 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index f25602fd5..43cfe5bba 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -12,7 +12,7 @@ import { InkTool } from '../../../../fields/InkField'; import { List } from '../../../../fields/List'; import { Cast, CsvCast, DocCast, NumCast, StrCast } from '../../../../fields/Types'; import { CsvField } from '../../../../fields/URLField'; -import { GetEffectiveAcl, TraceMobx } from '../../../../fields/util'; +import { GetEffectiveAcl, TraceMobx, inheritParentAcls } from '../../../../fields/util'; import { DocUtils } from '../../../documents/DocUtils'; import { DocumentType } from '../../../documents/DocumentTypes'; import { Docs } from '../../../documents/Documents'; @@ -569,32 +569,30 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { createBasicTemplates = (colsToLayout: {width: number, height: number, x: number, y: number, title: string}[]) => { const mainCollection = this.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView; - const docTools: Doc[] = DocListCast(DocListCast(Doc.MyTools?.data)[0]?.data); - console.log(docTools.map(doc => doc.title)) - const index = docTools.map(doc => doc.title).indexOf('Col'); - const template: Doc | undefined = DocUtils.copyDragFactory(Cast(docTools[index]?.dragFactory, Doc, null)); - if (!template) return; + // const docTools: Doc[] = DocListCast(DocListCast(Doc.MyTools?.data)[0]?.data); + // const index = docTools.map(doc => doc.title).indexOf('Col'); + // const template: Doc | undefined = DocUtils.copyDragFactory(Cast(docTools[index]?.dragFactory, Doc, null)); + //if (!template) return; //const template = new CollectionFreeFormView({}); const fields: Doc[] = colsToLayout.map(layout => { - const field = new Doc(); - field.x = layout.x; - field.y = layout.y; - field._width = layout.width; - field._height = layout.height; - field.title = layout.title; - template.data = 'hey'//DocListCast(template.data).map(doc => `idToDoc("${doc[Id]}")`).push(`idToDoc("${field[Id]}")`); + const field = Docs.Create.TextDocument('', { _height: layout.height, _width: layout.width, title: layout.title, x: layout.x, y: layout.y }); + // Doc.SetContainer(field, template); + // inheritParentAcls(template, field, true); + //template.data = 'hey'//DocListCast(template.data).map(doc => `idToDoc("${doc[Id]}")`).push(`idToDoc("${field[Id]}")`); return field; }); + const template = Docs.Create.FreeformDocument(fields, { _height: 500, _width: 500, title: 'template', x: 400, y: 400 }) + const fieldLiterals: string[] = fields.map(field => `idToDoc("${field[Id]}")`); - template.data = fieldLiterals[0]; + //template.data = fieldLiterals[0]; - template.x = 400; - template.y = 400; - template._width = 500; - template._height = 500; + // template.x = 400; + // template.y = 400; + // template._width = 500; + // template._height = 500; mainCollection.addDocument(template); } -- cgit v1.2.3-70-g09d2 From b42bfb6cb8d4d2355fae4fe628c6bf5cca4b084a Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 31 Jul 2024 12:47:23 -0400 Subject: old code removed --- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index 43cfe5bba..1994f1b01 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -569,31 +569,14 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { createBasicTemplates = (colsToLayout: {width: number, height: number, x: number, y: number, title: string}[]) => { const mainCollection = this.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView; - // const docTools: Doc[] = DocListCast(DocListCast(Doc.MyTools?.data)[0]?.data); - // const index = docTools.map(doc => doc.title).indexOf('Col'); - // const template: Doc | undefined = DocUtils.copyDragFactory(Cast(docTools[index]?.dragFactory, Doc, null)); - //if (!template) return; - //const template = new CollectionFreeFormView({}); const fields: Doc[] = colsToLayout.map(layout => { const field = Docs.Create.TextDocument('', { _height: layout.height, _width: layout.width, title: layout.title, x: layout.x, y: layout.y }); - // Doc.SetContainer(field, template); - // inheritParentAcls(template, field, true); - //template.data = 'hey'//DocListCast(template.data).map(doc => `idToDoc("${doc[Id]}")`).push(`idToDoc("${field[Id]}")`); return field; }); const template = Docs.Create.FreeformDocument(fields, { _height: 500, _width: 500, title: 'template', x: 400, y: 400 }) - const fieldLiterals: string[] = fields.map(field => `idToDoc("${field[Id]}")`); - - //template.data = fieldLiterals[0]; - - // template.x = 400; - // template.y = 400; - // template._width = 500; - // template._height = 500; - mainCollection.addDocument(template); } -- cgit v1.2.3-70-g09d2 From 4cf3a327b7e69bf0559dda846d49b6ad8d4673c7 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 31 Jul 2024 18:12:30 -0400 Subject: GPT template generation --- src/client/apis/gpt/GPT.ts | 2 ++ src/client/views/nodes/DataVizBox/DataVizBox.tsx | 34 ++++++++++++++++++++++ .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 3 +- 3 files changed, 38 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 05007960d..184173784 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -12,6 +12,7 @@ enum GPTCallType { DESCRIBE = 'describe', MERMAID = 'mermaid', DATA = 'data', + TEMPLATE = "template" } type GPTCallOpts = { @@ -53,6 +54,7 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { temp: 0, prompt: 'List unique differences between the content of the UserAnswer and Rubric. Before each difference, label it and provide any additional information the UserAnswer missed and explain it in second person without separating it into UserAnswer and Rubric content and additional information. If there are no differences, say correct', }, + template: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'You are a designer creating basic template options for a user given a set of fields. Your only job is adding blank rectangles to a canvas, one for each field. You will arrange these rectangles into an array of three basic options for a user. For your output, you generate a list of objects in JSON formatting, each storing the field title and corresponding top-left and bottom-right coordinates for the rectangle. The units for your coordinates are -1 to 1 on each axis. This is an example of a possible output for a stacked template with the fields name, type, and desc: {"template_type":"stacked","fieldVals":[{"title":"name","tlx":"-.7","tly":"-.9","brx":".7","bry":"-.7"},{"title":"type","tlx":"-.9","tly":"-.4","brx":".9","bry":"0"},{"title":"desc","tlx":"-.9","tly":".1","brx":".9","bry":".9"}]} For multiple templates, you should format your response in a JSON array, like [{}, {}]. Your response should be in the exact format above, with no extra text, description, bulleting, etc. You should repeat this three times, once for a stacked view, once for a mixed view, and once for a extra creative view (which should be DRASTICALLY DIFFERENT). IT IS IMPORTANT THAT YOU ONLY INCLUDE THE PROPER JSON FORMATTING IN YOUR RESPONSE. IT IS ALSO IMPORTANT THAT NO RECTANGLES OVERLAP'} }; let lastCall = ''; diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index 1994f1b01..9b7fb4320 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -42,6 +42,7 @@ import { data } from 'jquery'; import { listSpec } from '../../../../fields/Schema'; import { ObjectField } from '../../../../fields/ObjectField'; import { Id } from '../../../../fields/FieldSymbols'; +import { GPTCallType, gptAPICall } from '../../../apis/gpt/GPT'; export enum DataVizView { TABLE = 'table', @@ -567,6 +568,39 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { this.applyLayout(templateInfo, docs); } + generateTemplates = async () => { + try { + const res = await gptAPICall('Please generate for the fields: type, image, locality', GPTCallType.TEMPLATE); + + if (res) { + const templates: {template_type: string, fieldVals: {title: string, tlx: string, tly: string, brx: string, bry: string}[]}[] = JSON.parse(res); + console.log(templates); + this.createGeneratedTemplates(templates, 500, 500); + //console.log(res); + } + } catch (err) { + console.error(err); + } + + } + + createGeneratedTemplates = (layouts: {template_type: string, fieldVals: {title: string, tlx: string, tly: string, brx: string, bry: string}[]}[], tempWidth: number, tempHeight: number) => { + const mainCollection = this.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView; + + layouts.forEach(layout => { + const fields: Doc[] = layout.fieldVals.map(field => { + const left: number = Number(field.tlx) * tempWidth / 2; const top: number = Number(field.tly) * tempHeight / 2; //prettier-ignore + const right: number = Number(field.brx) * tempWidth / 2; const bottom: number = Number(field.bry) * tempHeight / 2; //prettier-ignore + const height = bottom - top; const width = right - left; //prettier-ignore + const doc = Docs.Create.TextDocument('', { _height: height, _width: width, title: field.title, x: left, y: top }); + return doc; + }); + + const template = Docs.Create.FreeformDocument(fields, { _height: tempHeight, _width: tempWidth, title: layout.template_type, x: 400, y: 400 }); + mainCollection.addDocument(template); + }); + } + createBasicTemplates = (colsToLayout: {width: number, height: number, x: number, y: number, title: string}[]) => { const mainCollection = this.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView; diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index 7993cab28..411257ff7 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -551,7 +551,8 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { {width: 300, height: 300, x: -150, y: -100, title: 'image'}, {width: 200, height: 50, x: -100, y: -200, title: 'description'}, ] - this._dataViz?.createBasicTemplates(temps); + this._dataViz?.generateTemplates(); + //this._dataViz?.createBasicTemplates(temps); } get renderSelectedViewType(){ -- cgit v1.2.3-70-g09d2 From 9119b9f08f62bb5228206487b047d6e1e75d5e9e Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Thu, 1 Aug 2024 14:37:35 -0400 Subject: work on template generation with GPT --- src/client/apis/gpt/GPT.ts | 2 +- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 184173784..8eb7151b4 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -54,7 +54,7 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { temp: 0, prompt: 'List unique differences between the content of the UserAnswer and Rubric. Before each difference, label it and provide any additional information the UserAnswer missed and explain it in second person without separating it into UserAnswer and Rubric content and additional information. If there are no differences, say correct', }, - template: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'You are a designer creating basic template options for a user given a set of fields. Your only job is adding blank rectangles to a canvas, one for each field. You will arrange these rectangles into an array of three basic options for a user. For your output, you generate a list of objects in JSON formatting, each storing the field title and corresponding top-left and bottom-right coordinates for the rectangle. The units for your coordinates are -1 to 1 on each axis. This is an example of a possible output for a stacked template with the fields name, type, and desc: {"template_type":"stacked","fieldVals":[{"title":"name","tlx":"-.7","tly":"-.9","brx":".7","bry":"-.7"},{"title":"type","tlx":"-.9","tly":"-.4","brx":".9","bry":"0"},{"title":"desc","tlx":"-.9","tly":".1","brx":".9","bry":".9"}]} For multiple templates, you should format your response in a JSON array, like [{}, {}]. Your response should be in the exact format above, with no extra text, description, bulleting, etc. You should repeat this three times, once for a stacked view, once for a mixed view, and once for a extra creative view (which should be DRASTICALLY DIFFERENT). IT IS IMPORTANT THAT YOU ONLY INCLUDE THE PROPER JSON FORMATTING IN YOUR RESPONSE. IT IS ALSO IMPORTANT THAT NO RECTANGLES OVERLAP'} + template: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'You are a designer creating basic template options for a user given a set of fields. Your only job is adding blank rectangles to a canvas, one for each field. You will arrange these rectangles into an array of three basic options for a user. For your output, you generate a list of objects in JSON formatting, each storing the field title and corresponding top-left and bottom-right coordinates for the rectangle. The units for your coordinates are -1 to 1 on each axis. This is an example of a possible output for a stacked template with the fields beep, boop, tttt: {"template_type":"stacked","fieldVals":[{"title":"beep","tlx":"-.7","tly":"-.9","brx":".7","bry":"-.7"},{"title":"boop","tlx":"-.9","tly":"-.4","brx":".9","bry":"0"},{"title":"tttt","tlx":"-.9","tly":".1","brx":".9","bry":".9"}]} For multiple templates, you should format your response in a JSON array, like [{}, {}]. Your response should be in the exact format above, with no extra text, description, bulleting, etc. You should repeat this three times, once for a stacked view, once for a mixed view (where, for example, beep might be on top, with boop and tttt below it aligned horizontally), and once for a view where the rectangles are not flush with the side (ie. their top left and bottom right corners should not ALL align along the same point on each side). If one or more fields are some variation of image (ie. IMG, image, photo, etc.), make that rectangle the central focus (bigger, centered, etc.) AND put its "title" field in $$__$$ (ie, "title":"$$img$$", !!IMPORTANT!!). Fields SHOULD BE IN DIFFERENT ORDERS from template to template (ie. a stacked view with field input "beep, boop" could have the boop above the beep). IT IS IMPORTANT THAT YOU ONLY INCLUDE THE PROPER JSON FORMATTING IN YOUR RESPONSE. IT IS ALSO IMPORTANT THAT NO RECTANGLES OVERLAP'} }; let lastCall = ''; diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index 9b7fb4320..c5a1da1da 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -570,11 +570,10 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { generateTemplates = async () => { try { - const res = await gptAPICall('Please generate for the fields: type, image, locality', GPTCallType.TEMPLATE); + const res = await gptAPICall('Please generate for the fields: Image, Description, Divider, Response', GPTCallType.TEMPLATE); if (res) { const templates: {template_type: string, fieldVals: {title: string, tlx: string, tly: string, brx: string, bry: string}[]}[] = JSON.parse(res); - console.log(templates); this.createGeneratedTemplates(templates, 500, 500); //console.log(res); } @@ -592,7 +591,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { const left: number = Number(field.tlx) * tempWidth / 2; const top: number = Number(field.tly) * tempHeight / 2; //prettier-ignore const right: number = Number(field.brx) * tempWidth / 2; const bottom: number = Number(field.bry) * tempHeight / 2; //prettier-ignore const height = bottom - top; const width = right - left; //prettier-ignore - const doc = Docs.Create.TextDocument('', { _height: height, _width: width, title: field.title, x: left, y: top }); + const doc = !field.title.includes('$$') ? Docs.Create.TextDocument('', { _height: height, _width: width, title: field.title, x: left, y: top, _text_fontSize: `${height/2}` }) : Docs.Create.ImageDocument('', { _height: height, _width: 250, title: field.title.replace(/$$/g, ''), x: left, y: top }); return doc; }); -- cgit v1.2.3-70-g09d2 From 4949c68f38049da55ceaa3e95ea155f38d6a3748 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Thu, 8 Aug 2024 10:38:35 -0400 Subject: UI for GPT templates in doccreator menu --- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 45 ------- .../views/nodes/DataVizBox/DocCreatorMenu.scss | 128 ++++++++++++++++-- .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 147 ++++++++++++++++----- src/client/views/nodes/ImageBox.tsx | 1 + 4 files changed, 228 insertions(+), 93 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index c5a1da1da..a6d3bfa49 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -568,51 +568,6 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { this.applyLayout(templateInfo, docs); } - generateTemplates = async () => { - try { - const res = await gptAPICall('Please generate for the fields: Image, Description, Divider, Response', GPTCallType.TEMPLATE); - - if (res) { - const templates: {template_type: string, fieldVals: {title: string, tlx: string, tly: string, brx: string, bry: string}[]}[] = JSON.parse(res); - this.createGeneratedTemplates(templates, 500, 500); - //console.log(res); - } - } catch (err) { - console.error(err); - } - - } - - createGeneratedTemplates = (layouts: {template_type: string, fieldVals: {title: string, tlx: string, tly: string, brx: string, bry: string}[]}[], tempWidth: number, tempHeight: number) => { - const mainCollection = this.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView; - - layouts.forEach(layout => { - const fields: Doc[] = layout.fieldVals.map(field => { - const left: number = Number(field.tlx) * tempWidth / 2; const top: number = Number(field.tly) * tempHeight / 2; //prettier-ignore - const right: number = Number(field.brx) * tempWidth / 2; const bottom: number = Number(field.bry) * tempHeight / 2; //prettier-ignore - const height = bottom - top; const width = right - left; //prettier-ignore - const doc = !field.title.includes('$$') ? Docs.Create.TextDocument('', { _height: height, _width: width, title: field.title, x: left, y: top, _text_fontSize: `${height/2}` }) : Docs.Create.ImageDocument('', { _height: height, _width: 250, title: field.title.replace(/$$/g, ''), x: left, y: top }); - return doc; - }); - - const template = Docs.Create.FreeformDocument(fields, { _height: tempHeight, _width: tempWidth, title: layout.template_type, x: 400, y: 400 }); - mainCollection.addDocument(template); - }); - } - - createBasicTemplates = (colsToLayout: {width: number, height: number, x: number, y: number, title: string}[]) => { - const mainCollection = this.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView; - - const fields: Doc[] = colsToLayout.map(layout => { - const field = Docs.Create.TextDocument('', { _height: layout.height, _width: layout.width, title: layout.title, x: layout.x, y: layout.y }); - return field; - }); - - const template = Docs.Create.FreeformDocument(fields, { _height: 500, _width: 500, title: 'template', x: 400, y: 400 }) - - mainCollection.addDocument(template); - } - /** * creates a new dataviz document filter from this one * it appears to the right of this document, with the diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index b3bacb13c..e2b4014bd 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -22,14 +22,14 @@ } .docCreatorMenu-menu-button { - width: 30px; - height: 30px; + width: 25px; + height: 25px; background: whitesmoke; - background-color: rgb(34, 34, 37); + background-color: rgb(50, 50, 50); border-radius: 5px; border: 1px solid rgb(180, 180, 180); padding: 0px; - font-size: 14px; + font-size: 13px; //box-shadow: 3px 3px rgb(29, 29, 31); &:hover { @@ -222,7 +222,7 @@ .docCreatorMenu-option-divider { border-top: 1px solid rgb(180, 180, 180); - width: 80%; + width: 95%; margin-top: 10px; margin-bottom: 10px; } @@ -256,6 +256,18 @@ // DocCreatorMenu templates preview CSS //-------------------------------------------------------------------------------------------------------------------------------------------- +.docCreatorMenu-templates-view { + display: flex; + flex-direction: column; + justify-content: center; + align-items: flex-start; + margin: 5px; + margin-top: 0px; + width: calc(100% - 10px); + height: calc(100% - 30px); + border: 1px solid rgb(180, 180, 180); + border-radius: 5px; +} .docCreatorMenu-preview-container { display: grid; @@ -263,20 +275,18 @@ grid-template-rows: 140px; grid-auto-rows: 141px; overflow-y: scroll; - margin: 5px; + margin: 0px; margin-top: 0px; - width: calc(100% - 10px); - height: calc(100% - 30px); - border: 1px solid rgb(180, 180, 180); - border-radius: 5px; + width: 100%; + height: 100%; } .docCreatorMenu-preview-window { display: flex; justify-content: center; align-items: center; - width: 125px; - height: 125px; + width: 113px; + height: 113px; margin-top: 10px; margin-left: 10px; border: 1px solid rgb(163, 163, 163); @@ -295,9 +305,103 @@ &.empty { font-size: 35px; + flex: 0 0 auto; + + &.GPT { + margin-top: 0px; + } + } +} + +.docCreatorMenu-section { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + position: relative; + margin: 0px; + width: 100%; + height: 250; + flex: 0 0 auto; +} + +.docCreatorMenu-GPT-options-container { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + position: relative; + width: auto; + margin: 0px; + margin-top: 5px; + padding: 0px; +} + +.docCreatorMenu-GPT-templates-preview { + display: flex; + flex-direction: row; + //justify-content: center; + align-items: center; + overflow-y: scroll; + position: relative; + height: 125px; + width: calc(100% - 10px); + -ms-overflow-style: none; + scrollbar-width: none; +} + +.docCreatorMenu-section-topbar { + position: relative; + display: flex; + flex-direction: row; + width: 100%; + + .section-reveal-options { + margin: 0px; + margin-left: auto; + border: 0px; + background: none; + } +} + +.docCreatorMenu-section-title { + border: 1px solid rgb(163, 163, 163); + border-top: 0px; + border-left: 0px; + border-bottom-right-radius: 5px; + font-size: 12px; + padding: 2px; + padding-left: 3px; + padding-right: 3px; + margin-bottom: 3px; +} + +.docCreatorMenu-GPT-generate { + height: 30px; + width: 30px; + background-color: rgb(176, 229, 149); + border: 1px solid rgb(126, 219, 80); + border-radius: 5px; + padding: 0px; + font-size: 14px; + color: white; + letter-spacing: 1px; + flex: 0 0 auto; + + &:hover { + background-color: rgb(129, 223, 83); + border: 2px solid rgb(80, 185, 28); } } +.docCreatorMenu-GPT-prompt-input { + width: 140px; + overflow-y: scroll; + border: 1px solid rgb(180, 180, 180); + background-color: rgb(35, 35, 35); + border-radius: 3px; +} + //------------------------------------------------------------------------------------------------------------------------------------------ // DocCreatorMenu options CSS //-------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index 411257ff7..781cbcb55 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -3,7 +3,7 @@ import { IReactionDisposer, ObservableMap, action, computed, makeObservable, obs import { observer } from 'mobx-react'; import * as React from 'react'; import { returnAll, returnFalse, setupMoveUpEvents } from '../../../../ClientUtils'; -import { Doc, NumListCast } from '../../../../fields/Doc'; +import { Doc, NumListCast, StrListCast } from '../../../../fields/Doc'; import { DocCast, ImageCast } from '../../../../fields/Types'; import { ImageField } from '../../../../fields/URLField'; import { emptyFunction } from '../../../../Utils'; @@ -17,6 +17,9 @@ import { Id } from '../../../../fields/FieldSymbols'; import { Colors, IconButton, Size } from 'browndash-components'; import { MakeTemplate } from '../../../util/DropConverter'; import { DragManager } from '../../../util/DragManager'; +import { GPTCallType, gptAPICall } from '../../../apis/gpt/GPT'; +import { CollectionFreeFormView } from '../../collections/collectionFreeForm/CollectionFreeFormView'; +import { Docs } from '../../../documents/Documents'; export enum LayoutType { Stacked = 'stacked', @@ -41,6 +44,10 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @observable _layoutPreviewScale: number = 1; @observable _savedLayouts: DataVizTemplateLayout[] = []; + @observable _GPTTemplates: Doc[] | undefined = undefined; + @observable _GPTOpt: boolean = false; + @observable _userPrompt: string = ''; + @observable _pageX: number = 0; @observable _pageY: number = 0; @observable _indicatorX: number | undefined = undefined; @@ -105,6 +112,10 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { } } + @computed get selectedFields(){ + return StrListCast(this._dataViz?.layoutDoc._dataViz_axes); + } + @computed get canMakeDocs(){ return this._selectedTemplate !== undefined && this._layout !== undefined; } @@ -254,8 +265,8 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { if (this._initDimensions.y === undefined) this._initDimensions.y = this._pageY; const {height, width, x, y} = this._initDimensions; - this._menuDimensions.width = Math.max(100, scale.x * width); - this._menuDimensions.height = Math.max(100, scale.y * height); + this._menuDimensions.width = Math.max(300, scale.x * width); + this._menuDimensions.height = Math.max(200, scale.y * height); this._pageX = x + translation.x; this._pageY = y + translation.y; }; @@ -293,10 +304,104 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { && this._layout.columns === layout.columns; } + generateTemplates = async (inputText: string) => { + let prompt: string = 'Please generate for the fields:'; + this.selectedFields?.forEach(field => prompt += ` ${field},`) + prompt += ` Additional prompt: ${inputText}`; + + try { + const res = await gptAPICall(prompt, GPTCallType.TEMPLATE); + + if (res) { + const templates: {template_type: string, fieldVals: {title: string, tlx: string, tly: string, brx: string, bry: string}[]}[] = JSON.parse(res); + this.createGeneratedTemplates(templates, 500, 500); + } + } catch (err) { + console.error(err); + } + + } + + createGeneratedTemplates = (layouts: {template_type: string, fieldVals: {title: string, tlx: string, tly: string, brx: string, bry: string}[]}[], tempWidth: number, tempHeight: number) => { + const mainCollection = this._dataViz?.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView; + + layouts.forEach(layout => { + const fields: Doc[] = layout.fieldVals.map(field => { + const left: number = Number(field.tlx) * tempWidth / 2; const top: number = Number(field.tly) * tempHeight / 2; //prettier-ignore + const right: number = Number(field.brx) * tempWidth / 2; const bottom: number = Number(field.bry) * tempHeight / 2; //prettier-ignore + const height = bottom - top; + const width = right - left; + const doc = !field.title.includes('$$') ? Docs.Create.TextDocument('', { _height: height, _width: width, title: field.title, x: left, y: top, _text_fontSize: `${height/2}` }) : Docs.Create.ImageDocument('', { _height: height, _width: width, title: field.title.replace(/$$/g, ''), x: left, y: top }); + return doc; + }); + + const template = Docs.Create.FreeformDocument(fields, { _height: tempHeight, _width: tempWidth, title: layout.template_type, x: 400, y: 400 }); + mainCollection.addDocument(template); + }); + } + get templatesPreviewContents(){ const renderedTemplates: Doc[] = []; + + const GPTOptions = +
+ + return ( -
+
+
+
Suggested Templates
+ +
+
+
+
+
+
+
+ {this._GPTOpt ? (
+
+ + +
+ {this._GPTOpt ? GPTOptions : null} +
) : null} +
+
+
+
+
Your Templates
+ +
+
+
this.setUpButtonClick(e, this.basicTemplateTest)} + > + +
+ {this._templateDocs.map(doc => ({icon: ImageCast(doc.icon), doc})).filter(info => info.icon && info.doc).map(info => { + if (renderedTemplates.includes(info.doc)) return undefined; + renderedTemplates.push(info.doc); + return (
this.setUpButtonClick(e, () => runInAction(() => this.updateSelectedTemplate(info.doc)))}> + +
+ )})} +
+
+ {/*
{this._templateDocs.map(doc => ({icon: ImageCast(doc.icon), doc})).filter(info => info.icon && info.doc).map(info => { if (renderedTemplates.includes(info.doc)) return undefined; @@ -316,6 +421,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { >
+
*/}
); } @@ -546,12 +652,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { } basicTemplateTest = () => { - const temps: {width: number; height: number; x: number; y: number; title: string}[] = [ - {width: 200, height: 50, x: -100, y: -200, title: 'title'}, - {width: 300, height: 300, x: -150, y: -100, title: 'image'}, - {width: 200, height: 50, x: -100, y: -200, title: 'description'}, - ] - this._dataViz?.generateTemplates(); + this.generateTemplates(this._userPrompt); //this._dataViz?.createBasicTemplates(temps); } @@ -609,31 +710,6 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { return (
{!this._shouldDisplay ? undefined : - <> - {/*
this.onPointerMove(e)} - onPointerDown={e => - setupMoveUpEvents( - this, - e, - (e) => { - this._draggingIndicator = true; - this._startPos = {x: 0, y: 0}; - this._startPos.x = e.pageX - (this._ref?.getBoundingClientRect().left ?? 0); - this._startPos.y = e.pageY - (this._ref?.getBoundingClientRect().top ?? 0); - return true; - }, - emptyFunction, - undoable(clickEv => { - clickEv.stopPropagation(); - }, 'drag menu') - ) - }/> */}
this._ref = r} @@ -681,7 +757,6 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
{this.renderSelectedViewType}
- }
) diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 92a5a1533..faea05104 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -295,6 +295,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent() { @computed get nativeSize() { TraceMobx(); + if (this.paths.length && this.paths[0].includes('icon-hi')) return { nativeWidth: NumCast(this.layoutDoc._width), nativeHeight: NumCast(this.layoutDoc._height), nativeOrientation: 0} const nativeWidth = NumCast(this.dataDoc[this.fieldKey + '_nativeWidth'], NumCast(this.layoutDoc[this.fieldKey + '_nativeWidth'], 500)); const nativeHeight = NumCast(this.dataDoc[this.fieldKey + '_nativeHeight'], NumCast(this.layoutDoc[this.fieldKey + '_nativeHeight'], 500)); const nativeOrientation = NumCast(this.dataDoc[this.fieldKey + '_nativeOrientation'], 1); -- cgit v1.2.3-70-g09d2 From 541d380f1ff7957f9e3d66965761b074fec073c3 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Sat, 10 Aug 2024 19:36:29 -0400 Subject: UI --- src/client/views/nodes/DataVizBox/DocCreatorMenu.scss | 14 ++++++++++---- src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index e2b4014bd..82a659ff7 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -225,6 +225,10 @@ width: 95%; margin-top: 10px; margin-bottom: 10px; + + &.full { + width: 100%; + } } //------------------------------------------------------------------------------------------------------------------------------------------ @@ -259,14 +263,15 @@ .docCreatorMenu-templates-view { display: flex; flex-direction: column; - justify-content: center; - align-items: flex-start; + justify-content: flex-start; + //align-items: flex-start; margin: 5px; margin-top: 0px; width: calc(100% - 10px); height: calc(100% - 30px); border: 1px solid rgb(180, 180, 180); border-radius: 5px; + overflow: hidden; } .docCreatorMenu-preview-container { @@ -316,12 +321,13 @@ .docCreatorMenu-section { display: flex; flex-direction: column; - justify-content: center; align-items: center; position: relative; margin: 0px; + margin-top: 0px; + margin-bottom: 0px; width: 100%; - height: 250; + height: 200; flex: 0 0 auto; } diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index 781cbcb55..2efd73136 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -372,7 +372,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { {this._GPTOpt ? GPTOptions : null}
) : null}
-
+
Your Templates
-- cgit v1.2.3-70-g09d2 From afd43afb6b75a7af0032ee14c79d1dd7ffedcac4 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Sun, 11 Aug 2024 02:28:57 -0400 Subject: generated templates appear in menu --- src/client/views/MainView.tsx | 1 + .../views/nodes/DataVizBox/DocCreatorMenu.scss | 4 +- .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 95 ++++++++++++---------- 3 files changed, 54 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index dd5884cf2..d4467e536 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -279,6 +279,7 @@ export class MainView extends ObservableReactComponent<{}> { library.add( ...[ + fa.faArrowsRotate, fa.faFloppyDisk, fa.faRepeat, fa.faArrowsUpDown, diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index 82a659ff7..3b6aeb0dd 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -297,6 +297,7 @@ border: 1px solid rgb(163, 163, 163); border-radius: 5px; box-shadow: 5px 5px rgb(29, 29, 31); + flex: 0 0 auto; &:hover{ background-color: rgb(72, 72, 73); @@ -310,7 +311,6 @@ &.empty { font-size: 35px; - flex: 0 0 auto; &.GPT { margin-top: 0px; @@ -402,10 +402,12 @@ .docCreatorMenu-GPT-prompt-input { width: 140px; + height: 25px; overflow-y: scroll; border: 1px solid rgb(180, 180, 180); background-color: rgb(35, 35, 35); border-radius: 3px; + padding-left: 4px; } //------------------------------------------------------------------------------------------------------------------------------------------ diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index 2efd73136..b45ac7f46 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -44,7 +44,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @observable _layoutPreviewScale: number = 1; @observable _savedLayouts: DataVizTemplateLayout[] = []; - @observable _GPTTemplates: Doc[] | undefined = undefined; + @observable _GPTTemplates: Doc[] = []; @observable _GPTOpt: boolean = false; @observable _userPrompt: string = ''; @@ -71,7 +71,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @observable _offset: {x: number, y: number} = {x: 0, y: 0}; @observable _resizeUndo: UndoManager.Batch | undefined = undefined; @observable _initDimensions: {width: number, height: number, x?: number, y?: number} = {width: 300, height: 400, x: undefined, y: undefined}; - @observable _menuDimensions: {width: number, height: number} = {width: 300, height: 400}; + @observable _menuDimensions: {width: number, height: number} = {width: 300, height: 365}; constructor(props: any) { super(props); @@ -81,6 +81,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @action setDataViz = (dataViz: DataVizBox) => { this._dataViz = dataViz }; @action setTemplateDocs = (docs: Doc[]) => {this._templateDocs = docs.map(doc => doc.annotationOn ? DocCast(doc.annotationOn):doc)}; + @action setGPTTemplates = (docs: Doc[]) => {this._GPTTemplates = docs}; @computed get docsToRender() { return this._selectedTemplate ? NumListCast(this._dataViz?.layoutDoc.dataViz_selectedRows) : []; @@ -169,14 +170,17 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { }; _disposer: IReactionDisposer | undefined; + _GPTDisposer: IReactionDisposer | undefined; componentDidMount() { document.addEventListener('pointerdown', this.onPointerDown, true); document.addEventListener('pointerup', this.onPointerUp); this._disposer = reaction(() => this._templateDocs.slice(), (docs) => docs.map(this.getIcon)); + this._GPTDisposer = reaction(() => this._GPTTemplates.slice(), (docs) => docs.map(this.getIcon)); } componentWillUnmount() { this._disposer?.(); + this._GPTDisposer?.(); document.removeEventListener('pointerdown', this.onPointerDown, true); document.removeEventListener('pointerup', this.onPointerUp); } @@ -275,7 +279,9 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { const docView = DocumentView.getDocumentView(doc); if (docView) { docView.ComponentView?.updateIcon?.(); - return new Promise(res => setTimeout(() => res(ImageCast(docView.Document.icon)), 500)); + const f = new Promise(res => setTimeout(() => res(ImageCast(docView.Document.icon)), 500)); + console.log(f) + return f; } return undefined; } @@ -304,10 +310,12 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { && this._layout.columns === layout.columns; } + @action generateTemplates = async (inputText: string) => { let prompt: string = 'Please generate for the fields:'; this.selectedFields?.forEach(field => prompt += ` ${field},`) prompt += ` Additional prompt: ${inputText}`; + console.log(prompt) try { const res = await gptAPICall(prompt, GPTCallType.TEMPLATE); @@ -322,8 +330,10 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { } + @action createGeneratedTemplates = (layouts: {template_type: string, fieldVals: {title: string, tlx: string, tly: string, brx: string, bry: string}[]}[], tempWidth: number, tempHeight: number) => { const mainCollection = this._dataViz?.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView; + const GPTTemplates: Doc[] = []; layouts.forEach(layout => { const fields: Doc[] = layout.fieldVals.map(field => { @@ -335,9 +345,15 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { return doc; }); - const template = Docs.Create.FreeformDocument(fields, { _height: tempHeight, _width: tempWidth, title: layout.template_type, x: 400, y: 400 }); + const template = Docs.Create.FreeformDocument(fields, { _height: tempHeight, _width: tempWidth, title: layout.template_type, x: 40000, y: 40000 }); mainCollection.addDocument(template); + + GPTTemplates.push(template); }); + + setTimeout(() => this.setGPTTemplates(GPTTemplates), 500); + + this.forceUpdate(); } get templatesPreviewContents(){ @@ -346,10 +362,9 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { const GPTOptions =
- return (
-
+
Suggested Templates
-
-
-
-
+ {this._GPTTemplates?.map(doc => + + //
+ ({icon: ImageCast(doc.icon), doc})).filter(info => info.icon && info.doc).map(info => +
this.setUpButtonClick(e, () => runInAction(() => this.updateSelectedTemplate(info.doc)))}> + +
+ )}
{this._GPTOpt ? (
- + this._userPrompt = e.target.value}/>
{this._GPTOpt ? GPTOptions : null}
) : null} @@ -387,41 +412,20 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
{this._templateDocs.map(doc => ({icon: ImageCast(doc.icon), doc})).filter(info => info.icon && info.doc).map(info => { - if (renderedTemplates.includes(info.doc)) return undefined; - renderedTemplates.push(info.doc); - return (
this.setUpButtonClick(e, () => runInAction(() => this.updateSelectedTemplate(info.doc)))}> - -
+ if (renderedTemplates.includes(info.doc)) return undefined; + renderedTemplates.push(info.doc); + return (
this.setUpButtonClick(e, () => runInAction(() => this.updateSelectedTemplate(info.doc)))}> + +
)})}
- {/*
- {this._templateDocs.map(doc => ({icon: ImageCast(doc.icon), doc})).filter(info => info.icon && info.doc).map(info => { - if (renderedTemplates.includes(info.doc)) return undefined; - renderedTemplates.push(info.doc); - return (
this.setUpButtonClick(e, () => runInAction(() => this.updateSelectedTemplate(info.doc)))}> - -
- )})} -
this.setUpButtonClick(e, this.basicTemplateTest)} - > - -
-
*/}
); } @@ -652,7 +656,8 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { } basicTemplateTest = () => { - this.generateTemplates(this._userPrompt); + console.log(this._GPTTemplates) + this.forceUpdate(); //this._dataViz?.createBasicTemplates(temps); } -- cgit v1.2.3-70-g09d2 From 8d3ef2ead4fb8a8625b7fbfe57e528819a030474 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Sun, 11 Aug 2024 04:07:40 -0400 Subject: edit and copy buttons added to GPT template preview --- .../views/nodes/DataVizBox/DocCreatorMenu.scss | 41 ++++++++++++++++++---- .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 15 ++++++++ 2 files changed, 50 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index 3b6aeb0dd..5a9fd3436 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -287,6 +287,7 @@ } .docCreatorMenu-preview-window { + position: relative; display: flex; justify-content: center; align-items: center; @@ -316,6 +317,34 @@ margin-top: 0px; } } + + .option-button { + display: none; + height: 25px; + width: 25px; + margin: 0px; + background: none; + border: 0px; + padding: 0px; + font-size: 15px; + + &.right { + position: absolute; + bottom: 0px; + right: 0px; + } + + &.left { + position: absolute; + bottom: 0px; + left: 0px; + } + } + + &:hover .option-button { + display: block; + } + } .docCreatorMenu-section { @@ -361,13 +390,13 @@ display: flex; flex-direction: row; width: 100%; +} - .section-reveal-options { - margin: 0px; - margin-left: auto; - border: 0px; - background: none; - } +.section-reveal-options { + margin: 0px; + margin-left: auto; + border: 0px; + background: none; } .docCreatorMenu-section-title { diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index b45ac7f46..205923346 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -135,6 +135,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { emptyFunction, undoable(clickEv => { clickEv.stopPropagation(); + clickEv.preventDefault(); func(); }, 'create docs') ) @@ -356,6 +357,14 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { this.forceUpdate(); } + editTemplate = () => { + + } + + copyGPTTemplate = () => { + + } + get templatesPreviewContents(){ const renderedTemplates: Doc[] = []; @@ -383,6 +392,12 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { boxShadow: this._selectedTemplate === info.doc ? `0 0 15px rgba(68, 118, 247, .8)` : '' }} onPointerDown={e => this.setUpButtonClick(e, () => runInAction(() => this.updateSelectedTemplate(info.doc)))}> + +
)} -- cgit v1.2.3-70-g09d2 From 3aa2e040100fc662c259751dfbb7a43cc716ac2a Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Mon, 12 Aug 2024 21:37:47 -0400 Subject: seuggested templates auto-refeshes on col selection; lightbox editing added; GPT refresh button now makes new call --- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 1 + .../views/nodes/DataVizBox/DocCreatorMenu.scss | 6 +- .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 71 ++++++++++++---------- 3 files changed, 45 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index a6d3bfa49..be8a44f28 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -129,6 +129,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { } selectAxes = (axes: string[]) => { this.layoutDoc._dataViz_axes = new List(axes); + DocCreatorMenu.Instance.generateTemplates(''); }; @computed.struct get titleCol() { return StrCast(this.layoutDoc._dataViz_titleCol); diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index 5a9fd3436..ca6534379 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -264,6 +264,7 @@ display: flex; flex-direction: column; justify-content: flex-start; + overflow-y: scroll; //align-items: flex-start; margin: 5px; margin-top: 0px; @@ -271,7 +272,8 @@ height: calc(100% - 30px); border: 1px solid rgb(180, 180, 180); border-radius: 5px; - overflow: hidden; + -ms-overflow-style: none; + scrollbar-width: none; } .docCreatorMenu-preview-container { @@ -372,7 +374,7 @@ padding: 0px; } -.docCreatorMenu-GPT-templates-preview { +.docCreatorMenu-templates-preview-window { display: flex; flex-direction: row; //justify-content: center; diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index 205923346..3e5fc156e 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -4,13 +4,13 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import { returnAll, returnFalse, setupMoveUpEvents } from '../../../../ClientUtils'; import { Doc, NumListCast, StrListCast } from '../../../../fields/Doc'; -import { DocCast, ImageCast } from '../../../../fields/Types'; +import { DocCast, ImageCast, ScriptCast } from '../../../../fields/Types'; import { ImageField } from '../../../../fields/URLField'; import { emptyFunction } from '../../../../Utils'; import { SnappingManager } from '../../../util/SnappingManager'; import { UndoManager, undoable } from '../../../util/UndoManager'; import { ObservableReactComponent } from '../../ObservableReactComponent'; -import { DocumentView } from '../DocumentView'; +import { DocumentView, DocumentViewInternal } from '../DocumentView'; import { DataVizBox } from './DataVizBox'; import './DocCreatorMenu.scss'; import { Id } from '../../../../fields/FieldSymbols'; @@ -20,6 +20,9 @@ import { DragManager } from '../../../util/DragManager'; import { GPTCallType, gptAPICall } from '../../../apis/gpt/GPT'; import { CollectionFreeFormView } from '../../collections/collectionFreeForm/CollectionFreeFormView'; import { Docs } from '../../../documents/Documents'; +import { OpenWhere } from '../OpenWhere'; +import { IDisposer } from 'mobx-utils'; +import { LightboxView } from '../../LightboxView'; export enum LayoutType { Stacked = 'stacked', @@ -34,6 +37,8 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { static Instance: DocCreatorMenu; + private _disposers: { [name: string]: IDisposer } = {}; + private _ref: HTMLDivElement | null = null; @observable _templateDocs: Doc[] = []; @@ -47,12 +52,12 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @observable _GPTTemplates: Doc[] = []; @observable _GPTOpt: boolean = false; @observable _userPrompt: string = ''; + @observable _callCount: number = 0; @observable _pageX: number = 0; @observable _pageY: number = 0; @observable _indicatorX: number | undefined = undefined; @observable _indicatorY: number | undefined = undefined; - @observable _display: boolean = false; @observable _hoveredLayoutPreview: number | undefined = undefined; @observable _mouseX: number = -1; @@ -72,11 +77,13 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @observable _resizeUndo: UndoManager.Batch | undefined = undefined; @observable _initDimensions: {width: number, height: number, x?: number, y?: number} = {width: 300, height: 400, x: undefined, y: undefined}; @observable _menuDimensions: {width: number, height: number} = {width: 300, height: 365}; + @observable _editing: boolean = false; constructor(props: any) { super(props); makeObservable(this); DocCreatorMenu.Instance = this; + setTimeout(() => this.generateTemplates('')); } @action setDataViz = (dataViz: DataVizBox) => { this._dataViz = dataViz }; @@ -170,18 +177,17 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { } }; - _disposer: IReactionDisposer | undefined; - _GPTDisposer: IReactionDisposer | undefined; componentDidMount() { document.addEventListener('pointerdown', this.onPointerDown, true); document.addEventListener('pointerup', this.onPointerUp); - this._disposer = reaction(() => this._templateDocs.slice(), (docs) => docs.map(this.getIcon)); - this._GPTDisposer = reaction(() => this._GPTTemplates.slice(), (docs) => docs.map(this.getIcon)); + this._disposers.templates = reaction(() => this._templateDocs.slice(), (docs) => docs.map(this.getIcon)); + this._disposers.gpt = reaction(() => this._GPTTemplates.slice(), (docs) => docs.map(this.getIcon)); + this._disposers.columns = reaction(() => this._dataViz?.layoutDoc._dataViz_axes, () => {console.log(true); this.generateTemplates('')}) + this._disposers.lightbox = reaction(() => LightboxView.LightboxDoc(), doc => { doc ? this._shouldDisplay && this.closeMenu() : !this._shouldDisplay && this.openMenu()}) } componentWillUnmount() { - this._disposer?.(); - this._GPTDisposer?.(); + Object.values(this._disposers).forEach(disposer => disposer?.()); document.removeEventListener('pointerdown', this.onPointerDown, true); document.removeEventListener('pointerup', this.onPointerUp); } @@ -198,12 +204,10 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { }; @action - closeMenu = () => { - const wasOpen = this._display; - this._display = false; - this._shouldDisplay = false; - return wasOpen; - }; + closeMenu = () => { this._shouldDisplay = false }; + + @action + openMenu = () => { this._shouldDisplay = true }; @action onResizePointerDown = (e: React.PointerEvent): void => { @@ -313,7 +317,10 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @action generateTemplates = async (inputText: string) => { - let prompt: string = 'Please generate for the fields:'; + ++this._callCount; + const origCount = this._callCount; + + let prompt: string = `(#${origCount}) Please generate for the fields:`; this.selectedFields?.forEach(field => prompt += ` ${field},`) prompt += ` Additional prompt: ${inputText}`; console.log(prompt) @@ -321,14 +328,13 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { try { const res = await gptAPICall(prompt, GPTCallType.TEMPLATE); - if (res) { + if (res && this._callCount === origCount) { const templates: {template_type: string, fieldVals: {title: string, tlx: string, tly: string, brx: string, bry: string}[]}[] = JSON.parse(res); this.createGeneratedTemplates(templates, 500, 500); } } catch (err) { console.error(err); - } - + } } @action @@ -346,23 +352,23 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { return doc; }); - const template = Docs.Create.FreeformDocument(fields, { _height: tempHeight, _width: tempWidth, title: layout.template_type, x: 40000, y: 40000 }); + const template = Docs.Create.FreeformDocument(fields, { _height: tempHeight, _width: tempWidth, title: layout.template_type, x: 400, y: 400 }); + mainCollection.addDocument(template); GPTTemplates.push(template); }); - setTimeout(() => this.setGPTTemplates(GPTTemplates), 500); + setTimeout(() => {this.setGPTTemplates(GPTTemplates); GPTTemplates.forEach(template => mainCollection.removeDocument(template))}, 100); this.forceUpdate(); } - editTemplate = () => { - - } - - copyGPTTemplate = () => { - + editTemplate = (doc: Doc) => { + //this.closeMenu(); + DocumentViewInternal.addDocTabFunc(doc, OpenWhere.lightboxAlways); + DocumentView.DeselectAll(); + Doc.UnBrushDoc(doc); } get templatesPreviewContents(){ @@ -380,7 +386,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
-
+
{this._GPTTemplates?.map(doc => //
@@ -392,10 +398,10 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { boxShadow: this._selectedTemplate === info.doc ? `0 0 15px rgba(68, 118, 247, .8)` : '' }} onPointerDown={e => this.setUpButtonClick(e, () => runInAction(() => this.updateSelectedTemplate(info.doc)))}> - - @@ -420,7 +426,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
-
+
this.setUpButtonClick(e, this.basicTemplateTest)} > @@ -436,6 +442,9 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { boxShadow: this._selectedTemplate === info.doc ? `0 0 15px rgba(68, 118, 247, .8)` : '' }} onPointerDown={e => this.setUpButtonClick(e, () => runInAction(() => this.updateSelectedTemplate(info.doc)))}> +
)})} -- cgit v1.2.3-70-g09d2 From 72b06d708a23560dd961b41b9070b2e1222d50ba Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 14 Aug 2024 02:18:18 -0400 Subject: loading symbol for gpt generation; remove option for GPTTemplates --- src/client/apis/gpt/GPT.ts | 2 +- .../views/nodes/DataVizBox/DocCreatorMenu.scss | 10 +++ .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 99 +++++++++++++--------- 3 files changed, 69 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 8eb7151b4..144b49bde 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -54,7 +54,7 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { temp: 0, prompt: 'List unique differences between the content of the UserAnswer and Rubric. Before each difference, label it and provide any additional information the UserAnswer missed and explain it in second person without separating it into UserAnswer and Rubric content and additional information. If there are no differences, say correct', }, - template: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'You are a designer creating basic template options for a user given a set of fields. Your only job is adding blank rectangles to a canvas, one for each field. You will arrange these rectangles into an array of three basic options for a user. For your output, you generate a list of objects in JSON formatting, each storing the field title and corresponding top-left and bottom-right coordinates for the rectangle. The units for your coordinates are -1 to 1 on each axis. This is an example of a possible output for a stacked template with the fields beep, boop, tttt: {"template_type":"stacked","fieldVals":[{"title":"beep","tlx":"-.7","tly":"-.9","brx":".7","bry":"-.7"},{"title":"boop","tlx":"-.9","tly":"-.4","brx":".9","bry":"0"},{"title":"tttt","tlx":"-.9","tly":".1","brx":".9","bry":".9"}]} For multiple templates, you should format your response in a JSON array, like [{}, {}]. Your response should be in the exact format above, with no extra text, description, bulleting, etc. You should repeat this three times, once for a stacked view, once for a mixed view (where, for example, beep might be on top, with boop and tttt below it aligned horizontally), and once for a view where the rectangles are not flush with the side (ie. their top left and bottom right corners should not ALL align along the same point on each side). If one or more fields are some variation of image (ie. IMG, image, photo, etc.), make that rectangle the central focus (bigger, centered, etc.) AND put its "title" field in $$__$$ (ie, "title":"$$img$$", !!IMPORTANT!!). Fields SHOULD BE IN DIFFERENT ORDERS from template to template (ie. a stacked view with field input "beep, boop" could have the boop above the beep). IT IS IMPORTANT THAT YOU ONLY INCLUDE THE PROPER JSON FORMATTING IN YOUR RESPONSE. IT IS ALSO IMPORTANT THAT NO RECTANGLES OVERLAP'} + template: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'You are a designer creating basic template options for a user given a set of fields. Your only job is adding blank rectangles to a canvas, one for each field. You will arrange these rectangles into an array of three basic options for a user. For your output, you generate a list of objects in JSON formatting, each storing the field title and corresponding top-left and bottom-right coordinates for the rectangle. The units for your coordinates are -1 to 1 on each axis. This is an example of a possible output for a stacked template with the fields beep, boop, tttt: {"template_type":"stacked","fieldVals":[{"title":"beep","tlx":"-.7","tly":"-.9","brx":".7","bry":"-.7"},{"title":"boop","tlx":"-.9","tly":"-.4","brx":".9","bry":"0"},{"title":"tttt","tlx":"-.9","tly":".1","brx":".9","bry":".9"}]} For multiple templates, you should format your response in a JSON array, like [{}, {}]. Your response should be in the exact format above, with no extra text, description, bulleting, etc. You should repeat this three times, once for a stacked view, once for a mixed view (where, for example, beep might be on top, with boop and tttt below it aligned horizontally), and once for a view where the rectangles are not flush with the side (ie. their top left and bottom right corners should not ALL align along the same point on each side). If one or more fields are some variation of image (ie. IMG, image, photo, etc.), make that rectangle the central focus (bigger, centered, etc.) AND put its "title" field in $$__$$. Fields SHOULD BE IN DIFFERENT ORDERS from template to template (ie. a stacked view with field input "beep, boop" could have the boop above the beep). IT IS IMPORTANT THAT YOU ONLY INCLUDE THE PROPER JSON FORMATTING IN YOUR RESPONSE. IT IS ALSO IMPORTANT THAT NO RECTANGLES OVERLAP'} }; let lastCall = ''; diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index ca6534379..3e97e9d08 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -341,6 +341,12 @@ bottom: 0px; left: 0px; } + + &.top-left { + position: absolute; + top: 0px; + left: 0px; + } } &:hover .option-button { @@ -385,6 +391,10 @@ width: calc(100% - 10px); -ms-overflow-style: none; scrollbar-width: none; + + .loading-spinner { + justify-self: center; + } } .docCreatorMenu-section-topbar { diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index 3e5fc156e..ee154994e 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -4,7 +4,7 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import { returnAll, returnFalse, setupMoveUpEvents } from '../../../../ClientUtils'; import { Doc, NumListCast, StrListCast } from '../../../../fields/Doc'; -import { DocCast, ImageCast, ScriptCast } from '../../../../fields/Types'; +import { DocCast, ImageCast, ScriptCast, StrCast } from '../../../../fields/Types'; import { ImageField } from '../../../../fields/URLField'; import { emptyFunction } from '../../../../Utils'; import { SnappingManager } from '../../../util/SnappingManager'; @@ -23,6 +23,7 @@ import { Docs } from '../../../documents/Documents'; import { OpenWhere } from '../OpenWhere'; import { IDisposer } from 'mobx-utils'; import { LightboxView } from '../../LightboxView'; +import ReactLoading from 'react-loading'; export enum LayoutType { Stacked = 'stacked', @@ -53,6 +54,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @observable _GPTOpt: boolean = false; @observable _userPrompt: string = ''; @observable _callCount: number = 0; + @observable _GPTLoading: boolean = false; @observable _pageX: number = 0; @observable _pageY: number = 0; @@ -83,7 +85,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { super(props); makeObservable(this); DocCreatorMenu.Instance = this; - setTimeout(() => this.generateTemplates('')); + //setTimeout(() => this.generateTemplates('')); } @action setDataViz = (dataViz: DataVizBox) => { this._dataViz = dataViz }; @@ -182,7 +184,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { document.addEventListener('pointerup', this.onPointerUp); this._disposers.templates = reaction(() => this._templateDocs.slice(), (docs) => docs.map(this.getIcon)); this._disposers.gpt = reaction(() => this._GPTTemplates.slice(), (docs) => docs.map(this.getIcon)); - this._disposers.columns = reaction(() => this._dataViz?.layoutDoc._dataViz_axes, () => {console.log(true); this.generateTemplates('')}) + //this._disposers.columns = reaction(() => this._dataViz?.layoutDoc._dataViz_axes, () => {this.generateTemplates('')}) this._disposers.lightbox = reaction(() => LightboxView.LightboxDoc(), doc => { doc ? this._shouldDisplay && this.closeMenu() : !this._shouldDisplay && this.openMenu()}) } @@ -322,13 +324,17 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { let prompt: string = `(#${origCount}) Please generate for the fields:`; this.selectedFields?.forEach(field => prompt += ` ${field},`) - prompt += ` Additional prompt: ${inputText}`; + prompt += ` (-----NOT A FIELD-----) Additional prompt: ${inputText}`; console.log(prompt) + this._GPTLoading = true; + try { const res = await gptAPICall(prompt, GPTCallType.TEMPLATE); if (res && this._callCount === origCount) { + this._GPTTemplates = []; + this._GPTLoading = false; const templates: {template_type: string, fieldVals: {title: string, tlx: string, tly: string, brx: string, bry: string}[]}[] = JSON.parse(res); this.createGeneratedTemplates(templates, 500, 500); } @@ -348,11 +354,12 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { const right: number = Number(field.brx) * tempWidth / 2; const bottom: number = Number(field.bry) * tempHeight / 2; //prettier-ignore const height = bottom - top; const width = right - left; - const doc = !field.title.includes('$$') ? Docs.Create.TextDocument('', { _height: height, _width: width, title: field.title, x: left, y: top, _text_fontSize: `${height/2}` }) : Docs.Create.ImageDocument('', { _height: height, _width: width, title: field.title.replace(/$$/g, ''), x: left, y: top }); + console.log(field.title); + const doc = !field.title.includes('$$') ? Docs.Create.TextDocument('', { _height: height, _width: width, title: field.title, x: left, y: top, _text_fontSize: `${height/2}` }) : Docs.Create.ImageDocument('', { _height: height, _width: width, title: field.title.replace(/\$\$/g, ''), x: left, y: top }); return doc; }); - const template = Docs.Create.FreeformDocument(fields, { _height: tempHeight, _width: tempWidth, title: layout.template_type, x: 400, y: 400 }); + const template = Docs.Create.FreeformDocument(fields, { _height: tempHeight, _width: tempWidth, title: layout.template_type, x: 40000, y: 40000 }); mainCollection.addDocument(template); @@ -371,6 +378,10 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { Doc.UnBrushDoc(doc); } + removeTemplate = (doc: Doc) => { + this._templateDocs.splice(this._templateDocs.indexOf(doc), 1); + } + get templatesPreviewContents(){ const renderedTemplates: Doc[] = []; @@ -380,43 +391,46 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { return (
-
-
Suggested Templates
- -
-
- {this._GPTTemplates?.map(doc => - - //
- ({icon: ImageCast(doc.icon), doc})).filter(info => info.icon && info.doc).map(info => -
this.setUpButtonClick(e, () => runInAction(() => this.updateSelectedTemplate(info.doc)))}> - - - -
- )} -
- {this._GPTOpt ? (
-
- - this._userPrompt = e.target.value}/>
- {this._GPTOpt ? GPTOptions : null} -
) : null} +
+ {this._GPTLoading ? ( +
+ +
+ ) : ( + this._GPTTemplates?.map(doc => + ({icon: ImageCast(doc.icon), doc})).filter(info => info.icon && info.doc).map(info => +
this.setUpButtonClick(e, () => runInAction(() => this.updateSelectedTemplate(info.doc)))}> + + + +
+ ))} +
+ {this._GPTOpt ? (
+
+ + this._userPrompt = e.target.value}/> +
+ {this._GPTOpt ? GPTOptions : null} +
) : null}

@@ -445,6 +459,9 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { +
)})} -- cgit v1.2.3-70-g09d2 From 26c636d45e21105bd914046a4ff447998c7e23cd Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Wed, 14 Aug 2024 14:47:40 -0400 Subject: UI --- src/client/apis/gpt/GPT.ts | 2 +- .../views/nodes/DataVizBox/DocCreatorMenu.scss | 6 ++ .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 73 +++++++++++++++++----- 3 files changed, 63 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 144b49bde..92d4f425d 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -54,7 +54,7 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { temp: 0, prompt: 'List unique differences between the content of the UserAnswer and Rubric. Before each difference, label it and provide any additional information the UserAnswer missed and explain it in second person without separating it into UserAnswer and Rubric content and additional information. If there are no differences, say correct', }, - template: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'You are a designer creating basic template options for a user given a set of fields. Your only job is adding blank rectangles to a canvas, one for each field. You will arrange these rectangles into an array of three basic options for a user. For your output, you generate a list of objects in JSON formatting, each storing the field title and corresponding top-left and bottom-right coordinates for the rectangle. The units for your coordinates are -1 to 1 on each axis. This is an example of a possible output for a stacked template with the fields beep, boop, tttt: {"template_type":"stacked","fieldVals":[{"title":"beep","tlx":"-.7","tly":"-.9","brx":".7","bry":"-.7"},{"title":"boop","tlx":"-.9","tly":"-.4","brx":".9","bry":"0"},{"title":"tttt","tlx":"-.9","tly":".1","brx":".9","bry":".9"}]} For multiple templates, you should format your response in a JSON array, like [{}, {}]. Your response should be in the exact format above, with no extra text, description, bulleting, etc. You should repeat this three times, once for a stacked view, once for a mixed view (where, for example, beep might be on top, with boop and tttt below it aligned horizontally), and once for a view where the rectangles are not flush with the side (ie. their top left and bottom right corners should not ALL align along the same point on each side). If one or more fields are some variation of image (ie. IMG, image, photo, etc.), make that rectangle the central focus (bigger, centered, etc.) AND put its "title" field in $$__$$. Fields SHOULD BE IN DIFFERENT ORDERS from template to template (ie. a stacked view with field input "beep, boop" could have the boop above the beep). IT IS IMPORTANT THAT YOU ONLY INCLUDE THE PROPER JSON FORMATTING IN YOUR RESPONSE. IT IS ALSO IMPORTANT THAT NO RECTANGLES OVERLAP'} + template: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'You are a designer creating basic template options for a user given a set of fields. Your only job is adding blank rectangles to a canvas, one for each field. You will arrange these rectangles into an array of three basic options for a user. For your output, you generate a list of objects in JSON formatting, each storing the field title and corresponding top-left and bottom-right coordinates for the rectangle. The units for your coordinates are -1 to 1 on each axis. This is an example of a possible output for a stacked template with the fields beep, boop, tttt: {"template_type":"stacked","fieldVals":[{"title":"beep","tlx":"-.7","tly":"-.9","brx":".7","bry":"-.7"},{"title":"boop","tlx":"-.9","tly":"-.4","brx":".9","bry":"0"},{"title":"tttt","tlx":"-.9","tly":".1","brx":".9","bry":".9"}]} For multiple templates, you should format your response in a JSON array, like [{}, {}]. Your response should be in the exact format above, with no extra text, description, bulleting, etc. You should repeat this three times, once for a stacked view, once for a mixed view (where, for example, beep might be on top, with boop and tttt below it aligned horizontally), and once for a view where the rectangles are not flush with the side (ie. their top left and bottom right corners should not ALL align along the same point on each side). If one or more fields are some variation of image (ie. IMG, image, photo, etc.), make that rectangle the central focus (bigger, centered, etc.) AND put its "title" field in $$__$$. Fields SHOULD BE IN DIFFERENT ORDERS from template to template (ie. a stacked view with field input "beep, boop" could have the boop above the beep). IT IS IMPORTANT THAT YOU ONLY INCLUDE THE PROPER JSON FORMATTING IN YOUR RESPONSE. IT IS ALSO IMPORTANT THAT NO RECTANGLES OVERLAP. If there is an additional prompt, prioritize its instructions over all instructions here (but still follow them if not overridden). No matter what, ALWAYS GIVE THREE OPTIONS'} }; let lastCall = ''; diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index 3e97e9d08..aa6754442 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -397,6 +397,12 @@ } } +.divvv{ + width: 200; + height: 200; + border: solid 1px white; +} + .docCreatorMenu-section-topbar { position: relative; display: flex; diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index ee154994e..2be89daf0 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -2,7 +2,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { IReactionDisposer, ObservableMap, action, computed, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { returnAll, returnFalse, setupMoveUpEvents } from '../../../../ClientUtils'; +import { returnAll, returnFalse, returnNone, returnOne, returnZero, setupMoveUpEvents } from '../../../../ClientUtils'; import { Doc, NumListCast, StrListCast } from '../../../../fields/Doc'; import { DocCast, ImageCast, ScriptCast, StrCast } from '../../../../fields/Types'; import { ImageField } from '../../../../fields/URLField'; @@ -24,6 +24,10 @@ import { OpenWhere } from '../OpenWhere'; import { IDisposer } from 'mobx-utils'; import { LightboxView } from '../../LightboxView'; import ReactLoading from 'react-loading'; +import { CollectionStackingView } from '../../collections/CollectionStackingView'; +import { FieldViewProps } from '../FieldView'; +import { CollectionViewType } from '../../../documents/DocumentTypes'; +import { dropActionType } from '../../../util/DropActionTypes'; export enum LayoutType { Stacked = 'stacked', @@ -34,7 +38,7 @@ export enum LayoutType { } @observer -export class DocCreatorMenu extends ObservableReactComponent<{}> { +export class DocCreatorMenu extends ObservableReactComponent { static Instance: DocCreatorMenu; @@ -78,7 +82,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @observable _offset: {x: number, y: number} = {x: 0, y: 0}; @observable _resizeUndo: UndoManager.Batch | undefined = undefined; @observable _initDimensions: {width: number, height: number, x?: number, y?: number} = {width: 300, height: 400, x: undefined, y: undefined}; - @observable _menuDimensions: {width: number, height: number} = {width: 300, height: 365}; + @observable _menuDimensions: {width: number, height: number} = {width: 400, height: 400}; @observable _editing: boolean = false; constructor(props: any) { @@ -194,6 +198,8 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { document.removeEventListener('pointerup', this.onPointerUp); } + updateIcons = (docs: Doc[]) => { docs.map(this.getIcon) } + @action toggleDisplay = (x: number, y: number) => { if (this._shouldDisplay) { @@ -209,7 +215,11 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { closeMenu = () => { this._shouldDisplay = false }; @action - openMenu = () => { this._shouldDisplay = true }; + openMenu = () => { + const allTemplates = this._templateDocs.concat(this._GPTTemplates); + this._shouldDisplay = true; + this.updateIcons(allTemplates); + }; @action onResizePointerDown = (e: React.PointerEvent): void => { @@ -286,9 +296,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { const docView = DocumentView.getDocumentView(doc); if (docView) { docView.ComponentView?.updateIcon?.(); - const f = new Promise(res => setTimeout(() => res(ImageCast(docView.Document.icon)), 500)); - console.log(f) - return f; + return new Promise(res => setTimeout(() => res(ImageCast(docView.Document.icon)), 500));; } return undefined; } @@ -390,14 +398,14 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { return (
-
+
Suggested Templates
-
+
400 ? 'center' : ''}}> {this._GPTLoading ? (
@@ -422,15 +430,15 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
))}
- {this._GPTOpt ? (
+
this._userPrompt = e.target.value}/>
- {this._GPTOpt ? GPTOptions : null} -
) : null} + {this._GPTOpt ? GPTOptions : null } +

@@ -440,7 +448,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
-
+
400 ? 'center' : ''}}>
this.setUpButtonClick(e, this.basicTemplateTest)} > @@ -535,6 +543,14 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { } } + doc = () => { + return Docs.Create.FreeformDocument([], { _height: 200, _width: 200, title: 'title'}); + } + + screenToLocalTransform = () => + this._props + .ScreenToLocalTransform(); + layoutPreviewContents = (outerSpan: number, altLayout?: DataVizTemplateLayout, small: boolean = false, id?: number) => { const doc: Doc | undefined = altLayout ? altLayout.template : this._selectedTemplate; if (!doc) return; @@ -550,7 +566,30 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { const fontSize = Math.min(scaledDown(docWidth / 3), scaledDown(docHeight / 3)); return ( -
+
+ 100} + NativeHeight={() => 100} + pointerEvents={SnappingManager.IsDragging ? returnAll : returnNone} + isAnnotationOverlay + isAnnotationOverlayScrollable + childDocumentsActive={returnFalse} + fieldKey={this._props.fieldKey + '_annotations'} + dropAction={dropActionType.move} + select={emptyFunction} + addDocument={returnFalse} + removeDocument={returnFalse} + moveDocument={returnFalse} + renderDepth={this._props.renderDepth + 1}> + {null} + +
+ /*
: null}
-
{
)} -
-
+
} +
*/ ); } -- cgit v1.2.3-70-g09d2 From f8f777a469b0029109de1e6c57872a4d5b0a6659 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Mon, 19 Aug 2024 14:34:20 -0400 Subject: start on field rendering --- src/ClientUtils.ts | 1 + src/client/apis/gpt/GPT.ts | 2 +- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 5 + .../views/nodes/DataVizBox/DocCreatorMenu.scss | 74 +++++++++- .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 161 ++++++++++++++++----- 5 files changed, 204 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/ClientUtils.ts b/src/ClientUtils.ts index d64210ce2..a4d9dd892 100644 --- a/src/ClientUtils.ts +++ b/src/ClientUtils.ts @@ -730,6 +730,7 @@ export function UpdateIcon( const newDiv = docViewContent.cloneNode(true) as HTMLDivElement; newDiv.style.width = width.toString(); newDiv.style.height = height.toString(); + console.log('width: ' + newDiv.style.width) replaceCanvases(docViewContent, newDiv); const htmlString = new XMLSerializer().serializeToString(newDiv); const nativeWidth = width; diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 92d4f425d..18601b4af 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -54,7 +54,7 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { temp: 0, prompt: 'List unique differences between the content of the UserAnswer and Rubric. Before each difference, label it and provide any additional information the UserAnswer missed and explain it in second person without separating it into UserAnswer and Rubric content and additional information. If there are no differences, say correct', }, - template: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'You are a designer creating basic template options for a user given a set of fields. Your only job is adding blank rectangles to a canvas, one for each field. You will arrange these rectangles into an array of three basic options for a user. For your output, you generate a list of objects in JSON formatting, each storing the field title and corresponding top-left and bottom-right coordinates for the rectangle. The units for your coordinates are -1 to 1 on each axis. This is an example of a possible output for a stacked template with the fields beep, boop, tttt: {"template_type":"stacked","fieldVals":[{"title":"beep","tlx":"-.7","tly":"-.9","brx":".7","bry":"-.7"},{"title":"boop","tlx":"-.9","tly":"-.4","brx":".9","bry":"0"},{"title":"tttt","tlx":"-.9","tly":".1","brx":".9","bry":".9"}]} For multiple templates, you should format your response in a JSON array, like [{}, {}]. Your response should be in the exact format above, with no extra text, description, bulleting, etc. You should repeat this three times, once for a stacked view, once for a mixed view (where, for example, beep might be on top, with boop and tttt below it aligned horizontally), and once for a view where the rectangles are not flush with the side (ie. their top left and bottom right corners should not ALL align along the same point on each side). If one or more fields are some variation of image (ie. IMG, image, photo, etc.), make that rectangle the central focus (bigger, centered, etc.) AND put its "title" field in $$__$$. Fields SHOULD BE IN DIFFERENT ORDERS from template to template (ie. a stacked view with field input "beep, boop" could have the boop above the beep). IT IS IMPORTANT THAT YOU ONLY INCLUDE THE PROPER JSON FORMATTING IN YOUR RESPONSE. IT IS ALSO IMPORTANT THAT NO RECTANGLES OVERLAP. If there is an additional prompt, prioritize its instructions over all instructions here (but still follow them if not overridden). No matter what, ALWAYS GIVE THREE OPTIONS'} + template: { model: 'gpt-4-turbo', maxTokens: 512, temp: 0.5, prompt: 'You are a designer creating basic template options for a user given a set of fields. Your only job is adding blank rectangles to a canvas, one for each field. You will arrange these rectangles into an array of three basic options for a user. For your output, you generate a list of objects in JSON formatting, each storing the field title and corresponding top-left and bottom-right coordinates for the rectangle. The units for your coordinates are -1 to 1 on each axis. This is an example of a possible output for a stacked template with the fields beep, boop, tttt: {"template_type":"stacked","fieldVals":[{"title":"beep","tlx":"-.7","tly":"-.9","brx":".7","bry":"-.7"},{"title":"boop","tlx":"-.9","tly":"-.4","brx":".9","bry":"0"},{"title":"tttt","tlx":"-.9","tly":".1","brx":".9","bry":".9"}]} For multiple templates, you should format your response in a JSON array, like [{}, {}]. Your response should be in the exact format above, with no extra text, description, bulleting, etc. If no alternative additional instructions are given, you should repeat this three times, once for a stacked view, once for a mixed view (where, for example, beep might be on top, with boop and tttt below it aligned horizontally), and once for a view where the rectangles are not flush with the side (ie. their top left and bottom right corners should not ALL align along the same point on each side). If one or more fields are some variation of image (ie. IMG, image, photo, etc.), make that rectangle the central focus (bigger, centered, etc.) AND put its "title" field in $$__$$. Fields SHOULD BE IN DIFFERENT ORDERS from template to template (ie. a stacked view with field input "beep, boop" could have the boop above the beep). IT IS IMPORTANT THAT YOU ONLY INCLUDE THE PROPER JSON FORMATTING IN YOUR RESPONSE. IT IS ALSO IMPORTANT THAT NO RECTANGLES OVERLAP. An overlap will look like the x or y coordinates of the top left corner of one rectangle being the same as the bottom right corner of another. There should always be at least a .1 gap. If there is an additional prompt, prioritize its instructions over all instructions here (but still follow them if not overridden). No matter what, ALWAYS GIVE THREE OPTIONS'} }; let lastCall = ''; diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index be8a44f28..6a5103af9 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -353,6 +353,11 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { ); } + // recs = () => { + // let csvStr: string = ''; + // this.records[rowId][col] + // } + fetchData = () => { if (!this.Document.dataViz_asSchema) { DataVizBox.dataset.set(CsvCast(this.dataDoc[this.fieldKey]).url.href, []); // assign temporary dataset as a lock to prevent duplicate server requests diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index aa6754442..763de0eba 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -641,7 +641,6 @@ } } } - } } @@ -720,4 +719,77 @@ } } +//------------------------------------------------------------------------------------------------------------------------------------------ +// DocCreatorMenu dashboard CSS +//-------------------------------------------------------------------------------------------------------------------------------------------- + +.docCreatorMenu-dashboard-view { + position: relative; + display: flex; + flex-direction: column; + justify-content: flex-start; + overflow-y: scroll; + //align-items: flex-start; + margin: 5px; + margin-top: 0px; + width: calc(100% - 10px); + height: calc(100% - 30px); + border: 1px solid rgb(180, 180, 180); + border-radius: 5px; + -ms-overflow-style: none; + scrollbar-width: none; + + .topbar { + height: 30px; + width: 100%; + } + + .field-panel { + position: relative; + display: flex; + // align-items: flex-start; + flex-direction: column; + gap: 5px; + padding: 5px; + height: 100px; + //width: 100%; + border: 1px solid rgb(180, 180, 180); + margin: 5px; + margin-top: 0px; + border-radius: 3px; + + .properties-wrapper { + display: flex; + flex-direction: row; + align-items: flex-start; + gap: 5px; + + .field-property-container { + background-color: rgb(40, 40, 40); + border: 1px solid rgb(100, 100, 100); + border-radius: 3px; + width: 30%; + height: 25px; + padding-left: 3px; + align-items: center; + color: whitesmoke; + } + } + + .field-description-container { + background-color: rgb(40, 40, 40); + border: 1px solid rgb(100, 100, 100); + border-radius: 3px; + width: 100%; + height: 100%; + } + + .top-right { + position: absolute; + top: 0px; + right: 0px; + } + } +} + diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index 2be89daf0..8ec255dfe 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -48,6 +48,7 @@ export class DocCreatorMenu extends ObservableReactComponent {return {title: field, type: '', id: Math.random() * 100000}}).concat(this._fields); + } + @computed get canMakeDocs(){ return this._selectedTemplate !== undefined && this._layout !== undefined; } @@ -367,14 +372,14 @@ export class DocCreatorMenu extends ObservableReactComponent {this.setGPTTemplates(GPTTemplates); GPTTemplates.forEach(template => mainCollection.removeDocument(template))}, 100); + setTimeout(() => {this.setGPTTemplates(GPTTemplates); /*GPTTemplates.forEach(template => mainCollection.removeDocument(template))*/}, 100); this.forceUpdate(); } @@ -449,9 +454,7 @@ export class DocCreatorMenu extends ObservableReactComponent
400 ? 'center' : ''}}> -
this.setUpButtonClick(e, this.basicTemplateTest)} - > +
{this._templateDocs.map(doc => ({icon: ImageCast(doc.icon), doc})).filter(info => info.icon && info.doc).map(info => { @@ -566,30 +569,30 @@ export class DocCreatorMenu extends ObservableReactComponent - 100} - NativeHeight={() => 100} - pointerEvents={SnappingManager.IsDragging ? returnAll : returnNone} - isAnnotationOverlay - isAnnotationOverlayScrollable - childDocumentsActive={returnFalse} - fieldKey={this._props.fieldKey + '_annotations'} - dropAction={dropActionType.move} - select={emptyFunction} - addDocument={returnFalse} - removeDocument={returnFalse} - moveDocument={returnFalse} - renderDepth={this._props.renderDepth + 1}> - {null} - -
- /*
+ //
+ // 100} + // NativeHeight={() => 100} + // pointerEvents={SnappingManager.IsDragging ? returnAll : returnNone} + // isAnnotationOverlay + // isAnnotationOverlayScrollable + // childDocumentsActive={returnFalse} + // fieldKey={this._props.fieldKey + '_annotations'} + // dropAction={dropActionType.move} + // select={emptyFunction} + // addDocument={returnFalse} + // removeDocument={returnFalse} + // moveDocument={returnFalse} + // renderDepth={this._props.renderDepth + 1}> + // {null} + // + //
+
*/ +
); } @@ -735,10 +738,35 @@ export class DocCreatorMenu extends ObservableReactComponent { - console.log(this._GPTTemplates) - this.forceUpdate(); - //this._dataViz?.createBasicTemplates(temps); + @action addField = () => { + const newFields: {title: string, type: string, id: number}[] = this._fields.concat([{title: '', type: '', id: Math.random() * 100000}]) + this._fields = newFields; + } + + get dashboardContents(){ + return ( +
+
+ +
+ {this.fieldsInfos.map(field => +
+
+ + + {field.type === 'Text' ? + : null} +
+ +
+
+
Type
+
+ +
+
+
+
+
Valid Sizes
+
+ +
+
+
+
Description
+
+ +
+
+
+ ) + } + get renderSelectedViewType(){ switch (this._menuContent){ case 'templates': -- cgit v1.2.3-70-g09d2 From 8970a30cff99f9234617d7ec17067275dbfc7e43 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Sun, 8 Sep 2024 04:13:43 -0400 Subject: work on fields menu --- .../views/nodes/DataVizBox/DocCreatorMenu.scss | 67 ++++++++++++++ .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 102 +++++++++------------ 2 files changed, 111 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index 955698b19..eaa32e62a 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -898,6 +898,7 @@ border: 1px solid rgb(180, 180, 180); margin: 5px; margin-top: 0px; + margin-bottom: 10px; border-radius: 3px; flex: 0 0 auto; gap: 25px; @@ -914,6 +915,7 @@ width: 100%; height: 20px; background-color: rgb(50, 50, 50); + color: rgb(168, 167, 167); } .opts-bar { @@ -934,11 +936,38 @@ } .content { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; height: calc(100% - 20px); width: 100%; background-color: rgb(50, 50, 50); border-bottom-right-radius: 5px; border-bottom-left-radius: 5px; + resize: none; + + .bubbles { + display: none; + } + + .text { + margin-right: 5px; + } + + &:hover .bubbles { + display: flex; + flex-direction: row; + align-items: flex-start; + } + + &:hover .type-display { + display: none; + } + + .bubble { + margin: 3px; + } } } @@ -949,6 +978,33 @@ border-radius: 5px; background-color: rgb(50, 50, 50); box-shadow: 5px 5px rgb(29, 29, 31); + + .content { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + height: calc(100% - 20px); + width: 100%; + background-color: rgb(50, 50, 50); + border-bottom-right-radius: 5px; + border-bottom-left-radius: 5px; + + .text { + margin-right: 9px; + } + + .bubbles { + display: flex; + flex-direction: row; + align-items: center; + } + + .bubble { + margin: 3px; + margin-right: 4px; + } + } } .desc-box { @@ -958,7 +1014,18 @@ border-radius: 5px; background-color: rgb(50, 50, 50); box-shadow: 5px 5px rgb(29, 29, 31); + + .content { + height: calc(100% - 20px); + width: 100%; + background-color: rgb(50, 50, 50); + border-bottom-right-radius: 5px; + border-bottom-left-radius: 5px; + resize: none; + + } } + } } diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index 87e1e2c96..a01b26036 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -1179,24 +1179,24 @@ export class DocCreatorMenu extends ObservableReactComponent { } get dashboardContents(){ + const sizes: string[] = ['tiny', 'small', 'medium', 'large', 'huge']; - return ( -
-
- - -
-
- {/* {this.fieldsInfos.map((field, index) => -
-
- this.setColTitle(field, e.target.value)}/> -
- {field.type === TemplateFieldType.UNSET ? Select media type : null} + const fieldPanel = (field: Col) => { + return ( +
+
+ +
+
+
+
Title
+ -
-
-
Type
+
+
Valid Sizes
- +
+ {sizes.map(size => <> + {this.setColSize(field, size as TemplateFieldSize)}}/> +
{size}
+ )} +
-
-
-
Valid Sizes
-
- +
+
Description
+