aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/collectionSchema
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2023-12-21 14:55:48 -0500
committerbobzel <zzzman@gmail.com>2023-12-21 14:55:48 -0500
commit1caba64ee0f32ee8af79263cd4ef2a8bc5d5146e (patch)
tree0fa0e957d1f342fdc6ed4a4b43f5dddfddb1298a /src/client/views/collections/collectionSchema
parent02eb7da95df283606d4275a22d9451cef371c3b5 (diff)
parent2691b951d96f2ce7652acbea9e340b61737b3b57 (diff)
Merge branch 'moreUpgrading' into dataViz-annotations
Diffstat (limited to 'src/client/views/collections/collectionSchema')
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaView.scss2
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaView.tsx129
-rw-r--r--src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx4
-rw-r--r--src/client/views/collections/collectionSchema/SchemaRowBox.tsx42
-rw-r--r--src/client/views/collections/collectionSchema/SchemaTableCell.tsx170
5 files changed, 192 insertions, 155 deletions
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
index 76bd392a5..02131ae22 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
@@ -1,4 +1,4 @@
-@import '../../global/globalCssVariables.scss';
+@import '../../global/globalCssVariables.module.scss';
.collectionSchemaView {
cursor: default;
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 190e4ff2a..2546f5b02 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -1,7 +1,7 @@
-import React = require('react');
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, observable, ObservableMap, observe } from 'mobx';
+import { action, computed, makeObservable, observable, ObservableMap, observe } from 'mobx';
import { observer } from 'mobx-react';
+import * as React from 'react';
import { Doc, DocListCast, Field, NumListCast, Opt, StrListCast } from '../../../../fields/Doc';
import { Id } from '../../../../fields/FieldSymbols';
import { List } from '../../../../fields/List';
@@ -18,6 +18,7 @@ import { EditableView } from '../../EditableView';
import { Colors } from '../../global/globalEnums';
import { DocFocusOptions, DocumentView, DocumentViewProps } from '../../nodes/DocumentView';
import { KeyValueBox } from '../../nodes/KeyValueBox';
+import { ObservableReactComponent } from '../../ObservableReactComponent';
import { DefaultStyleProvider, StyleProp } from '../../StyleProvider';
import { CollectionSubView } from '../CollectionSubView';
import './CollectionSchemaView.scss';
@@ -57,6 +58,11 @@ export class CollectionSchemaView extends CollectionSubView() {
private _tableContentRef: HTMLDivElement | null = null;
private _menuTarget = React.createRef<HTMLDivElement>();
+ constructor(props: any) {
+ super(props);
+ makeObservable(this);
+ }
+
static _rowHeight: number = 50;
static _rowSingleLineHeight: number = 32;
public static _minColWidth: number = 25;
@@ -68,16 +74,16 @@ export class CollectionSchemaView extends CollectionSubView() {
@observable _menuKeys: string[] = [];
@observable _rowEles: ObservableMap = new ObservableMap<Doc, HTMLDivElement>();
@observable _colEles: HTMLDivElement[] = [];
- @observable _displayColumnWidths: number[] | undefined;
- @observable _columnMenuIndex: number | undefined;
+ @observable _displayColumnWidths: number[] | undefined = undefined;
+ @observable _columnMenuIndex: number | undefined = undefined;
@observable _newFieldWarning: string = '';
@observable _makeNewField: boolean = false;
@observable _newFieldDefault: any = 0;
@observable _newFieldType: ColumnType = ColumnType.Number;
@observable _menuValue: string = '';
- @observable _filterColumnIndex: number | undefined;
+ @observable _filterColumnIndex: number | undefined = undefined;
@observable _filterSearchValue: string = '';
- @observable _selectedCell: [Doc, number] | undefined;
+ @observable _selectedCell: [Doc, number] | undefined = undefined;
// target HTMLelement portal for showing a popup menu to edit cell values.
public get MenuTarget() {
@@ -85,12 +91,12 @@ export class CollectionSchemaView extends CollectionSubView() {
}
@computed get _selectedDocs() {
- const selected = SelectionManager.Docs().filter(doc => Doc.AreProtosEqual(DocCast(doc.embedContainer), this.rootDoc));
+ const selected = SelectionManager.Docs.filter(doc => Doc.AreProtosEqual(DocCast(doc.embedContainer), this.Document));
if (!selected.length) {
- for (const sel of SelectionManager.Docs()) {
+ for (const sel of SelectionManager.Docs) {
const contextPath = DocumentManager.GetContextPath(sel, true);
- if (contextPath.includes(this.rootDoc)) {
- const parentInd = contextPath.indexOf(this.rootDoc);
+ if (contextPath.includes(this.Document)) {
+ const parentInd = contextPath.indexOf(this.Document);
return parentInd < contextPath.length - 1 ? [contextPath[parentInd + 1]] : [];
}
}
@@ -107,7 +113,7 @@ export class CollectionSchemaView extends CollectionSubView() {
}
@computed get tableWidth() {
- return this.props.PanelWidth() - this.previewWidth - (this.previewWidth === 0 ? 0 : CollectionSchemaView._previewDividerWidth);
+ return this._props.PanelWidth() - this.previewWidth - (this.previewWidth === 0 ? 0 : CollectionSchemaView._previewDividerWidth);
}
@computed get columnKeys() {
@@ -139,14 +145,13 @@ export class CollectionSchemaView extends CollectionSubView() {
return BoolCast(this.layoutDoc.sortDesc);
}
- @action
componentDidMount() {
- this.props.setContentView?.(this);
+ this._props.setContentView?.(this);
document.addEventListener('keydown', this.onKeyDown);
Object.entries(this._documentOptions).forEach((pair: [string, FInfo]) => this.fieldInfos.set(pair[0], pair[1]));
this._keysDisposer = observe(
- this.rootDoc[this.fieldKey ?? 'data'] as List<Doc>,
+ this.dataDoc[this.fieldKey ?? 'data'] as List<Doc>,
change => {
switch (change.type as any) {
case 'splice':
@@ -154,7 +159,7 @@ export class CollectionSchemaView extends CollectionSubView() {
(change as any).added.forEach((doc: Doc) => // for each document added
Doc.GetAllPrototypes(doc.value as Doc).forEach(proto => // for all of its prototypes (and itself)
Object.keys(proto).forEach(action(key => // check if any of its keys are new, and add them
- !this.fieldInfos.get(key) && this.fieldInfos.set(key, new FInfo(''))))));
+ !this.fieldInfos.get(key) && this.fieldInfos.set(key, new FInfo(key, key === 'author'))))));
break;
case 'update': //let oldValue = change.oldValue; // fill this in if the entire child list will ever be reassigned with a new list
}
@@ -239,7 +244,6 @@ export class CollectionSchemaView extends CollectionSubView() {
};
@undoBatch
- @action
setColumnSort = (field: string | undefined, desc: boolean = false) => {
this.layoutDoc.sortField = field;
this.layoutDoc.sortDesc = desc;
@@ -248,7 +252,6 @@ export class CollectionSchemaView extends CollectionSubView() {
addRow = (doc: Doc | Doc[]) => this.addDocument(doc);
@undoBatch
- @action
changeColumnKey = (index: number, newKey: string, defaultVal?: any) => {
if (!this.documentKeys.includes(newKey)) {
this.addNewKey(newKey, defaultVal);
@@ -260,7 +263,6 @@ export class CollectionSchemaView extends CollectionSubView() {
};
@undoBatch
- @action
addColumn = (key: string, defaultVal?: any) => {
if (!this.documentKeys.includes(key)) {
this.addNewKey(key, defaultVal);
@@ -281,7 +283,6 @@ export class CollectionSchemaView extends CollectionSubView() {
addNewKey = (key: string, defaultVal: any) => this.childDocs.forEach(doc => (doc[key] = defaultVal));
@undoBatch
- @action
removeColumn = (index: number) => {
if (this.columnKeys.length === 1) return;
const currWidths = this.storedColumnWidths.slice();
@@ -320,8 +321,8 @@ export class CollectionSchemaView extends CollectionSubView() {
change = this._displayColumnWidths[shrinking] - CollectionSchemaView._minColWidth;
}
- this._displayColumnWidths[shrinking] -= change * this.props.ScreenToLocalTransform().Scale;
- this._displayColumnWidths[growing] += change * this.props.ScreenToLocalTransform().Scale;
+ this._displayColumnWidths[shrinking] -= change * this._props.ScreenToLocalTransform().Scale;
+ this._displayColumnWidths[growing] += change * this._props.ScreenToLocalTransform().Scale;
return false;
}
@@ -335,7 +336,6 @@ export class CollectionSchemaView extends CollectionSubView() {
};
@undoBatch
- @action
moveColumn = (fromIndex: number, toIndex: number) => {
let currKeys = this.columnKeys.slice();
currKeys.splice(toIndex, 0, currKeys.splice(fromIndex, 1)[0]);
@@ -379,7 +379,7 @@ export class CollectionSchemaView extends CollectionSubView() {
@action
highlightDropColumn = (e: PointerEvent) => {
e.stopPropagation();
- const mouseX = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[0];
+ const mouseX = this._props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[0];
const index = this.findDropIndex(mouseX);
this._colEles.forEach((colRef, i) => {
let leftStyle = '';
@@ -416,8 +416,8 @@ export class CollectionSchemaView extends CollectionSubView() {
@action
clearSelection = () => SelectionManager.DeselectAll();
- selectRows = (rootDoc: Doc, lastSelected: Doc) => {
- const index = this.rowIndex(rootDoc);
+ selectRows = (doc: Doc, lastSelected: Doc) => {
+ const index = this.rowIndex(doc);
const lastSelectedRow = this.rowIndex(lastSelected);
const startRow = Math.min(lastSelectedRow, index);
const endRow = Math.max(lastSelectedRow, index);
@@ -437,10 +437,9 @@ export class CollectionSchemaView extends CollectionSubView() {
setDropIndex = (index: number) => (this._closestDropIndex = index);
- @action
onInternalDrop = (e: Event, de: DragManager.DropEvent) => {
if (de.complete.columnDragData) {
- const mouseX = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y)[0];
+ const mouseX = this._props.ScreenToLocalTransform().transformPoint(de.x, de.y)[0];
const index = this.findDropIndex(mouseX);
this.moveColumn(de.complete.columnDragData.colIndex, index ?? de.complete.columnDragData.colIndex);
@@ -473,7 +472,6 @@ export class CollectionSchemaView extends CollectionSubView() {
return false;
};
- @action
onExternalDrop = async (e: React.DragEvent): Promise<void> => {
super.onExternalDrop(e, {}, undoBatch(action(docus => docus.map((doc: Doc) => this.addDocument(doc)))));
};
@@ -485,7 +483,7 @@ export class CollectionSchemaView extends CollectionSubView() {
const nativeWidth = this._previewRef!.getBoundingClientRect();
const minWidth = 40;
const maxWidth = 1000;
- const movedWidth = this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0];
+ const movedWidth = this._props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0];
const width = movedWidth < minWidth ? minWidth : movedWidth > maxWidth ? maxWidth : movedWidth;
this.layoutDoc.schema_previewWidth = width;
return false;
@@ -509,8 +507,8 @@ export class CollectionSchemaView extends CollectionSubView() {
const found = this._tableContentRef && Array.from(this._tableContentRef.getElementsByClassName('documentView-node')).find((node: any) => node.id === doc[Id]);
if (found) {
const rect = found.getBoundingClientRect();
- const localRect = this.props.ScreenToLocalTransform().transformBounds(rect.left, rect.top, rect.width, rect.height);
- if (localRect.y < this.rowHeightFunc() || localRect.y + localRect.height > this.props.PanelHeight()) {
+ const localRect = this._props.ScreenToLocalTransform().transformBounds(rect.left, rect.top, rect.width, rect.height);
+ if (localRect.y < this.rowHeightFunc() || localRect.y + localRect.height > this._props.PanelHeight()) {
let focusSpeed = options.zoomTime ?? 50;
smoothScroll(focusSpeed, this._tableContentRef!, localRect.y + this._tableContentRef!.scrollTop - this.rowHeightFunc(), options.easeFunc);
return focusSpeed;
@@ -757,7 +755,7 @@ export class CollectionSchemaView extends CollectionSubView() {
@computed get renderFilterOptions() {
const keyOptions: string[] = [];
const columnKey = this.columnKeys[this._filterColumnIndex!];
- const allDocs = DocListCast(this.dataDoc[this.props.fieldKey]);
+ const allDocs = DocListCast(this.dataDoc[this._props.fieldKey]);
allDocs.forEach(doc => {
const value = StrCast(doc[columnKey]);
if (!keyOptions.includes(value) && value !== '' && (this._filterSearchValue === '' || value.includes(this._filterSearchValue))) {
@@ -781,9 +779,9 @@ export class CollectionSchemaView extends CollectionSubView() {
onClick={e => e.stopPropagation()}
onChange={action(e => {
if (e.target.checked) {
- Doc.setDocFilter(this.props.Document, columnKey, key, 'check');
+ Doc.setDocFilter(this.Document, columnKey, key, 'check');
} else {
- Doc.setDocFilter(this.props.Document, columnKey, key, 'remove');
+ Doc.setDocFilter(this.Document, columnKey, key, 'remove');
}
})}
checked={bool}
@@ -830,8 +828,8 @@ export class CollectionSchemaView extends CollectionSubView() {
}
rowHeightFunc = () => (BoolCast(this.layoutDoc._schema_singleLine) ? CollectionSchemaView._rowSingleLineHeight : CollectionSchemaView._rowHeight);
sortedDocsFunc = () => this.sortedDocs;
- isContentActive = () => this.props.isSelected() || this.props.isContentActive();
- screenToLocal = () => this.props.ScreenToLocalTransform().translate(-this.tableWidth, 0);
+ isContentActive = () => this._props.isSelected() || this._props.isContentActive();
+ screenToLocal = () => this._props.ScreenToLocalTransform().translate(-this.tableWidth, 0);
previewWidthFunc = () => this.previewWidth;
render() {
return (
@@ -840,7 +838,7 @@ export class CollectionSchemaView extends CollectionSubView() {
<div
className="schema-table"
style={{ width: `calc(100% - ${this.previewWidth}px)` }}
- onWheel={e => this.props.isContentActive() && e.stopPropagation()}
+ onWheel={e => this._props.isContentActive() && e.stopPropagation()}
ref={r => {
// prevent wheel events from passively propagating up through containers
r?.addEventListener('wheel', (e: WheelEvent) => {}, { passive: false });
@@ -866,7 +864,7 @@ export class CollectionSchemaView extends CollectionSubView() {
openContextMenu={this.openContextMenu}
dragColumn={this.dragColumn}
setColRef={this.setColRef}
- isContentActive={this.props.isContentActive}
+ isContentActive={this._props.isContentActive}
/>
))}
</div>
@@ -892,16 +890,15 @@ export class CollectionSchemaView extends CollectionSubView() {
{Array.from(this._selectedDocs).lastElement() && (
<DocumentView
Document={Array.from(this._selectedDocs).lastElement()}
- DataDoc={undefined}
fitContentsToBox={returnTrue}
dontCenter={'y'}
onClickScriptDisable="always"
focus={emptyFunction}
defaultDoubleClick={returnIgnore}
- renderDepth={this.props.renderDepth + 1}
+ renderDepth={this._props.renderDepth + 1}
rootSelected={this.rootSelected}
PanelWidth={this.previewWidthFunc}
- PanelHeight={this.props.PanelHeight}
+ PanelHeight={this._props.PanelHeight}
isContentActive={returnTrue}
isDocumentActive={returnFalse}
ScreenToLocalTransform={this.screenToLocal}
@@ -910,12 +907,12 @@ export class CollectionSchemaView extends CollectionSubView() {
searchFilterDocs={this.searchFilterDocs}
styleProvider={DefaultStyleProvider}
docViewPath={returnEmptyDoclist}
- moveDocument={this.props.moveDocument}
+ moveDocument={this._props.moveDocument}
addDocument={this.addRow}
- removeDocument={this.props.removeDocument}
+ removeDocument={this._props.removeDocument}
whenChildContentsActiveChanged={returnFalse}
- addDocTab={this.props.addDocTab}
- pinToPres={this.props.pinToPres}
+ addDocTab={this._props.addDocTab}
+ pinToPres={this._props.pinToPres}
bringToFront={returnFalse}
/>
)}
@@ -939,7 +936,7 @@ class CollectionSchemaViewDocs extends React.Component<CollectionSchemaViewDocsP
return (
<div className="schema-table-content" ref={this.props.setRef} style={{ height: `calc(100% - ${CollectionSchemaView._newNodeInputHeight + this.props.rowHeight()}px)` }}>
{this.props.childDocs().docs.map((doc: Doc, index: number) => (
- <div className="schema-row-wrapper" style={{ height: this.props.rowHeight() }}>
+ <div key={doc[Id]} className="schema-row-wrapper" style={{ height: this.props.rowHeight() }}>
<CollectionSchemaViewDoc doc={doc} schema={this.props.schema} index={index} rowHeight={this.props.rowHeight} />
</div>
))}
@@ -956,9 +953,14 @@ interface CollectionSchemaViewDocProps {
}
@observer
-class CollectionSchemaViewDoc extends React.Component<CollectionSchemaViewDocProps> {
- tableWidthFunc = () => this.props.schema.tableWidth;
- screenToLocalXf = () => this.props.schema.props.ScreenToLocalTransform().translate(0, -this.props.rowHeight() - this.props.index * this.props.rowHeight());
+class CollectionSchemaViewDoc extends ObservableReactComponent<CollectionSchemaViewDocProps> {
+ constructor(props: any) {
+ super(props);
+ makeObservable(this);
+ }
+
+ tableWidthFunc = () => this._props.schema.tableWidth;
+ screenToLocalXf = () => this._props.schema._props.ScreenToLocalTransform().translate(0, -this._props.rowHeight() - this._props.index * this._props.rowHeight());
noOpacityStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string) => {
if (property === StyleProp.Opacity) return 1;
return DefaultStyleProvider(doc, props, property);
@@ -966,31 +968,30 @@ class CollectionSchemaViewDoc extends React.Component<CollectionSchemaViewDocPro
render() {
return (
<DocumentView
- key={this.props.doc[Id]}
- {...this.props.schema.props}
- LayoutTemplate={this.props.schema.props.childLayoutTemplate}
- LayoutTemplateString={SchemaRowBox.LayoutString(this.props.schema.props.fieldKey, this.props.index)}
- Document={this.props.doc}
- DataDoc={undefined}
- renderDepth={this.props.schema.props.renderDepth + 1}
+ key={this._props.doc[Id]}
+ {...this._props.schema._props}
+ LayoutTemplate={this._props.schema._props.childLayoutTemplate}
+ LayoutTemplateString={SchemaRowBox.LayoutString(this._props.schema._props.fieldKey, this._props.index)}
+ Document={this._props.doc}
+ renderDepth={this._props.schema._props.renderDepth + 1}
PanelWidth={this.tableWidthFunc}
- PanelHeight={this.props.rowHeight}
+ PanelHeight={this._props.rowHeight}
styleProvider={this.noOpacityStyleProvider}
waitForDoubleClickToClick={returnNever}
defaultDoubleClick={returnIgnore}
dragAction="move"
onClickScriptDisable="always"
- focus={this.props.schema.focusDocument}
- childFilters={this.props.schema.childDocFilters}
- childFiltersByRanges={this.props.schema.childDocRangeFilters}
- searchFilterDocs={this.props.schema.searchFilterDocs}
- rootSelected={this.props.schema.rootSelected}
+ focus={this._props.schema.focusDocument}
+ childFilters={this._props.schema.childDocFilters}
+ childFiltersByRanges={this._props.schema.childDocRangeFilters}
+ searchFilterDocs={this._props.schema.searchFilterDocs}
+ rootSelected={this._props.schema.rootSelected}
ScreenToLocalTransform={this.screenToLocalXf}
bringToFront={emptyFunction}
dragWhenActive={true}
- isDocumentActive={this.props.schema.props.childDocumentsActive?.() ? this.props.schema.props.isDocumentActive : this.props.schema.isContentActive}
+ isDocumentActive={this._props.schema._props.childDocumentsActive?.() ? this._props.schema._props.isDocumentActive : this._props.schema.isContentActive}
isContentActive={emptyFunction}
- whenChildContentsActiveChanged={this.props.schema.props.whenChildContentsActiveChanged}
+ whenChildContentsActiveChanged={this._props.schema._props.whenChildContentsActiveChanged}
hideDecorations={true}
hideTitle={true}
hideDocumentButtonBar={true}
diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
index 65e47f441..04443b4a7 100644
--- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
@@ -1,4 +1,4 @@
-import React = require('react');
+import * as React from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, observable } from 'mobx';
import { observer } from 'mobx-react';
@@ -26,7 +26,7 @@ export interface SchemaColumnHeaderProps {
export class SchemaColumnHeader extends React.Component<SchemaColumnHeaderProps> {
@observable _ref: HTMLDivElement | null = null;
- @computed get fieldKey() {
+ get fieldKey() {
return this.props.columnKeys[this.props.columnIndex];
}
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 7346c4f12..5a3be826b 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -1,13 +1,13 @@
-import React = require('react');
import { IconButton, Size } from 'browndash-components';
-import { computed } from 'mobx';
+import { computed, makeObservable } from 'mobx';
import { observer } from 'mobx-react';
import { computedFn } from 'mobx-utils';
+import * as React from 'react';
import { CgClose } from 'react-icons/cg';
import { FaExternalLinkAlt } from 'react-icons/fa';
+import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../../Utils';
import { Doc } from '../../../../fields/Doc';
import { BoolCast } from '../../../../fields/Types';
-import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../../Utils';
import { DragManager } from '../../../util/DragManager';
import { SnappingManager } from '../../../util/SnappingManager';
import { Transform } from '../../../util/Transform';
@@ -28,38 +28,42 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps & SchemaRo
public static LayoutString(fieldKey: string, rowIndex: number) {
return FieldView.LayoutString(SchemaRowBox, fieldKey).replace('fieldKey', `rowIndex={${rowIndex}} fieldKey`);
}
-
private _ref: HTMLDivElement | null = null;
+ constructor(props: any) {
+ super(props);
+ makeObservable(this);
+ }
+
bounds = () => this._ref?.getBoundingClientRect();
@computed get schemaView() {
- return this.props.DocumentView?.().props.docViewPath().lastElement()?.ComponentView as CollectionSchemaView;
+ return this._props.DocumentView?.()._props.docViewPath().lastElement()?.ComponentView as CollectionSchemaView;
}
@computed get schemaDoc() {
- return this.props.DocumentView?.().props.docViewPath().lastElement()?.rootDoc;
+ return this._props.DocumentView?.()._props.docViewPath().lastElement()?.Document;
}
@computed get rowIndex() {
- return this.schemaView?.rowIndex(this.rootDoc) ?? -1;
+ return this.schemaView?.rowIndex(this.Document) ?? -1;
}
componentDidMount(): void {
- this.props.setContentView?.(this);
+ this._props.setContentView?.(this);
}
select = (ctrlKey: boolean, shiftKey: boolean) => {
if (!this.schemaView) return;
const lastSelected = Array.from(this.schemaView._selectedDocs).lastElement();
- if (shiftKey && lastSelected) this.schemaView.selectRows(this.rootDoc, lastSelected);
+ if (shiftKey && lastSelected) this.schemaView.selectRows(this.Document, lastSelected);
else {
- this.props.select?.(ctrlKey);
+ this._props.select?.(ctrlKey);
}
};
onPointerEnter = (e: any) => {
- if (SnappingManager.GetIsDragging() && this.props.isContentActive()) {
+ if (SnappingManager.IsDragging && this._props.isContentActive()) {
document.removeEventListener('pointermove', this.onPointerMove);
document.addEventListener('pointermove', this.onPointerMove);
}
@@ -103,18 +107,18 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps & SchemaRo
return (
<div
className="schema-row"
- style={{ height: this.props.PanelHeight(), backgroundColor: this.props.isSelected() ? Colors.LIGHT_BLUE : undefined }}
+ style={{ height: this._props.PanelHeight(), backgroundColor: this._props.isSelected() ? Colors.LIGHT_BLUE : undefined }}
onPointerEnter={this.onPointerEnter}
onPointerLeave={this.onPointerLeave}
ref={(row: HTMLDivElement | null) => {
- row && this.schemaView?.addRowRef?.(this.rootDoc, row);
+ row && this.schemaView?.addRowRef?.(this.Document, row);
this._ref = row;
}}>
<div
className="row-menu"
style={{
width: CollectionSchemaView._rowMenuWidth,
- pointerEvents: !this.props.isContentActive() ? 'none' : undefined,
+ pointerEvents: !this._props.isContentActive() ? 'none' : undefined,
}}>
<IconButton
tooltip="close"
@@ -128,7 +132,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps & SchemaRo
emptyFunction,
undoable(e => {
e.stopPropagation();
- this.props.removeDocument?.(this.rootDoc);
+ this._props.removeDocument?.(this.Document);
}, 'Delete Row')
)
}
@@ -145,7 +149,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps & SchemaRo
emptyFunction,
undoable(e => {
e.stopPropagation();
- this.props.addDocTab(this.rootDoc, OpenWhere.addRight);
+ this._props.addDocTab(this.Document, OpenWhere.addRight);
}, 'Open schema Doc preview')
)
}
@@ -155,13 +159,13 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps & SchemaRo
{this.schemaView?.columnKeys?.map((key, index) => (
<SchemaTableCell
key={key}
- Document={this.rootDoc}
+ Document={this.Document}
col={index}
fieldKey={key}
allowCRs={false} // to enter text with new lines, must use \n
columnWidth={this.columnWidth(index)}
rowHeight={this.schemaView.rowHeightFunc}
- isRowActive={this.props.isContentActive}
+ isRowActive={this._props.isContentActive}
getFinfo={this.getFinfo}
selectCell={this.selectCell}
deselectCell={this.deselectCell}
@@ -172,7 +176,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps & SchemaRo
transform={() => {
const ind = index === this.schemaView.columnKeys.length - 1 ? this.schemaView.columnKeys.length - 3 : index;
const x = this.schemaView?.displayColumnWidths.reduce((p, c, i) => (i <= ind ? p + c : p), 0);
- const y = (this.props.rowIndex ?? 0) * this.props.PanelHeight();
+ const y = (this._props.rowIndex ?? 0) * this._props.PanelHeight();
return new Transform(x + CollectionSchemaView._rowMenuWidth, y, 1);
}}
/>
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index 9d5b533d1..85269028b 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -1,27 +1,28 @@
-import * as React from 'react';
-import Select, { MenuPlacement } from 'react-select';
-import { action, computed, observable } from 'mobx';
+import { action, computed, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import { extname } from 'path';
+import * as React from 'react';
import DatePicker from 'react-datepicker';
+import Select from 'react-select';
+import { Utils, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnZero } from '../../../../Utils';
import { DateField } from '../../../../fields/DateField';
import { Doc, DocListCast, Field } from '../../../../fields/Doc';
import { RichTextField } from '../../../../fields/RichTextField';
import { BoolCast, Cast, DateCast, DocCast, FieldValue, StrCast } from '../../../../fields/Types';
import { ImageField } from '../../../../fields/URLField';
-import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnZero, Utils } from '../../../../Utils';
import { FInfo } from '../../../documents/Documents';
import { DocFocusOrOpen } from '../../../util/DocumentManager';
import { Transform } from '../../../util/Transform';
-import { undoable, undoBatch } from '../../../util/UndoManager';
+import { undoBatch, undoable } from '../../../util/UndoManager';
import { EditableView } from '../../EditableView';
+import { ObservableReactComponent } from '../../ObservableReactComponent';
+import { DefaultStyleProvider } from '../../StyleProvider';
import { Colors } from '../../global/globalEnums';
import { OpenWhere } from '../../nodes/DocumentView';
-import { FieldView, FieldViewProps } from '../../nodes/FieldView';
-import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox';
+import { FieldViewProps } from '../../nodes/FieldView';
import { KeyValueBox } from '../../nodes/KeyValueBox';
-import { DefaultStyleProvider } from '../../StyleProvider';
-import { CollectionSchemaView, ColumnType, FInfotoColType } from './CollectionSchemaView';
+import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox';
+import { ColumnType, FInfotoColType } from './CollectionSchemaView';
import './CollectionSchemaView.scss';
export interface SchemaTableCellProps {
@@ -47,7 +48,12 @@ export interface SchemaTableCellProps {
}
@observer
-export class SchemaTableCell extends React.Component<SchemaTableCellProps> {
+export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellProps> {
+ constructor(props: any) {
+ super(props);
+ makeObservable(this);
+ }
+
static addFieldDoc = (doc: Doc, where: OpenWhere) => {
DocFocusOrOpen(doc);
return true;
@@ -72,7 +78,6 @@ export class SchemaTableCell extends React.Component<SchemaTableCellProps> {
searchFilterDocs: returnEmptyDoclist,
styleProvider: DefaultStyleProvider,
docViewPath: returnEmptyDoclist,
- rootSelected: returnFalse,
isSelected: returnFalse,
setHeight: returnFalse,
select: emptyFunction,
@@ -97,12 +102,12 @@ export class SchemaTableCell extends React.Component<SchemaTableCellProps> {
}
@computed get selected() {
- const selected: [Doc, number] | undefined = this.props.selectedCell();
- return this.props.isRowActive() && selected?.[0] === this.props.Document && selected[1] === this.props.col;
+ const selected: [Doc, number] | undefined = this._props.selectedCell();
+ return this._props.isRowActive() && selected?.[0] === this._props.Document && selected[1] === this._props.col;
}
@computed get defaultCellContent() {
- const { color, textDecoration, fieldProps } = SchemaTableCell.renderProps(this.props);
+ const { color, textDecoration, fieldProps, pointerEvents } = SchemaTableCell.renderProps(this._props);
return (
<div
@@ -111,19 +116,21 @@ export class SchemaTableCell extends React.Component<SchemaTableCellProps> {
color,
textDecoration,
width: '100%',
+ pointerEvents,
}}>
<EditableView
- oneLine={this.props.oneLine}
- allowCRs={this.props.allowCRs}
- contents={<FieldView {...fieldProps} />}
+ oneLine={this._props.oneLine}
+ allowCRs={this._props.allowCRs}
+ contents={undefined}
+ fieldContents={fieldProps}
editing={this.selected ? undefined : false}
- GetValue={() => Field.toKeyValueString(this.props.Document, this.props.fieldKey)}
+ GetValue={() => Field.toKeyValueString(this._props.Document, this._props.fieldKey)}
SetValue={undoable((value: string, shiftDown?: boolean, enterKey?: boolean) => {
if (shiftDown && enterKey) {
- this.props.setColumnValues(this.props.fieldKey.replace(/^_/, ''), value);
+ this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), value);
}
- const ret = KeyValueBox.SetField(this.props.Document, this.props.fieldKey.replace(/^_/, ''), value);
- this.props.finishEdit?.();
+ const ret = KeyValueBox.SetField(this._props.Document, this._props.fieldKey.replace(/^_/, ''), value);
+ this._props.finishEdit?.();
return ret;
}, 'edit schema cell')}
/>
@@ -132,8 +139,8 @@ export class SchemaTableCell extends React.Component<SchemaTableCellProps> {
}
get getCellType() {
- const columnTypeStr = this.props.getFinfo(this.props.fieldKey)?.fieldType;
- const cellValue = this.props.Document[this.props.fieldKey];
+ const columnTypeStr = this._props.getFinfo(this._props.fieldKey)?.fieldType;
+ const cellValue = this._props.Document[this._props.fieldKey];
if (cellValue instanceof ImageField) return ColumnType.Image;
if (cellValue instanceof DateField) return ColumnType.Date;
if (cellValue instanceof RichTextField) return ColumnType.RTF;
@@ -152,11 +159,11 @@ export class SchemaTableCell extends React.Component<SchemaTableCellProps> {
const cellType: ColumnType = this.getCellType;
// prettier-ignore
switch (cellType) {
- case ColumnType.Image: return <SchemaImageCell {...this.props} />;
- case ColumnType.Boolean: return <SchemaBoolCell {...this.props} />;
- case ColumnType.RTF: return <SchemaRTFCell {...this.props} />;
- case ColumnType.Enumeration: return <SchemaEnumerationCell {...this.props} options={this.props.getFinfo(this.props.fieldKey)?.values?.map(val => val.toString())} />;
- case ColumnType.Date: // return <SchemaDateCell {...this.props} />;
+ case ColumnType.Image: return <SchemaImageCell {...this._props} />;
+ case ColumnType.Boolean: return <SchemaBoolCell {...this._props} />;
+ case ColumnType.RTF: return <SchemaRTFCell {...this._props} />;
+ case ColumnType.Enumeration: return <SchemaEnumerationCell {...this._props} options={this._props.getFinfo(this._props.fieldKey)?.values?.map(val => val.toString())} />;
+ case ColumnType.Date: // return <SchemaDateCell {...this._props} />;
default: return this.defaultCellContent;
}
}
@@ -165,8 +172,8 @@ export class SchemaTableCell extends React.Component<SchemaTableCellProps> {
return (
<div
className="schema-table-cell"
- onPointerDown={action(e => !this.selected && this.props.selectCell(this.props.Document, this.props.col))}
- style={{ padding: this.props.padding, maxWidth: this.props.maxWidth?.(), width: this.props.columnWidth() || undefined, border: this.selected ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined }}>
+ onPointerDown={action(e => !this.selected && this._props.selectCell(this._props.Document, this._props.col))}
+ style={{ padding: this._props.padding, maxWidth: this._props.maxWidth?.(), width: this._props.columnWidth() || undefined, border: this.selected ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined }}>
{this.content}
</div>
);
@@ -175,8 +182,13 @@ export class SchemaTableCell extends React.Component<SchemaTableCellProps> {
// mj: most of this is adapted from old schema code so I'm not sure what it does tbh
@observer
-export class SchemaImageCell extends React.Component<SchemaTableCellProps> {
- @observable _previewRef: HTMLImageElement | undefined;
+export class SchemaImageCell extends ObservableReactComponent<SchemaTableCellProps> {
+ constructor(props: any) {
+ super(props);
+ makeObservable(this);
+ }
+
+ @observable _previewRef: HTMLImageElement | undefined = undefined;
choosePath(url: URL) {
if (url.protocol === 'data') return url.href; // if the url ises the data protocol, just return the href
@@ -188,8 +200,8 @@ export class SchemaImageCell extends React.Component<SchemaTableCellProps> {
}
get url() {
- const field = Cast(this.props.Document[this.props.fieldKey], ImageField, null); // retrieve the primary image URL that is being rendered from the data doc
- const alts = DocListCast(this.props.Document[this.props.fieldKey + '-alternates']); // retrieve alternate documents that may be rendered as alternate images
+ const field = Cast(this._props.Document[this._props.fieldKey], ImageField, null); // retrieve the primary image URL that is being rendered from the data doc
+ const alts = DocListCast(this._props.Document[this._props.fieldKey + '-alternates']); // retrieve alternate documents that may be rendered as alternate images
const altpaths = alts
.map(doc => Cast(doc[Doc.LayoutFieldKey(doc)], ImageField, null)?.url)
.filter(url => url)
@@ -226,10 +238,10 @@ export class SchemaImageCell extends React.Component<SchemaTableCellProps> {
};
render() {
- const aspect = Doc.NativeAspect(this.props.Document); // aspect ratio
- // let width = Math.max(75, this.props.columnWidth); // get a with that is no smaller than 75px
+ const aspect = Doc.NativeAspect(this._props.Document); // aspect ratio
+ // let width = Math.max(75, this._props.columnWidth); // get a with that is no smaller than 75px
// const height = Math.max(75, width / aspect); // get a height either proportional to that or 75 px
- const height = this.props.rowHeight() ? this.props.rowHeight() - (this.props.padding || 6) * 2 : undefined;
+ const height = this._props.rowHeight() ? this._props.rowHeight() - (this._props.padding || 6) * 2 : undefined;
const width = height ? height * aspect : undefined; // increase the width of the image if necessary to maintain proportionality
return <img src={this.url} width={width ? width : undefined} height={height} style={{}} draggable="false" onPointerEnter={this.showHoverPreview} onPointerMove={this.moveHoverPreview} onPointerLeave={this.removeHoverPreview} />;
@@ -237,22 +249,26 @@ export class SchemaImageCell extends React.Component<SchemaTableCellProps> {
}
@observer
-export class SchemaDateCell extends React.Component<SchemaTableCellProps> {
- @observable _pickingDate: boolean = false;
+export class SchemaDateCell extends ObservableReactComponent<SchemaTableCellProps> {
+ constructor(props: any) {
+ super(props);
+ makeObservable(this);
+ }
+ @observable _pickingDate: boolean = false;
@computed get date(): DateField {
// if the cell is a date field, cast then contents to a date. Otherrwwise, make the contents undefined.
- return DateCast(this.props.Document[this.props.fieldKey]);
+ return DateCast(this._props.Document[this._props.fieldKey]);
}
@action
handleChange = (date: any) => {
// const script = CompileScript(date.toString(), { requiredType: "Date", addReturn: true, params: { this: Doc.name } });
// if (script.compiled) {
- // this.applyToDoc(this._document, this.props.row, this.props.col, script.run);
+ // this.applyToDoc(this._document, this._props.row, this._props.col, script.run);
// } else {
// ^ DateCast is always undefined for some reason, but that is what the field should be set to
- this.props.Document[this.props.fieldKey] = new DateField(date as Date);
+ this._props.Document[this._props.fieldKey] = new DateField(date as Date);
//}
};
@@ -261,53 +277,64 @@ export class SchemaDateCell extends React.Component<SchemaTableCellProps> {
}
}
@observer
-export class SchemaRTFCell extends React.Component<SchemaTableCellProps> {
+export class SchemaRTFCell extends ObservableReactComponent<SchemaTableCellProps> {
+ constructor(props: any) {
+ super(props);
+ makeObservable(this);
+ }
+
@computed get selected() {
- const selected: [Doc, number] | undefined = this.props.selectedCell();
- return this.props.isRowActive() && selected?.[0] === this.props.Document && selected[1] === this.props.col;
+ const selected: [Doc, number] | undefined = this._props.selectedCell();
+ return this._props.isRowActive() && selected?.[0] === this._props.Document && selected[1] === this._props.col;
}
selectedFunc = () => this.selected;
render() {
- const { color, textDecoration, fieldProps, cursor, pointerEvents } = SchemaTableCell.renderProps(this.props);
+ const { color, textDecoration, fieldProps, cursor, pointerEvents } = SchemaTableCell.renderProps(this._props);
fieldProps.isContentActive = this.selectedFunc;
return (
<div className="schemaRTFCell" style={{ display: 'flex', fontStyle: this.selected ? undefined : 'italic', width: '100%', height: '100%', position: 'relative', color, textDecoration, cursor, pointerEvents }}>
- {this.selected ? <FormattedTextBox {...fieldProps} DataDoc={this.props.Document} /> : (field => (field ? Field.toString(field) : ''))(FieldValue(fieldProps.Document[fieldProps.fieldKey]))}
+ {this.selected ? <FormattedTextBox {...fieldProps} /> : (field => (field ? Field.toString(field) : ''))(FieldValue(fieldProps.Document[fieldProps.fieldKey]))}
</div>
);
}
}
@observer
-export class SchemaBoolCell extends React.Component<SchemaTableCellProps> {
+export class SchemaBoolCell extends ObservableReactComponent<SchemaTableCellProps> {
+ constructor(props: any) {
+ super(props);
+ makeObservable(this);
+ }
+
@computed get selected() {
- const selected: [Doc, number] | undefined = this.props.selectedCell();
- return this.props.isRowActive() && selected?.[0] === this.props.Document && selected[1] === this.props.col;
+ const selected: [Doc, number] | undefined = this._props.selectedCell();
+ return this._props.isRowActive() && selected?.[0] === this._props.Document && selected[1] === this._props.col;
}
render() {
- const { color, textDecoration, fieldProps, cursor, pointerEvents } = SchemaTableCell.renderProps(this.props);
+ const { color, textDecoration, fieldProps, cursor, pointerEvents } = SchemaTableCell.renderProps(this._props);
return (
<div className="schemaBoolCell" style={{ display: 'flex', color, textDecoration, cursor, pointerEvents }}>
<input
style={{ marginRight: 4 }}
type="checkbox"
- checked={BoolCast(this.props.Document[this.props.fieldKey])}
+ checked={BoolCast(this._props.Document[this._props.fieldKey])}
onChange={undoBatch((value: React.ChangeEvent<HTMLInputElement> | undefined) => {
if ((value?.nativeEvent as any).shiftKey) {
- this.props.setColumnValues(this.props.fieldKey.replace(/^_/, ''), (color === 'black' ? '=' : '') + value?.target?.checked.toString());
+ this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), (color === 'black' ? '=' : '') + value?.target?.checked.toString());
}
- KeyValueBox.SetField(this.props.Document, this.props.fieldKey.replace(/^_/, ''), (color === 'black' ? '=' : '') + value?.target?.checked.toString());
+ KeyValueBox.SetField(this._props.Document, this._props.fieldKey.replace(/^_/, ''), (color === 'black' ? '=' : '') + value?.target?.checked.toString());
})}
/>
<EditableView
- contents={<FieldView {...fieldProps} />}
+ contents={undefined}
+ fieldContents={fieldProps}
editing={this.selected ? undefined : false}
- GetValue={() => Field.toKeyValueString(this.props.Document, this.props.fieldKey)}
+ GetValue={() => Field.toKeyValueString(this._props.Document, this._props.fieldKey)}
SetValue={undoBatch((value: string, shiftDown?: boolean, enterKey?: boolean) => {
if (shiftDown && enterKey) {
- this.props.setColumnValues(this.props.fieldKey.replace(/^_/, ''), value);
+ this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), value);
}
- const set = KeyValueBox.SetField(this.props.Document, this.props.fieldKey.replace(/^_/, ''), value);
- this.props.finishEdit?.();
+ const set = KeyValueBox.SetField(this._props.Document, this._props.fieldKey.replace(/^_/, ''), value);
+ this._props.finishEdit?.();
return set;
})}
/>
@@ -316,14 +343,19 @@ export class SchemaBoolCell extends React.Component<SchemaTableCellProps> {
}
}
@observer
-export class SchemaEnumerationCell extends React.Component<SchemaTableCellProps> {
+export class SchemaEnumerationCell extends ObservableReactComponent<SchemaTableCellProps> {
+ constructor(props: any) {
+ super(props);
+ makeObservable(this);
+ }
+
@computed get selected() {
- const selected: [Doc, number] | undefined = this.props.selectedCell();
- return this.props.isRowActive() && selected?.[0] === this.props.Document && selected[1] === this.props.col;
+ const selected: [Doc, number] | undefined = this._props.selectedCell();
+ return this._props.isRowActive() && selected?.[0] === this._props.Document && selected[1] === this._props.col;
}
render() {
- const { color, textDecoration, fieldProps, cursor, pointerEvents } = SchemaTableCell.renderProps(this.props);
- const options = this.props.options?.map(facet => ({ value: facet, label: facet }));
+ const { color, textDecoration, fieldProps, cursor, pointerEvents } = SchemaTableCell.renderProps(this._props);
+ const options = this._props.options?.map(facet => ({ value: facet, label: facet }));
return (
<div className="schemaSelectionCell" style={{ color, textDecoration, cursor, pointerEvents }}>
<div style={{ width: '100%' }}>
@@ -357,17 +389,17 @@ export class SchemaEnumerationCell extends React.Component<SchemaTableCellProps>
...base,
left: 0,
top: 0,
- transform: `translate(${this.props.transform().TranslateX}px, ${this.props.transform().TranslateY}px)`,
- width: Number(base.width) * this.props.transform().Scale,
+ transform: `translate(${this._props.transform().TranslateX}px, ${this._props.transform().TranslateY}px)`,
+ width: Number(base.width) * this._props.transform().Scale,
zIndex: 9999,
}),
}}
- menuPortalTarget={this.props.menuTarget}
+ menuPortalTarget={this._props.menuTarget}
menuPosition={'absolute'}
- placeholder={StrCast(this.props.Document[this.props.fieldKey], 'select...')}
+ placeholder={StrCast(this._props.Document[this._props.fieldKey], 'select...')}
options={options}
isMulti={false}
- onChange={val => KeyValueBox.SetField(this.props.Document, this.props.fieldKey.replace(/^_/, ''), `"${val?.value ?? ''}"`)}
+ onChange={val => KeyValueBox.SetField(this._props.Document, this._props.fieldKey.replace(/^_/, ''), `"${val?.value ?? ''}"`)}
/>
</div>
</div>