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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/documents') 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 -- 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/client/documents') 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/client/documents') 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/client/documents') 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 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/client/documents') 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 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/client/documents') 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 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/client/documents') 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 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/client/documents') 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 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/client/documents') 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 9b8e2853c7ea53578c3dbf180018c25b8b322617 Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Thu, 18 Jul 2024 04:27:44 -0400 Subject: saving layouts --- src/client/documents/Documents.ts | 1 + src/client/views/nodes/DataVizBox/DataVizBox.tsx | 15 +- .../views/nodes/DataVizBox/DocCreatorMenu.scss | 214 +++++++++++++-------- .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 130 ++++++++++--- 4 files changed, 244 insertions(+), 116 deletions(-) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index dabbf9591..dc649ec4e 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -235,6 +235,7 @@ export class DocumentOptions { dataViz_pie?: string; dataViz_histogram?: string; dataViz?: string; + dataViz_savedTemplates?: LISTt; layout?: string | Doc; // default layout string or template document layout_isSvg?: BOOLt = new BoolInfo('whether document decorations and other selections should handle pointerEvents for svg content or use doc bounding box'); diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index 765642891..e943dd2e3 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -33,12 +33,14 @@ import { LineChart } from './components/LineChart'; import { PieChart } from './components/PieChart'; import { TableBox } from './components/TableBox'; import { LinkManager } from '../../../util/LinkManager'; -import { DataVizTemplateInfo, DocCreatorMenu, LayoutType } from './DocCreatorMenu'; +import { DataVizTemplateInfo, DataVizTemplateLayout, 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'; import { data } from 'jquery'; +import { listSpec } from '../../../../fields/Schema'; +import { ObjectField } from '../../../../fields/ObjectField'; export enum DataVizView { TABLE = 'table', @@ -532,14 +534,9 @@ 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 addSavedLayout = (layout: DataVizTemplateLayout) => { + // const saved = Cast(this.layoutDoc.dataViz_savedTemplates, listSpec('RefField')); + // } @action diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss index 0fc85ba5d..d18f75545 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.scss @@ -68,6 +68,13 @@ height: 0; width: 50px; } + + &.preview-toggle { + margin: 0px; + border-top-left-radius: 0px; + border-bottom-left-radius: 0px; + border-left: 0px; + } } .docCreatorMenu-top-buttons-container { @@ -168,16 +175,44 @@ height: 25px; } +.docCreatorMenu-general-options-container { + display: flex; + justify-content: center; + align-items: center; + margin: 0px; + padding: 0px; + gap: 5px; +} + +.docCreatorMenu-save-layout-button { + display: flex; + justify-content: center; + align-items: center; + width: 40px; + height: 40px; + background-color: rgb(99, 148, 238); + border: 2px solid rgb(80, 107, 152); + border-radius: 5px; + margin-bottom: 20px; + font-size: 25px; + + &:hover{ + background-color: rgb(59, 128, 255); + border: 2px solid rgb(53, 80, 127); + } +} + .docCreatorMenu-create-docs-button { - width: 80px; + width: 40px; height: 40px; background-color: rgb(176, 229, 149); - border-radius: 5px; border: 2px solid rgb(126, 219, 80); + border-radius: 5px; padding: 0px; - font-size: 16px; - color: black; + font-size: 25px; + color: white; flex: 0 0 auto; + margin-bottom: 20px; //remove later !!! &:hover { background-color: rgb(129, 223, 83); @@ -185,6 +220,13 @@ } } +.docCreatorMenu-option-divider { + border-top: 1px solid rgb(180, 180, 180); + width: 225px; + margin-top: 10px; + margin-bottom: 10px; +} + //------------------------------------------------------------------------------------------------------------------------------------------ //DocCreatorMenu templates preview CSS //-------------------------------------------------------------------------------------------------------------------------------------------- @@ -202,29 +244,32 @@ height: calc(100% - 30px); border: 1px solid rgb(180, 180, 180); 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 rgb(163, 163, 163); - border-radius: 5px; - box-shadow: 5px 5px rgb(29, 29, 31); +.docCreatorMenu-preview-window { + display: flex; + justify-content: center; + align-items: center; + width: 125px; + height: 125px; + margin-top: 10px; + margin-left: 10px; + border: 1px solid rgb(163, 163, 163); + border-radius: 5px; + box-shadow: 5px 5px rgb(29, 29, 31); - &:hover{ - background-color: rgb(72, 72, 73); - } + &:hover{ + background-color: rgb(72, 72, 73); + } - .docCreatorMenu-preview-image{ - width: 105px; - height: 105px; - border-radius: 5px; - } + .docCreatorMenu-preview-image{ + width: 105px; + height: 105px; + border-radius: 5px; + } + &.empty { + font-size: 35px; } } @@ -254,6 +299,8 @@ background: whitesmoke; background-color: rgb(34, 34, 37); border-radius: 5px; + border-top-right-radius: 0px; + border-bottom-right-radius: 0px; border: 1px solid rgb(180, 180, 180); padding: 0px; font-size: 12px; @@ -412,75 +459,80 @@ } } +} - .docCreatorMenu-layout-preview-window-wrapper { - display: flex; - justify-content: center; - align-items: center; - width: 85%; - height: auto; - position: relative; - padding: 0px; +.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-container { - display: block; - } + &:hover .docCreatorMenu-zoom-button-container { + 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 rgb(180, 180, 180); - 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; - - &:hover { - border: solid 2px rgb(68, 153, 233); - z-index: 2; - } - } + .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 rgb(180, 180, 180); + border-radius: 5px; + background-color: rgb(34, 34, 37); + -ms-overflow-style: none; + scrollbar-width: none; + + &.small { + max-width: 100; + max-height: 100; } - .docCreatorMenu-zoom-button-container { - position: absolute; - top: 0px; + .docCreatorMenu-layout-preview-item { display: flex; justify-content: center; align-items: center; - display: none; - z-index: 999; - } - - .docCreatorMenu-zoom-button{ - width: 15px; - height: 15px; - background: whitesmoke; - background-color: rgb(34, 34, 37); border-radius: 3px; - border: 1px solid rgb(180, 180, 180); - padding: 0px; - font-size: 10px; - z-index: 6; - margin-left: 0px; - margin-top: 0px; - margin-right: 0px; //225px - margin-bottom: 0px; + border: solid 1px lightblue; + + &:hover { + border: solid 2px rgb(68, 153, 233); + z-index: 2; + } } } + + .docCreatorMenu-zoom-button-container { + position: absolute; + top: 0px; + display: flex; + justify-content: center; + align-items: center; + display: none; + z-index: 999; + } + + .docCreatorMenu-zoom-button{ + width: 15px; + height: 15px; + background: whitesmoke; + background-color: rgb(34, 34, 37); + border-radius: 3px; + border: 1px solid rgb(180, 180, 180); + padding: 0px; + font-size: 10px; + z-index: 6; + margin-left: 0px; + margin-top: 0px; + margin-right: 0px; //225px + margin-bottom: 0px; + } } diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index 67999fc39..fdf623150 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -40,6 +40,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { @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; + @observable _savedLayouts: DataVizTemplateLayout[] = []; @observable _pageX: number = 0; @observable _pageY: number = 0; @@ -193,6 +194,20 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { } } + @action updateSelectedSavedLayout = (layout: DataVizTemplateLayout) => { + this._layout.xMargin = layout.layout.xMargin; + this._layout.yMargin = layout.layout.yMargin; + this._layout.type = layout.layout.type; + this._layout.columns = layout.columns; + } + + isSelectedLayout = (layout: DataVizTemplateLayout) => { + return this._layout.xMargin === layout.layout.xMargin + && this._layout.yMargin === layout.layout.yMargin + && this._layout.type === layout.layout.type + && this._layout.columns === layout.columns; + } + get templatesPreviewContents(){ const renderedTemplates: Doc[] = []; return ( @@ -203,13 +218,35 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> { return (
this.setUpButtonClick(e, () => runInAction(() => this.updateSelectedTemplate(info.doc)))}>
)})} +
+ +
+
+ ); + } + + 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 f5c2f5bc8710a965a0b52e2e414f62a2a459a94f Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Sun, 25 Aug 2024 04:26:12 -0400 Subject: border work --- src/client/documents/Documents.ts | 2 + src/client/views/ContextMenu.scss | 35 ++++++++++ src/client/views/ContextMenu.tsx | 118 ++++++++++++++++++++++---------- src/client/views/ContextMenuItem.tsx | 12 +++- src/client/views/MainView.tsx | 6 +- src/client/views/PropertiesView.tsx | 10 +++ src/client/views/StyleProvider.tsx | 37 ++++++---- src/client/views/nodes/DocumentView.tsx | 37 ++++++---- 8 files changed, 191 insertions(+), 66 deletions(-) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 751fe6d91..aecc79189 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -256,6 +256,8 @@ export class DocumentOptions { layout_hideContextMenu?: BOOLt = new BoolInfo('whether the context menu can be shown'); layout_borderRounding?: string; _layout_borderRounding?: STRt = new StrInfo('amount of rounding to document view corners'); + _layout_borderWidth?: NUMt = new NumInfo('Hey now', false); + _layout_borderColor?: STRt = new StrInfo('No no', false); _layout_modificationDate?: DATEt = new DateInfo('last modification date of doc layout', false); _layout_nativeDimEditable?: BOOLt = new BoolInfo('native dimensions can be modified using document decoration reizers', false); _layout_reflowVertical?: BOOLt = new BoolInfo('permit vertical resizing with content "reflow"'); diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index 232362c5c..ff6ad526e 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -165,3 +165,38 @@ border: solid black 1px; border-radius: 5px; } + +.contextMenu-borderMenu { + display: flex; + flex-direction: column; + align-items: flex-start; + width: 222px; + height: 300px; + background-color: white; + border: solid 1px black; + + .top-bar { + height: 20px; + width: 100%; + display: flex; + + .close-menu { + margin-top: 0; + margin-bottom: 0; + margin-right: 0; + padding: 0; + margin-left: auto; + z-index: 999999999; + width: 20px; + height: 20px; + color: black; + background-color: transparent; + } + } + + .bottom-box{ + .width-selector{ + + } + } +} diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index de985263d..9472fb95c 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -5,11 +5,17 @@ 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 { DivHeight, DivWidth } from '../../ClientUtils'; +import { DivHeight, DivWidth, returnFalse, setupMoveUpEvents } from '../../ClientUtils'; import { SnappingManager } from '../util/SnappingManager'; import './ContextMenu.scss'; import { ContextMenuItem, ContextMenuProps, OriginalMenuProps } from './ContextMenuItem'; import { ObservableReactComponent } from './ObservableReactComponent'; +import { ColorResult, SketchPicker } from 'react-color'; +import { DocumentView } from './nodes/DocumentView'; +import { Doc } from '../../fields/Doc'; +import { undoable } from '../util/UndoManager'; +import { NumCast, StrCast } from '../../fields/Types'; +import { emptyFunction } from '../../Utils'; @observer export class ContextMenu extends ObservableReactComponent<{}> { @@ -38,6 +44,8 @@ export class ContextMenu extends ObservableReactComponent<{}> { @observable _mouseX: number = -1; @observable _mouseY: number = -1; @observable _shouldDisplay: boolean = false; + @observable _displayColorPicker: boolean = false; + @observable _selectorWidth: number = 0; constructor(props: any) { super(props); @@ -116,6 +124,10 @@ export class ContextMenu extends ObservableReactComponent<{}> { this._defaultItem = item; } + @action setColorPickerDisplay = (display: boolean) => { + this._displayColorPicker = display; + } + static readonly buffer = 20; get pageX() { return this._pageX + this._width > window.innerWidth - ContextMenu.buffer ? window.innerWidth - ContextMenu.buffer - this._width : Math.max(0, this._pageX); @@ -206,45 +218,79 @@ export class ContextMenu extends ObservableReactComponent<{}> { _searchRef = React.createRef(); // bcz: we shouldn't need this, since we set autoFocus on the tag, but for some reason we do... + get colorPicker() { + const doc = DocumentView.Selected().lastElement().Document; + const layoutDoc = doc ? Doc.Layout(doc) : doc; + + return ( +
+
+ +
+ layoutDoc._layout_borderColor = col.hex), + 'set stroke color property' + )} + presetColors={[]} + color={StrCast(layoutDoc._layout_borderColor)} + /> +
+ {layoutDoc._layout_borderWidth = e.target.value; this._selectorWidth = Number(e.target.value); console.log(layoutDoc._layout_borderWidth)}}/> +
+
+ ); + } + render() { this.itemsNeedSearch && setTimeout(() => this._searchRef.current?.focus()); return ( -
{ - if (r) { - this._width = DivWidth(r); - this._height = DivHeight(r); - } - this._searchRef.current?.focus(); - })} - style={{ - display: this._display ? '' : 'none', - left: this.pageX, - ...(this._yRelativeToTop ? { top: Math.max(0, this.pageY) } : { bottom: this.pageY }), - background: SnappingManager.userBackgroundColor, - color: SnappingManager.userColor, - }}> - {!this.itemsNeedSearch ? null : ( - - - +
+ {this._displayColorPicker ? this.colorPicker : null} +
{ + if (r) { + this._width = DivWidth(r); + this._height = DivHeight(r); + } + this._searchRef.current?.focus(); + })} + style={{ + display: this._display ? '' : 'none', + left: this.pageX, + ...(this._yRelativeToTop ? { top: Math.max(0, this.pageY) } : { bottom: this.pageY }), + background: SnappingManager.userBackgroundColor, + color: SnappingManager.userColor, + }}> + {!this.itemsNeedSearch ? null : ( + + + + + - - - )} - {this.menuItems} + )} + {this.menuItems} +
); } diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index eb1030eec..782077fd6 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -5,8 +5,14 @@ import { action, makeObservable, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { SnappingManager } from '../util/SnappingManager'; -import { UndoManager } from '../util/UndoManager'; +import { UndoManager, undoable } from '../util/UndoManager'; import { ObservableReactComponent } from './ObservableReactComponent'; +import { ColorPicker, Type } from 'browndash-components'; +import { DocumentView } from './nodes/DocumentView'; +import { Doc } from '../../fields/Doc'; +import { StrCast } from '../../fields/Types'; +import { ColorResult, SketchPicker } from 'react-color'; +import color from 'color'; export interface OriginalMenuProps { description: string; @@ -14,6 +20,7 @@ export interface OriginalMenuProps { undoable?: boolean; icon: IconProp | JSX.Element; // maybe should be optional (icon?) closeMenu?: () => void; + colorPicker?: boolean; } export interface SubmenuProps { @@ -24,6 +31,7 @@ export interface SubmenuProps { addDivider?: boolean; icon: IconProp; // maybe should be optional (icon?) closeMenu?: () => void; + colorPicker?: boolean; } export type ContextMenuProps = OriginalMenuProps | SubmenuProps; @@ -101,7 +109,7 @@ export class ContextMenuItem extends ObservableReactComponent +
{this._props.icon ? {this.isJSXElement(this._props.icon) ? this._props.icon : } : null}
{this._props.description.replace(':', '')}
{ public static Live: boolean = false; private _docBtnRef = React.createRef(); + @observable private _keepContextMenuOpen: boolean = false; @observable private _windowWidth: number = 0; @observable private _windowHeight: number = 0; @observable private _dashUIWidth: number = 0; // width of entire main dashboard region including left menu buttons and properties panel (but not including the dashboard selector button row) @@ -590,7 +591,10 @@ export class MainView extends ObservableReactComponent<{}> { if (typeof targets[i].className === 'object') targClass = targets[i + 1].className.toString(); else break; } - !targClass.includes('contextMenu') && ContextMenu.Instance.closeMenu(); + if (!targClass.includes('contextMenu')) { + console.log(targClass) + ContextMenu.Instance.closeMenu(); + } !['timeline-menu-desc', 'timeline-menu-item', 'timeline-menu-input'].includes(targClass) && TimelineMenu.Instance.closeMenu(); } }); diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 024db82a4..775e15772 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -847,6 +847,12 @@ export class PropertiesView extends ObservableReactComponent void) { return ( @@ -898,6 +904,10 @@ export class PropertiesView extends ObservableReactComponent { this.colorStk = color; }); // prettier-ignore } + @computed get borderColorPicker() { + return this.colorPicker(this.colorStk, (color: string) => { this.colorStk = color; }); // prettier-ignore + } + @computed get strokeAndFill() { return (
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 8c100f238..3a48ec957 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -55,14 +55,25 @@ export function styleFromLayoutString(doc: Doc, props: FieldViewProps, scale: nu return style; } -export function wavyBorderPath(pw: number, ph: number, inset: number = 0.05) { - return `M ${pw * 0.5} ${ph * inset} C ${pw * 0.6} ${ph * inset} ${pw * (1 - 2 * inset)} 0 ${pw * (1 - inset)} ${ph * inset} C ${pw} ${ph * (2 * inset)} ${pw * (1 - inset)} ${ph * 0.25} ${pw * (1 - inset)} ${ph * 0.3} C ${ - pw * (1 - inset) - } ${ph * 0.4} ${pw} ${ph * (1 - 2 * inset)} ${pw * (1 - inset)} ${ph * (1 - inset)} C ${pw * (1 - 2 * inset)} ${ph} ${pw * 0.6} ${ph * (1 - inset)} ${pw * 0.5} ${ph * (1 - inset)} C ${pw * 0.3} ${ph * (1 - inset)} ${pw * (2 * inset)} ${ph} ${ - pw * inset - } ${ph * (1 - inset)} C 0 ${ph * (1 - 2 * inset)} ${pw * inset} ${ph * 0.8} ${pw * inset} ${ph * 0.75} C ${pw * inset} ${ph * 0.7} 0 ${ph * (2 * inset)} ${pw * inset} ${ph * inset} C ${pw * (2 * inset)} 0 ${pw * 0.25} ${ph * inset} ${ - pw * 0.5 - } ${ph * inset}`; +export function wavyBorderPath(doc: Doc, pw: number, ph: number, inset: number = 0) { + const layoutDoc = doc ? Doc.Layout(doc) : doc; + const width = pw * inset; + const height = ph * inset; + + const radius = Math.min(Number(StrCast(layoutDoc._layout_borderRounding).replace('px', '')), (pw - 2 * width) / 2, (ph - 2 * height) / 2); + + return ` + M ${width + radius} ${height} + L ${pw - width - radius} ${height} + A ${radius} ${radius} 0 0 1 ${pw - width} ${height + radius} + L ${pw - width} ${ph - height - radius} + A ${radius} ${radius} 0 0 1 ${pw - width - radius} ${ph - height} + L ${width + radius} ${ph - height} + A ${radius} ${radius} 0 0 1 ${width} ${ph - height - radius} + L ${width} ${height + radius} + A ${radius} ${radius} 0 0 1 ${width + radius} ${height} + Z + `; } let _filterOpener: () => void; @@ -189,10 +200,12 @@ export function DefaultStyleProvider(doc: Opt, props: Opt, props: Opt - +
), diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 8edb37acc..fe6d529ba 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -634,6 +634,7 @@ export class DocumentViewInternal extends DocComponent Doc.MakeMetadataFieldTemplate(this.Document, this._props.TemplateDataDocument), icon: 'concierge-bell' }); moreItems.push({ description: `${this.Document._chromeHidden ? 'Show' : 'Hide'} Chrome`, event: () => { this.Document._chromeHidden = !this.Document._chromeHidden; }, icon: 'project-diagram' }); // prettier-ignore moreItems.push({ description: 'Copy ID', event: () => ClientUtils.CopyText(Doc.globalServerPath(this.Document)), icon: 'fingerprint' }); + moreItems.push({ description: 'Add border', event: () => ContextMenu.Instance.setColorPickerDisplay(true), icon: 'square', colorPicker: true }); } } @@ -944,22 +945,28 @@ export class DocumentViewInternal extends DocComponent + //
+ //
+ //
+ //
(!SnappingManager.IsDragging || SnappingManager.CanEmbed) && Doc.BrushDoc(this.Document)} - onPointerOver={() => (!SnappingManager.IsDragging || SnappingManager.CanEmbed) && Doc.BrushDoc(this.Document)} - onPointerLeave={e => !isParentOf(this._contentDiv, document.elementFromPoint(e.nativeEvent.x, e.nativeEvent.y)) && Doc.UnBrushDoc(this.Document)} - style={{ - borderRadius: this.borderRounding, - pointerEvents: this._pointerEvents === 'visiblePainted' ? 'none' : this._pointerEvents, // visible painted means that the underlying doc contents are irregular and will process their own pointer events (otherwise, the contents are expected to fill the entire doc view box so we can handle pointer events here) - }}> - {this._componentView?.isUnstyledView?.() || this.Document.type === DocumentType.CONFIG ? renderDoc : DocumentViewInternal.AnimationEffect(renderDoc, this.Document[Animation], this.Document)} - {borderPath?.jsx} -
+ className={`${DocumentView.ROOT_DIV} docView-hack`} + ref={this._mainCont} + onContextMenu={this.onContextMenu} + onPointerDown={this.onPointerDown} + onClick={SnappingManager.ExploreMode ? this.onBrowseClick : this.onClick} + onPointerEnter={() => (!SnappingManager.IsDragging || SnappingManager.CanEmbed) && Doc.BrushDoc(this.Document)} + onPointerOver={() => (!SnappingManager.IsDragging || SnappingManager.CanEmbed) && Doc.BrushDoc(this.Document)} + onPointerLeave={e => !isParentOf(this._contentDiv, document.elementFromPoint(e.nativeEvent.x, e.nativeEvent.y)) && Doc.UnBrushDoc(this.Document)} + style={{ + borderRadius: this.borderRounding, + pointerEvents: this._pointerEvents === 'visiblePainted' ? 'none' : this._pointerEvents, // visible painted means that the underlying doc contents are irregular and will process their own pointer events (otherwise, the contents are expected to fill the entire doc view box so we can handle pointer events here) + }}> + {this._componentView?.isUnstyledView?.() || this.Document.type === DocumentType.CONFIG ? renderDoc : DocumentViewInternal.AnimationEffect(renderDoc, this.Document[Animation], this.Document)} + {borderPath?.jsx} +
+ //
); } -- cgit v1.2.3-70-g09d2 From f00a5326fa331859db131bb1d8988db93602830b Mon Sep 17 00:00:00 2001 From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> Date: Tue, 27 Aug 2024 19:16:28 -0400 Subject: maxmatching algorithm --- src/client/documents/Documents.ts | 5 +- src/client/views/ContextMenu.tsx | 9 +- src/client/views/StyleProvider.tsx | 4 +- .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 190 ++++++++++++++------- src/client/views/nodes/DocumentView.tsx | 14 +- 5 files changed, 139 insertions(+), 83 deletions(-) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index aecc79189..a4ba2978c 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -237,6 +237,9 @@ export class DocumentOptions { dataViz?: string; dataViz_savedTemplates?: LISTt; + borderWidth?: NUMt = new NumInfo('Width of user-added border', false); + borderColor?: STRt = new StrInfo('Color of user-added border', false); + layout?: string | Doc; // default layout string or template document layout_isSvg?: BOOLt = new BoolInfo('whether document decorations and other selections should handle pointerEvents for svg content or use doc bounding box'); layout_keyValue?: STRt = new StrInfo('layout definition for showing keyValue view of document', false); @@ -256,8 +259,6 @@ export class DocumentOptions { layout_hideContextMenu?: BOOLt = new BoolInfo('whether the context menu can be shown'); layout_borderRounding?: string; _layout_borderRounding?: STRt = new StrInfo('amount of rounding to document view corners'); - _layout_borderWidth?: NUMt = new NumInfo('Hey now', false); - _layout_borderColor?: STRt = new StrInfo('No no', false); _layout_modificationDate?: DATEt = new DateInfo('last modification date of doc layout', false); _layout_nativeDimEditable?: BOOLt = new BoolInfo('native dimensions can be modified using document decoration reizers', false); _layout_reflowVertical?: BOOLt = new BoolInfo('permit vertical resizing with content "reflow"'); diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index b80d97e81..f5654446d 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -2,7 +2,7 @@ /* eslint-disable react/jsx-props-no-spreading */ /* eslint-disable default-param-last */ 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 { DivHeight, DivWidth, returnFalse, setupMoveUpEvents } from '../../ClientUtils'; @@ -222,7 +222,6 @@ export class ContextMenu extends ObservableReactComponent<{}> { get colorPicker() { const doc = DocumentView.Selected().lastElement().Document; - const layoutDoc = doc ? Doc.Layout(doc) : doc; return (
{
layoutDoc._layout_borderColor = col.hex), + action((col: ColorResult) => doc.borderColor = col.hex), 'set stroke color property' )} presetColors={[]} - color={StrCast(layoutDoc._layout_borderColor)} + color={StrCast(doc.borderColor)} />
this._widthMinMax.max = e.target.value}/> - {layoutDoc._layout_borderWidth = e.target.value; this._selectorWidth = Number(e.target.value); console.log(layoutDoc._layout_borderWidth)}}/> + runInAction(() => {doc.borderWidth = e.target.value; this._selectorWidth = Number(e.target.value)})}/> this._widthMinMax.max = e.target.value}/>
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index b7dbcf7a6..3ecb101f8 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -205,7 +205,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt, props: Opt - +
), diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index 7df445b88..ffc4dd0b1 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -419,6 +419,8 @@ export class DocCreatorMenu extends ObservableReactComponent { + + } + + maxMatches = (fieldsCt: number, matches: number[][]) => { + const used: boolean[] = Array(fieldsCt).fill(false); + const mt: number[] = Array(fieldsCt).fill(-1); + + const augmentingPath = (v: number): boolean => { + if (used[v]) return false; + used[v] = true; + for (const to of matches[v]) { + if (mt[to] === -1 || augmentingPath(mt[to])) { + mt[to] = v; + return true; + } + } + return false; + } + + for (let v = 0; v < fieldsCt; ++v) { + console.log(v) + used.fill(false); + augmentingPath(v); + } + + let numMatches: number = 0; + + for (let i = 0; i < fieldsCt; ++i) { + if (mt[i] !== -1) ++numMatches; + } + + return numMatches; + } + get dashboardContents(){ return (
@@ -985,26 +1022,31 @@ enum FieldSize { HUGE = 'huge' } +type Field = { + tl: [number, number], + br: [number, number], + types: FieldType[], + sizes?: FieldSize[], + opts: FieldOpts; +}; + export interface TemplateDocInfos { height: number; width: number; - fields: {tl: [number, number], br: [number, number], types: FieldType[], sizes?: FieldSize[]}[]; -} - -export interface TemplateDocField { - coordinates: {tl: [number, number], br: [number, number]}; - getDoc: (parentWidth: number, parentHeight: number, title: string, content: string) => Doc; + fields: Field[]; } export interface FieldOpts { backgroundColor?: string; - roundedCorners?: boolean; - vertCenteredText?: boolean; - horizCenteredText?: boolean; - transparency?: number; + color?: string; + cornerRounding?: number; + borderWidth?: number; + borderColor?: string; + contentXCentering?: 'left' | 'center' | 'right'; + contentYCentering?: 'top' | 'center' | 'bottom'; + opacity?: number; rotation?: number; //animation?: boolean; - fontColor?: string; fontBold?: boolean; fontTransform?: 'toUpper' | 'toLower'; } @@ -1023,7 +1065,9 @@ export class FieldFuncs { public static TextField = (coords: {tl: [number, number], br: [number, number]}, parentWidth: number, parentHeight: number, title: string, content: string, opts: FieldOpts) => { const {width, height, coord} = FieldFuncs.getDimensions(coords, parentWidth, parentHeight); - const doc = Docs.Create.TextDocument(content, { + const bool = true; + + const docWithBasicOpts = (Docs.Create.TextDocument)(content, { _height: height, _width: width, title: title, @@ -1031,11 +1075,15 @@ export class FieldFuncs { y: coord.y, _text_fontSize: `${height/2}` , backgroundColor: opts.backgroundColor ?? '', - - - }) + color: opts.color, + _layout_borderRounding: `${opts.cornerRounding}`, + borderWidth: opts.borderWidth, + borderColor: opts.borderColor, + opacity: opts.opacity, + _layout_centered: opts.contentXCentering === 'center' ? true : false, + }); - return doc; + return docWithBasicOpts; } public static ImageField = (coords: {tl: [number, number], br: [number, number]}, parentWidth: number, parentHeight: number, title: string, content: string) => { @@ -1071,70 +1119,82 @@ export class TemplateLayouts { tl: [-.6, -.9], br: [.6, -.8], types: [FieldType.TEXT], - sizes: [FieldSize.TINY] + sizes: [FieldSize.TINY], + opts: { + + } }, { tl: [-.9, -.7], br: [.9, .2], types: [FieldType.TEXT, FieldType.VISUAL], - sizes: [FieldSize.MEDIUM, FieldSize.LARGE, FieldSize.HUGE] + sizes: [FieldSize.MEDIUM, FieldSize.LARGE, FieldSize.HUGE], + opts: { + + } }, { tl: [-.6, .3], br: [.6, .4], types: [FieldType.TEXT], - sizes: [FieldSize.TINY] + sizes: [FieldSize.TINY], + opts: { + + } }, { tl: [-.9, .5], br: [.9, .9], types: [FieldType.TEXT, FieldType.VISUAL], - sizes: [FieldSize.MEDIUM, FieldSize.LARGE, FieldSize.HUGE] - }] - }; + sizes: [FieldSize.MEDIUM, FieldSize.LARGE, FieldSize.HUGE], + opts: { - public static FourField002: TemplateDocInfos = { - width: 450, - height: 600, - fields: [{ - tl: [-.6, -.9], - br: [.6, -.8], - types: [FieldType.TEXT], - sizes: [FieldSize.TINY] - }, { - tl: [-.9, -.7], - br: [.9, .2], - types: [FieldType.TEXT, FieldType.VISUAL], - sizes: [FieldSize.MEDIUM, FieldSize.LARGE, FieldSize.HUGE] - }, { - tl: [-.9, .3], - br: [-.05, .9], - types: [FieldType.TEXT], - sizes: [FieldSize.TINY] - }, { - tl: [.05, .3], - br: [.9, .9], - types: [FieldType.TEXT, FieldType.VISUAL], - sizes: [FieldSize.MEDIUM, FieldSize.LARGE, FieldSize.HUGE] + } }] }; - public static TwoFieldPlusCarousel: TemplateDocInfos = { - width: 500, - height: 600, - fields: [{ - tl: [-.9, -.99], - br: [.9, -.7], - types: [FieldType.TEXT], - sizes: [FieldSize.TINY] - }, { - tl: [-.9, -.65], - br: [.9, .35], - types: [], - sizes: [] - }, { - tl: [-.9, .4], - br: [.9, .95], - types: [FieldType.TEXT], - sizes: [FieldSize.TINY] - }] - }; +// public static FourField002: TemplateDocInfos = { +// width: 450, +// height: 600, +// fields: [{ +// tl: [-.6, -.9], +// br: [.6, -.8], +// types: [FieldType.TEXT], +// sizes: [FieldSize.TINY] +// }, { +// tl: [-.9, -.7], +// br: [.9, .2], +// types: [FieldType.TEXT, FieldType.VISUAL], +// sizes: [FieldSize.MEDIUM, FieldSize.LARGE, FieldSize.HUGE] +// }, { +// tl: [-.9, .3], +// br: [-.05, .9], +// types: [FieldType.TEXT], +// sizes: [FieldSize.TINY] +// }, { +// tl: [.05, .3], +// br: [.9, .9], +// types: [FieldType.TEXT, FieldType.VISUAL], +// sizes: [FieldSize.MEDIUM, FieldSize.LARGE, FieldSize.HUGE] +// }] +// }; + +// public static TwoFieldPlusCarousel: TemplateDocInfos = { +// width: 500, +// height: 600, +// fields: [{ +// tl: [-.9, -.99], +// br: [.9, -.7], +// types: [FieldType.TEXT], +// sizes: [FieldSize.TINY] +// }, { +// tl: [-.9, -.65], +// br: [.9, .35], +// types: [], +// sizes: [] +// }, { +// tl: [-.9, .4], +// br: [.9, .95], +// types: [FieldType.TEXT], +// sizes: [FieldSize.TINY] +// }] +// }; } \ No newline at end of file diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 3c898dea2..5af6e65de 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -948,12 +948,7 @@ export class DocumentViewInternal extends DocComponent - //
- //
- //
- //
-
- //
); } @@ -1138,7 +1132,7 @@ export class DocumentView extends DocComponent() { return Math.max(minTextScale, this._props.PanelHeight() / (this.effectiveNativeHeight || 1)); // height-limited or unscaled } @computed private get panelWidth() { - return this.effectiveNativeWidth ? this.effectiveNativeWidth * this.nativeScaling : this._props.PanelWidth(); + return this.effectiveNativeWidth ? this.effectiveNativeWidth * this.nativeScaling: this._props.PanelWidth(); } @computed private get panelHeight() { if (this.effectiveNativeHeight && (!this.layout_fitWidth || !this.layoutDoc.layout_reflowVertical)) { @@ -1449,6 +1443,8 @@ export class DocumentView extends DocComponent() { render() { TraceMobx(); + const borderWidth = 50/*Number(StrCast(this.layoutDoc.layout_borderWidth).replace('px', ''))*/; + console.log(this._props.PanelWidth(), borderWidth) const xshift = Math.abs(this.Xshift) <= 0.001 ? this._props.PanelWidth() : undefined; const yshift = Math.abs(this.Yshift) <= 0.001 ? this._props.PanelHeight() : undefined; @@ -1468,7 +1464,7 @@ export class DocumentView extends DocComponent() { style={{ transform: `translate(${this.centeringX}px, ${this.centeringY}px)`, width: xshift ?? `${this._props.PanelWidth() - this.Xshift * 2}px`, - height: this._props.forceAutoHeight ? undefined : yshift ?? (this.layout_fitWidth ? `${this.panelHeight}px` : `${(this.effectiveNativeHeight / this.effectiveNativeWidth) * this._props.PanelWidth()}px`), + height: this._props.forceAutoHeight ? '1000px' : yshift ?? (this.layout_fitWidth ? `${this.panelHeight + 500}px` : `${(this.effectiveNativeHeight / this.effectiveNativeWidth) * this._props.PanelWidth() + 500}px`), }}> Date: Thu, 29 Aug 2024 04:06:15 -0400 Subject: Dataviz crash hopefully fixed; prototype func for generating templates; radius NaN bug handled --- src/client/documents/Documents.ts | 3 +- src/client/views/StyleProvider.tsx | 5 + src/client/views/nodes/DataVizBox/DataVizBox.tsx | 18 ++- .../views/nodes/DataVizBox/DocCreatorMenu.tsx | 149 +++++++++++++++------ .../views/nodes/DataVizBox/components/TableBox.tsx | 13 +- src/client/views/nodes/DocumentView.tsx | 1 - 6 files changed, 137 insertions(+), 52 deletions(-) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index a4ba2978c..723f851c6 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -178,6 +178,7 @@ export class DocumentOptions { 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); + _rotation?: NUMt = new NumInfo('Amount of rotation on a document in degrees', false); date_range?: STRt = new StrInfo('date range for calendar', false); @@ -237,7 +238,7 @@ export class DocumentOptions { dataViz?: string; dataViz_savedTemplates?: LISTt; - borderWidth?: NUMt = new NumInfo('Width of user-added border', false); + borderWidth?: STRt = new StrInfo('Width of user-added border', false); borderColor?: STRt = new StrInfo('Color of user-added border', false); layout?: string | Doc; // default layout string or template document diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 3ecb101f8..bb0883cc0 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -56,11 +56,14 @@ export function styleFromLayoutString(doc: Doc, props: FieldViewProps, scale: nu } export function border(doc: Doc, pw: number, ph: number, rad: number = 0, inset: number = 0) { + if (!rad) rad = 0; const width = pw * inset; const height = ph * inset; const radius = Math.min(rad, (pw - 2 * width) / 2, (ph - 2 * height) / 2); + console.log(pw, ph, rad, inset) + return ` M ${width + radius} ${height} L ${pw - width - radius} ${height} @@ -206,8 +209,10 @@ export function DefaultStyleProvider(doc: Opt, props: Opt() { + private _urlError: boolean = false; private _mainCont: React.RefObject = React.createRef(); private _marqueeref = React.createRef(); private _annotationLayer: React.RefObject = React.createRef(); @@ -116,8 +117,17 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { // all CSV records in the dataset (that aren't an empty row) @computed.struct get records() { - const records = DataVizBox.dataset.get(CsvCast(this.dataDoc[this.fieldKey]).url.href); - return records?.filter(record => Object.keys(record).some(key => record[key])) ?? []; + try { + const records = DataVizBox.dataset.get(CsvCast(this.dataDoc[this.fieldKey]).url.href); + this._urlError = false; + return records?.filter(record => Object.keys(record).some(key => record[key])) ?? []; + } catch (e){ + this._urlError = true; + const data: { [key: string]: string; }[] = [ + { error: "Data not found"}, + ]; + return data; + } } // currently chosen visualization type: line, pie, histogram, table @@ -133,8 +143,6 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { } selectAxes = (axes: string[]) => { this.layoutDoc._dataViz_axes = new List(axes); - //axes.forEach(axis => console.log(axis)) - //DocCreatorMenu.Instance.generateTemplates(''); }; @computed.struct get titleCol() { return StrCast(this.layoutDoc._dataViz_titleCol); @@ -315,7 +323,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { componentDidMount() { this._props.setContentViewBox?.(this); - if (!DataVizBox.dataset.has(CsvCast(this.dataDoc[this.fieldKey]).url.href)) this.fetchData(); + if (!this._urlError) { if (!DataVizBox.dataset.has(CsvCast(this.dataDoc[this.fieldKey]).url.href)) this.fetchData() }; this._disposers.datavis = reaction( () => { if (this.layoutDoc.dataViz_schemaLive === undefined) this.layoutDoc.dataViz_schemaLive = true; diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx index 43cf57167..27ffc63ef 100644 --- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx +++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx @@ -404,21 +404,21 @@ export class DocCreatorMenu extends ObservableReactComponent { testTemplate = () => { - // const temp = TemplateLayouts.TwoFieldPlusCarousel; - // const title = new TemplateDocTextField({tl: temp.fields[0].tl, br: temp.fields[0].br}); - // const title1 = new TemplateDocTextField({tl: temp.fields[0].tl, br: temp.fields[0].br}); - // const title2 = new TemplateDocTextField({tl: temp.fields[0].tl, br: temp.fields[0].br}); - // const title3 = new TemplateDocTextField({tl: temp.fields[0].tl, br: temp.fields[0].br}); - // const focus = new TemplateDocCarouselField({tl: temp.fields[1].tl, br: temp.fields[1].br}, temp.width, temp.height, '', [title1, title2, title3].map(field => field.getDoc(temp.width, temp.height, 'hey now', ''))); - // const caption = new TemplateDocTextField({tl: temp.fields[2].tl, br: temp.fields[2].br}); - // let fields = [title, caption].map(field => field.getDoc(temp.width, temp.height, 'hey now', '')); - // fields = fields.concat(focus.getDoc()); - // console.log(temp.height, temp.width) - // const doc = Docs.Create.StackingDocument(fields, { _height: temp.height, _width: temp.width, title: 'hey', x: 400, y: 400 }); - - // const mainCollection = this._dataViz?.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView; - // mainCollection.addDocument(doc); - //this._dataViz?.getRandomSample(); + const temp = TemplateLayouts.FourField001; + const title: Doc = FieldFuncs.TextField({tl: temp.fields[0].tl, br: temp.fields[0].br}, temp.height, temp.width, 'title', 'Title', {backgroundColor: 'transparent'}); + const image: Doc = FieldFuncs.ImageField({tl: temp.fields[1].tl, br: temp.fields[1].br}, temp.height, temp.width, 'title', '', {borderColor: '#159fe4', borderWidth: '10', cornerRounding: 10, rotation: 40}); + const caption: Doc = FieldFuncs.TextField({tl: temp.fields[2].tl, br: temp.fields[2].br}, temp.height, temp.width, 'title', 'Caption', {backgroundColor: 'transparent'}); + const desc: Doc = FieldFuncs.TextField({tl: temp.fields[3].tl, br: temp.fields[3].br}, temp.height, temp.width, 'title', '', {backgroundColor: 'lightblue', borderColor: '#159fe4', borderWidth: '10', cornerRounding: 10}); + + const doc = Docs.Create.FreeformDocument([title, image, caption, desc], { _height: temp.height, _width: temp.width, title: 'hey', x: 400, y: 400 }); + + const mainCollection = this._dataViz?.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView; + mainCollection.addDocument(doc); + + // setTimeout(() => image.borderWidth = '10', 1000); + // setTimeout(() => desc.borderWidth = '10', 1000); + + // this._dataViz?.getRandomSample(); // public static FourField001: TemplateDocInfos = { @@ -450,12 +450,12 @@ export class DocCreatorMenu extends ObservableReactComponent { // opts: { - const field1: Col = {title: 'hey', type: TemplateFieldType.TEXT, size: FieldSize.HUGE, desc: ''} - const field2: Col = {title: 'heyo', type: TemplateFieldType.TEXT, size: FieldSize.TINY, desc: ''} - const field3: Col = {title: 'heya', type: TemplateFieldType.VISUAL, size: FieldSize.LARGE, desc: ''} - const field4: Col = {title: 'heyy', type: TemplateFieldType.TEXT, size: FieldSize.MEDIUM, desc: ''} + // const field1: Col = {title: 'hey', type: TemplateFieldType.TEXT, size: FieldSize.HUGE, desc: ''} + // const field2: Col = {title: 'heyo', type: TemplateFieldType.TEXT, size: FieldSize.TINY, desc: ''} + // const field3: Col = {title: 'heya', type: TemplateFieldType.VISUAL, size: FieldSize.LARGE, desc: ''} + // const field4: Col = {title: 'heyy', type: TemplateFieldType.TEXT, size: FieldSize.MEDIUM, desc: ''} - console.log(this.findValidTemplates([field1, field2, field3, field4], [TemplateLayouts.FourField001])); + // console.log(this.findValidTemplates([field1, field2, field3, field4], [TemplateLayouts.FourField001])); } get templatesPreviewContents(){ @@ -609,9 +609,9 @@ export class DocCreatorMenu extends ObservableReactComponent { } } - doc = () => { - return Docs.Create.FreeformDocument([], { _height: 200, _width: 200, title: 'title'}); - } + // doc = () => { + // return Docs.Create.FreeformDocument([], { _height: 200, _width: 200, title: 'title'}); + // } screenToLocalTransform = () => this._props @@ -802,7 +802,7 @@ export class DocCreatorMenu extends ObservableReactComponent { } @action addField = () => { - const newFields: Col[] = this._columns.concat([{title: '', type: TemplateFieldType.TEXT, desc: '', size: FieldSize.MEDIUM}]) + const newFields: Col[] = this._columns.concat([{title: '', type: TemplateFieldType.UNSET, desc: '', size: FieldSize.MEDIUM}]) this._columns = newFields; } @@ -822,9 +822,7 @@ export class DocCreatorMenu extends ObservableReactComponent { if (this._columns.length === 1) { this._columns = [] } else { - console.log(this._columns) this._columns.splice(this._columns.indexOf(toRemove[0]), 1); - console.log(this._columns) } } } @@ -899,7 +897,6 @@ export class DocCreatorMenu extends ObservableReactComponent { templates.forEach(template => { const numFields = template.fields.length; const matches = this.matchesForTemplate(template, cols); - console.log(matches) if (this.maxMatches(numFields, matches) === numFields) { validTemplates.push(template.title); } @@ -908,7 +905,32 @@ export class DocCreatorMenu extends ObservableReactComponent { return validTemplates; } + createEmptyTemplate = (template: TemplateDocInfos, assignments: {[field: number]: Col}) => { + const fields: Doc[] = []; + + Object.entries(assignments).forEach(([f, col]) => { + const field: Field = template.fields[Number(f)]; + const doc = (col.type === TemplateFieldType.VISUAL ? FieldFuncs.ImageField : FieldFuncs.TextField)({ + tl: field.tl, + br: field.br }, + template.height, + template.width, + col.title, + '', + field.opts + ); + + fields.push(doc); + }); + + const renderedTemplate = Docs.Create.FreeformDocument(fields, { _height: template.height, _width: template.width, title: template.title, x: 400, y: 400 }); + + const mainCollection = this._dataViz?.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView; + mainCollection.addDocument(renderedTemplate); + } + get dashboardContents(){ + return (
@@ -919,10 +941,10 @@ export class DocCreatorMenu extends ObservableReactComponent { {this.fieldsInfos.map((field, index) =>
- +
- {field.type ? null : Select media type} - {field.type ? field.type === 'text' ? 'Text Field' : 'File Field' : ''} + {field.type === TemplateFieldType.UNSET ? Select media type : null} + {field.type === TemplateFieldType.TEXT ? 'Text Field' : field.type === TemplateFieldType.VISUAL ? 'File Field' : ''}
{this.setFieldType(field, TemplateFieldType.TEXT)}}/>
Text
@@ -930,15 +952,13 @@ export class DocCreatorMenu extends ObservableReactComponent {
File
+