aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormehekj <mehek.jethani@gmail.com>2023-01-28 22:38:41 -0500
committermehekj <mehek.jethani@gmail.com>2023-01-28 22:38:41 -0500
commit9d2af1180f0dd5af5ab86b922cd8b0cdfcf4ea09 (patch)
treeb5ea43352db00566b1338cd8ce4c575c4bd00a6c
parent82de335e0643f907e44cb193c9b2c6da1b3cbaf1 (diff)
checkpoint: schemarow as documentview functioning
-rw-r--r--package-lock.json39
-rw-r--r--src/client/documents/Documents.ts4
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaView.scss6
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaView.tsx129
-rw-r--r--src/client/views/collections/collectionSchema/SchemaRowBox.tsx80
-rw-r--r--src/client/views/collections/old_collectionSchema/OldCollectionSchemaCells.tsx1366
-rw-r--r--src/client/views/collections/old_collectionSchema/OldCollectionSchemaMovableColumn.tsx250
-rw-r--r--src/client/views/collections/old_collectionSchema/OldCollectionSchemaMovableRow.tsx274
-rw-r--r--src/client/views/collections/old_collectionSchema/OldCollectionSchemaView.tsx1298
-rw-r--r--src/client/views/collections/old_collectionSchema/OldSchemaTable.tsx1388
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx2
11 files changed, 2451 insertions, 2385 deletions
diff --git a/package-lock.json b/package-lock.json
index 26e7a41d7..7f93ef3c8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5303,16 +5303,6 @@
"integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=",
"dev": true
},
- "d": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
- "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
- "dev": true,
- "requires": {
- "es5-ext": "^0.10.50",
- "type": "^1.0.1"
- }
- },
"d3-array": {
"version": "2.12.1",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz",
@@ -6480,28 +6470,6 @@
"is-symbol": "^1.0.2"
}
},
- "es5-ext": {
- "version": "0.10.62",
- "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz",
- "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==",
- "dev": true,
- "requires": {
- "es6-iterator": "^2.0.3",
- "es6-symbol": "^3.1.3",
- "next-tick": "^1.1.0"
- }
- },
- "es6-iterator": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
- "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
- "dev": true,
- "requires": {
- "d": "1",
- "es5-ext": "^0.10.35",
- "es6-symbol": "^3.1.1"
- }
- },
"es6-promise": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz",
@@ -6513,7 +6481,6 @@
"integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
"dev": true,
"requires": {
- "d": "^1.0.1",
"ext": "^1.1.2"
}
},
@@ -21699,12 +21666,6 @@
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
},
- "type": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
- "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==",
- "dev": true
- },
"type-check": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 1fd07d61d..58e318879 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -1150,6 +1150,10 @@ export namespace Docs {
return InstanceFromProto(Prototypes.get(DocumentType.DATAVIZ), new CsvField(url), { title: 'Data Viz', ...options });
}
+ export function SchemaRowDocument(options?: DocumentOptions) {
+ return InstanceFromProto(Prototypes.get(DocumentType.SCHEMAROW), undefined, { ...(options || {}) });
+ }
+
export function DockDocument(documents: Array<Doc>, config: string, options: DocumentOptions, id?: string) {
return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { freezeChildren: 'remove|add', ...options, viewType: CollectionViewType.Docking, _viewType: CollectionViewType.Docking, dockingConfig: config }, id);
}
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
index 4fa5d80e2..e0d0101a2 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
@@ -126,10 +126,16 @@
}
}
+.schema-row-wrapper {
+ max-height: 70px;
+ overflow: hidden;
+}
+
.schema-header-row,
.schema-row {
display: flex;
flex-direction: row;
+ height: 100%;
max-height: 70px;
overflow: auto;
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index f7c68c803..c9f934aec 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -1,14 +1,14 @@
import React = require('react');
import { action, computed, observable, ObservableMap, ObservableSet, trace, untracked } from 'mobx';
import { observer } from 'mobx-react';
-import { Doc, DocListCast, StrListCast } from '../../../../fields/Doc';
+import { DataSym, Doc, DocListCast, Opt, StrListCast } from '../../../../fields/Doc';
import { Id } from '../../../../fields/FieldSymbols';
import { List } from '../../../../fields/List';
import { RichTextField } from '../../../../fields/RichTextField';
import { listSpec } from '../../../../fields/Schema';
-import { Cast, StrCast } from '../../../../fields/Types';
+import { BoolCast, Cast, StrCast } from '../../../../fields/Types';
import { ImageField } from '../../../../fields/URLField';
-import { emptyFunction, returnEmptyString, setupMoveUpEvents } from '../../../../Utils';
+import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, setupMoveUpEvents, smoothScroll, Utils } from '../../../../Utils';
import { Docs, DocUtils } from '../../../documents/Documents';
import { DragManager } from '../../../util/DragManager';
import { SelectionManager } from '../../../util/SelectionManager';
@@ -21,6 +21,9 @@ import { CollectionSubView } from '../CollectionSubView';
import './CollectionSchemaView.scss';
import { SchemaColumnHeader } from './SchemaColumnHeader';
import { SchemaRowBox } from './SchemaRowBox';
+import { DocFocusOptions, DocumentView, ViewAdjustment } from '../../nodes/DocumentView';
+import { DefaultStyleProvider } from '../../StyleProvider';
+import { Transform } from '../../../util/Transform';
export enum ColumnType {
Number,
@@ -40,7 +43,7 @@ export class CollectionSchemaView extends CollectionSubView() {
private _closestDropIndex: number = 0;
private _minColWidth: number = 150;
- @observable _rowMenuWidth: number = 100;
+ public static _rowMenuWidth: number = 100;
@observable _selectedDocs: ObservableSet = new ObservableSet<Doc>();
@observable _rowEles: ObservableMap = new ObservableMap<Doc, HTMLDivElement>();
@observable _isDragging: boolean = false;
@@ -69,16 +72,15 @@ export class CollectionSchemaView extends CollectionSubView() {
let widths = Cast(
this.layoutDoc.columnWidths,
listSpec('number'),
- this.columnKeys.map(() => (this.props.PanelWidth() - this._rowMenuWidth) / this.columnKeys.length)
+ this.columnKeys.map(() => (this.props.PanelWidth() - CollectionSchemaView._rowMenuWidth) / this.columnKeys.length)
);
const totalWidth = widths.reduce((sum, width) => sum + width, 0);
- if (totalWidth !== this.props.PanelWidth() - this._rowMenuWidth) {
+ if (totalWidth !== this.props.PanelWidth() - CollectionSchemaView._rowMenuWidth) {
widths = widths.map(w => {
const proportion = w / totalWidth;
- return proportion * (this.props.PanelWidth() - this._rowMenuWidth);
+ return proportion * (this.props.PanelWidth() - CollectionSchemaView._rowMenuWidth);
});
- // this.layoutDoc.columnWidths = new List<number>(widths);
}
return widths;
@@ -110,8 +112,8 @@ export class CollectionSchemaView extends CollectionSubView() {
let currWidths = [...this.storedColumnWidths];
const newColWidth = this.props.PanelWidth() / (currWidths.length + 1);
currWidths = currWidths.map(w => {
- const proportion = w / (this.props.PanelWidth() - this._rowMenuWidth);
- return proportion * (this.props.PanelWidth() - this._rowMenuWidth - newColWidth);
+ const proportion = w / (this.props.PanelWidth() - CollectionSchemaView._rowMenuWidth);
+ return proportion * (this.props.PanelWidth() - CollectionSchemaView._rowMenuWidth - newColWidth);
});
currWidths.splice(index + 1, 0, newColWidth);
this.layoutDoc.columnWidths = new List<number>(currWidths);
@@ -133,8 +135,8 @@ export class CollectionSchemaView extends CollectionSubView() {
let currWidths = [...this.storedColumnWidths];
const removedColWidth = currWidths[index];
currWidths = currWidths.map(w => {
- const proportion = w / (this.props.PanelWidth() - this._rowMenuWidth - removedColWidth);
- return proportion * (this.props.PanelWidth() - this._rowMenuWidth);
+ const proportion = w / (this.props.PanelWidth() - CollectionSchemaView._rowMenuWidth - removedColWidth);
+ return proportion * (this.props.PanelWidth() - CollectionSchemaView._rowMenuWidth);
});
currWidths.splice(index, 1);
this.layoutDoc.columnWidths = new List<number>(currWidths);
@@ -142,8 +144,6 @@ export class CollectionSchemaView extends CollectionSubView() {
let currKeys = [...this.columnKeys];
currKeys.splice(index, 1);
this.layoutDoc.columnKeys = new List<string>(currKeys);
- console.log([...this.storedColumnWidths]);
- console.log([...this.columnKeys]);
};
@action
@@ -399,6 +399,34 @@ export class CollectionSchemaView extends CollectionSubView() {
ContextMenu.Instance.displayMenu(x, y, undefined, true);
};
+ focusDocument = (doc: Doc, options: DocFocusOptions) => {
+ Doc.BrushDoc(doc);
+
+ let focusSpeed = 0;
+ const found = this._mainCont && Array.from(this._mainCont.getElementsByClassName('documentView-node')).find((node: any) => node.id === doc[Id]);
+ if (found) {
+ const top = found.getBoundingClientRect().top;
+ const localTop = this.props.ScreenToLocalTransform().transformPoint(0, top);
+ if (Math.floor(localTop[1]) !== 0) {
+ smoothScroll((focusSpeed = options.zoomTime ?? 500), this._mainCont!, localTop[1] + this._mainCont!.scrollTop, options.easeFunc);
+ }
+ }
+ const endFocus = async (moved: boolean) => options?.afterFocus?.(moved) ?? ViewAdjustment.doNothing;
+ this.props.focus(this.rootDoc, {
+ ...options,
+ afterFocus: (didFocus: boolean) => new Promise<ViewAdjustment>(res => setTimeout(async () => res(await endFocus(didFocus)), focusSpeed)),
+ });
+ };
+
+ isChildContentActive = () =>
+ this.props.isDocumentActive?.() && (this.props.childDocumentsActive?.() || BoolCast(this.rootDoc.childDocumentsActive)) ? true : this.props.childDocumentsActive?.() === false || this.rootDoc.childDocumentsActive === false ? false : undefined;
+
+ getDocTransform(doc: Doc, dref?: DocumentView) {
+ const { scale, translateX, translateY } = Utils.GetScreenTransform(dref?.ContentDiv || undefined);
+ // the document view may center its contents and if so, will prepend that onto the screenToLocalTansform. so we have to subtract that off
+ return new Transform(-translateX + (dref?.centeringX || 0), -translateY + (dref?.centeringY || 0), 1).scale(this.props.ScreenToLocalTransform().Scale);
+ }
+
render() {
return (
<div
@@ -413,7 +441,7 @@ export class CollectionSchemaView extends CollectionSubView() {
onDrop={this.onExternalDrop.bind(this)}>
<div className="schema-table">
<div className="schema-header-row">
- <div className="row-menu" style={{ width: this._rowMenuWidth }}></div>
+ <div className="row-menu" style={{ width: CollectionSchemaView._rowMenuWidth }}></div>
{this.columnKeys.map((key, index) => {
return (
<SchemaColumnHeader
@@ -432,25 +460,58 @@ export class CollectionSchemaView extends CollectionSubView() {
})}
</div>
<div className="schema-table-content">
- {this.childDocs.map((doc: Doc, index: number) => (
- <SchemaRowBox
- {...this.props}
- key={index}
- Document={doc}
- ContainingCollectionDoc={this.props.CollectionView?.props.Document}
- ContainingCollectionView={this.props.CollectionView}
- rowIndex={index}
- columnKeys={this.columnKeys}
- columnWidths={this.displayColumnWidths}
- rowMenuWidth={this._rowMenuWidth}
- selectedDocs={this._selectedDocs}
- selectRow={this.selectRow}
- startDrag={this.startDrag}
- dragging={this._isDragging}
- dropIndex={this.setDropIndex}
- addRowRef={this.addRowRef}
- />
- ))}
+ {this.childDocs.map((doc: Doc, index: number) => {
+ const dataDoc = !doc.isTemplateDoc && !doc.isTemplateForField && !doc.PARAMS ? undefined : this.props.DataDoc;
+ let dref: Opt<DocumentView>;
+
+ return (
+ <div className="schema-row-wrapper">
+ <DocumentView
+ {...this.props}
+ ref={r => (dref = r || undefined)}
+ LayoutTemplate={this.props.childLayoutTemplate}
+ LayoutTemplateString={SchemaRowBox.LayoutString(this.props.fieldKey)}
+ renderDepth={this.props.renderDepth + 1}
+ Document={doc}
+ DataDoc={dataDoc}
+ ContainingCollectionView={this.props.CollectionView}
+ ContainingCollectionDoc={this.Document}
+ PanelWidth={this.props.PanelWidth}
+ PanelHeight={() => 70}
+ styleProvider={DefaultStyleProvider}
+ focus={this.focusDocument}
+ docFilters={this.childDocFilters}
+ docRangeFilters={this.childDocRangeFilters}
+ searchFilterDocs={this.searchFilterDocs}
+ rootSelected={this.rootSelected}
+ ScreenToLocalTransform={() => this.getDocTransform(doc, dref)}
+ bringToFront={emptyFunction}
+ isContentActive={this.isChildContentActive}
+ hideDecorations={true}
+ hideTitle={true}
+ hideDocumentButtonBar={true}
+ />
+ </div>
+ );
+
+ // <SchemaRowBox
+ // {...this.props}
+ // key={index}
+ // Document={doc}
+ // ContainingCollectionDoc={this.props.CollectionView?.props.Document}
+ // ContainingCollectionView={this.props.CollectionView}
+ // rowIndex={index}
+ // columnKeys={this.columnKeys}
+ // columnWidths={this.displayColumnWidths}
+ // rowMenuWidth={CollectionSchemaView._rowMenuWidth}
+ // selectedDocs={this._selectedDocs}
+ // selectRow={this.selectRow}
+ // startDrag={this.startDrag}
+ // dragging={this._isDragging}
+ // dropIndex={this.setDropIndex}
+ // addRowRef={this.addRowRef}
+ // />
+ })}
</div>
</div>
<EditableView GetValue={returnEmptyString} SetValue={this.addNewTextDoc} placeholder={"Type ':' for commands"} contents={'+ New Node'} menuCallback={this.menuCallback} />
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 5c1f32565..f790e9dbf 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -1,8 +1,8 @@
import React = require('react');
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, ObservableMap, ObservableSet } from 'mobx';
+import { action, computed, ObservableMap, ObservableSet } from 'mobx';
import { observer } from 'mobx-react';
-import { Doc } from '../../../../fields/Doc';
+import { Doc, StrListCast } from '../../../../fields/Doc';
import { undoBatch } from '../../../util/UndoManager';
import { ViewBoxBaseComponent } from '../../DocComponent';
import { Colors } from '../../global/globalEnums';
@@ -11,6 +11,10 @@ import './CollectionSchemaView.scss';
import { SchemaTableCell } from './SchemaTableCell';
import { emptyFunction, setupMoveUpEvents } from '../../../../Utils';
import { DragManager } from '../../../util/DragManager';
+import { OpenWhere } from '../../nodes/DocumentView';
+import { Cast } from '../../../../fields/Types';
+import { listSpec } from '../../../../fields/Schema';
+import { CollectionSchemaView } from './CollectionSchemaView';
export interface SchemaRowBoxProps extends FieldViewProps {
rowIndex: number;
@@ -26,40 +30,61 @@ export interface SchemaRowBoxProps extends FieldViewProps {
}
@observer
-export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
+export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps>() {
public static LayoutString(fieldKey: string) {
return FieldView.LayoutString(SchemaRowBox, fieldKey);
}
private _ref: HTMLDivElement | null = null;
- isSelected = () => this.props.selectedDocs.has(this.props.Document);
bounds = () => this._ref?.getBoundingClientRect();
+ @computed get columnKeys() {
+ return StrListCast(this.props.ContainingCollectionDoc?.columnKeys);
+ }
+
+ @computed get storedColumnWidths() {
+ let widths = Cast(
+ this.props.ContainingCollectionDoc?.columnWidths,
+ listSpec('number'),
+ this.columnKeys.map(() => (this.props.PanelWidth() - CollectionSchemaView._rowMenuWidth) / this.columnKeys.length)
+ );
+
+ const totalWidth = widths.reduce((sum, width) => sum + width, 0);
+ if (totalWidth !== this.props.PanelWidth() - CollectionSchemaView._rowMenuWidth) {
+ widths = widths.map(w => {
+ const proportion = w / totalWidth;
+ return proportion * (this.props.PanelWidth() - CollectionSchemaView._rowMenuWidth);
+ });
+ }
+
+ return widths;
+ }
+
@action
onRowPointerDown = (e: React.PointerEvent) => {
e.stopPropagation();
- setupMoveUpEvents(
- this,
- e,
- e => this.props.startDrag(e, this.props.Document, this._ref!, this.props.rowIndex),
- emptyFunction,
- e => this.props.selectRow(e, this.props.Document, this._ref!, this.props.rowIndex)
- );
+ // setupMoveUpEvents(
+ // this,
+ // e,
+ // e => this.props.startDrag(e, this.props.Document, this._ref!, this.props.rowIndex),
+ // emptyFunction,
+ // e => this.props.selectRow(e, this.props.Document, this._ref!, this.props.rowIndex)
+ // );
};
onPointerEnter = (e: any) => {
- if (!this.props.dragging) return;
+ // if (!this.props.dragging) return;
document.removeEventListener('pointermove', this.onPointerMove);
document.addEventListener('pointermove', this.onPointerMove);
};
onPointerMove = (e: any) => {
- if (!this.props.dragging) return;
+ // if (!this.props.dragging) return;
let dragIsRow: boolean = true;
DragManager.docsBeingDragged.forEach(doc => {
- dragIsRow = this.props.selectedDocs.has(doc);
+ // dragIsRow = this.props.selectedDocs.has(doc);
});
if (this._ref && dragIsRow) {
const rect = this._ref.getBoundingClientRect();
@@ -69,11 +94,11 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
if (y <= halfLine) {
this._ref.style.borderTop = `solid 2px ${Colors.MEDIUM_BLUE}`;
this._ref.style.borderBottom = '0px';
- this.props.dropIndex(this.props.rowIndex);
+ // this.props.dropIndex(this.props.rowIndex);
} else if (y > halfLine) {
this._ref.style.borderTop = '0px';
this._ref.style.borderBottom = `solid 2px ${Colors.MEDIUM_BLUE}`;
- this.props.dropIndex(this.props.rowIndex + 1);
+ // this.props.dropIndex(this.props.rowIndex + 1);
}
}
};
@@ -90,15 +115,22 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
return (
<div
className="schema-row"
- style={this.isSelected() ? { backgroundColor: Colors.LIGHT_BLUE, opacity: this.props.dragging ? 0.5 : 1 } : {}}
- onPointerDown={this.onRowPointerDown}
- onPointerEnter={this.onPointerEnter}
+ style={this.props.isSelected() ? { backgroundColor: Colors.LIGHT_BLUE } : {}}
+ // style={this.isSelected() ? { backgroundColor: Colors.LIGHT_BLUE, opacity: this.props.dragging ? 0.5 : 1 } : {}}
+ // onPointerDown={this.onRowPointerDown}
+ // onPointerEnter={this.onPointerEnter}
onPointerLeave={this.onPointerLeave}
ref={(row: HTMLDivElement | null) => {
- row && this.props.addRowRef(this.props.Document, row);
+ // row && this.props.addRowRef(this.props.Document, row);
this._ref = row;
}}>
- <div className="row-menu" style={{ width: this.props.rowMenuWidth }}>
+ <div
+ className="row-menu"
+ style={
+ {
+ /* width: this.props.rowMenuWidth */
+ }
+ }>
<div
className="schema-row-button"
onPointerDown={undoBatch(e => {
@@ -111,14 +143,14 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
className="schema-row-button"
onPointerDown={e => {
e.stopPropagation();
- this.props.addDocTab(this.props.Document, 'add:right');
+ this.props.addDocTab(this.props.Document, OpenWhere.addRight);
}}>
<FontAwesomeIcon icon="external-link-alt" />
</div>
</div>
<div className="row-cells">
- {this.props.columnKeys.map((key, index) => (
- <SchemaTableCell key={key} Document={this.props.Document} fieldKey={key} columnWidth={this.props.columnWidths[index]} />
+ {this.columnKeys.map((key, index) => (
+ <SchemaTableCell key={key} Document={this.props.Document} fieldKey={key} columnWidth={this.storedColumnWidths[index]} />
))}
</div>
</div>
diff --git a/src/client/views/collections/old_collectionSchema/OldCollectionSchemaCells.tsx b/src/client/views/collections/old_collectionSchema/OldCollectionSchemaCells.tsx
index 97a6c5c18..5953f85ad 100644
--- a/src/client/views/collections/old_collectionSchema/OldCollectionSchemaCells.tsx
+++ b/src/client/views/collections/old_collectionSchema/OldCollectionSchemaCells.tsx
@@ -1,683 +1,683 @@
-import React = require('react');
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, observable } from 'mobx';
-import { observer } from 'mobx-react';
-import { extname } from 'path';
-import DatePicker from 'react-datepicker';
-import { CellInfo } from 'react-table';
-import { DateField } from '../../../../fields/DateField';
-import { Doc, DocListCast, Field, Opt } from '../../../../fields/Doc';
-import { Id } from '../../../../fields/FieldSymbols';
-import { List } from '../../../../fields/List';
-import { SchemaHeaderField } from '../../../../fields/SchemaHeaderField';
-import { ComputedField } from '../../../../fields/ScriptField';
-import { BoolCast, Cast, DateCast, FieldValue, StrCast } from '../../../../fields/Types';
-import { ImageField } from '../../../../fields/URLField';
-import { emptyFunction, Utils } from '../../../../Utils';
-import { Docs } from '../../../documents/Documents';
-import { DocumentType } from '../../../documents/DocumentTypes';
-import { DocumentManager } from '../../../util/DocumentManager';
-import { DragManager } from '../../../util/DragManager';
-import { KeyCodes } from '../../../util/KeyCodes';
-import { CompileScript } from '../../../util/Scripting';
-import { SearchUtil } from '../../../util/SearchUtil';
-import { SnappingManager } from '../../../util/SnappingManager';
-import { undoBatch } from '../../../util/UndoManager';
-import '../../../views/DocumentDecorations.scss';
-import { EditableView } from '../../EditableView';
-import { MAX_ROW_HEIGHT } from '../../global/globalCssVariables.scss';
-import { DocumentIconContainer } from '../../nodes/DocumentIcon';
-import { OverlayView } from '../../OverlayView';
-import { CollectionView } from '../CollectionView';
-import './CollectionSchemaView.scss';
-import { OpenWhere } from '../../nodes/DocumentView';
-import { PinProps } from '../../nodes/trails';
-
-// intialize cell properties
-export interface CellProps {
- row: number;
- col: number;
- rowProps: CellInfo;
- // currently unused
- CollectionView: Opt<CollectionView>;
- // currently unused
- ContainingCollection: Opt<CollectionView>;
- Document: Doc;
- // column name
- fieldKey: string;
- // currently unused
- renderDepth: number;
- // called when a button is pressed on the node itself
- addDocTab: (document: Doc, where: OpenWhere) => boolean;
- pinToPres: (document: Doc, pinProps: PinProps) => void;
- moveDocument?: (document: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => boolean;
- isFocused: boolean;
- changeFocusedCellByIndex: (row: number, col: number) => void;
- // set whether the cell is in the isEditing mode
- setIsEditing: (isEditing: boolean) => void;
- isEditable: boolean;
- setPreviewDoc: (doc: Doc) => void;
- setComputed: (script: string, doc: Doc, field: string, row: number, col: number) => boolean;
- getField: (row: number, col?: number) => void;
- // currnetly unused
- showDoc: (doc: Doc | undefined, dataDoc?: any, screenX?: number, screenY?: number) => void;
-}
-
-@observer
-export class CollectionSchemaCell extends React.Component<CellProps> {
- // return a field key that is corrected for whether it COMMENT
- public static resolvedFieldKey(column: string, rowDoc: Doc) {
- const fieldKey = column;
- if (fieldKey.startsWith('*')) {
- const rootKey = fieldKey.substring(1);
- const allKeys = [...Array.from(Object.keys(rowDoc)), ...Array.from(Object.keys(Doc.GetProto(rowDoc)))];
- const matchedKeys = allKeys.filter(key => key.includes(rootKey));
- if (matchedKeys.length) return matchedKeys[0];
- }
- return fieldKey;
- }
- @observable protected _isEditing: boolean = false;
- protected _focusRef = React.createRef<HTMLDivElement>();
- protected _rowDoc = this.props.rowProps.original;
- // Gets the serialized data in proto form of the base proto that this document's proto inherits from
- protected _rowDataDoc = Doc.GetProto(this.props.rowProps.original);
- // methods for dragging and dropping
- protected _dropDisposer?: DragManager.DragDropDisposer;
- @observable contents: string = '';
-
- componentDidMount() {
- document.addEventListener('keydown', this.onKeyDown);
- }
- componentWillUnmount() {
- document.removeEventListener('keydown', this.onKeyDown);
- }
-
- @action
- onKeyDown = (e: KeyboardEvent): void => {
- // If a cell is editable and clicked, hitting enter shoudl allow the user to edit it
- if (this.props.isFocused && this.props.isEditable && e.keyCode === KeyCodes.ENTER) {
- document.removeEventListener('keydown', this.onKeyDown);
- this._isEditing = true;
- this.props.setIsEditing(true);
- }
- };
-
- @action
- isEditingCallback = (isEditing: boolean): void => {
- // a general method that takes a boolean that determines whether the cell should be in
- // is-editing mode
- // remove the event listener if it's there
- document.removeEventListener('keydown', this.onKeyDown);
- // it's not already in is-editing mode, re-add the event listener
- isEditing && document.addEventListener('keydown', this.onKeyDown);
- this._isEditing = isEditing;
- this.props.setIsEditing(isEditing);
- this.props.changeFocusedCellByIndex(this.props.row, this.props.col);
- };
-
- @action
- onPointerDown = async (e: React.PointerEvent): Promise<void> => {
- // pan to the cell
- this.onItemDown(e);
- // focus on it
- this.props.changeFocusedCellByIndex(this.props.row, this.props.col);
- this.props.setPreviewDoc(this.props.rowProps.original);
-
- let url: string;
- if ((url = StrCast(this.props.rowProps.row.href))) {
- // opens up the the doc in a new window, blurring the old one
- try {
- new URL(url);
- const temp = window.open(url)!;
- temp.blur();
- window.focus();
- } catch {}
- }
-
- const doc = Cast(this._rowDoc[this.renderFieldKey], Doc, null);
- doc && this.props.setPreviewDoc(doc);
- };
-
- @undoBatch
- applyToDoc = (doc: Doc, row: number, col: number, run: (args?: { [name: string]: any }) => any) => {
- // apply a specified change to the cell
- const res = run({ this: doc, $r: row, $c: col, $: (r: number = 0, c: number = 0) => this.props.getField(r + row, c + col) });
- if (!res.success) return false;
- // change what is rendered to this new changed cell content
- doc[this.renderFieldKey] = res.result;
- return true;
- // return whether the change was successful
- };
-
- private drop = (e: Event, de: DragManager.DropEvent) => {
- // if the drag has data at its completion
- if (de.complete.docDragData) {
- // if only one doc was dragged
- if (de.complete.docDragData.draggedDocuments.length === 1) {
- // update the renderFieldKey
- this._rowDataDoc[this.renderFieldKey] = de.complete.docDragData.draggedDocuments[0];
- } else {
- // create schema document reflecting the new column arrangement
- const coll = Docs.Create.SchemaDocument([new SchemaHeaderField('title', '#f1efeb')], de.complete.docDragData.draggedDocuments, {});
- this._rowDataDoc[this.renderFieldKey] = coll;
- }
- e.stopPropagation();
- }
- };
-
- protected dropRef = (ele: HTMLElement | null) => {
- // if the drop disposer is not undefined, run its function
- this._dropDisposer?.();
- // if ele is not null, give ele a non-undefined drop disposer
- ele && (this._dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this)));
- };
-
- returnHighlights(contents: string, positions?: number[]) {
- if (positions) {
- const results = [];
- StrCast(this.props.Document._searchString);
- const length = StrCast(this.props.Document._searchString).length;
- const color = contents ? 'black' : 'grey';
-
- results.push(
- <span key="-1" style={{ color }}>
- {contents?.slice(0, positions[0])}
- </span>
- );
- positions.forEach((num, cur) => {
- results.push(
- <span key={'start' + cur} style={{ backgroundColor: '#FFFF00', color }}>
- {contents?.slice(num, num + length)}
- </span>
- );
- let end = 0;
- cur === positions.length - 1 ? (end = contents.length) : (end = positions[cur + 1]);
- results.push(
- <span key={'end' + cur} style={{ color }}>
- {contents?.slice(num + length, end)}
- </span>
- );
- });
- return results;
- }
- return <span style={{ color: contents ? 'black' : 'grey' }}>{contents ? contents?.valueOf() : 'undefined'}</span>;
- }
-
- @computed get renderFieldKey() {
- // gets the resolved field key of this cell
- return CollectionSchemaCell.resolvedFieldKey(this.props.rowProps.column.id!, this.props.rowProps.original);
- }
-
- onItemDown = async (e: React.PointerEvent) => {
- // if the document is a document used to change UI for search results in schema view
- if (this.props.Document._searchDoc) {
- const aliasdoc = await SearchUtil.GetAliasesOfDocument(this._rowDataDoc);
- const targetContext = aliasdoc.length <= 0 ? undefined : Cast(aliasdoc[0].context, Doc, null);
- // Jump to the this document
- DocumentManager.Instance.jumpToDocument(this._rowDoc, { willPan: true }, emptyFunction, targetContext ? [targetContext] : [], () => this.props.setPreviewDoc(this._rowDoc));
- }
- };
-
- renderCellWithType(type: string | undefined) {
- const dragRef: React.RefObject<HTMLDivElement> = React.createRef();
-
- // the column
- const fieldKey = this.renderFieldKey;
- // the exact cell
- const field = this._rowDoc[fieldKey];
-
- const onPointerEnter = (e: React.PointerEvent): void => {
- // e.buttons === 1 means the left moue pointer is down
- if (e.buttons === 1 && SnappingManager.GetIsDragging() && (type === 'document' || type === undefined)) {
- dragRef.current!.className = 'collectionSchemaView-cellContainer doc-drag-over';
- }
- };
- const onPointerLeave = (e: React.PointerEvent): void => {
- // change the class name to indicate that the cell is no longer being dragged
- dragRef.current!.className = 'collectionSchemaView-cellContainer';
- };
-
- let contents = Field.toString(field as Field);
- // display 2 hyphens instead of a blank box for empty cells
- contents = contents === '' ? '--' : contents;
-
- // classname reflects the tatus of the cell
- let className = 'collectionSchemaView-cellWrapper';
- if (this._isEditing) className += ' editing';
- if (this.props.isFocused && this.props.isEditable) className += ' focused';
- if (this.props.isFocused && !this.props.isEditable) className += ' inactive';
-
- const positions = [];
- if (StrCast(this.props.Document._searchString).toLowerCase() !== '') {
- // term is ...promise pending... if the field is a Promise, otherwise it is the cell's contents
- let term = field instanceof Promise ? '...promise pending...' : contents.toLowerCase();
- const search = StrCast(this.props.Document._searchString).toLowerCase();
- let start = term.indexOf(search);
- let tally = 0;
- // if search is found in term
- if (start !== -1) {
- positions.push(start);
- }
- // if search is found in term, continue finding all instances of search in term
- while (start < contents?.length && start !== -1) {
- term = term.slice(start + search.length + 1);
- tally += start + search.length + 1;
- start = term.indexOf(search);
- positions.push(tally + start);
- }
- // remove the last position
- if (positions.length > 1) {
- positions.pop();
- }
- }
- const placeholder = type === 'number' ? '0' : contents === '' ? '--' : 'undefined';
- return (
- <div
- className="collectionSchemaView-cellContainer"
- style={{ cursor: field instanceof Doc ? 'grab' : 'auto' }}
- ref={dragRef}
- onPointerDown={this.onPointerDown}
- onClick={action(e => (this._isEditing = true))}
- onPointerEnter={onPointerEnter}
- onPointerLeave={onPointerLeave}>
- <div className={className} ref={this._focusRef} tabIndex={-1}>
- <div className="collectionSchemaView-cellContents" ref={type === undefined || type === 'document' ? this.dropRef : null}>
- {!this.props.Document._searchDoc ? (
- <EditableView
- editing={this._isEditing}
- isEditingCallback={this.isEditingCallback}
- display={'inline'}
- contents={contents}
- height={'auto'}
- maxHeight={Number(MAX_ROW_HEIGHT)}
- placeholder={placeholder}
- GetValue={() => {
- const cfield = ComputedField.WithoutComputed(() => FieldValue(field));
- const cscript = cfield instanceof ComputedField ? cfield.script.originalScript : undefined;
- const cfinalScript = cscript?.split('return')[cscript.split('return').length - 1];
- return cscript ? (cfinalScript?.endsWith(';') ? `:=${cfinalScript?.substring(0, cfinalScript.length - 2)}` : cfinalScript) : Field.IsField(cfield) ? Field.toScriptString(cfield) : '';
- }}
- SetValue={action((value: string) => {
- // sets what is displayed after the user makes an input
- let retVal = false;
- if (value.startsWith(':=') || value.startsWith('=:=')) {
- // decides how to compute a value when given either of the above strings
- const script = value.substring(value.startsWith('=:=') ? 3 : 2);
- retVal = this.props.setComputed(script, value.startsWith(':=') ? this._rowDataDoc : this._rowDoc, this.renderFieldKey, this.props.row, this.props.col);
- } else {
- // check if the input is a number
- let inputIsNum = true;
- for (const s of value) {
- if (isNaN(parseInt(s)) && !(s === '.') && !(s === ',')) {
- inputIsNum = false;
- }
- }
- // check if the input is a boolean
- const inputIsBool: boolean = value === 'false' || value === 'true';
- // what to do in the case
- if (!inputIsNum && !inputIsBool && !value.startsWith('=')) {
- // if it's not a number, it's a string, and should be processed as such
- // strips the string of quotes when it is edited to prevent quotes form being added to the text automatically
- // after each edit
- let valueSansQuotes = value;
- if (this._isEditing) {
- const vsqLength = valueSansQuotes.length;
- // get rid of outer quotes
- valueSansQuotes = valueSansQuotes.substring(value.startsWith('"') ? 1 : 0, valueSansQuotes.charAt(vsqLength - 1) === '"' ? vsqLength - 1 : vsqLength);
- }
- let inputAsString = '"';
- // escape any quotes in the string
- for (const i of valueSansQuotes) {
- if (i === '"') {
- inputAsString += '\\"';
- } else {
- inputAsString += i;
- }
- }
- // add a closing quote
- inputAsString += '"';
- //two options here: we can strip off outer quotes or we can figure out what's going on with the script
- const script = CompileScript(inputAsString, { requiredType: type, typecheck: false, editable: true, addReturn: true, params: { this: Doc.name, $r: 'number', $c: 'number', $: 'any' } });
- const changeMade = inputAsString.length !== value.length || inputAsString.length - 2 !== value.length;
- // change it if a change is made, otherwise, just compile using the old cell conetnts
- script.compiled && (retVal = this.applyToDoc(changeMade ? this._rowDoc : this._rowDataDoc, this.props.row, this.props.col, script.run));
- // handle numbers and expressions
- } else if (inputIsNum || value.startsWith('=')) {
- //TODO: make accept numbers
- const inputscript = value.substring(value.startsWith('=') ? 1 : 0);
- // if commas are not stripped, the parser only considers the numbers after the last comma
- let inputSansCommas = '';
- for (const s of inputscript) {
- if (!(s === ',')) {
- inputSansCommas += s;
- }
- }
- const script = CompileScript(inputSansCommas, { requiredType: type, typecheck: false, editable: true, addReturn: true, params: { this: Doc.name, $r: 'number', $c: 'number', $: 'any' } });
- const changeMade = value.length - 2 !== value.length;
- script.compiled && (retVal = this.applyToDoc(changeMade ? this._rowDoc : this._rowDataDoc, this.props.row, this.props.col, script.run));
- // handle booleans
- } else if (inputIsBool) {
- const script = CompileScript(value, { requiredType: type, typecheck: false, editable: true, addReturn: true, params: { this: Doc.name, $r: 'number', $c: 'number', $: 'any' } });
- const changeMade = value.length - 2 !== value.length;
- script.compiled && (retVal = this.applyToDoc(changeMade ? this._rowDoc : this._rowDataDoc, this.props.row, this.props.col, script.run));
- }
- }
- if (retVal) {
- this._isEditing = false; // need to set this here. otherwise, the assignment of the field will invalidate & cause render() to be called with the wrong value for 'editing'
- this.props.setIsEditing(false);
- }
- return retVal;
- })}
- OnFillDown={async (value: string) => {
- // computes all of the value preceded by :=
- const script = CompileScript(value, { requiredType: type, typecheck: false, editable: true, addReturn: true, params: { this: Doc.name, $r: 'number', $c: 'number', $: 'any' } });
- script.compiled &&
- DocListCast(this.props.Document[this.props.fieldKey]).forEach((doc, i) =>
- value.startsWith(':=') ? this.props.setComputed(value.substring(2), Doc.GetProto(doc), this.renderFieldKey, i, this.props.col) : this.applyToDoc(Doc.GetProto(doc), i, this.props.col, script.run)
- );
- }}
- />
- ) : (
- this.returnHighlights(contents, positions)
- )}
- </div>
- </div>
- </div>
- );
- }
-
- render() {
- return this.renderCellWithType(undefined);
- }
-}
-
-@observer
-export class CollectionSchemaNumberCell extends CollectionSchemaCell {
- render() {
- return this.renderCellWithType('number');
- }
-}
-
-@observer
-export class CollectionSchemaBooleanCell extends CollectionSchemaCell {
- render() {
- return this.renderCellWithType('boolean');
- }
-}
-
-@observer
-export class CollectionSchemaStringCell extends CollectionSchemaCell {
- render() {
- return this.renderCellWithType('string');
- }
-}
-
-@observer
-export class CollectionSchemaDateCell extends CollectionSchemaCell {
- @computed get _date(): Opt<DateField> {
- // if the cell is a date field, cast then contents to a date. Otherrwwise, make the contents undefined.
- return this._rowDoc[this.renderFieldKey] instanceof DateField ? DateCast(this._rowDoc[this.renderFieldKey]) : undefined;
- }
-
- @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);
- // } else {
- // ^ DateCast is always undefined for some reason, but that is what the field should be set to
- this._rowDoc[this.renderFieldKey] = new DateField(date as Date);
- //}
- };
-
- render() {
- return !this.props.isFocused ? (
- <span onPointerDown={this.onPointerDown}>{this._date ? Field.toString(this._date as Field) : '--'}</span>
- ) : (
- <DatePicker selected={this._date?.date || new Date()} onSelect={date => this.handleChange(date)} onChange={date => this.handleChange(date)} />
- );
- }
-}
-
-@observer
-export class CollectionSchemaDocCell extends CollectionSchemaCell {
- _overlayDisposer?: () => void;
-
- @computed get _doc() {
- return FieldValue(Cast(this._rowDoc[this.renderFieldKey], Doc));
- }
-
- @action
- onSetValue = (value: string) => {
- this._doc && (Doc.GetProto(this._doc).title = value);
-
- const script = CompileScript(value, {
- addReturn: true,
- typecheck: true,
- transformer: DocumentIconContainer.getTransformer(),
- });
- // compile the script
- const results = script.compiled && script.run();
- // if the script was compiled and run
- if (results && results.success) {
- this._rowDoc[this.renderFieldKey] = results.result;
- return true;
- }
- return false;
- };
-
- componentWillUnmount() {
- this.onBlur();
- }
-
- onBlur = () => {
- this._overlayDisposer?.();
- };
- onFocus = () => {
- this.onBlur();
- this._overlayDisposer = OverlayView.Instance.addElement(<DocumentIconContainer />, { x: 0, y: 0 });
- };
-
- @action
- isEditingCallback = (isEditing: boolean): void => {
- // the isEditingCallback from a general CollectionSchemaCell
- document.removeEventListener('keydown', this.onKeyDown);
- isEditing && document.addEventListener('keydown', this.onKeyDown);
- this._isEditing = isEditing;
- this.props.setIsEditing(isEditing);
- this.props.changeFocusedCellByIndex(this.props.row, this.props.col);
- };
-
- render() {
- // if there's a doc, render it
- return !this._doc ? (
- this.renderCellWithType('document')
- ) : (
- <div className="collectionSchemaView-cellWrapper" ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}>
- <div className="collectionSchemaView-cellContents-document" style={{ padding: '5.9px' }} ref={this.dropRef} onFocus={this.onFocus} onBlur={this.onBlur}>
- <EditableView
- editing={this._isEditing}
- isEditingCallback={this.isEditingCallback}
- display={'inline'}
- contents={this._doc.title || '--'}
- height={'auto'}
- maxHeight={Number(MAX_ROW_HEIGHT)}
- GetValue={() => StrCast(this._doc?.title)}
- SetValue={action((value: string) => {
- this.onSetValue(value);
- return true;
- })}
- />
- </div>
- <div onClick={() => this._doc && this.props.addDocTab(this._doc, OpenWhere.addRight)} className="collectionSchemaView-cellContents-docButton">
- <FontAwesomeIcon icon="external-link-alt" size="lg" />
- </div>
- </div>
- );
- }
-}
-
-@observer
-export class CollectionSchemaImageCell extends CollectionSchemaCell {
- choosePath(url: URL) {
- if (url.protocol === 'data') return url.href; // if the url ises the data protocol, just return the href
- if (url.href.indexOf(window.location.origin) === -1) return Utils.CorsProxy(url.href); // otherwise, put it through the cors proxy erver
- if (!/\.(png|jpg|jpeg|gif|webp)$/.test(url.href.toLowerCase())) return url.href; //Why is this here — good question
-
- const ext = extname(url.href);
- return url.href.replace(ext, '_o' + ext);
- }
-
- render() {
- const field = Cast(this._rowDoc[this.renderFieldKey], ImageField, null); // retrieve the primary image URL that is being rendered from the data doc
- const alts = DocListCast(this._rowDoc[this.renderFieldKey + '-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)
- .map(url => this.choosePath(url)); // access the primary layout data of the alternate documents
- const paths = field ? [this.choosePath(field.url), ...altpaths] : altpaths;
- // If there is a path, follow it; otherwise, follow a link to a default image icon
- const url = paths.length ? paths : [Utils.CorsProxy('http://www.cs.brown.edu/~bcz/noImage.png')];
-
- const aspect = Doc.NativeAspect(this._rowDoc); // aspect ratio
- let width = Math.min(75, this.props.rowProps.width); // get a with that is no smaller than 75px
- const height = Math.min(75, width / aspect); // get a height either proportional to that or 75 px
- width = height * aspect; // increase the width of the image if necessary to maintain proportionality
-
- const reference = React.createRef<HTMLDivElement>();
- return (
- <div className="collectionSchemaView-cellWrapper" ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}>
- <div className="collectionSchemaView-cellContents" key={this._rowDoc[Id]} ref={reference}>
- <img src={url[0]} width={paths.length ? width : '20px'} height={paths.length ? height : '20px'} />
- </div>
- </div>
- );
- }
-}
-
-@observer
-export class CollectionSchemaListCell extends CollectionSchemaCell {
- _overlayDisposer?: () => void;
-
- @computed get _field() {
- return this._rowDoc[this.renderFieldKey];
- }
- @computed get _optionsList() {
- return this._field as List<any>;
- }
- @observable private _opened = false; // whether the list is opened
- @observable private _text = 'select an item';
- @observable private _selectedNum = 0; // the index of the list item selected
-
- @action
- onSetValue = (value: string) => {
- // change if it's a document
- this._optionsList[this._selectedNum] = this._text = value;
-
- (this._field as List<any>).splice(this._selectedNum, 1, value);
- };
-
- @action
- onSelected = (element: string, index: number) => {
- // if an item is selected, the private variables should update to reflect this
- this._text = element;
- this._selectedNum = index;
- };
-
- onFocus = () => {
- this._overlayDisposer?.();
- this._overlayDisposer = OverlayView.Instance.addElement(<DocumentIconContainer />, { x: 0, y: 0 });
- };
-
- render() {
- const link = false;
- const reference = React.createRef<HTMLDivElement>();
-
- // if the list is not opened, don't display it; otherwise, do.
- if (this._optionsList?.length) {
- const options = !this._opened ? null : (
- <div>
- {this._optionsList.map((element, index) => {
- const val = Field.toString(element);
- return (
- <div className="collectionSchemaView-dropdownOption" key={index} style={{ padding: '6px' }} onPointerDown={e => this.onSelected(StrCast(element), index)}>
- {val}
- </div>
- );
- })}
- </div>
- );
-
- const plainText = <div style={{ padding: '5.9px' }}>{this._text}</div>;
- const textarea = (
- <div className="collectionSchemaView-cellContents" key={this._rowDoc[Id]} style={{ padding: '5.9px' }} ref={this.dropRef}>
- <EditableView
- editing={this._isEditing}
- isEditingCallback={this.isEditingCallback}
- display={'inline'}
- contents={this._text}
- height={'auto'}
- maxHeight={Number(MAX_ROW_HEIGHT)}
- GetValue={() => this._text}
- SetValue={action((value: string) => {
- // add special for params
- this.onSetValue(value);
- return true;
- })}
- />
- </div>
- );
-
- //☰
- return (
- <div className="collectionSchemaView-cellWrapper" ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}>
- <div className="collectionSchemaView-cellContents" key={this._rowDoc[Id]} ref={reference}>
- <div className="collectionSchemaView-dropDownWrapper">
- <button type="button" className="collectionSchemaView-dropdownButton" style={{ right: 'length', position: 'relative' }} onClick={action(e => (this._opened = !this._opened))}>
- <FontAwesomeIcon icon={this._opened ? 'caret-up' : 'caret-down'} size="sm" />
- </button>
- <div className="collectionSchemaView-dropdownText"> {link ? plainText : textarea} </div>
- </div>
- {options}
- </div>
- </div>
- );
- }
- return this.renderCellWithType('list');
- }
-}
-
-@observer
-export class CollectionSchemaCheckboxCell extends CollectionSchemaCell {
- @computed get _isChecked() {
- return BoolCast(this._rowDoc[this.renderFieldKey]);
- }
-
- render() {
- const reference = React.createRef<HTMLDivElement>();
- return (
- <div className="collectionSchemaView-cellWrapper" ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}>
- <input type="checkbox" checked={this._isChecked} onChange={e => (this._rowDoc[this.renderFieldKey] = e.target.checked)} />
- </div>
- );
- }
-}
-
-@observer
-export class CollectionSchemaButtons extends CollectionSchemaCell {
- // the navigation buttons for schema view when it is used for search.
- render() {
- return !this.props.Document._searchDoc || ![DocumentType.PDF, DocumentType.RTF].includes(StrCast(this._rowDoc.type) as DocumentType) ? (
- <></>
- ) : (
- <div style={{ paddingTop: 8, paddingLeft: 3 }}>
- <button style={{ padding: 2, left: 77 }} onClick={() => Doc.SearchMatchNext(this._rowDoc, true)}>
- <FontAwesomeIcon icon="arrow-up" size="sm" />
- </button>
- <button style={{ padding: 2 }} onClick={() => Doc.SearchMatchNext(this._rowDoc, false)}>
- <FontAwesomeIcon icon="arrow-down" size="sm" />
- </button>
- </div>
- );
- }
-}
+// import React = require('react');
+// import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+// import { action, computed, observable } from 'mobx';
+// import { observer } from 'mobx-react';
+// import { extname } from 'path';
+// import DatePicker from 'react-datepicker';
+// import { CellInfo } from 'react-table';
+// import { DateField } from '../../../../fields/DateField';
+// import { Doc, DocListCast, Field, Opt } from '../../../../fields/Doc';
+// import { Id } from '../../../../fields/FieldSymbols';
+// import { List } from '../../../../fields/List';
+// import { SchemaHeaderField } from '../../../../fields/SchemaHeaderField';
+// import { ComputedField } from '../../../../fields/ScriptField';
+// import { BoolCast, Cast, DateCast, FieldValue, StrCast } from '../../../../fields/Types';
+// import { ImageField } from '../../../../fields/URLField';
+// import { emptyFunction, Utils } from '../../../../Utils';
+// import { Docs } from '../../../documents/Documents';
+// import { DocumentType } from '../../../documents/DocumentTypes';
+// import { DocumentManager } from '../../../util/DocumentManager';
+// import { DragManager } from '../../../util/DragManager';
+// import { KeyCodes } from '../../../util/KeyCodes';
+// import { CompileScript } from '../../../util/Scripting';
+// import { SearchUtil } from '../../../util/SearchUtil';
+// import { SnappingManager } from '../../../util/SnappingManager';
+// import { undoBatch } from '../../../util/UndoManager';
+// import '../../../views/DocumentDecorations.scss';
+// import { EditableView } from '../../EditableView';
+// import { MAX_ROW_HEIGHT } from '../../global/globalCssVariables.scss';
+// import { DocumentIconContainer } from '../../nodes/DocumentIcon';
+// import { OverlayView } from '../../OverlayView';
+// import { CollectionView } from '../CollectionView';
+// import './CollectionSchemaView.scss';
+// import { OpenWhere } from '../../nodes/DocumentView';
+// import { PinProps } from '../../nodes/trails';
+
+// // intialize cell properties
+// export interface CellProps {
+// row: number;
+// col: number;
+// rowProps: CellInfo;
+// // currently unused
+// CollectionView: Opt<CollectionView>;
+// // currently unused
+// ContainingCollection: Opt<CollectionView>;
+// Document: Doc;
+// // column name
+// fieldKey: string;
+// // currently unused
+// renderDepth: number;
+// // called when a button is pressed on the node itself
+// addDocTab: (document: Doc, where: OpenWhere) => boolean;
+// pinToPres: (document: Doc, pinProps: PinProps) => void;
+// moveDocument?: (document: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => boolean;
+// isFocused: boolean;
+// changeFocusedCellByIndex: (row: number, col: number) => void;
+// // set whether the cell is in the isEditing mode
+// setIsEditing: (isEditing: boolean) => void;
+// isEditable: boolean;
+// setPreviewDoc: (doc: Doc) => void;
+// setComputed: (script: string, doc: Doc, field: string, row: number, col: number) => boolean;
+// getField: (row: number, col?: number) => void;
+// // currnetly unused
+// showDoc: (doc: Doc | undefined, dataDoc?: any, screenX?: number, screenY?: number) => void;
+// }
+
+// @observer
+// export class CollectionSchemaCell extends React.Component<CellProps> {
+// // return a field key that is corrected for whether it COMMENT
+// public static resolvedFieldKey(column: string, rowDoc: Doc) {
+// const fieldKey = column;
+// if (fieldKey.startsWith('*')) {
+// const rootKey = fieldKey.substring(1);
+// const allKeys = [...Array.from(Object.keys(rowDoc)), ...Array.from(Object.keys(Doc.GetProto(rowDoc)))];
+// const matchedKeys = allKeys.filter(key => key.includes(rootKey));
+// if (matchedKeys.length) return matchedKeys[0];
+// }
+// return fieldKey;
+// }
+// @observable protected _isEditing: boolean = false;
+// protected _focusRef = React.createRef<HTMLDivElement>();
+// protected _rowDoc = this.props.rowProps.original;
+// // Gets the serialized data in proto form of the base proto that this document's proto inherits from
+// protected _rowDataDoc = Doc.GetProto(this.props.rowProps.original);
+// // methods for dragging and dropping
+// protected _dropDisposer?: DragManager.DragDropDisposer;
+// @observable contents: string = '';
+
+// componentDidMount() {
+// document.addEventListener('keydown', this.onKeyDown);
+// }
+// componentWillUnmount() {
+// document.removeEventListener('keydown', this.onKeyDown);
+// }
+
+// @action
+// onKeyDown = (e: KeyboardEvent): void => {
+// // If a cell is editable and clicked, hitting enter shoudl allow the user to edit it
+// if (this.props.isFocused && this.props.isEditable && e.keyCode === KeyCodes.ENTER) {
+// document.removeEventListener('keydown', this.onKeyDown);
+// this._isEditing = true;
+// this.props.setIsEditing(true);
+// }
+// };
+
+// @action
+// isEditingCallback = (isEditing: boolean): void => {
+// // a general method that takes a boolean that determines whether the cell should be in
+// // is-editing mode
+// // remove the event listener if it's there
+// document.removeEventListener('keydown', this.onKeyDown);
+// // it's not already in is-editing mode, re-add the event listener
+// isEditing && document.addEventListener('keydown', this.onKeyDown);
+// this._isEditing = isEditing;
+// this.props.setIsEditing(isEditing);
+// this.props.changeFocusedCellByIndex(this.props.row, this.props.col);
+// };
+
+// @action
+// onPointerDown = async (e: React.PointerEvent): Promise<void> => {
+// // pan to the cell
+// this.onItemDown(e);
+// // focus on it
+// this.props.changeFocusedCellByIndex(this.props.row, this.props.col);
+// this.props.setPreviewDoc(this.props.rowProps.original);
+
+// let url: string;
+// if ((url = StrCast(this.props.rowProps.row.href))) {
+// // opens up the the doc in a new window, blurring the old one
+// try {
+// new URL(url);
+// const temp = window.open(url)!;
+// temp.blur();
+// window.focus();
+// } catch {}
+// }
+
+// const doc = Cast(this._rowDoc[this.renderFieldKey], Doc, null);
+// doc && this.props.setPreviewDoc(doc);
+// };
+
+// @undoBatch
+// applyToDoc = (doc: Doc, row: number, col: number, run: (args?: { [name: string]: any }) => any) => {
+// // apply a specified change to the cell
+// const res = run({ this: doc, $r: row, $c: col, $: (r: number = 0, c: number = 0) => this.props.getField(r + row, c + col) });
+// if (!res.success) return false;
+// // change what is rendered to this new changed cell content
+// doc[this.renderFieldKey] = res.result;
+// return true;
+// // return whether the change was successful
+// };
+
+// private drop = (e: Event, de: DragManager.DropEvent) => {
+// // if the drag has data at its completion
+// if (de.complete.docDragData) {
+// // if only one doc was dragged
+// if (de.complete.docDragData.draggedDocuments.length === 1) {
+// // update the renderFieldKey
+// this._rowDataDoc[this.renderFieldKey] = de.complete.docDragData.draggedDocuments[0];
+// } else {
+// // create schema document reflecting the new column arrangement
+// const coll = Docs.Create.SchemaDocument([new SchemaHeaderField('title', '#f1efeb')], de.complete.docDragData.draggedDocuments, {});
+// this._rowDataDoc[this.renderFieldKey] = coll;
+// }
+// e.stopPropagation();
+// }
+// };
+
+// protected dropRef = (ele: HTMLElement | null) => {
+// // if the drop disposer is not undefined, run its function
+// this._dropDisposer?.();
+// // if ele is not null, give ele a non-undefined drop disposer
+// ele && (this._dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this)));
+// };
+
+// returnHighlights(contents: string, positions?: number[]) {
+// if (positions) {
+// const results = [];
+// StrCast(this.props.Document._searchString);
+// const length = StrCast(this.props.Document._searchString).length;
+// const color = contents ? 'black' : 'grey';
+
+// results.push(
+// <span key="-1" style={{ color }}>
+// {contents?.slice(0, positions[0])}
+// </span>
+// );
+// positions.forEach((num, cur) => {
+// results.push(
+// <span key={'start' + cur} style={{ backgroundColor: '#FFFF00', color }}>
+// {contents?.slice(num, num + length)}
+// </span>
+// );
+// let end = 0;
+// cur === positions.length - 1 ? (end = contents.length) : (end = positions[cur + 1]);
+// results.push(
+// <span key={'end' + cur} style={{ color }}>
+// {contents?.slice(num + length, end)}
+// </span>
+// );
+// });
+// return results;
+// }
+// return <span style={{ color: contents ? 'black' : 'grey' }}>{contents ? contents?.valueOf() : 'undefined'}</span>;
+// }
+
+// @computed get renderFieldKey() {
+// // gets the resolved field key of this cell
+// return CollectionSchemaCell.resolvedFieldKey(this.props.rowProps.column.id!, this.props.rowProps.original);
+// }
+
+// onItemDown = async (e: React.PointerEvent) => {
+// // if the document is a document used to change UI for search results in schema view
+// if (this.props.Document._searchDoc) {
+// const aliasdoc = await SearchUtil.GetAliasesOfDocument(this._rowDataDoc);
+// const targetContext = aliasdoc.length <= 0 ? undefined : Cast(aliasdoc[0].context, Doc, null);
+// // Jump to the this document
+// DocumentManager.Instance.jumpToDocument(this._rowDoc, { willPan: true }, emptyFunction, targetContext ? [targetContext] : [], () => this.props.setPreviewDoc(this._rowDoc));
+// }
+// };
+
+// renderCellWithType(type: string | undefined) {
+// const dragRef: React.RefObject<HTMLDivElement> = React.createRef();
+
+// // the column
+// const fieldKey = this.renderFieldKey;
+// // the exact cell
+// const field = this._rowDoc[fieldKey];
+
+// const onPointerEnter = (e: React.PointerEvent): void => {
+// // e.buttons === 1 means the left moue pointer is down
+// if (e.buttons === 1 && SnappingManager.GetIsDragging() && (type === 'document' || type === undefined)) {
+// dragRef.current!.className = 'collectionSchemaView-cellContainer doc-drag-over';
+// }
+// };
+// const onPointerLeave = (e: React.PointerEvent): void => {
+// // change the class name to indicate that the cell is no longer being dragged
+// dragRef.current!.className = 'collectionSchemaView-cellContainer';
+// };
+
+// let contents = Field.toString(field as Field);
+// // display 2 hyphens instead of a blank box for empty cells
+// contents = contents === '' ? '--' : contents;
+
+// // classname reflects the tatus of the cell
+// let className = 'collectionSchemaView-cellWrapper';
+// if (this._isEditing) className += ' editing';
+// if (this.props.isFocused && this.props.isEditable) className += ' focused';
+// if (this.props.isFocused && !this.props.isEditable) className += ' inactive';
+
+// const positions = [];
+// if (StrCast(this.props.Document._searchString).toLowerCase() !== '') {
+// // term is ...promise pending... if the field is a Promise, otherwise it is the cell's contents
+// let term = field instanceof Promise ? '...promise pending...' : contents.toLowerCase();
+// const search = StrCast(this.props.Document._searchString).toLowerCase();
+// let start = term.indexOf(search);
+// let tally = 0;
+// // if search is found in term
+// if (start !== -1) {
+// positions.push(start);
+// }
+// // if search is found in term, continue finding all instances of search in term
+// while (start < contents?.length && start !== -1) {
+// term = term.slice(start + search.length + 1);
+// tally += start + search.length + 1;
+// start = term.indexOf(search);
+// positions.push(tally + start);
+// }
+// // remove the last position
+// if (positions.length > 1) {
+// positions.pop();
+// }
+// }
+// const placeholder = type === 'number' ? '0' : contents === '' ? '--' : 'undefined';
+// return (
+// <div
+// className="collectionSchemaView-cellContainer"
+// style={{ cursor: field instanceof Doc ? 'grab' : 'auto' }}
+// ref={dragRef}
+// onPointerDown={this.onPointerDown}
+// onClick={action(e => (this._isEditing = true))}
+// onPointerEnter={onPointerEnter}
+// onPointerLeave={onPointerLeave}>
+// <div className={className} ref={this._focusRef} tabIndex={-1}>
+// <div className="collectionSchemaView-cellContents" ref={type === undefined || type === 'document' ? this.dropRef : null}>
+// {!this.props.Document._searchDoc ? (
+// <EditableView
+// editing={this._isEditing}
+// isEditingCallback={this.isEditingCallback}
+// display={'inline'}
+// contents={contents}
+// height={'auto'}
+// maxHeight={Number(MAX_ROW_HEIGHT)}
+// placeholder={placeholder}
+// GetValue={() => {
+// const cfield = ComputedField.WithoutComputed(() => FieldValue(field));
+// const cscript = cfield instanceof ComputedField ? cfield.script.originalScript : undefined;
+// const cfinalScript = cscript?.split('return')[cscript.split('return').length - 1];
+// return cscript ? (cfinalScript?.endsWith(';') ? `:=${cfinalScript?.substring(0, cfinalScript.length - 2)}` : cfinalScript) : Field.IsField(cfield) ? Field.toScriptString(cfield) : '';
+// }}
+// SetValue={action((value: string) => {
+// // sets what is displayed after the user makes an input
+// let retVal = false;
+// if (value.startsWith(':=') || value.startsWith('=:=')) {
+// // decides how to compute a value when given either of the above strings
+// const script = value.substring(value.startsWith('=:=') ? 3 : 2);
+// retVal = this.props.setComputed(script, value.startsWith(':=') ? this._rowDataDoc : this._rowDoc, this.renderFieldKey, this.props.row, this.props.col);
+// } else {
+// // check if the input is a number
+// let inputIsNum = true;
+// for (const s of value) {
+// if (isNaN(parseInt(s)) && !(s === '.') && !(s === ',')) {
+// inputIsNum = false;
+// }
+// }
+// // check if the input is a boolean
+// const inputIsBool: boolean = value === 'false' || value === 'true';
+// // what to do in the case
+// if (!inputIsNum && !inputIsBool && !value.startsWith('=')) {
+// // if it's not a number, it's a string, and should be processed as such
+// // strips the string of quotes when it is edited to prevent quotes form being added to the text automatically
+// // after each edit
+// let valueSansQuotes = value;
+// if (this._isEditing) {
+// const vsqLength = valueSansQuotes.length;
+// // get rid of outer quotes
+// valueSansQuotes = valueSansQuotes.substring(value.startsWith('"') ? 1 : 0, valueSansQuotes.charAt(vsqLength - 1) === '"' ? vsqLength - 1 : vsqLength);
+// }
+// let inputAsString = '"';
+// // escape any quotes in the string
+// for (const i of valueSansQuotes) {
+// if (i === '"') {
+// inputAsString += '\\"';
+// } else {
+// inputAsString += i;
+// }
+// }
+// // add a closing quote
+// inputAsString += '"';
+// //two options here: we can strip off outer quotes or we can figure out what's going on with the script
+// const script = CompileScript(inputAsString, { requiredType: type, typecheck: false, editable: true, addReturn: true, params: { this: Doc.name, $r: 'number', $c: 'number', $: 'any' } });
+// const changeMade = inputAsString.length !== value.length || inputAsString.length - 2 !== value.length;
+// // change it if a change is made, otherwise, just compile using the old cell conetnts
+// script.compiled && (retVal = this.applyToDoc(changeMade ? this._rowDoc : this._rowDataDoc, this.props.row, this.props.col, script.run));
+// // handle numbers and expressions
+// } else if (inputIsNum || value.startsWith('=')) {
+// //TODO: make accept numbers
+// const inputscript = value.substring(value.startsWith('=') ? 1 : 0);
+// // if commas are not stripped, the parser only considers the numbers after the last comma
+// let inputSansCommas = '';
+// for (const s of inputscript) {
+// if (!(s === ',')) {
+// inputSansCommas += s;
+// }
+// }
+// const script = CompileScript(inputSansCommas, { requiredType: type, typecheck: false, editable: true, addReturn: true, params: { this: Doc.name, $r: 'number', $c: 'number', $: 'any' } });
+// const changeMade = value.length - 2 !== value.length;
+// script.compiled && (retVal = this.applyToDoc(changeMade ? this._rowDoc : this._rowDataDoc, this.props.row, this.props.col, script.run));
+// // handle booleans
+// } else if (inputIsBool) {
+// const script = CompileScript(value, { requiredType: type, typecheck: false, editable: true, addReturn: true, params: { this: Doc.name, $r: 'number', $c: 'number', $: 'any' } });
+// const changeMade = value.length - 2 !== value.length;
+// script.compiled && (retVal = this.applyToDoc(changeMade ? this._rowDoc : this._rowDataDoc, this.props.row, this.props.col, script.run));
+// }
+// }
+// if (retVal) {
+// this._isEditing = false; // need to set this here. otherwise, the assignment of the field will invalidate & cause render() to be called with the wrong value for 'editing'
+// this.props.setIsEditing(false);
+// }
+// return retVal;
+// })}
+// OnFillDown={async (value: string) => {
+// // computes all of the value preceded by :=
+// const script = CompileScript(value, { requiredType: type, typecheck: false, editable: true, addReturn: true, params: { this: Doc.name, $r: 'number', $c: 'number', $: 'any' } });
+// script.compiled &&
+// DocListCast(this.props.Document[this.props.fieldKey]).forEach((doc, i) =>
+// value.startsWith(':=') ? this.props.setComputed(value.substring(2), Doc.GetProto(doc), this.renderFieldKey, i, this.props.col) : this.applyToDoc(Doc.GetProto(doc), i, this.props.col, script.run)
+// );
+// }}
+// />
+// ) : (
+// this.returnHighlights(contents, positions)
+// )}
+// </div>
+// </div>
+// </div>
+// );
+// }
+
+// render() {
+// return this.renderCellWithType(undefined);
+// }
+// }
+
+// @observer
+// export class CollectionSchemaNumberCell extends CollectionSchemaCell {
+// render() {
+// return this.renderCellWithType('number');
+// }
+// }
+
+// @observer
+// export class CollectionSchemaBooleanCell extends CollectionSchemaCell {
+// render() {
+// return this.renderCellWithType('boolean');
+// }
+// }
+
+// @observer
+// export class CollectionSchemaStringCell extends CollectionSchemaCell {
+// render() {
+// return this.renderCellWithType('string');
+// }
+// }
+
+// @observer
+// export class CollectionSchemaDateCell extends CollectionSchemaCell {
+// @computed get _date(): Opt<DateField> {
+// // if the cell is a date field, cast then contents to a date. Otherrwwise, make the contents undefined.
+// return this._rowDoc[this.renderFieldKey] instanceof DateField ? DateCast(this._rowDoc[this.renderFieldKey]) : undefined;
+// }
+
+// @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);
+// // } else {
+// // ^ DateCast is always undefined for some reason, but that is what the field should be set to
+// this._rowDoc[this.renderFieldKey] = new DateField(date as Date);
+// //}
+// };
+
+// render() {
+// return !this.props.isFocused ? (
+// <span onPointerDown={this.onPointerDown}>{this._date ? Field.toString(this._date as Field) : '--'}</span>
+// ) : (
+// <DatePicker selected={this._date?.date || new Date()} onSelect={date => this.handleChange(date)} onChange={date => this.handleChange(date)} />
+// );
+// }
+// }
+
+// @observer
+// export class CollectionSchemaDocCell extends CollectionSchemaCell {
+// _overlayDisposer?: () => void;
+
+// @computed get _doc() {
+// return FieldValue(Cast(this._rowDoc[this.renderFieldKey], Doc));
+// }
+
+// @action
+// onSetValue = (value: string) => {
+// this._doc && (Doc.GetProto(this._doc).title = value);
+
+// const script = CompileScript(value, {
+// addReturn: true,
+// typecheck: true,
+// transformer: DocumentIconContainer.getTransformer(),
+// });
+// // compile the script
+// const results = script.compiled && script.run();
+// // if the script was compiled and run
+// if (results && results.success) {
+// this._rowDoc[this.renderFieldKey] = results.result;
+// return true;
+// }
+// return false;
+// };
+
+// componentWillUnmount() {
+// this.onBlur();
+// }
+
+// onBlur = () => {
+// this._overlayDisposer?.();
+// };
+// onFocus = () => {
+// this.onBlur();
+// this._overlayDisposer = OverlayView.Instance.addElement(<DocumentIconContainer />, { x: 0, y: 0 });
+// };
+
+// @action
+// isEditingCallback = (isEditing: boolean): void => {
+// // the isEditingCallback from a general CollectionSchemaCell
+// document.removeEventListener('keydown', this.onKeyDown);
+// isEditing && document.addEventListener('keydown', this.onKeyDown);
+// this._isEditing = isEditing;
+// this.props.setIsEditing(isEditing);
+// this.props.changeFocusedCellByIndex(this.props.row, this.props.col);
+// };
+
+// render() {
+// // if there's a doc, render it
+// return !this._doc ? (
+// this.renderCellWithType('document')
+// ) : (
+// <div className="collectionSchemaView-cellWrapper" ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}>
+// <div className="collectionSchemaView-cellContents-document" style={{ padding: '5.9px' }} ref={this.dropRef} onFocus={this.onFocus} onBlur={this.onBlur}>
+// <EditableView
+// editing={this._isEditing}
+// isEditingCallback={this.isEditingCallback}
+// display={'inline'}
+// contents={this._doc.title || '--'}
+// height={'auto'}
+// maxHeight={Number(MAX_ROW_HEIGHT)}
+// GetValue={() => StrCast(this._doc?.title)}
+// SetValue={action((value: string) => {
+// this.onSetValue(value);
+// return true;
+// })}
+// />
+// </div>
+// <div onClick={() => this._doc && this.props.addDocTab(this._doc, OpenWhere.addRight)} className="collectionSchemaView-cellContents-docButton">
+// <FontAwesomeIcon icon="external-link-alt" size="lg" />
+// </div>
+// </div>
+// );
+// }
+// }
+
+// @observer
+// export class CollectionSchemaImageCell extends CollectionSchemaCell {
+// choosePath(url: URL) {
+// if (url.protocol === 'data') return url.href; // if the url ises the data protocol, just return the href
+// if (url.href.indexOf(window.location.origin) === -1) return Utils.CorsProxy(url.href); // otherwise, put it through the cors proxy erver
+// if (!/\.(png|jpg|jpeg|gif|webp)$/.test(url.href.toLowerCase())) return url.href; //Why is this here — good question
+
+// const ext = extname(url.href);
+// return url.href.replace(ext, '_o' + ext);
+// }
+
+// render() {
+// const field = Cast(this._rowDoc[this.renderFieldKey], ImageField, null); // retrieve the primary image URL that is being rendered from the data doc
+// const alts = DocListCast(this._rowDoc[this.renderFieldKey + '-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)
+// .map(url => this.choosePath(url)); // access the primary layout data of the alternate documents
+// const paths = field ? [this.choosePath(field.url), ...altpaths] : altpaths;
+// // If there is a path, follow it; otherwise, follow a link to a default image icon
+// const url = paths.length ? paths : [Utils.CorsProxy('http://www.cs.brown.edu/~bcz/noImage.png')];
+
+// const aspect = Doc.NativeAspect(this._rowDoc); // aspect ratio
+// let width = Math.min(75, this.props.rowProps.width); // get a with that is no smaller than 75px
+// const height = Math.min(75, width / aspect); // get a height either proportional to that or 75 px
+// width = height * aspect; // increase the width of the image if necessary to maintain proportionality
+
+// const reference = React.createRef<HTMLDivElement>();
+// return (
+// <div className="collectionSchemaView-cellWrapper" ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}>
+// <div className="collectionSchemaView-cellContents" key={this._rowDoc[Id]} ref={reference}>
+// <img src={url[0]} width={paths.length ? width : '20px'} height={paths.length ? height : '20px'} />
+// </div>
+// </div>
+// );
+// }
+// }
+
+// @observer
+// export class CollectionSchemaListCell extends CollectionSchemaCell {
+// _overlayDisposer?: () => void;
+
+// @computed get _field() {
+// return this._rowDoc[this.renderFieldKey];
+// }
+// @computed get _optionsList() {
+// return this._field as List<any>;
+// }
+// @observable private _opened = false; // whether the list is opened
+// @observable private _text = 'select an item';
+// @observable private _selectedNum = 0; // the index of the list item selected
+
+// @action
+// onSetValue = (value: string) => {
+// // change if it's a document
+// this._optionsList[this._selectedNum] = this._text = value;
+
+// (this._field as List<any>).splice(this._selectedNum, 1, value);
+// };
+
+// @action
+// onSelected = (element: string, index: number) => {
+// // if an item is selected, the private variables should update to reflect this
+// this._text = element;
+// this._selectedNum = index;
+// };
+
+// onFocus = () => {
+// this._overlayDisposer?.();
+// this._overlayDisposer = OverlayView.Instance.addElement(<DocumentIconContainer />, { x: 0, y: 0 });
+// };
+
+// render() {
+// const link = false;
+// const reference = React.createRef<HTMLDivElement>();
+
+// // if the list is not opened, don't display it; otherwise, do.
+// if (this._optionsList?.length) {
+// const options = !this._opened ? null : (
+// <div>
+// {this._optionsList.map((element, index) => {
+// const val = Field.toString(element);
+// return (
+// <div className="collectionSchemaView-dropdownOption" key={index} style={{ padding: '6px' }} onPointerDown={e => this.onSelected(StrCast(element), index)}>
+// {val}
+// </div>
+// );
+// })}
+// </div>
+// );
+
+// const plainText = <div style={{ padding: '5.9px' }}>{this._text}</div>;
+// const textarea = (
+// <div className="collectionSchemaView-cellContents" key={this._rowDoc[Id]} style={{ padding: '5.9px' }} ref={this.dropRef}>
+// <EditableView
+// editing={this._isEditing}
+// isEditingCallback={this.isEditingCallback}
+// display={'inline'}
+// contents={this._text}
+// height={'auto'}
+// maxHeight={Number(MAX_ROW_HEIGHT)}
+// GetValue={() => this._text}
+// SetValue={action((value: string) => {
+// // add special for params
+// this.onSetValue(value);
+// return true;
+// })}
+// />
+// </div>
+// );
+
+// //☰
+// return (
+// <div className="collectionSchemaView-cellWrapper" ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}>
+// <div className="collectionSchemaView-cellContents" key={this._rowDoc[Id]} ref={reference}>
+// <div className="collectionSchemaView-dropDownWrapper">
+// <button type="button" className="collectionSchemaView-dropdownButton" style={{ right: 'length', position: 'relative' }} onClick={action(e => (this._opened = !this._opened))}>
+// <FontAwesomeIcon icon={this._opened ? 'caret-up' : 'caret-down'} size="sm" />
+// </button>
+// <div className="collectionSchemaView-dropdownText"> {link ? plainText : textarea} </div>
+// </div>
+// {options}
+// </div>
+// </div>
+// );
+// }
+// return this.renderCellWithType('list');
+// }
+// }
+
+// @observer
+// export class CollectionSchemaCheckboxCell extends CollectionSchemaCell {
+// @computed get _isChecked() {
+// return BoolCast(this._rowDoc[this.renderFieldKey]);
+// }
+
+// render() {
+// const reference = React.createRef<HTMLDivElement>();
+// return (
+// <div className="collectionSchemaView-cellWrapper" ref={this._focusRef} tabIndex={-1} onPointerDown={this.onPointerDown}>
+// <input type="checkbox" checked={this._isChecked} onChange={e => (this._rowDoc[this.renderFieldKey] = e.target.checked)} />
+// </div>
+// );
+// }
+// }
+
+// @observer
+// export class CollectionSchemaButtons extends CollectionSchemaCell {
+// // the navigation buttons for schema view when it is used for search.
+// render() {
+// return !this.props.Document._searchDoc || ![DocumentType.PDF, DocumentType.RTF].includes(StrCast(this._rowDoc.type) as DocumentType) ? (
+// <></>
+// ) : (
+// <div style={{ paddingTop: 8, paddingLeft: 3 }}>
+// <button style={{ padding: 2, left: 77 }} onClick={() => Doc.SearchMatchNext(this._rowDoc, true)}>
+// <FontAwesomeIcon icon="arrow-up" size="sm" />
+// </button>
+// <button style={{ padding: 2 }} onClick={() => Doc.SearchMatchNext(this._rowDoc, false)}>
+// <FontAwesomeIcon icon="arrow-down" size="sm" />
+// </button>
+// </div>
+// );
+// }
+// }
diff --git a/src/client/views/collections/old_collectionSchema/OldCollectionSchemaMovableColumn.tsx b/src/client/views/collections/old_collectionSchema/OldCollectionSchemaMovableColumn.tsx
index 28d2e6ab1..c2182ae0c 100644
--- a/src/client/views/collections/old_collectionSchema/OldCollectionSchemaMovableColumn.tsx
+++ b/src/client/views/collections/old_collectionSchema/OldCollectionSchemaMovableColumn.tsx
@@ -1,138 +1,138 @@
-import React = require('react');
-import { action } from 'mobx';
-import { SchemaHeaderField } from '../../../../fields/SchemaHeaderField';
-import { DragManager } from '../../../util/DragManager';
-import { SnappingManager } from '../../../util/SnappingManager';
-import { Transform } from '../../../util/Transform';
-import './CollectionSchemaView.scss';
+// import React = require('react');
+// import { action } from 'mobx';
+// import { SchemaHeaderField } from '../../../../fields/SchemaHeaderField';
+// import { DragManager } from '../../../util/DragManager';
+// import { SnappingManager } from '../../../util/SnappingManager';
+// import { Transform } from '../../../util/Transform';
+// import './CollectionSchemaView.scss';
-export interface MovableColumnProps {
- columnRenderer: React.ReactNode;
- columnValue: SchemaHeaderField;
- allColumns: SchemaHeaderField[];
- reorderColumns: (toMove: SchemaHeaderField, relativeTo: SchemaHeaderField, before: boolean, columns: SchemaHeaderField[]) => void;
- ScreenToLocalTransform: () => Transform;
-}
-export class MovableColumn extends React.Component<MovableColumnProps> {
- // The header of the column
- private _header?: React.RefObject<HTMLDivElement> = React.createRef();
- // The container of the function that is responsible for moving the column over to a new plac
- private _colDropDisposer?: DragManager.DragDropDisposer;
- // initial column position
- private _startDragPosition: { x: number; y: number } = { x: 0, y: 0 };
- // sensitivity to being dragged, in pixels
- private _sensitivity: number = 16;
- // Column reference ID
- private _dragRef: React.RefObject<HTMLDivElement> = React.createRef();
+// export interface MovableColumnProps {
+// columnRenderer: React.ReactNode;
+// columnValue: SchemaHeaderField;
+// allColumns: SchemaHeaderField[];
+// reorderColumns: (toMove: SchemaHeaderField, relativeTo: SchemaHeaderField, before: boolean, columns: SchemaHeaderField[]) => void;
+// ScreenToLocalTransform: () => Transform;
+// }
+// export class MovableColumn extends React.Component<MovableColumnProps> {
+// // The header of the column
+// private _header?: React.RefObject<HTMLDivElement> = React.createRef();
+// // The container of the function that is responsible for moving the column over to a new plac
+// private _colDropDisposer?: DragManager.DragDropDisposer;
+// // initial column position
+// private _startDragPosition: { x: number; y: number } = { x: 0, y: 0 };
+// // sensitivity to being dragged, in pixels
+// private _sensitivity: number = 16;
+// // Column reference ID
+// private _dragRef: React.RefObject<HTMLDivElement> = React.createRef();
- onPointerEnter = (e: React.PointerEvent): void => {
- // if the column is left-clicked and it is being dragged
- if (e.buttons === 1 && SnappingManager.GetIsDragging()) {
- this._header!.current!.className = 'collectionSchema-col-wrapper';
- document.addEventListener('pointermove', this.onDragMove, true);
- }
- };
+// onPointerEnter = (e: React.PointerEvent): void => {
+// // if the column is left-clicked and it is being dragged
+// if (e.buttons === 1 && SnappingManager.GetIsDragging()) {
+// this._header!.current!.className = 'collectionSchema-col-wrapper';
+// document.addEventListener('pointermove', this.onDragMove, true);
+// }
+// };
- onPointerLeave = (e: React.PointerEvent): void => {
- this._header!.current!.className = 'collectionSchema-col-wrapper';
- document.removeEventListener('pointermove', this.onDragMove, true);
- !e.buttons && document.removeEventListener('pointermove', this.onPointerMove);
- };
+// onPointerLeave = (e: React.PointerEvent): void => {
+// this._header!.current!.className = 'collectionSchema-col-wrapper';
+// document.removeEventListener('pointermove', this.onDragMove, true);
+// !e.buttons && document.removeEventListener('pointermove', this.onPointerMove);
+// };
- onDragMove = (e: PointerEvent): void => {
- // only take into account the horizonal direction when a column is dragged
- const x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY);
- const rect = this._header!.current!.getBoundingClientRect();
- // Now store the point at the top center of the column when it was in its original position
- const bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left + (rect.right - rect.left) / 2, rect.top);
- // to be compared with its new horizontal position
- const before = x[0] < bounds[0];
- this._header!.current!.className = 'collectionSchema-col-wrapper';
- if (before) this._header!.current!.className += ' col-before';
- if (!before) this._header!.current!.className += ' col-after';
- e.stopPropagation();
- };
+// onDragMove = (e: PointerEvent): void => {
+// // only take into account the horizonal direction when a column is dragged
+// const x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY);
+// const rect = this._header!.current!.getBoundingClientRect();
+// // Now store the point at the top center of the column when it was in its original position
+// const bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left + (rect.right - rect.left) / 2, rect.top);
+// // to be compared with its new horizontal position
+// const before = x[0] < bounds[0];
+// this._header!.current!.className = 'collectionSchema-col-wrapper';
+// if (before) this._header!.current!.className += ' col-before';
+// if (!before) this._header!.current!.className += ' col-after';
+// e.stopPropagation();
+// };
- createColDropTarget = (ele: HTMLDivElement) => {
- this._colDropDisposer?.();
- if (ele) {
- this._colDropDisposer = DragManager.MakeDropTarget(ele, this.colDrop.bind(this));
- }
- };
+// createColDropTarget = (ele: HTMLDivElement) => {
+// this._colDropDisposer?.();
+// if (ele) {
+// this._colDropDisposer = DragManager.MakeDropTarget(ele, this.colDrop.bind(this));
+// }
+// };
- colDrop = (e: Event, de: DragManager.DropEvent) => {
- document.removeEventListener('pointermove', this.onDragMove, true);
- // we only care about whether the column is shifted to the side
- const x = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y);
- // get the dimensions of the smallest rectangle that bounds the header
- const rect = this._header!.current!.getBoundingClientRect();
- const bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left + (rect.right - rect.left) / 2, rect.top);
- // get whether the column was dragged before or after where it is now
- const before = x[0] < bounds[0];
- const colDragData = de.complete.columnDragData;
- // if there is colDragData, which happen when the drag is complete, reorder the columns according to the established variables
- if (colDragData) {
- e.stopPropagation();
- this.props.reorderColumns(colDragData.colKey, this.props.columnValue, before, this.props.allColumns);
- return true;
- }
- return false;
- };
+// colDrop = (e: Event, de: DragManager.DropEvent) => {
+// document.removeEventListener('pointermove', this.onDragMove, true);
+// // we only care about whether the column is shifted to the side
+// const x = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y);
+// // get the dimensions of the smallest rectangle that bounds the header
+// const rect = this._header!.current!.getBoundingClientRect();
+// const bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left + (rect.right - rect.left) / 2, rect.top);
+// // get whether the column was dragged before or after where it is now
+// const before = x[0] < bounds[0];
+// const colDragData = de.complete.columnDragData;
+// // if there is colDragData, which happen when the drag is complete, reorder the columns according to the established variables
+// if (colDragData) {
+// e.stopPropagation();
+// this.props.reorderColumns(colDragData.colKey, this.props.columnValue, before, this.props.allColumns);
+// return true;
+// }
+// return false;
+// };
- onPointerMove = (e: PointerEvent) => {
- const onRowMove = (e: PointerEvent) => {
- e.stopPropagation();
- e.preventDefault();
+// onPointerMove = (e: PointerEvent) => {
+// const onRowMove = (e: PointerEvent) => {
+// e.stopPropagation();
+// e.preventDefault();
- document.removeEventListener('pointermove', onRowMove);
- document.removeEventListener('pointerup', onRowUp);
- const dragData = new DragManager.ColumnDragData(this.props.columnValue);
- DragManager.StartColumnDrag(this._dragRef.current!, dragData, e.x, e.y);
- };
- const onRowUp = (): void => {
- document.removeEventListener('pointermove', onRowMove);
- document.removeEventListener('pointerup', onRowUp);
- };
- // if the left mouse button is the one being held
- if (e.buttons === 1) {
- const [dx, dy] = this.props.ScreenToLocalTransform().transformDirection(e.clientX - this._startDragPosition.x, e.clientY - this._startDragPosition.y);
- // If the movemnt of the drag exceeds the sensitivity value
- if (Math.abs(dx) + Math.abs(dy) > this._sensitivity) {
- document.removeEventListener('pointermove', this.onPointerMove);
- e.stopPropagation();
+// document.removeEventListener('pointermove', onRowMove);
+// document.removeEventListener('pointerup', onRowUp);
+// const dragData = new DragManager.ColumnDragData(this.props.columnValue);
+// DragManager.StartColumnDrag(this._dragRef.current!, dragData, e.x, e.y);
+// };
+// const onRowUp = (): void => {
+// document.removeEventListener('pointermove', onRowMove);
+// document.removeEventListener('pointerup', onRowUp);
+// };
+// // if the left mouse button is the one being held
+// if (e.buttons === 1) {
+// const [dx, dy] = this.props.ScreenToLocalTransform().transformDirection(e.clientX - this._startDragPosition.x, e.clientY - this._startDragPosition.y);
+// // If the movemnt of the drag exceeds the sensitivity value
+// if (Math.abs(dx) + Math.abs(dy) > this._sensitivity) {
+// document.removeEventListener('pointermove', this.onPointerMove);
+// e.stopPropagation();
- document.addEventListener('pointermove', onRowMove);
- document.addEventListener('pointerup', onRowUp);
- }
- }
- };
+// document.addEventListener('pointermove', onRowMove);
+// document.addEventListener('pointerup', onRowUp);
+// }
+// }
+// };
- onPointerUp = (e: React.PointerEvent) => {
- document.removeEventListener('pointermove', this.onPointerMove);
- };
+// onPointerUp = (e: React.PointerEvent) => {
+// document.removeEventListener('pointermove', this.onPointerMove);
+// };
- @action
- onPointerDown = (e: React.PointerEvent, ref: React.RefObject<HTMLDivElement>) => {
- this._dragRef = ref;
- const [dx, dy] = this.props.ScreenToLocalTransform().transformDirection(e.clientX, e.clientY);
- // If the cell thing dragged is not being edited
- if (!(e.target as any)?.tagName.includes('INPUT')) {
- this._startDragPosition = { x: dx, y: dy };
- document.addEventListener('pointermove', this.onPointerMove);
- }
- };
+// @action
+// onPointerDown = (e: React.PointerEvent, ref: React.RefObject<HTMLDivElement>) => {
+// this._dragRef = ref;
+// const [dx, dy] = this.props.ScreenToLocalTransform().transformDirection(e.clientX, e.clientY);
+// // If the cell thing dragged is not being edited
+// if (!(e.target as any)?.tagName.includes('INPUT')) {
+// this._startDragPosition = { x: dx, y: dy };
+// document.addEventListener('pointermove', this.onPointerMove);
+// }
+// };
- render() {
- const reference = React.createRef<HTMLDivElement>();
+// render() {
+// const reference = React.createRef<HTMLDivElement>();
- return (
- <div className="collectionSchema-col" ref={this.createColDropTarget}>
- <div className="collectionSchema-col-wrapper" ref={this._header} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}>
- <div className="col-dragger" ref={reference} onPointerDown={e => this.onPointerDown(e, reference)} onPointerUp={this.onPointerUp}>
- {this.props.columnRenderer}
- </div>
- </div>
- </div>
- );
- }
-}
+// return (
+// <div className="collectionSchema-col" ref={this.createColDropTarget}>
+// <div className="collectionSchema-col-wrapper" ref={this._header} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}>
+// <div className="col-dragger" ref={reference} onPointerDown={e => this.onPointerDown(e, reference)} onPointerUp={this.onPointerUp}>
+// {this.props.columnRenderer}
+// </div>
+// </div>
+// </div>
+// );
+// }
+// }
diff --git a/src/client/views/collections/old_collectionSchema/OldCollectionSchemaMovableRow.tsx b/src/client/views/collections/old_collectionSchema/OldCollectionSchemaMovableRow.tsx
index 3cb2df7d3..2b39df201 100644
--- a/src/client/views/collections/old_collectionSchema/OldCollectionSchemaMovableRow.tsx
+++ b/src/client/views/collections/old_collectionSchema/OldCollectionSchemaMovableRow.tsx
@@ -1,152 +1,152 @@
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action } from 'mobx';
-import * as React from 'react';
-import { ReactTableDefaults, RowInfo } from 'react-table';
-import { Doc } from '../../../../fields/Doc';
-import { Cast, FieldValue, StrCast } from '../../../../fields/Types';
-import { DocumentManager } from '../../../util/DocumentManager';
-import { DragManager, dropActionType, SetupDrag } from '../../../util/DragManager';
-import { SnappingManager } from '../../../util/SnappingManager';
-import { Transform } from '../../../util/Transform';
-import { undoBatch } from '../../../util/UndoManager';
-import { ContextMenu } from '../../ContextMenu';
-import { OpenWhere } from '../../nodes/DocumentView';
-import './CollectionSchemaView.scss';
+// import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+// import { action } from 'mobx';
+// import * as React from 'react';
+// import { ReactTableDefaults, RowInfo } from 'react-table';
+// import { Doc } from '../../../../fields/Doc';
+// import { Cast, FieldValue, StrCast } from '../../../../fields/Types';
+// import { DocumentManager } from '../../../util/DocumentManager';
+// import { DragManager, dropActionType, SetupDrag } from '../../../util/DragManager';
+// import { SnappingManager } from '../../../util/SnappingManager';
+// import { Transform } from '../../../util/Transform';
+// import { undoBatch } from '../../../util/UndoManager';
+// import { ContextMenu } from '../../ContextMenu';
+// import { OpenWhere } from '../../nodes/DocumentView';
+// import './CollectionSchemaView.scss';
-export interface MovableRowProps {
- rowInfo: RowInfo;
- ScreenToLocalTransform: () => Transform;
- addDoc: (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => boolean;
- removeDoc: (doc: Doc | Doc[]) => boolean;
- rowFocused: boolean;
- textWrapRow: (doc: Doc) => void;
- rowWrapped: boolean;
- dropAction: string;
- addDocTab: any;
-}
+// export interface MovableRowProps {
+// rowInfo: RowInfo;
+// ScreenToLocalTransform: () => Transform;
+// addDoc: (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => boolean;
+// removeDoc: (doc: Doc | Doc[]) => boolean;
+// rowFocused: boolean;
+// textWrapRow: (doc: Doc) => void;
+// rowWrapped: boolean;
+// dropAction: string;
+// addDocTab: any;
+// }
-export class MovableRow extends React.Component<React.PropsWithChildren<MovableRowProps>> {
- private _header?: React.RefObject<HTMLDivElement> = React.createRef();
- private _rowDropDisposer?: DragManager.DragDropDisposer;
+// export class MovableRow extends React.Component<React.PropsWithChildren<MovableRowProps>> {
+// private _header?: React.RefObject<HTMLDivElement> = React.createRef();
+// private _rowDropDisposer?: DragManager.DragDropDisposer;
- // Event listeners are only necessary when the user is hovering over the table
- // Create one when the mouse starts hovering...
- onPointerEnter = (e: React.PointerEvent): void => {
- if (e.buttons === 1 && SnappingManager.GetIsDragging()) {
- this._header!.current!.className = 'collectionSchema-row-wrapper';
- document.addEventListener('pointermove', this.onDragMove, true);
- }
- };
- // ... and delete it when the mouse leaves
- onPointerLeave = (e: React.PointerEvent): void => {
- this._header!.current!.className = 'collectionSchema-row-wrapper';
- document.removeEventListener('pointermove', this.onDragMove, true);
- };
- // The method for the event listener, reorders columns when dragged to their new locations.
- onDragMove = (e: PointerEvent): void => {
- const x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY);
- const rect = this._header!.current!.getBoundingClientRect();
- const bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2);
- const before = x[1] < bounds[1];
- this._header!.current!.className = 'collectionSchema-row-wrapper';
- if (before) this._header!.current!.className += ' row-above';
- if (!before) this._header!.current!.className += ' row-below';
- e.stopPropagation();
- };
- componentWillUnmount() {
- this._rowDropDisposer?.();
- }
- //
- createRowDropTarget = (ele: HTMLDivElement) => {
- this._rowDropDisposer?.();
- if (ele) {
- this._rowDropDisposer = DragManager.MakeDropTarget(ele, this.rowDrop.bind(this));
- }
- };
- // Controls what hppens when a row is dragged and dropped
- rowDrop = (e: Event, de: DragManager.DropEvent) => {
- this.onPointerLeave(e as any);
- const rowDoc = FieldValue(Cast(this.props.rowInfo.original, Doc));
- if (!rowDoc) return false;
+// // Event listeners are only necessary when the user is hovering over the table
+// // Create one when the mouse starts hovering...
+// onPointerEnter = (e: React.PointerEvent): void => {
+// if (e.buttons === 1 && SnappingManager.GetIsDragging()) {
+// this._header!.current!.className = 'collectionSchema-row-wrapper';
+// document.addEventListener('pointermove', this.onDragMove, true);
+// }
+// };
+// // ... and delete it when the mouse leaves
+// onPointerLeave = (e: React.PointerEvent): void => {
+// this._header!.current!.className = 'collectionSchema-row-wrapper';
+// document.removeEventListener('pointermove', this.onDragMove, true);
+// };
+// // The method for the event listener, reorders columns when dragged to their new locations.
+// onDragMove = (e: PointerEvent): void => {
+// const x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY);
+// const rect = this._header!.current!.getBoundingClientRect();
+// const bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2);
+// const before = x[1] < bounds[1];
+// this._header!.current!.className = 'collectionSchema-row-wrapper';
+// if (before) this._header!.current!.className += ' row-above';
+// if (!before) this._header!.current!.className += ' row-below';
+// e.stopPropagation();
+// };
+// componentWillUnmount() {
+// this._rowDropDisposer?.();
+// }
+// //
+// createRowDropTarget = (ele: HTMLDivElement) => {
+// this._rowDropDisposer?.();
+// if (ele) {
+// this._rowDropDisposer = DragManager.MakeDropTarget(ele, this.rowDrop.bind(this));
+// }
+// };
+// // Controls what hppens when a row is dragged and dropped
+// rowDrop = (e: Event, de: DragManager.DropEvent) => {
+// this.onPointerLeave(e as any);
+// const rowDoc = FieldValue(Cast(this.props.rowInfo.original, Doc));
+// if (!rowDoc) return false;
- const x = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y);
- const rect = this._header!.current!.getBoundingClientRect();
- const bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2);
- const before = x[1] < bounds[1];
+// const x = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y);
+// const rect = this._header!.current!.getBoundingClientRect();
+// const bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2);
+// const before = x[1] < bounds[1];
- const docDragData = de.complete.docDragData;
- if (docDragData) {
- e.stopPropagation();
- if (docDragData.draggedDocuments[0] === rowDoc) return true;
- const addDocument = (doc: Doc | Doc[]) => this.props.addDoc(doc, rowDoc, before);
- const movedDocs = docDragData.draggedDocuments;
- return docDragData.dropAction || docDragData.userDropAction
- ? docDragData.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before) || added, false)
- : docDragData.moveDocument
- ? movedDocs.reduce((added: boolean, d) => docDragData.moveDocument?.(d, rowDoc, addDocument) || added, false)
- : docDragData.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before), false);
- }
- return false;
- };
+// const docDragData = de.complete.docDragData;
+// if (docDragData) {
+// e.stopPropagation();
+// if (docDragData.draggedDocuments[0] === rowDoc) return true;
+// const addDocument = (doc: Doc | Doc[]) => this.props.addDoc(doc, rowDoc, before);
+// const movedDocs = docDragData.draggedDocuments;
+// return docDragData.dropAction || docDragData.userDropAction
+// ? docDragData.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before) || added, false)
+// : docDragData.moveDocument
+// ? movedDocs.reduce((added: boolean, d) => docDragData.moveDocument?.(d, rowDoc, addDocument) || added, false)
+// : docDragData.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before), false);
+// }
+// return false;
+// };
- onRowContextMenu = (e: React.MouseEvent): void => {
- const description = this.props.rowWrapped ? 'Unwrap text on row' : 'Text wrap row';
- ContextMenu.Instance.addItem({ description: description, event: () => this.props.textWrapRow(this.props.rowInfo.original), icon: 'file-pdf' });
- };
+// onRowContextMenu = (e: React.MouseEvent): void => {
+// const description = this.props.rowWrapped ? 'Unwrap text on row' : 'Text wrap row';
+// ContextMenu.Instance.addItem({ description: description, event: () => this.props.textWrapRow(this.props.rowInfo.original), icon: 'file-pdf' });
+// };
- @undoBatch
- @action
- move: DragManager.MoveFunction = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDoc) => {
- const targetView = targetCollection && DocumentManager.Instance.getDocumentView(targetCollection);
- return doc !== targetCollection && doc !== targetView?.props.ContainingCollectionDoc && this.props.removeDoc(doc) && addDoc(doc);
- };
+// @undoBatch
+// @action
+// move: DragManager.MoveFunction = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDoc) => {
+// const targetView = targetCollection && DocumentManager.Instance.getDocumentView(targetCollection);
+// return doc !== targetCollection && doc !== targetView?.props.ContainingCollectionDoc && this.props.removeDoc(doc) && addDoc(doc);
+// };
- @action
- onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
- console.log('yes');
- if (e.key === 'Backspace' || e.key === 'Delete') {
- undoBatch(() => this.props.removeDoc(this.props.rowInfo.original));
- }
- };
+// @action
+// onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
+// console.log('yes');
+// if (e.key === 'Backspace' || e.key === 'Delete') {
+// undoBatch(() => this.props.removeDoc(this.props.rowInfo.original));
+// }
+// };
- render() {
- const { children = null, rowInfo } = this.props;
+// render() {
+// const { children = null, rowInfo } = this.props;
- if (!rowInfo) {
- return <ReactTableDefaults.TrComponent>{children}</ReactTableDefaults.TrComponent>;
- }
+// if (!rowInfo) {
+// return <ReactTableDefaults.TrComponent>{children}</ReactTableDefaults.TrComponent>;
+// }
- const { original } = rowInfo;
- const doc = FieldValue(Cast(original, Doc));
+// const { original } = rowInfo;
+// const doc = FieldValue(Cast(original, Doc));
- if (!doc) return null;
+// if (!doc) return null;
- const reference = React.createRef<HTMLDivElement>();
- const onItemDown = SetupDrag(reference, () => doc, this.move, StrCast(this.props.dropAction) as dropActionType);
+// const reference = React.createRef<HTMLDivElement>();
+// const onItemDown = SetupDrag(reference, () => doc, this.move, StrCast(this.props.dropAction) as dropActionType);
- let className = 'collectionSchema-row';
- if (this.props.rowFocused) className += ' row-focused';
- if (this.props.rowWrapped) className += ' row-wrapped';
+// let className = 'collectionSchema-row';
+// if (this.props.rowFocused) className += ' row-focused';
+// if (this.props.rowWrapped) className += ' row-wrapped';
- return (
- <div className={className} onKeyPress={this.onKeyDown} ref={this.createRowDropTarget} onContextMenu={this.onRowContextMenu}>
- <div className="collectionSchema-row-wrapper" onKeyPress={this.onKeyDown} ref={this._header} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}>
- <ReactTableDefaults.TrComponent onKeyPress={this.onKeyDown}>
- <div className="row-dragger">
- <div className="row-option" onClick={undoBatch(() => this.props.removeDoc(this.props.rowInfo.original))}>
- <FontAwesomeIcon icon="trash" size="sm" />
- </div>
- <div className="row-option" style={{ cursor: 'grab' }} ref={reference} onPointerDown={onItemDown}>
- <FontAwesomeIcon icon="grip-vertical" size="sm" />
- </div>
- <div className="row-option" onClick={() => this.props.addDocTab(this.props.rowInfo.original, OpenWhere.addRight)}>
- <FontAwesomeIcon icon="external-link-alt" size="sm" />
- </div>
- </div>
- {children}
- </ReactTableDefaults.TrComponent>
- </div>
- </div>
- );
- }
-}
+// return (
+// <div className={className} onKeyPress={this.onKeyDown} ref={this.createRowDropTarget} onContextMenu={this.onRowContextMenu}>
+// <div className="collectionSchema-row-wrapper" onKeyPress={this.onKeyDown} ref={this._header} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}>
+// <ReactTableDefaults.TrComponent onKeyPress={this.onKeyDown}>
+// <div className="row-dragger">
+// <div className="row-option" onClick={undoBatch(() => this.props.removeDoc(this.props.rowInfo.original))}>
+// <FontAwesomeIcon icon="trash" size="sm" />
+// </div>
+// <div className="row-option" style={{ cursor: 'grab' }} ref={reference} onPointerDown={onItemDown}>
+// <FontAwesomeIcon icon="grip-vertical" size="sm" />
+// </div>
+// <div className="row-option" onClick={() => this.props.addDocTab(this.props.rowInfo.original, OpenWhere.addRight)}>
+// <FontAwesomeIcon icon="external-link-alt" size="sm" />
+// </div>
+// </div>
+// {children}
+// </ReactTableDefaults.TrComponent>
+// </div>
+// </div>
+// );
+// }
+// }
diff --git a/src/client/views/collections/old_collectionSchema/OldCollectionSchemaView.tsx b/src/client/views/collections/old_collectionSchema/OldCollectionSchemaView.tsx
index 260db4b88..f3f09cbf0 100644
--- a/src/client/views/collections/old_collectionSchema/OldCollectionSchemaView.tsx
+++ b/src/client/views/collections/old_collectionSchema/OldCollectionSchemaView.tsx
@@ -1,649 +1,649 @@
-import React = require('react');
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, observable, untracked } from 'mobx';
-import { observer } from 'mobx-react';
-import Measure from 'react-measure';
-// import { Resize } from 'react-table';
-import { Doc, Opt } from '../../../../fields/Doc';
-import { List } from '../../../../fields/List';
-import { listSpec } from '../../../../fields/Schema';
-import { PastelSchemaPalette, SchemaHeaderField } from '../../../../fields/SchemaHeaderField';
-import { Cast, NumCast } from '../../../../fields/Types';
-import { TraceMobx } from '../../../../fields/util';
-import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents } from '../../../../Utils';
-import { DocUtils } from '../../../documents/Documents';
-import { SelectionManager } from '../../../util/SelectionManager';
-import { SnappingManager } from '../../../util/SnappingManager';
-import { Transform } from '../../../util/Transform';
-import { undoBatch } from '../../../util/UndoManager';
-import { ContextMenu } from '../../ContextMenu';
-import { ContextMenuProps } from '../../ContextMenuItem';
-import { COLLECTION_BORDER_WIDTH, SCHEMA_DIVIDER_WIDTH } from '../../global/globalCssVariables.scss';
-import { DocumentView } from '../../nodes/DocumentView';
-import { DefaultStyleProvider } from '../../StyleProvider';
-import { CollectionSubView } from '../CollectionSubView';
-import './CollectionSchemaView.scss';
-// import { SchemaTable } from './SchemaTable';
-// bcz: need to add drag and drop of rows and columns. This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
-
-export enum ColumnType {
- Any,
- Number,
- String,
- Boolean,
- Doc,
- Image,
- List,
- Date,
-}
-// this map should be used for keys that should have a const type of value
-const columnTypes: Map<string, ColumnType> = new Map([
- ['title', ColumnType.String],
- ['x', ColumnType.Number],
- ['y', ColumnType.Number],
- ['_width', ColumnType.Number],
- ['_height', ColumnType.Number],
- ['_nativeWidth', ColumnType.Number],
- ['_nativeHeight', ColumnType.Number],
- ['isPrototype', ColumnType.Boolean],
- ['_curPage', ColumnType.Number],
- ['_currentTimecode', ColumnType.Number],
- ['zIndex', ColumnType.Number],
-]);
-
-@observer
-export class CollectionSchemaView extends CollectionSubView() {
- private _previewCont?: HTMLDivElement;
-
- @observable _previewDoc: Doc | undefined = undefined;
- @observable _focusedTable: Doc = this.props.Document;
- @observable _col: any = '';
- @observable _menuWidth = 0;
- @observable _headerOpen = false;
- @observable _headerIsEditing = false;
- @observable _menuHeight = 0;
- @observable _pointerX = 0;
- @observable _pointerY = 0;
- @observable _openTypes: boolean = false;
-
- @computed get previewWidth() {
- return () => NumCast(this.props.Document.schemaPreviewWidth);
- }
- @computed get previewHeight() {
- return () => this.props.PanelHeight() - 2 * this.borderWidth;
- }
- @computed get tableWidth() {
- return this.props.PanelWidth() - 2 * this.borderWidth - Number(SCHEMA_DIVIDER_WIDTH) - this.previewWidth();
- }
- @computed get borderWidth() {
- return Number(COLLECTION_BORDER_WIDTH);
- }
- @computed get scale() {
- return this.props.ScreenToLocalTransform().Scale;
- }
- @computed get columns() {
- return Cast(this.props.Document._schemaHeaders, listSpec(SchemaHeaderField), []);
- }
- set columns(columns: SchemaHeaderField[]) {
- this.props.Document._schemaHeaders = new List<SchemaHeaderField>(columns);
- }
-
- @computed get menuCoordinates() {
- let searchx = 0;
- let searchy = 0;
- if (this.props.Document._searchDoc) {
- const el = document.getElementsByClassName('collectionSchemaView-searchContainer')[0];
- if (el !== undefined) {
- const rect = el.getBoundingClientRect();
- searchx = rect.x;
- searchy = rect.y;
- }
- }
- const x = Math.max(0, Math.min(document.body.clientWidth - this._menuWidth, this._pointerX)) - searchx;
- const y = Math.max(0, Math.min(document.body.clientHeight - this._menuHeight, this._pointerY)) - searchy;
- return this.props.ScreenToLocalTransform().transformPoint(x, y);
- }
-
- get documentKeys() {
- const docs = this.childDocs;
- const keys: { [key: string]: boolean } = {};
- // bcz: ugh. this is untracked since otherwise a large collection of documents will blast the server for all their fields.
- // then as each document's fields come back, we update the documents _proxies. Each time we do this, the whole schema will be
- // invalidated and re-rendered. This workaround will inquire all of the document fields before the options button is clicked.
- // then by the time the options button is clicked, all of the fields should be in place. If a new field is added while this menu
- // is displayed (unlikely) it won't show up until something else changes.
- //TODO Types
- untracked(() => docs.map(doc => Doc.GetAllPrototypes(doc).map(proto => Object.keys(proto).forEach(key => (keys[key] = false)))));
-
- this.columns.forEach(key => (keys[key.heading] = true));
- return Array.from(Object.keys(keys));
- }
-
- @action setHeaderIsEditing = (isEditing: boolean) => (this._headerIsEditing = isEditing);
-
- @undoBatch
- setColumnType = action((columnField: SchemaHeaderField, type: ColumnType): void => {
- this._openTypes = false;
- if (columnTypes.get(columnField.heading)) return;
-
- const columns = this.columns;
- const index = columns.indexOf(columnField);
- if (index > -1) {
- columnField.setType(NumCast(type));
- columns[index] = columnField;
- this.columns = columns;
- }
- });
-
- @undoBatch
- setColumnColor = (columnField: SchemaHeaderField, color: string): void => {
- const columns = this.columns;
- const index = columns.indexOf(columnField);
- if (index > -1) {
- columnField.setColor(color);
- columns[index] = columnField;
- this.columns = columns; // need to set the columns to trigger rerender
- }
- };
-
- @undoBatch
- @action
- setColumnSort = (columnField: SchemaHeaderField, descending: boolean | undefined) => {
- const columns = this.columns;
- columns.forEach(col => col.setDesc(undefined));
-
- const index = columns.findIndex(c => c.heading === columnField.heading);
- const column = columns[index];
- column.setDesc(descending);
- columns[index] = column;
- this.columns = columns;
- };
-
- renderTypes = (col: any) => {
- if (columnTypes.get(col.heading)) return null;
-
- const type = col.type;
-
- const anyType = (
- <div className={'columnMenu-option' + (type === ColumnType.Any ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.Any)}>
- <FontAwesomeIcon icon={'align-justify'} size="sm" />
- Any
- </div>
- );
-
- const numType = (
- <div className={'columnMenu-option' + (type === ColumnType.Number ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.Number)}>
- <FontAwesomeIcon icon={'hashtag'} size="sm" />
- Number
- </div>
- );
-
- const textType = (
- <div className={'columnMenu-option' + (type === ColumnType.String ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.String)}>
- <FontAwesomeIcon icon={'font'} size="sm" />
- Text
- </div>
- );
-
- const boolType = (
- <div className={'columnMenu-option' + (type === ColumnType.Boolean ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.Boolean)}>
- <FontAwesomeIcon icon={'check-square'} size="sm" />
- Checkbox
- </div>
- );
-
- const listType = (
- <div className={'columnMenu-option' + (type === ColumnType.List ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.List)}>
- <FontAwesomeIcon icon={'list-ul'} size="sm" />
- List
- </div>
- );
-
- const docType = (
- <div className={'columnMenu-option' + (type === ColumnType.Doc ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.Doc)}>
- <FontAwesomeIcon icon={'file'} size="sm" />
- Document
- </div>
- );
-
- const imageType = (
- <div className={'columnMenu-option' + (type === ColumnType.Image ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.Image)}>
- <FontAwesomeIcon icon={'image'} size="sm" />
- Image
- </div>
- );
-
- const dateType = (
- <div className={'columnMenu-option' + (type === ColumnType.Date ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.Date)}>
- <FontAwesomeIcon icon={'calendar'} size="sm" />
- Date
- </div>
- );
-
- const allColumnTypes = (
- <div className="columnMenu-types">
- {anyType}
- {numType}
- {textType}
- {boolType}
- {listType}
- {docType}
- {imageType}
- {dateType}
- </div>
- );
-
- const justColType =
- type === ColumnType.Any
- ? anyType
- : type === ColumnType.Number
- ? numType
- : type === ColumnType.String
- ? textType
- : type === ColumnType.Boolean
- ? boolType
- : type === ColumnType.List
- ? listType
- : type === ColumnType.Doc
- ? docType
- : type === ColumnType.Date
- ? dateType
- : imageType;
-
- return (
- <div className="collectionSchema-headerMenu-group" onClick={action(() => (this._openTypes = !this._openTypes))}>
- <div>
- <label style={{ cursor: 'pointer' }}>Column type:</label>
- <FontAwesomeIcon icon={'caret-down'} size="lg" style={{ float: 'right', transform: `rotate(${this._openTypes ? '180deg' : 0})`, transition: '0.2s all ease' }} />
- </div>
- {this._openTypes ? allColumnTypes : justColType}
- </div>
- );
- };
-
- renderSorting = (col: any) => {
- const sort = col.desc;
- return (
- <div className="collectionSchema-headerMenu-group">
- <label>Sort by:</label>
- <div className="columnMenu-sort">
- <div className={'columnMenu-option' + (sort === true ? ' active' : '')} onClick={() => this.setColumnSort(col, true)}>
- <FontAwesomeIcon icon="sort-amount-down" size="sm" />
- Sort descending
- </div>
- <div className={'columnMenu-option' + (sort === false ? ' active' : '')} onClick={() => this.setColumnSort(col, false)}>
- <FontAwesomeIcon icon="sort-amount-up" size="sm" />
- Sort ascending
- </div>
- <div className="columnMenu-option" onClick={() => this.setColumnSort(col, undefined)}>
- <FontAwesomeIcon icon="times" size="sm" />
- Clear sorting
- </div>
- </div>
- </div>
- );
- };
-
- renderColors = (col: any) => {
- const selected = col.color;
-
- const pink = PastelSchemaPalette.get('pink2');
- const purple = PastelSchemaPalette.get('purple2');
- const blue = PastelSchemaPalette.get('bluegreen1');
- const yellow = PastelSchemaPalette.get('yellow4');
- const red = PastelSchemaPalette.get('red2');
- const gray = '#f1efeb';
-
- return (
- <div className="collectionSchema-headerMenu-group">
- <label>Color:</label>
- <div className="columnMenu-colors">
- <div className={'columnMenu-colorPicker' + (selected === pink ? ' active' : '')} style={{ backgroundColor: pink }} onClick={() => this.setColumnColor(col, pink!)}></div>
- <div className={'columnMenu-colorPicker' + (selected === purple ? ' active' : '')} style={{ backgroundColor: purple }} onClick={() => this.setColumnColor(col, purple!)}></div>
- <div className={'columnMenu-colorPicker' + (selected === blue ? ' active' : '')} style={{ backgroundColor: blue }} onClick={() => this.setColumnColor(col, blue!)}></div>
- <div className={'columnMenu-colorPicker' + (selected === yellow ? ' active' : '')} style={{ backgroundColor: yellow }} onClick={() => this.setColumnColor(col, yellow!)}></div>
- <div className={'columnMenu-colorPicker' + (selected === red ? ' active' : '')} style={{ backgroundColor: red }} onClick={() => this.setColumnColor(col, red!)}></div>
- <div className={'columnMenu-colorPicker' + (selected === gray ? ' active' : '')} style={{ backgroundColor: gray }} onClick={() => this.setColumnColor(col, gray)}></div>
- </div>
- </div>
- );
- };
-
- @undoBatch
- @action
- changeColumns = (oldKey: string, newKey: string, addNew: boolean, filter?: string) => {
- const columns = this.columns;
- if (columns === undefined) {
- this.columns = new List<SchemaHeaderField>([new SchemaHeaderField(newKey, 'f1efeb')]);
- } else {
- if (addNew) {
- columns.push(new SchemaHeaderField(newKey, 'f1efeb'));
- this.columns = columns;
- } else {
- const index = columns.map(c => c.heading).indexOf(oldKey);
- if (index > -1) {
- const column = columns[index];
- column.setHeading(newKey);
- columns[index] = column;
- this.columns = columns;
- if (filter) {
- Doc.setDocFilter(this.props.Document, newKey, filter, 'match');
- } else {
- this.props.Document._docFilters = undefined;
- }
- }
- }
- }
- };
-
- @action
- openHeader = (col: any, screenx: number, screeny: number) => {
- this._col = col;
- this._headerOpen = true;
- this._pointerX = screenx;
- this._pointerY = screeny;
- };
-
- @action
- closeHeader = () => {
- this._headerOpen = false;
- };
-
- @undoBatch
- @action
- deleteColumn = (key: string) => {
- const columns = this.columns;
- if (columns === undefined) {
- this.columns = new List<SchemaHeaderField>([]);
- } else {
- const index = columns.map(c => c.heading).indexOf(key);
- if (index > -1) {
- columns.splice(index, 1);
- this.columns = columns;
- }
- }
- this.closeHeader();
- };
-
- getPreviewTransform = (): Transform => {
- return this.props.ScreenToLocalTransform().translate(-this.borderWidth - NumCast(COLLECTION_BORDER_WIDTH) - this.tableWidth, -this.borderWidth);
- };
-
- @action
- onHeaderClick = (e: React.PointerEvent) => {
- e.stopPropagation();
- };
-
- @action
- onWheel(e: React.WheelEvent) {
- const scale = this.props.ScreenToLocalTransform().Scale;
- this.props.isContentActive(true) && e.stopPropagation();
- }
-
- @computed get renderMenuContent() {
- TraceMobx();
- return (
- <div className="collectionSchema-header-menuOptions">
- {this.renderTypes(this._col)}
- {this.renderColors(this._col)}
- <div className="collectionSchema-headerMenu-group">
- <button
- onClick={() => {
- this.deleteColumn(this._col.heading);
- }}>
- Hide Column
- </button>
- </div>
- </div>
- );
- }
-
- private createTarget = (ele: HTMLDivElement) => {
- this._previewCont = ele;
- super.CreateDropTarget(ele);
- };
-
- isFocused = (doc: Doc, outsideReaction: boolean): boolean => this.props.isSelected(outsideReaction) && doc === this._focusedTable;
-
- @action setFocused = (doc: Doc) => (this._focusedTable = doc);
-
- @action setPreviewDoc = (doc: Opt<Doc>) => {
- SelectionManager.SelectSchemaViewDoc(doc);
- this._previewDoc = doc;
- };
-
- //toggles preview side-panel of schema
- @action
- toggleExpander = () => {
- this.props.Document.schemaPreviewWidth = this.previewWidth() === 0 ? Math.min(this.tableWidth / 3, 200) : 0;
- };
-
- onDividerDown = (e: React.PointerEvent) => {
- setupMoveUpEvents(this, e, this.onDividerMove, emptyFunction, this.toggleExpander);
- };
- @action
- onDividerMove = (e: PointerEvent, down: number[], delta: number[]) => {
- const nativeWidth = this._previewCont!.getBoundingClientRect();
- const minWidth = 40;
- const maxWidth = 1000;
- const movedWidth = this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0];
- const width = movedWidth < minWidth ? minWidth : movedWidth > maxWidth ? maxWidth : movedWidth;
- this.props.Document.schemaPreviewWidth = width;
- return false;
- };
-
- onPointerDown = (e: React.PointerEvent): void => {
- if (e.button === 0 && !e.altKey && !e.ctrlKey && !e.metaKey) {
- if (this.props.isSelected(true)) e.stopPropagation();
- else this.props.select(false);
- }
- };
-
- @computed
- get previewDocument(): Doc | undefined {
- return this._previewDoc;
- }
-
- @computed
- get dividerDragger() {
- return this.previewWidth() === 0 ? null : (
- <div className="collectionSchemaView-dividerDragger" onPointerDown={this.onDividerDown}>
- <div className="collectionSchemaView-dividerDragger" />
- </div>
- );
- }
-
- @computed
- get previewPanel() {
- return (
- <div ref={this.createTarget} style={{ width: `${this.previewWidth()}px` }}>
- {!this.previewDocument ? null : (
- <DocumentView
- Document={this.previewDocument}
- DataDoc={undefined}
- fitContentsToBox={returnTrue}
- dontCenter={'y'}
- focus={DocUtils.DefaultFocus}
- renderDepth={this.props.renderDepth}
- rootSelected={this.rootSelected}
- PanelWidth={this.previewWidth}
- PanelHeight={this.previewHeight}
- isContentActive={returnTrue}
- isDocumentActive={returnFalse}
- ScreenToLocalTransform={this.getPreviewTransform}
- docFilters={this.childDocFilters}
- docRangeFilters={this.childDocRangeFilters}
- searchFilterDocs={this.searchFilterDocs}
- styleProvider={DefaultStyleProvider}
- docViewPath={returnEmptyDoclist}
- ContainingCollectionDoc={this.props.CollectionView?.props.Document}
- ContainingCollectionView={this.props.CollectionView}
- moveDocument={this.props.moveDocument}
- addDocument={this.props.addDocument}
- removeDocument={this.props.removeDocument}
- whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged}
- addDocTab={this.props.addDocTab}
- pinToPres={this.props.pinToPres}
- bringToFront={returnFalse}
- />
- )}
- </div>
- );
- }
-
- @computed
- get schemaTable() {
- return (
- <SchemaTable
- Document={this.props.Document}
- PanelHeight={this.props.PanelHeight}
- PanelWidth={this.props.PanelWidth}
- childDocs={this.childDocs}
- CollectionView={this.props.CollectionView}
- ContainingCollectionView={this.props.ContainingCollectionView}
- ContainingCollectionDoc={this.props.ContainingCollectionDoc}
- fieldKey={this.props.fieldKey}
- renderDepth={this.props.renderDepth}
- moveDocument={this.props.moveDocument}
- ScreenToLocalTransform={this.props.ScreenToLocalTransform}
- active={this.props.isContentActive}
- onDrop={this.onExternalDrop}
- addDocTab={this.props.addDocTab}
- pinToPres={this.props.pinToPres}
- isSelected={this.props.isSelected}
- isFocused={this.isFocused}
- setFocused={this.setFocused}
- setPreviewDoc={this.setPreviewDoc}
- deleteDocument={this.props.removeDocument}
- addDocument={this.props.addDocument}
- dataDoc={this.props.DataDoc}
- columns={this.columns}
- documentKeys={this.documentKeys}
- headerIsEditing={this._headerIsEditing}
- openHeader={this.openHeader}
- onClick={this.onTableClick}
- onPointerDown={emptyFunction}
- onResizedChange={this.onResizedChange}
- setColumns={this.setColumns}
- reorderColumns={this.reorderColumns}
- changeColumns={this.changeColumns}
- setHeaderIsEditing={this.setHeaderIsEditing}
- changeColumnSort={this.setColumnSort}
- />
- );
- }
-
- @computed
- public get schemaToolbar() {
- return (
- <div className="collectionSchemaView-toolbar">
- <div className="collectionSchemaView-toolbar-item">
- <div id="preview-schema-checkbox-div">
- <input type="checkbox" key={'Show Preview'} checked={this.previewWidth() !== 0} onChange={this.toggleExpander} />
- Show Preview
- </div>
- </div>
- </div>
- );
- }
-
- onSpecificMenu = (e: React.MouseEvent) => {
- if ((e.target as any)?.className?.includes?.('collectionSchemaView-cell') || e.target instanceof HTMLSpanElement) {
- const cm = ContextMenu.Instance;
- const options = cm.findByDescription('Options...');
- const optionItems: ContextMenuProps[] = options && 'subitems' in options ? options.subitems : [];
- optionItems.push({ description: 'remove', event: () => this._previewDoc && this.props.removeDocument?.(this._previewDoc), icon: 'trash' });
- !options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'compass' });
- cm.displayMenu(e.clientX, e.clientY);
- (e.nativeEvent as any).SchemaHandled = true; // not sure why this is needed, but if you right-click quickly on a cell, the Document/Collection contextMenu handlers still fire without this.
- e.stopPropagation();
- }
- };
-
- @action
- onTableClick = (e: React.MouseEvent): void => {
- if (!(e.target as any)?.className?.includes?.('collectionSchemaView-cell') && !(e.target instanceof HTMLSpanElement)) {
- this.setPreviewDoc(undefined);
- } else {
- e.stopPropagation();
- }
- this.setFocused(this.props.Document);
- this.closeHeader();
- };
-
- onResizedChange = (newResized: Resize[], event: any) => {
- const columns = this.columns;
- newResized.forEach(resized => {
- const index = columns.findIndex(c => c.heading === resized.id);
- const column = columns[index];
- column.setWidth(resized.value);
- columns[index] = column;
- });
- this.columns = columns;
- };
-
- @action
- setColumns = (columns: SchemaHeaderField[]) => (this.columns = columns);
-
- @undoBatch
- reorderColumns = (toMove: SchemaHeaderField, relativeTo: SchemaHeaderField, before: boolean, columnsValues: SchemaHeaderField[]) => {
- const columns = [...columnsValues];
- const oldIndex = columns.indexOf(toMove);
- const relIndex = columns.indexOf(relativeTo);
- const newIndex = oldIndex > relIndex && !before ? relIndex + 1 : oldIndex < relIndex && before ? relIndex - 1 : relIndex;
-
- if (oldIndex === newIndex) return;
-
- columns.splice(newIndex, 0, columns.splice(oldIndex, 1)[0]);
- this.columns = columns;
- };
-
- onZoomMenu = (e: React.WheelEvent) => this.props.isContentActive(true) && e.stopPropagation();
-
- render() {
- TraceMobx();
- if (!this.props.isContentActive()) setTimeout(() => this.closeHeader(), 0);
- const menuContent = this.renderMenuContent;
- const menu = (
- <div className="collectionSchema-header-menu" onWheel={e => this.onZoomMenu(e)} onPointerDown={e => this.onHeaderClick(e)} style={{ transform: `translate(${this.menuCoordinates[0]}px, ${this.menuCoordinates[1]}px)` }}>
- <Measure
- offset
- onResize={action((r: any) => {
- const dim = this.props.ScreenToLocalTransform().inverse().transformDirection(r.offset.width, r.offset.height);
- this._menuWidth = dim[0];
- this._menuHeight = dim[1];
- })}>
- {({ measureRef }) => <div ref={measureRef}> {menuContent} </div>}
- </Measure>
- </div>
- );
- return (
- <div
- className={'collectionSchemaView' + (this.props.Document._searchDoc ? '-searchContainer' : '-container')}
- style={{
- overflow: this.props.scrollOverflow === true ? 'scroll' : undefined,
- backgroundColor: 'white',
- pointerEvents: this.props.Document._searchDoc !== undefined && !this.props.isContentActive() && !SnappingManager.GetIsDragging() ? 'none' : undefined,
- width: this.props.PanelWidth() || '100%',
- height: this.props.PanelHeight() || '100%',
- position: 'relative',
- }}>
- <div
- className="collectionSchemaView-tableContainer"
- style={{ width: `calc(100% - ${this.previewWidth()}px)` }}
- onContextMenu={this.onSpecificMenu}
- onPointerDown={this.onPointerDown}
- onWheel={e => this.props.isContentActive(true) && e.stopPropagation()}
- onDrop={e => this.onExternalDrop(e, {})}
- ref={this.createTarget}>
- {this.schemaTable}
- </div>
- {this.dividerDragger}
- {!this.previewWidth() ? null : this.previewPanel}
- {this._headerOpen && this.props.isContentActive() ? menu : null}
- </div>
- );
- TraceMobx();
- return <div>HELLO</div>;
- }
-}
+// import React = require('react');
+// import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+// import { action, computed, observable, untracked } from 'mobx';
+// import { observer } from 'mobx-react';
+// import Measure from 'react-measure';
+// // import { Resize } from 'react-table';
+// import { Doc, Opt } from '../../../../fields/Doc';
+// import { List } from '../../../../fields/List';
+// import { listSpec } from '../../../../fields/Schema';
+// import { PastelSchemaPalette, SchemaHeaderField } from '../../../../fields/SchemaHeaderField';
+// import { Cast, NumCast } from '../../../../fields/Types';
+// import { TraceMobx } from '../../../../fields/util';
+// import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents } from '../../../../Utils';
+// import { DocUtils } from '../../../documents/Documents';
+// import { SelectionManager } from '../../../util/SelectionManager';
+// import { SnappingManager } from '../../../util/SnappingManager';
+// import { Transform } from '../../../util/Transform';
+// import { undoBatch } from '../../../util/UndoManager';
+// import { ContextMenu } from '../../ContextMenu';
+// import { ContextMenuProps } from '../../ContextMenuItem';
+// import { COLLECTION_BORDER_WIDTH, SCHEMA_DIVIDER_WIDTH } from '../../global/globalCssVariables.scss';
+// import { DocumentView } from '../../nodes/DocumentView';
+// import { DefaultStyleProvider } from '../../StyleProvider';
+// import { CollectionSubView } from '../CollectionSubView';
+// import './CollectionSchemaView.scss';
+// // import { SchemaTable } from './SchemaTable';
+// // bcz: need to add drag and drop of rows and columns. This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
+
+// export enum ColumnType {
+// Any,
+// Number,
+// String,
+// Boolean,
+// Doc,
+// Image,
+// List,
+// Date,
+// }
+// // this map should be used for keys that should have a const type of value
+// const columnTypes: Map<string, ColumnType> = new Map([
+// ['title', ColumnType.String],
+// ['x', ColumnType.Number],
+// ['y', ColumnType.Number],
+// ['_width', ColumnType.Number],
+// ['_height', ColumnType.Number],
+// ['_nativeWidth', ColumnType.Number],
+// ['_nativeHeight', ColumnType.Number],
+// ['isPrototype', ColumnType.Boolean],
+// ['_curPage', ColumnType.Number],
+// ['_currentTimecode', ColumnType.Number],
+// ['zIndex', ColumnType.Number],
+// ]);
+
+// @observer
+// export class CollectionSchemaView extends CollectionSubView() {
+// private _previewCont?: HTMLDivElement;
+
+// @observable _previewDoc: Doc | undefined = undefined;
+// @observable _focusedTable: Doc = this.props.Document;
+// @observable _col: any = '';
+// @observable _menuWidth = 0;
+// @observable _headerOpen = false;
+// @observable _headerIsEditing = false;
+// @observable _menuHeight = 0;
+// @observable _pointerX = 0;
+// @observable _pointerY = 0;
+// @observable _openTypes: boolean = false;
+
+// @computed get previewWidth() {
+// return () => NumCast(this.props.Document.schemaPreviewWidth);
+// }
+// @computed get previewHeight() {
+// return () => this.props.PanelHeight() - 2 * this.borderWidth;
+// }
+// @computed get tableWidth() {
+// return this.props.PanelWidth() - 2 * this.borderWidth - Number(SCHEMA_DIVIDER_WIDTH) - this.previewWidth();
+// }
+// @computed get borderWidth() {
+// return Number(COLLECTION_BORDER_WIDTH);
+// }
+// @computed get scale() {
+// return this.props.ScreenToLocalTransform().Scale;
+// }
+// @computed get columns() {
+// return Cast(this.props.Document._schemaHeaders, listSpec(SchemaHeaderField), []);
+// }
+// set columns(columns: SchemaHeaderField[]) {
+// this.props.Document._schemaHeaders = new List<SchemaHeaderField>(columns);
+// }
+
+// @computed get menuCoordinates() {
+// let searchx = 0;
+// let searchy = 0;
+// if (this.props.Document._searchDoc) {
+// const el = document.getElementsByClassName('collectionSchemaView-searchContainer')[0];
+// if (el !== undefined) {
+// const rect = el.getBoundingClientRect();
+// searchx = rect.x;
+// searchy = rect.y;
+// }
+// }
+// const x = Math.max(0, Math.min(document.body.clientWidth - this._menuWidth, this._pointerX)) - searchx;
+// const y = Math.max(0, Math.min(document.body.clientHeight - this._menuHeight, this._pointerY)) - searchy;
+// return this.props.ScreenToLocalTransform().transformPoint(x, y);
+// }
+
+// get documentKeys() {
+// const docs = this.childDocs;
+// const keys: { [key: string]: boolean } = {};
+// // bcz: ugh. this is untracked since otherwise a large collection of documents will blast the server for all their fields.
+// // then as each document's fields come back, we update the documents _proxies. Each time we do this, the whole schema will be
+// // invalidated and re-rendered. This workaround will inquire all of the document fields before the options button is clicked.
+// // then by the time the options button is clicked, all of the fields should be in place. If a new field is added while this menu
+// // is displayed (unlikely) it won't show up until something else changes.
+// //TODO Types
+// untracked(() => docs.map(doc => Doc.GetAllPrototypes(doc).map(proto => Object.keys(proto).forEach(key => (keys[key] = false)))));
+
+// this.columns.forEach(key => (keys[key.heading] = true));
+// return Array.from(Object.keys(keys));
+// }
+
+// @action setHeaderIsEditing = (isEditing: boolean) => (this._headerIsEditing = isEditing);
+
+// @undoBatch
+// setColumnType = action((columnField: SchemaHeaderField, type: ColumnType): void => {
+// this._openTypes = false;
+// if (columnTypes.get(columnField.heading)) return;
+
+// const columns = this.columns;
+// const index = columns.indexOf(columnField);
+// if (index > -1) {
+// columnField.setType(NumCast(type));
+// columns[index] = columnField;
+// this.columns = columns;
+// }
+// });
+
+// @undoBatch
+// setColumnColor = (columnField: SchemaHeaderField, color: string): void => {
+// const columns = this.columns;
+// const index = columns.indexOf(columnField);
+// if (index > -1) {
+// columnField.setColor(color);
+// columns[index] = columnField;
+// this.columns = columns; // need to set the columns to trigger rerender
+// }
+// };
+
+// @undoBatch
+// @action
+// setColumnSort = (columnField: SchemaHeaderField, descending: boolean | undefined) => {
+// const columns = this.columns;
+// columns.forEach(col => col.setDesc(undefined));
+
+// const index = columns.findIndex(c => c.heading === columnField.heading);
+// const column = columns[index];
+// column.setDesc(descending);
+// columns[index] = column;
+// this.columns = columns;
+// };
+
+// renderTypes = (col: any) => {
+// if (columnTypes.get(col.heading)) return null;
+
+// const type = col.type;
+
+// const anyType = (
+// <div className={'columnMenu-option' + (type === ColumnType.Any ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.Any)}>
+// <FontAwesomeIcon icon={'align-justify'} size="sm" />
+// Any
+// </div>
+// );
+
+// const numType = (
+// <div className={'columnMenu-option' + (type === ColumnType.Number ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.Number)}>
+// <FontAwesomeIcon icon={'hashtag'} size="sm" />
+// Number
+// </div>
+// );
+
+// const textType = (
+// <div className={'columnMenu-option' + (type === ColumnType.String ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.String)}>
+// <FontAwesomeIcon icon={'font'} size="sm" />
+// Text
+// </div>
+// );
+
+// const boolType = (
+// <div className={'columnMenu-option' + (type === ColumnType.Boolean ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.Boolean)}>
+// <FontAwesomeIcon icon={'check-square'} size="sm" />
+// Checkbox
+// </div>
+// );
+
+// const listType = (
+// <div className={'columnMenu-option' + (type === ColumnType.List ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.List)}>
+// <FontAwesomeIcon icon={'list-ul'} size="sm" />
+// List
+// </div>
+// );
+
+// const docType = (
+// <div className={'columnMenu-option' + (type === ColumnType.Doc ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.Doc)}>
+// <FontAwesomeIcon icon={'file'} size="sm" />
+// Document
+// </div>
+// );
+
+// const imageType = (
+// <div className={'columnMenu-option' + (type === ColumnType.Image ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.Image)}>
+// <FontAwesomeIcon icon={'image'} size="sm" />
+// Image
+// </div>
+// );
+
+// const dateType = (
+// <div className={'columnMenu-option' + (type === ColumnType.Date ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.Date)}>
+// <FontAwesomeIcon icon={'calendar'} size="sm" />
+// Date
+// </div>
+// );
+
+// const allColumnTypes = (
+// <div className="columnMenu-types">
+// {anyType}
+// {numType}
+// {textType}
+// {boolType}
+// {listType}
+// {docType}
+// {imageType}
+// {dateType}
+// </div>
+// );
+
+// const justColType =
+// type === ColumnType.Any
+// ? anyType
+// : type === ColumnType.Number
+// ? numType
+// : type === ColumnType.String
+// ? textType
+// : type === ColumnType.Boolean
+// ? boolType
+// : type === ColumnType.List
+// ? listType
+// : type === ColumnType.Doc
+// ? docType
+// : type === ColumnType.Date
+// ? dateType
+// : imageType;
+
+// return (
+// <div className="collectionSchema-headerMenu-group" onClick={action(() => (this._openTypes = !this._openTypes))}>
+// <div>
+// <label style={{ cursor: 'pointer' }}>Column type:</label>
+// <FontAwesomeIcon icon={'caret-down'} size="lg" style={{ float: 'right', transform: `rotate(${this._openTypes ? '180deg' : 0})`, transition: '0.2s all ease' }} />
+// </div>
+// {this._openTypes ? allColumnTypes : justColType}
+// </div>
+// );
+// };
+
+// renderSorting = (col: any) => {
+// const sort = col.desc;
+// return (
+// <div className="collectionSchema-headerMenu-group">
+// <label>Sort by:</label>
+// <div className="columnMenu-sort">
+// <div className={'columnMenu-option' + (sort === true ? ' active' : '')} onClick={() => this.setColumnSort(col, true)}>
+// <FontAwesomeIcon icon="sort-amount-down" size="sm" />
+// Sort descending
+// </div>
+// <div className={'columnMenu-option' + (sort === false ? ' active' : '')} onClick={() => this.setColumnSort(col, false)}>
+// <FontAwesomeIcon icon="sort-amount-up" size="sm" />
+// Sort ascending
+// </div>
+// <div className="columnMenu-option" onClick={() => this.setColumnSort(col, undefined)}>
+// <FontAwesomeIcon icon="times" size="sm" />
+// Clear sorting
+// </div>
+// </div>
+// </div>
+// );
+// };
+
+// renderColors = (col: any) => {
+// const selected = col.color;
+
+// const pink = PastelSchemaPalette.get('pink2');
+// const purple = PastelSchemaPalette.get('purple2');
+// const blue = PastelSchemaPalette.get('bluegreen1');
+// const yellow = PastelSchemaPalette.get('yellow4');
+// const red = PastelSchemaPalette.get('red2');
+// const gray = '#f1efeb';
+
+// return (
+// <div className="collectionSchema-headerMenu-group">
+// <label>Color:</label>
+// <div className="columnMenu-colors">
+// <div className={'columnMenu-colorPicker' + (selected === pink ? ' active' : '')} style={{ backgroundColor: pink }} onClick={() => this.setColumnColor(col, pink!)}></div>
+// <div className={'columnMenu-colorPicker' + (selected === purple ? ' active' : '')} style={{ backgroundColor: purple }} onClick={() => this.setColumnColor(col, purple!)}></div>
+// <div className={'columnMenu-colorPicker' + (selected === blue ? ' active' : '')} style={{ backgroundColor: blue }} onClick={() => this.setColumnColor(col, blue!)}></div>
+// <div className={'columnMenu-colorPicker' + (selected === yellow ? ' active' : '')} style={{ backgroundColor: yellow }} onClick={() => this.setColumnColor(col, yellow!)}></div>
+// <div className={'columnMenu-colorPicker' + (selected === red ? ' active' : '')} style={{ backgroundColor: red }} onClick={() => this.setColumnColor(col, red!)}></div>
+// <div className={'columnMenu-colorPicker' + (selected === gray ? ' active' : '')} style={{ backgroundColor: gray }} onClick={() => this.setColumnColor(col, gray)}></div>
+// </div>
+// </div>
+// );
+// };
+
+// @undoBatch
+// @action
+// changeColumns = (oldKey: string, newKey: string, addNew: boolean, filter?: string) => {
+// const columns = this.columns;
+// if (columns === undefined) {
+// this.columns = new List<SchemaHeaderField>([new SchemaHeaderField(newKey, 'f1efeb')]);
+// } else {
+// if (addNew) {
+// columns.push(new SchemaHeaderField(newKey, 'f1efeb'));
+// this.columns = columns;
+// } else {
+// const index = columns.map(c => c.heading).indexOf(oldKey);
+// if (index > -1) {
+// const column = columns[index];
+// column.setHeading(newKey);
+// columns[index] = column;
+// this.columns = columns;
+// if (filter) {
+// Doc.setDocFilter(this.props.Document, newKey, filter, 'match');
+// } else {
+// this.props.Document._docFilters = undefined;
+// }
+// }
+// }
+// }
+// };
+
+// @action
+// openHeader = (col: any, screenx: number, screeny: number) => {
+// this._col = col;
+// this._headerOpen = true;
+// this._pointerX = screenx;
+// this._pointerY = screeny;
+// };
+
+// @action
+// closeHeader = () => {
+// this._headerOpen = false;
+// };
+
+// @undoBatch
+// @action
+// deleteColumn = (key: string) => {
+// const columns = this.columns;
+// if (columns === undefined) {
+// this.columns = new List<SchemaHeaderField>([]);
+// } else {
+// const index = columns.map(c => c.heading).indexOf(key);
+// if (index > -1) {
+// columns.splice(index, 1);
+// this.columns = columns;
+// }
+// }
+// this.closeHeader();
+// };
+
+// getPreviewTransform = (): Transform => {
+// return this.props.ScreenToLocalTransform().translate(-this.borderWidth - NumCast(COLLECTION_BORDER_WIDTH) - this.tableWidth, -this.borderWidth);
+// };
+
+// @action
+// onHeaderClick = (e: React.PointerEvent) => {
+// e.stopPropagation();
+// };
+
+// @action
+// onWheel(e: React.WheelEvent) {
+// const scale = this.props.ScreenToLocalTransform().Scale;
+// this.props.isContentActive(true) && e.stopPropagation();
+// }
+
+// @computed get renderMenuContent() {
+// TraceMobx();
+// return (
+// <div className="collectionSchema-header-menuOptions">
+// {this.renderTypes(this._col)}
+// {this.renderColors(this._col)}
+// <div className="collectionSchema-headerMenu-group">
+// <button
+// onClick={() => {
+// this.deleteColumn(this._col.heading);
+// }}>
+// Hide Column
+// </button>
+// </div>
+// </div>
+// );
+// }
+
+// private createTarget = (ele: HTMLDivElement) => {
+// this._previewCont = ele;
+// super.CreateDropTarget(ele);
+// };
+
+// isFocused = (doc: Doc, outsideReaction: boolean): boolean => this.props.isSelected(outsideReaction) && doc === this._focusedTable;
+
+// @action setFocused = (doc: Doc) => (this._focusedTable = doc);
+
+// @action setPreviewDoc = (doc: Opt<Doc>) => {
+// SelectionManager.SelectSchemaViewDoc(doc);
+// this._previewDoc = doc;
+// };
+
+// //toggles preview side-panel of schema
+// @action
+// toggleExpander = () => {
+// this.props.Document.schemaPreviewWidth = this.previewWidth() === 0 ? Math.min(this.tableWidth / 3, 200) : 0;
+// };
+
+// onDividerDown = (e: React.PointerEvent) => {
+// setupMoveUpEvents(this, e, this.onDividerMove, emptyFunction, this.toggleExpander);
+// };
+// @action
+// onDividerMove = (e: PointerEvent, down: number[], delta: number[]) => {
+// const nativeWidth = this._previewCont!.getBoundingClientRect();
+// const minWidth = 40;
+// const maxWidth = 1000;
+// const movedWidth = this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0];
+// const width = movedWidth < minWidth ? minWidth : movedWidth > maxWidth ? maxWidth : movedWidth;
+// this.props.Document.schemaPreviewWidth = width;
+// return false;
+// };
+
+// onPointerDown = (e: React.PointerEvent): void => {
+// if (e.button === 0 && !e.altKey && !e.ctrlKey && !e.metaKey) {
+// if (this.props.isSelected(true)) e.stopPropagation();
+// else this.props.select(false);
+// }
+// };
+
+// @computed
+// get previewDocument(): Doc | undefined {
+// return this._previewDoc;
+// }
+
+// @computed
+// get dividerDragger() {
+// return this.previewWidth() === 0 ? null : (
+// <div className="collectionSchemaView-dividerDragger" onPointerDown={this.onDividerDown}>
+// <div className="collectionSchemaView-dividerDragger" />
+// </div>
+// );
+// }
+
+// @computed
+// get previewPanel() {
+// return (
+// <div ref={this.createTarget} style={{ width: `${this.previewWidth()}px` }}>
+// {!this.previewDocument ? null : (
+// <DocumentView
+// Document={this.previewDocument}
+// DataDoc={undefined}
+// fitContentsToBox={returnTrue}
+// dontCenter={'y'}
+// focus={DocUtils.DefaultFocus}
+// renderDepth={this.props.renderDepth}
+// rootSelected={this.rootSelected}
+// PanelWidth={this.previewWidth}
+// PanelHeight={this.previewHeight}
+// isContentActive={returnTrue}
+// isDocumentActive={returnFalse}
+// ScreenToLocalTransform={this.getPreviewTransform}
+// docFilters={this.childDocFilters}
+// docRangeFilters={this.childDocRangeFilters}
+// searchFilterDocs={this.searchFilterDocs}
+// styleProvider={DefaultStyleProvider}
+// docViewPath={returnEmptyDoclist}
+// ContainingCollectionDoc={this.props.CollectionView?.props.Document}
+// ContainingCollectionView={this.props.CollectionView}
+// moveDocument={this.props.moveDocument}
+// addDocument={this.props.addDocument}
+// removeDocument={this.props.removeDocument}
+// whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged}
+// addDocTab={this.props.addDocTab}
+// pinToPres={this.props.pinToPres}
+// bringToFront={returnFalse}
+// />
+// )}
+// </div>
+// );
+// }
+
+// @computed
+// get schemaTable() {
+// return (
+// <SchemaTable
+// Document={this.props.Document}
+// PanelHeight={this.props.PanelHeight}
+// PanelWidth={this.props.PanelWidth}
+// childDocs={this.childDocs}
+// CollectionView={this.props.CollectionView}
+// ContainingCollectionView={this.props.ContainingCollectionView}
+// ContainingCollectionDoc={this.props.ContainingCollectionDoc}
+// fieldKey={this.props.fieldKey}
+// renderDepth={this.props.renderDepth}
+// moveDocument={this.props.moveDocument}
+// ScreenToLocalTransform={this.props.ScreenToLocalTransform}
+// active={this.props.isContentActive}
+// onDrop={this.onExternalDrop}
+// addDocTab={this.props.addDocTab}
+// pinToPres={this.props.pinToPres}
+// isSelected={this.props.isSelected}
+// isFocused={this.isFocused}
+// setFocused={this.setFocused}
+// setPreviewDoc={this.setPreviewDoc}
+// deleteDocument={this.props.removeDocument}
+// addDocument={this.props.addDocument}
+// dataDoc={this.props.DataDoc}
+// columns={this.columns}
+// documentKeys={this.documentKeys}
+// headerIsEditing={this._headerIsEditing}
+// openHeader={this.openHeader}
+// onClick={this.onTableClick}
+// onPointerDown={emptyFunction}
+// onResizedChange={this.onResizedChange}
+// setColumns={this.setColumns}
+// reorderColumns={this.reorderColumns}
+// changeColumns={this.changeColumns}
+// setHeaderIsEditing={this.setHeaderIsEditing}
+// changeColumnSort={this.setColumnSort}
+// />
+// );
+// }
+
+// @computed
+// public get schemaToolbar() {
+// return (
+// <div className="collectionSchemaView-toolbar">
+// <div className="collectionSchemaView-toolbar-item">
+// <div id="preview-schema-checkbox-div">
+// <input type="checkbox" key={'Show Preview'} checked={this.previewWidth() !== 0} onChange={this.toggleExpander} />
+// Show Preview
+// </div>
+// </div>
+// </div>
+// );
+// }
+
+// onSpecificMenu = (e: React.MouseEvent) => {
+// if ((e.target as any)?.className?.includes?.('collectionSchemaView-cell') || e.target instanceof HTMLSpanElement) {
+// const cm = ContextMenu.Instance;
+// const options = cm.findByDescription('Options...');
+// const optionItems: ContextMenuProps[] = options && 'subitems' in options ? options.subitems : [];
+// optionItems.push({ description: 'remove', event: () => this._previewDoc && this.props.removeDocument?.(this._previewDoc), icon: 'trash' });
+// !options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'compass' });
+// cm.displayMenu(e.clientX, e.clientY);
+// (e.nativeEvent as any).SchemaHandled = true; // not sure why this is needed, but if you right-click quickly on a cell, the Document/Collection contextMenu handlers still fire without this.
+// e.stopPropagation();
+// }
+// };
+
+// @action
+// onTableClick = (e: React.MouseEvent): void => {
+// if (!(e.target as any)?.className?.includes?.('collectionSchemaView-cell') && !(e.target instanceof HTMLSpanElement)) {
+// this.setPreviewDoc(undefined);
+// } else {
+// e.stopPropagation();
+// }
+// this.setFocused(this.props.Document);
+// this.closeHeader();
+// };
+
+// onResizedChange = (newResized: Resize[], event: any) => {
+// const columns = this.columns;
+// newResized.forEach(resized => {
+// const index = columns.findIndex(c => c.heading === resized.id);
+// const column = columns[index];
+// column.setWidth(resized.value);
+// columns[index] = column;
+// });
+// this.columns = columns;
+// };
+
+// @action
+// setColumns = (columns: SchemaHeaderField[]) => (this.columns = columns);
+
+// @undoBatch
+// reorderColumns = (toMove: SchemaHeaderField, relativeTo: SchemaHeaderField, before: boolean, columnsValues: SchemaHeaderField[]) => {
+// const columns = [...columnsValues];
+// const oldIndex = columns.indexOf(toMove);
+// const relIndex = columns.indexOf(relativeTo);
+// const newIndex = oldIndex > relIndex && !before ? relIndex + 1 : oldIndex < relIndex && before ? relIndex - 1 : relIndex;
+
+// if (oldIndex === newIndex) return;
+
+// columns.splice(newIndex, 0, columns.splice(oldIndex, 1)[0]);
+// this.columns = columns;
+// };
+
+// onZoomMenu = (e: React.WheelEvent) => this.props.isContentActive(true) && e.stopPropagation();
+
+// render() {
+// TraceMobx();
+// if (!this.props.isContentActive()) setTimeout(() => this.closeHeader(), 0);
+// const menuContent = this.renderMenuContent;
+// const menu = (
+// <div className="collectionSchema-header-menu" onWheel={e => this.onZoomMenu(e)} onPointerDown={e => this.onHeaderClick(e)} style={{ transform: `translate(${this.menuCoordinates[0]}px, ${this.menuCoordinates[1]}px)` }}>
+// <Measure
+// offset
+// onResize={action((r: any) => {
+// const dim = this.props.ScreenToLocalTransform().inverse().transformDirection(r.offset.width, r.offset.height);
+// this._menuWidth = dim[0];
+// this._menuHeight = dim[1];
+// })}>
+// {({ measureRef }) => <div ref={measureRef}> {menuContent} </div>}
+// </Measure>
+// </div>
+// );
+// return (
+// <div
+// className={'collectionSchemaView' + (this.props.Document._searchDoc ? '-searchContainer' : '-container')}
+// style={{
+// overflow: this.props.scrollOverflow === true ? 'scroll' : undefined,
+// backgroundColor: 'white',
+// pointerEvents: this.props.Document._searchDoc !== undefined && !this.props.isContentActive() && !SnappingManager.GetIsDragging() ? 'none' : undefined,
+// width: this.props.PanelWidth() || '100%',
+// height: this.props.PanelHeight() || '100%',
+// position: 'relative',
+// }}>
+// <div
+// className="collectionSchemaView-tableContainer"
+// style={{ width: `calc(100% - ${this.previewWidth()}px)` }}
+// onContextMenu={this.onSpecificMenu}
+// onPointerDown={this.onPointerDown}
+// onWheel={e => this.props.isContentActive(true) && e.stopPropagation()}
+// onDrop={e => this.onExternalDrop(e, {})}
+// ref={this.createTarget}>
+// {this.schemaTable}
+// </div>
+// {this.dividerDragger}
+// {!this.previewWidth() ? null : this.previewPanel}
+// {this._headerOpen && this.props.isContentActive() ? menu : null}
+// </div>
+// );
+// TraceMobx();
+// return <div>HELLO</div>;
+// }
+// }
diff --git a/src/client/views/collections/old_collectionSchema/OldSchemaTable.tsx b/src/client/views/collections/old_collectionSchema/OldSchemaTable.tsx
index 1b4fcf0a4..bc33f3be5 100644
--- a/src/client/views/collections/old_collectionSchema/OldSchemaTable.tsx
+++ b/src/client/views/collections/old_collectionSchema/OldSchemaTable.tsx
@@ -1,694 +1,694 @@
-import { IconProp } from '@fortawesome/fontawesome-svg-core';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, observable } from 'mobx';
-import { observer } from 'mobx-react';
-import * as React from 'react';
-import ReactTable, { CellInfo, Column, ComponentPropsGetterR, Resize, SortingRule } from 'react-table';
-import { DateField } from '../../../../fields/DateField';
-import { AclPrivate, AclReadonly, DataSym, Doc, DocListCast, Field, Opt } from '../../../../fields/Doc';
-import { Id } from '../../../../fields/FieldSymbols';
-import { List } from '../../../../fields/List';
-import { listSpec } from '../../../../fields/Schema';
-import { SchemaHeaderField } from '../../../../fields/SchemaHeaderField';
-import { ComputedField } from '../../../../fields/ScriptField';
-import { Cast, FieldValue, NumCast, StrCast } from '../../../../fields/Types';
-import { ImageField } from '../../../../fields/URLField';
-import { GetEffectiveAcl } from '../../../../fields/util';
-import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../../../../Utils';
-import { Docs, DocumentOptions, DocUtils } from '../../../documents/Documents';
-import { DocumentType } from '../../../documents/DocumentTypes';
-import { CompileScript, Transformer, ts } from '../../../util/Scripting';
-import { Transform } from '../../../util/Transform';
-import { undoBatch } from '../../../util/UndoManager';
-import '../../../views/DocumentDecorations.scss';
-import { ContextMenu } from '../../ContextMenu';
-import { COLLECTION_BORDER_WIDTH, SCHEMA_DIVIDER_WIDTH } from '../../global/globalCssVariables.scss';
-import { DocumentView, OpenWhere } from '../../nodes/DocumentView';
-import { PinProps } from '../../nodes/trails';
-import { DefaultStyleProvider } from '../../StyleProvider';
-import { CollectionView } from '../CollectionView';
-import {
- CellProps,
- CollectionSchemaButtons,
- CollectionSchemaCell,
- CollectionSchemaCheckboxCell,
- CollectionSchemaDateCell,
- CollectionSchemaDocCell,
- CollectionSchemaImageCell,
- CollectionSchemaListCell,
- CollectionSchemaNumberCell,
- CollectionSchemaStringCell,
-} from './CollectionSchemaCells';
-import { CollectionSchemaAddColumnHeader, KeysDropdown } from './CollectionSchemaHeaders';
-import { MovableColumn } from './OldCollectionSchemaMovableColumn';
-import { MovableRow } from './CollectionSchemaMovableRow';
-import './CollectionSchemaView.scss';
-
-enum ColumnType {
- Any,
- Number,
- String,
- Boolean,
- Doc,
- Image,
- List,
- Date,
-}
-
-// this map should be used for keys that should have a const type of value
-const columnTypes: Map<string, ColumnType> = new Map([
- ['title', ColumnType.String],
- ['x', ColumnType.Number],
- ['y', ColumnType.Number],
- ['_width', ColumnType.Number],
- ['_height', ColumnType.Number],
- ['_nativeWidth', ColumnType.Number],
- ['_nativeHeight', ColumnType.Number],
- ['isPrototype', ColumnType.Boolean],
- ['_curPage', ColumnType.Number],
- ['_currentTimecode', ColumnType.Number],
- ['zIndex', ColumnType.Number],
-]);
-
-export interface SchemaTableProps {
- Document: Doc; // child doc
- dataDoc?: Doc;
- PanelHeight: () => number;
- PanelWidth: () => number;
- childDocs?: Doc[];
- CollectionView: Opt<CollectionView>;
- ContainingCollectionView: Opt<CollectionView>;
- ContainingCollectionDoc: Opt<Doc>;
- fieldKey: string;
- renderDepth: number;
- deleteDocument?: (document: Doc | Doc[]) => boolean;
- addDocument?: (document: Doc | Doc[]) => boolean;
- moveDocument?: (document: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => boolean;
- ScreenToLocalTransform: () => Transform;
- active: (outsideReaction: boolean | undefined) => boolean | undefined;
- onDrop: (e: React.DragEvent<Element>, options: DocumentOptions, completed?: (() => void) | undefined) => void;
- addDocTab: (document: Doc, where: OpenWhere) => boolean;
- pinToPres: (document: Doc, pinProps: PinProps) => void;
- isSelected: (outsideReaction?: boolean) => boolean;
- isFocused: (document: Doc, outsideReaction: boolean) => boolean;
- setFocused: (document: Doc) => void;
- setPreviewDoc: (document: Opt<Doc>) => void;
- columns: SchemaHeaderField[];
- documentKeys: any[];
- headerIsEditing: boolean;
- openHeader: (column: any, screenx: number, screeny: number) => void;
- onClick: (e: React.MouseEvent) => void;
- onPointerDown: (e: React.PointerEvent) => void;
- onResizedChange: (newResized: Resize[], event: any) => void;
- setColumns: (columns: SchemaHeaderField[]) => void;
- reorderColumns: (toMove: SchemaHeaderField, relativeTo: SchemaHeaderField, before: boolean, columnsValues: SchemaHeaderField[]) => void;
- changeColumns: (oldKey: string, newKey: string, addNew: boolean) => void;
- setHeaderIsEditing: (isEditing: boolean) => void;
- changeColumnSort: (columnField: SchemaHeaderField, descending: boolean | undefined) => void;
-}
-
-@observer
-export class SchemaTable extends React.Component<SchemaTableProps> {
- @observable _cellIsEditing: boolean = false;
- @observable _focusedCell: { row: number; col: number } = { row: 0, col: 0 };
- @observable _openCollections: Set<number> = new Set();
-
- @observable _showDoc: Doc | undefined;
- @observable _showDataDoc: any = '';
- @observable _showDocPos: number[] = [];
-
- @observable _showTitleDropdown: boolean = false;
-
- @computed get previewWidth() {
- return () => NumCast(this.props.Document.schemaPreviewWidth);
- }
- @computed get previewHeight() {
- return () => this.props.PanelHeight() - 2 * this.borderWidth;
- }
- @computed get tableWidth() {
- return this.props.PanelWidth() - 2 * this.borderWidth - Number(SCHEMA_DIVIDER_WIDTH) - this.previewWidth();
- }
-
- @computed get childDocs() {
- if (this.props.childDocs) return this.props.childDocs;
-
- const doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
- return DocListCast(doc[this.props.fieldKey]);
- }
- set childDocs(docs: Doc[]) {
- const doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
- doc[this.props.fieldKey] = new List<Doc>(docs);
- }
-
- @computed get textWrappedRows() {
- return Cast(this.props.Document.textwrappedSchemaRows, listSpec('string'), []);
- }
- set textWrappedRows(textWrappedRows: string[]) {
- this.props.Document.textwrappedSchemaRows = new List<string>(textWrappedRows);
- }
-
- @computed get resized(): { id: string; value: number }[] {
- return this.props.columns.reduce((resized, shf) => {
- shf.width > -1 && resized.push({ id: shf.heading, value: shf.width });
- return resized;
- }, [] as { id: string; value: number }[]);
- }
- @computed get sorted(): SortingRule[] {
- return this.props.columns.reduce((sorted, shf) => {
- shf.desc !== undefined && sorted.push({ id: shf.heading, desc: shf.desc });
- return sorted;
- }, [] as SortingRule[]);
- }
-
- @action
- changeSorting = (col: any) => {
- this.props.changeColumnSort(col, col.desc === true ? false : col.desc === false ? undefined : true);
- };
-
- @action
- changeTitleMode = () => (this._showTitleDropdown = !this._showTitleDropdown);
-
- @computed get borderWidth() {
- return Number(COLLECTION_BORDER_WIDTH);
- }
- @computed get tableColumns(): Column<Doc>[] {
- const possibleKeys = this.props.documentKeys.filter(key => this.props.columns.findIndex(existingKey => existingKey.heading.toUpperCase() === key.toUpperCase()) === -1);
- const columns: Column<Doc>[] = [];
- const tableIsFocused = this.props.isFocused(this.props.Document, false);
- const focusedRow = this._focusedCell.row;
- const focusedCol = this._focusedCell.col;
- const isEditable = !this.props.headerIsEditing;
-
- columns.push({
- expander: true,
- Header: '',
- width: 58,
- Expander: rowInfo => {
- return rowInfo.original.type !== DocumentType.COL ? null : (
- <div className="collectionSchemaView-expander" onClick={action(() => this._openCollections[rowInfo.isExpanded ? 'delete' : 'add'](rowInfo.viewIndex))}>
- <FontAwesomeIcon icon={rowInfo.isExpanded ? 'caret-down' : 'caret-right'} size="lg" />
- </div>
- );
- },
- });
- columns.push(
- ...this.props.columns.map(col => {
- const icon: IconProp =
- this.getColumnType(col) === ColumnType.Number
- ? 'hashtag'
- : this.getColumnType(col) === ColumnType.String
- ? 'font'
- : this.getColumnType(col) === ColumnType.Boolean
- ? 'check-square'
- : this.getColumnType(col) === ColumnType.Doc
- ? 'file'
- : this.getColumnType(col) === ColumnType.Image
- ? 'image'
- : this.getColumnType(col) === ColumnType.List
- ? 'list-ul'
- : this.getColumnType(col) === ColumnType.Date
- ? 'calendar'
- : 'align-justify';
-
- const keysDropdown = (
- <KeysDropdown
- keyValue={col.heading}
- possibleKeys={possibleKeys}
- existingKeys={this.props.columns.map(c => c.heading)}
- canAddNew={true}
- addNew={false}
- onSelect={this.props.changeColumns}
- setIsEditing={this.props.setHeaderIsEditing}
- docs={this.props.childDocs}
- Document={this.props.Document}
- dataDoc={this.props.dataDoc}
- fieldKey={this.props.fieldKey}
- ContainingCollectionDoc={this.props.ContainingCollectionDoc}
- ContainingCollectionView={this.props.ContainingCollectionView}
- active={this.props.active}
- openHeader={this.props.openHeader}
- icon={icon}
- col={col}
- // try commenting this out
- width={'100%'}
- />
- );
-
- const sortIcon = col.desc === undefined ? 'caret-right' : col.desc === true ? 'caret-down' : 'caret-up';
- const header = (
- <div className="collectionSchemaView-menuOptions-wrapper" style={{ background: col.color, padding: '2px', display: 'flex', cursor: 'default', height: '100%' }}>
- {keysDropdown}
- <div onClick={e => this.changeSorting(col)} style={{ width: 21, padding: 1, display: 'inline', zIndex: 1, background: 'inherit', cursor: 'pointer' }}>
- <FontAwesomeIcon icon={sortIcon} size="lg" />
- </div>
- {/* {this.props.Document._chromeHidden || this.props.addDocument == returnFalse ? undefined : <div className="collectionSchemaView-addRow" onClick={this.createRow}>+ new</div>} */}
- </div>
- );
-
- return {
- Header: <MovableColumn columnRenderer={header} columnValue={col} allColumns={this.props.columns} reorderColumns={this.props.reorderColumns} ScreenToLocalTransform={this.props.ScreenToLocalTransform} />,
- accessor: (doc: Doc) => (doc ? Field.toString(doc[col.heading] as Field) : 0),
- id: col.heading,
- Cell: (rowProps: CellInfo) => {
- const rowIndex = rowProps.index;
- const columnIndex = this.props.columns.map(c => c.heading).indexOf(rowProps.column.id!);
- const isFocused = focusedRow === rowIndex && focusedCol === columnIndex && tableIsFocused;
-
- const props: CellProps = {
- row: rowIndex,
- col: columnIndex,
- rowProps: rowProps,
- isFocused: isFocused,
- changeFocusedCellByIndex: this.changeFocusedCellByIndex,
- CollectionView: this.props.CollectionView,
- ContainingCollection: this.props.ContainingCollectionView,
- Document: this.props.Document,
- fieldKey: this.props.fieldKey,
- renderDepth: this.props.renderDepth,
- addDocTab: this.props.addDocTab,
- pinToPres: this.props.pinToPres,
- moveDocument: this.props.moveDocument,
- setIsEditing: this.setCellIsEditing,
- isEditable: isEditable,
- setPreviewDoc: this.props.setPreviewDoc,
- setComputed: this.setComputed,
- getField: this.getField,
- showDoc: this.showDoc,
- };
-
- switch (this.getColumnType(col, rowProps.original, rowProps.column.id)) {
- case ColumnType.Number:
- return <CollectionSchemaNumberCell {...props} />;
- case ColumnType.String:
- return <CollectionSchemaStringCell {...props} />;
- case ColumnType.Boolean:
- return <CollectionSchemaCheckboxCell {...props} />;
- case ColumnType.Doc:
- return <CollectionSchemaDocCell {...props} />;
- case ColumnType.Image:
- return <CollectionSchemaImageCell {...props} />;
- case ColumnType.List:
- return <CollectionSchemaListCell {...props} />;
- case ColumnType.Date:
- return <CollectionSchemaDateCell {...props} />;
- default:
- return <CollectionSchemaCell {...props} />;
- }
- },
- minWidth: 200,
- };
- })
- );
- columns.push({
- Header: <CollectionSchemaAddColumnHeader createColumn={this.createColumn} />,
- accessor: (doc: Doc) => 0,
- id: 'add',
- Cell: (rowProps: CellInfo) => {
- const rowIndex = rowProps.index;
- const columnIndex = this.props.columns.map(c => c.heading).indexOf(rowProps.column.id!);
- const isFocused = focusedRow === rowIndex && focusedCol === columnIndex && tableIsFocused;
- return (
- <CollectionSchemaButtons
- {...{
- row: rowProps.index,
- col: columnIndex,
- rowProps: rowProps,
- isFocused: isFocused,
- changeFocusedCellByIndex: this.changeFocusedCellByIndex,
- CollectionView: this.props.CollectionView,
- ContainingCollection: this.props.ContainingCollectionView,
- Document: this.props.Document,
- fieldKey: this.props.fieldKey,
- renderDepth: this.props.renderDepth,
- addDocTab: this.props.addDocTab,
- pinToPres: this.props.pinToPres,
- moveDocument: this.props.moveDocument,
- setIsEditing: this.setCellIsEditing,
- isEditable: isEditable,
- setPreviewDoc: this.props.setPreviewDoc,
- setComputed: this.setComputed,
- getField: this.getField,
- showDoc: this.showDoc,
- }}
- />
- );
- },
- width: 28,
- resizable: false,
- });
- return columns;
- }
-
- constructor(props: SchemaTableProps) {
- super(props);
- if (this.props.Document._schemaHeaders === undefined) {
- this.props.Document._schemaHeaders = new List<SchemaHeaderField>([
- new SchemaHeaderField('title', '#f1efeb'),
- new SchemaHeaderField('author', '#f1efeb'),
- new SchemaHeaderField('*lastModified', '#f1efeb', ColumnType.Date),
- new SchemaHeaderField('text', '#f1efeb', ColumnType.String),
- new SchemaHeaderField('type', '#f1efeb'),
- new SchemaHeaderField('context', '#f1efeb', ColumnType.Doc),
- ]);
- }
- }
-
- componentDidMount() {
- document.addEventListener('keydown', this.onKeyDown);
- }
-
- componentWillUnmount() {
- document.removeEventListener('keydown', this.onKeyDown);
- }
-
- tableAddDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => {
- const tableDoc = this.props.Document[DataSym];
- const effectiveAcl = GetEffectiveAcl(tableDoc);
-
- if (effectiveAcl !== AclPrivate && effectiveAcl !== AclReadonly) {
- doc.context = this.props.Document;
- tableDoc[this.props.fieldKey + '-lastModified'] = new DateField(new Date(Date.now()));
- return Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before);
- }
- return false;
- };
-
- private getTrProps: ComponentPropsGetterR = (state, rowInfo) => {
- return !rowInfo
- ? {}
- : {
- ScreenToLocalTransform: this.props.ScreenToLocalTransform,
- addDoc: this.tableAddDoc,
- removeDoc: this.props.deleteDocument,
- rowInfo,
- rowFocused: !this.props.headerIsEditing && rowInfo.index === this._focusedCell.row && this.props.isFocused(this.props.Document, true),
- textWrapRow: this.toggleTextWrapRow,
- rowWrapped: this.textWrappedRows.findIndex(id => rowInfo.original[Id] === id) > -1,
- dropAction: StrCast(this.props.Document.childDropAction),
- addDocTab: this.props.addDocTab,
- };
- };
-
- private getTdProps: ComponentPropsGetterR = (state, rowInfo, column, instance) => {
- if (!rowInfo || column) return {};
-
- const row = rowInfo.index;
- //@ts-ignore
- const col = this.columns.map(c => c.heading).indexOf(column!.id);
- const isFocused = this._focusedCell.row === row && this._focusedCell.col === col && this.props.isFocused(this.props.Document, true);
- // TODO: editing border doesn't work :(
- return {
- style: { border: !this.props.headerIsEditing && isFocused ? '2px solid rgb(255, 160, 160)' : '1px solid #f1efeb' },
- };
- };
-
- @action setCellIsEditing = (isEditing: boolean) => (this._cellIsEditing = isEditing);
-
- @action
- onKeyDown = (e: KeyboardEvent): void => {
- if (!this._cellIsEditing && !this.props.headerIsEditing && this.props.isFocused(this.props.Document, true)) {
- // && this.props.isSelected(true)) {
- const direction = e.key === 'Tab' ? 'tab' : e.which === 39 ? 'right' : e.which === 37 ? 'left' : e.which === 38 ? 'up' : e.which === 40 ? 'down' : '';
- this._focusedCell = this.changeFocusedCellByDirection(direction, this._focusedCell.row, this._focusedCell.col);
-
- if (direction) {
- const pdoc = FieldValue(this.childDocs[this._focusedCell.row]);
- pdoc && this.props.setPreviewDoc(pdoc);
- e.stopPropagation();
- }
- } else if (e.keyCode === 27) {
- this.props.setPreviewDoc(undefined);
- e.stopPropagation(); // stopPropagation for left/right arrows
- }
- };
-
- changeFocusedCellByDirection = (direction: string, curRow: number, curCol: number) => {
- switch (direction) {
- case 'tab':
- return { row: curRow + 1 === this.childDocs.length ? 0 : curRow + 1, col: curCol + 1 === this.props.columns.length ? 0 : curCol + 1 };
- case 'right':
- return { row: curRow, col: curCol + 1 === this.props.columns.length ? curCol : curCol + 1 };
- case 'left':
- return { row: curRow, col: curCol === 0 ? curCol : curCol - 1 };
- case 'up':
- return { row: curRow === 0 ? curRow : curRow - 1, col: curCol };
- case 'down':
- return { row: curRow + 1 === this.childDocs.length ? curRow : curRow + 1, col: curCol };
- }
- return this._focusedCell;
- };
-
- @action
- changeFocusedCellByIndex = (row: number, col: number): void => {
- if (this._focusedCell.row !== row || this._focusedCell.col !== col) {
- this._focusedCell = { row: row, col: col };
- }
- this.props.setFocused(this.props.Document);
- };
-
- @undoBatch
- createRow = action(() => {
- this.props.addDocument?.(Docs.Create.TextDocument('', { title: '', _width: 100, _height: 30 }));
- this._focusedCell = { row: this.childDocs.length, col: this._focusedCell.col };
- });
-
- @undoBatch
- @action
- createColumn = () => {
- const newFieldName = (index: number) => `New field${index ? ` (${index})` : ''}`;
- for (let index = 0; index < 100; index++) {
- if (this.props.columns.findIndex(col => col.heading === newFieldName(index)) === -1) {
- this.props.columns.push(new SchemaHeaderField(newFieldName(index), '#f1efeb'));
- break;
- }
- }
- };
-
- @action
- getColumnType = (column: SchemaHeaderField, doc?: Doc, field?: string): ColumnType => {
- if (doc && field && column.type === ColumnType.Any) {
- const val = doc[CollectionSchemaCell.resolvedFieldKey(field, doc)];
- if (val instanceof ImageField) return ColumnType.Image;
- if (val instanceof Doc) return ColumnType.Doc;
- if (val instanceof DateField) return ColumnType.Date;
- if (val instanceof List) return ColumnType.List;
- }
- if (column.type && column.type !== 0) {
- return column.type;
- }
- if (columnTypes.get(column.heading)) {
- return (column.type = columnTypes.get(column.heading)!);
- }
- return (column.type = ColumnType.Any);
- };
-
- @undoBatch
- @action
- toggleTextwrap = async () => {
- const textwrappedRows = Cast(this.props.Document.textwrappedSchemaRows, listSpec('string'), []);
- if (textwrappedRows.length) {
- this.props.Document.textwrappedSchemaRows = new List<string>([]);
- } else {
- const docs = DocListCast(this.props.Document[this.props.fieldKey]);
- const allRows = docs instanceof Doc ? [docs[Id]] : docs.map(doc => doc[Id]);
- this.props.Document.textwrappedSchemaRows = new List<string>(allRows);
- }
- };
-
- @action
- toggleTextWrapRow = (doc: Doc): void => {
- const textWrapped = this.textWrappedRows;
- const index = textWrapped.findIndex(id => doc[Id] === id);
-
- index > -1 ? textWrapped.splice(index, 1) : textWrapped.push(doc[Id]);
-
- this.textWrappedRows = textWrapped;
- };
-
- @computed
- get reactTable() {
- const children = this.childDocs;
- const hasCollectionChild = children.reduce((found, doc) => found || doc.type === DocumentType.COL, false);
- const expanded: { [name: string]: any } = {};
- Array.from(this._openCollections.keys()).map(col => (expanded[col.toString()] = true));
- const rerender = [...this.textWrappedRows]; // TODO: get component to rerender on text wrap change without needign to console.log :((((
-
- return (
- <ReactTable
- style={{ position: 'relative' }}
- data={children}
- page={0}
- pageSize={children.length}
- showPagination={false}
- columns={this.tableColumns}
- getTrProps={this.getTrProps}
- getTdProps={this.getTdProps}
- sortable={false}
- TrComponent={MovableRow}
- sorted={this.sorted}
- expanded={expanded}
- resized={this.resized}
- onResizedChange={this.props.onResizedChange}
- // if it has a child, render another table with the children
- SubComponent={
- !hasCollectionChild
- ? undefined
- : row =>
- row.original.type !== DocumentType.COL ? null : (
- <div style={{ paddingLeft: 57 + 'px' }} className="reactTable-sub">
- <SchemaTable {...this.props} Document={row.original} dataDoc={undefined} childDocs={undefined} />
- </div>
- )
- }
- />
- );
- }
-
- onContextMenu = (e: React.MouseEvent): void => {
- ContextMenu.Instance.addItem({ description: 'Toggle text wrapping', event: this.toggleTextwrap, icon: 'table' });
- };
-
- getField = (row: number, col?: number) => {
- const docs = this.childDocs;
-
- row = row % docs.length;
- while (row < 0) row += docs.length;
- const columns = this.props.columns;
- const doc = docs[row];
- if (col === undefined) {
- return doc;
- }
- if (col >= 0 && col < columns.length) {
- const column = this.props.columns[col].heading;
- return doc[column];
- }
- return undefined;
- };
-
- createTransformer = (row: number, col: number): Transformer => {
- const self = this;
- const captures: { [name: string]: Field } = {};
-
- const transformer: ts.TransformerFactory<ts.SourceFile> = context => {
- return root => {
- function visit(node: ts.Node) {
- node = ts.visitEachChild(node, visit, context);
- if (ts.isIdentifier(node)) {
- const isntPropAccess = !ts.isPropertyAccessExpression(node.parent) || node.parent.expression === node;
- const isntPropAssign = !ts.isPropertyAssignment(node.parent) || node.parent.name !== node;
- if (isntPropAccess && isntPropAssign) {
- if (node.text === '$r') {
- return ts.createNumericLiteral(row.toString());
- } else if (node.text === '$c') {
- return ts.createNumericLiteral(col.toString());
- } else if (node.text === '$') {
- if (ts.isCallExpression(node.parent)) {
- // captures.doc = self.props.Document;
- // captures.key = self.props.fieldKey;
- }
- }
- }
- }
-
- return node;
- }
- return ts.visitNode(root, visit);
- };
- };
-
- // const getVars = () => {
- // return { capturedVariables: captures };
- // };
-
- return { transformer /*getVars*/ };
- };
-
- setComputed = (script: string, doc: Doc, field: string, row: number, col: number): boolean => {
- script = `const $ = (row:number, col?:number) => {
- const rval = (doc as any)[key][row + ${row}];
- return col === undefined ? rval : rval[(doc as any)._schemaHeaders[col + ${col}].heading];
- }
- return ${script}`;
- const compiled = CompileScript(script, { params: { this: Doc.name }, capturedVariables: { doc: this.props.Document, key: this.props.fieldKey }, typecheck: false, transformer: this.createTransformer(row, col) });
- if (compiled.compiled) {
- doc[field] = new ComputedField(compiled);
- return true;
- }
- return false;
- };
-
- @action
- showDoc = (doc: Doc | undefined, dataDoc?: Doc, screenX?: number, screenY?: number) => {
- this._showDoc = doc;
- if (dataDoc && screenX && screenY) {
- this._showDocPos = this.props.ScreenToLocalTransform().transformPoint(screenX, screenY);
- }
- };
-
- onOpenClick = () => {
- this._showDoc && this.props.addDocTab(this._showDoc, OpenWhere.addRight);
- };
-
- getPreviewTransform = (): Transform => {
- return this.props.ScreenToLocalTransform().translate(-this.borderWidth - 4 - this.tableWidth, -this.borderWidth);
- };
-
- render() {
- const preview = '';
- return (
- <div
- className="collectionSchemaView-table"
- onPointerDown={this.props.onPointerDown}
- onClick={this.props.onClick}
- onWheel={e => this.props.active(true) && e.stopPropagation()}
- onDrop={e => this.props.onDrop(e, {})}
- onContextMenu={this.onContextMenu}>
- {this.reactTable}
- {this.props.Document._chromeHidden || this.props.addDocument === returnFalse ? undefined : (
- <div className="collectionSchemaView-addRow" onClick={this.createRow}>
- + new
- </div>
- )}
- {!this._showDoc ? null : (
- <div
- className="collectionSchemaView-documentPreview"
- ref="overlay"
- style={{
- position: 'absolute',
- width: 150,
- height: 150,
- background: 'dimgray',
- display: 'block',
- top: 0,
- left: 0,
- transform: `translate(${this._showDocPos[0]}px, ${this._showDocPos[1] - 180}px)`,
- }}>
- <DocumentView
- Document={this._showDoc}
- DataDoc={this._showDataDoc}
- styleProvider={DefaultStyleProvider}
- docViewPath={returnEmptyDoclist}
- focus={DocUtils.DefaultFocus}
- renderDepth={this.props.renderDepth}
- rootSelected={returnFalse}
- isContentActive={returnTrue}
- isDocumentActive={returnFalse}
- PanelWidth={() => 150}
- PanelHeight={() => 150}
- ScreenToLocalTransform={this.getPreviewTransform}
- docFilters={returnEmptyFilter}
- docRangeFilters={returnEmptyFilter}
- searchFilterDocs={returnEmptyDoclist}
- ContainingCollectionDoc={this.props.CollectionView?.props.Document}
- ContainingCollectionView={this.props.CollectionView}
- moveDocument={this.props.moveDocument}
- whenChildContentsActiveChanged={emptyFunction}
- addDocTab={this.props.addDocTab}
- pinToPres={this.props.pinToPres}
- bringToFront={returnFalse}></DocumentView>
- </div>
- )}
- </div>
- );
- }
-}
+// import { IconProp } from '@fortawesome/fontawesome-svg-core';
+// import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+// import { action, computed, observable } from 'mobx';
+// import { observer } from 'mobx-react';
+// import * as React from 'react';
+// import ReactTable, { CellInfo, Column, ComponentPropsGetterR, Resize, SortingRule } from 'react-table';
+// import { DateField } from '../../../../fields/DateField';
+// import { AclPrivate, AclReadonly, DataSym, Doc, DocListCast, Field, Opt } from '../../../../fields/Doc';
+// import { Id } from '../../../../fields/FieldSymbols';
+// import { List } from '../../../../fields/List';
+// import { listSpec } from '../../../../fields/Schema';
+// import { SchemaHeaderField } from '../../../../fields/SchemaHeaderField';
+// import { ComputedField } from '../../../../fields/ScriptField';
+// import { Cast, FieldValue, NumCast, StrCast } from '../../../../fields/Types';
+// import { ImageField } from '../../../../fields/URLField';
+// import { GetEffectiveAcl } from '../../../../fields/util';
+// import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../../../../Utils';
+// import { Docs, DocumentOptions, DocUtils } from '../../../documents/Documents';
+// import { DocumentType } from '../../../documents/DocumentTypes';
+// import { CompileScript, Transformer, ts } from '../../../util/Scripting';
+// import { Transform } from '../../../util/Transform';
+// import { undoBatch } from '../../../util/UndoManager';
+// import '../../../views/DocumentDecorations.scss';
+// import { ContextMenu } from '../../ContextMenu';
+// import { COLLECTION_BORDER_WIDTH, SCHEMA_DIVIDER_WIDTH } from '../../global/globalCssVariables.scss';
+// import { DocumentView, OpenWhere } from '../../nodes/DocumentView';
+// import { PinProps } from '../../nodes/trails';
+// import { DefaultStyleProvider } from '../../StyleProvider';
+// import { CollectionView } from '../CollectionView';
+// import {
+// CellProps,
+// CollectionSchemaButtons,
+// CollectionSchemaCell,
+// CollectionSchemaCheckboxCell,
+// CollectionSchemaDateCell,
+// CollectionSchemaDocCell,
+// CollectionSchemaImageCell,
+// CollectionSchemaListCell,
+// CollectionSchemaNumberCell,
+// CollectionSchemaStringCell,
+// } from './CollectionSchemaCells';
+// import { CollectionSchemaAddColumnHeader, KeysDropdown } from './CollectionSchemaHeaders';
+// import { MovableColumn } from './OldCollectionSchemaMovableColumn';
+// import { MovableRow } from './CollectionSchemaMovableRow';
+// import './CollectionSchemaView.scss';
+
+// enum ColumnType {
+// Any,
+// Number,
+// String,
+// Boolean,
+// Doc,
+// Image,
+// List,
+// Date,
+// }
+
+// // this map should be used for keys that should have a const type of value
+// const columnTypes: Map<string, ColumnType> = new Map([
+// ['title', ColumnType.String],
+// ['x', ColumnType.Number],
+// ['y', ColumnType.Number],
+// ['_width', ColumnType.Number],
+// ['_height', ColumnType.Number],
+// ['_nativeWidth', ColumnType.Number],
+// ['_nativeHeight', ColumnType.Number],
+// ['isPrototype', ColumnType.Boolean],
+// ['_curPage', ColumnType.Number],
+// ['_currentTimecode', ColumnType.Number],
+// ['zIndex', ColumnType.Number],
+// ]);
+
+// export interface SchemaTableProps {
+// Document: Doc; // child doc
+// dataDoc?: Doc;
+// PanelHeight: () => number;
+// PanelWidth: () => number;
+// childDocs?: Doc[];
+// CollectionView: Opt<CollectionView>;
+// ContainingCollectionView: Opt<CollectionView>;
+// ContainingCollectionDoc: Opt<Doc>;
+// fieldKey: string;
+// renderDepth: number;
+// deleteDocument?: (document: Doc | Doc[]) => boolean;
+// addDocument?: (document: Doc | Doc[]) => boolean;
+// moveDocument?: (document: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => boolean;
+// ScreenToLocalTransform: () => Transform;
+// active: (outsideReaction: boolean | undefined) => boolean | undefined;
+// onDrop: (e: React.DragEvent<Element>, options: DocumentOptions, completed?: (() => void) | undefined) => void;
+// addDocTab: (document: Doc, where: OpenWhere) => boolean;
+// pinToPres: (document: Doc, pinProps: PinProps) => void;
+// isSelected: (outsideReaction?: boolean) => boolean;
+// isFocused: (document: Doc, outsideReaction: boolean) => boolean;
+// setFocused: (document: Doc) => void;
+// setPreviewDoc: (document: Opt<Doc>) => void;
+// columns: SchemaHeaderField[];
+// documentKeys: any[];
+// headerIsEditing: boolean;
+// openHeader: (column: any, screenx: number, screeny: number) => void;
+// onClick: (e: React.MouseEvent) => void;
+// onPointerDown: (e: React.PointerEvent) => void;
+// onResizedChange: (newResized: Resize[], event: any) => void;
+// setColumns: (columns: SchemaHeaderField[]) => void;
+// reorderColumns: (toMove: SchemaHeaderField, relativeTo: SchemaHeaderField, before: boolean, columnsValues: SchemaHeaderField[]) => void;
+// changeColumns: (oldKey: string, newKey: string, addNew: boolean) => void;
+// setHeaderIsEditing: (isEditing: boolean) => void;
+// changeColumnSort: (columnField: SchemaHeaderField, descending: boolean | undefined) => void;
+// }
+
+// @observer
+// export class SchemaTable extends React.Component<SchemaTableProps> {
+// @observable _cellIsEditing: boolean = false;
+// @observable _focusedCell: { row: number; col: number } = { row: 0, col: 0 };
+// @observable _openCollections: Set<number> = new Set();
+
+// @observable _showDoc: Doc | undefined;
+// @observable _showDataDoc: any = '';
+// @observable _showDocPos: number[] = [];
+
+// @observable _showTitleDropdown: boolean = false;
+
+// @computed get previewWidth() {
+// return () => NumCast(this.props.Document.schemaPreviewWidth);
+// }
+// @computed get previewHeight() {
+// return () => this.props.PanelHeight() - 2 * this.borderWidth;
+// }
+// @computed get tableWidth() {
+// return this.props.PanelWidth() - 2 * this.borderWidth - Number(SCHEMA_DIVIDER_WIDTH) - this.previewWidth();
+// }
+
+// @computed get childDocs() {
+// if (this.props.childDocs) return this.props.childDocs;
+
+// const doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+// return DocListCast(doc[this.props.fieldKey]);
+// }
+// set childDocs(docs: Doc[]) {
+// const doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
+// doc[this.props.fieldKey] = new List<Doc>(docs);
+// }
+
+// @computed get textWrappedRows() {
+// return Cast(this.props.Document.textwrappedSchemaRows, listSpec('string'), []);
+// }
+// set textWrappedRows(textWrappedRows: string[]) {
+// this.props.Document.textwrappedSchemaRows = new List<string>(textWrappedRows);
+// }
+
+// @computed get resized(): { id: string; value: number }[] {
+// return this.props.columns.reduce((resized, shf) => {
+// shf.width > -1 && resized.push({ id: shf.heading, value: shf.width });
+// return resized;
+// }, [] as { id: string; value: number }[]);
+// }
+// @computed get sorted(): SortingRule[] {
+// return this.props.columns.reduce((sorted, shf) => {
+// shf.desc !== undefined && sorted.push({ id: shf.heading, desc: shf.desc });
+// return sorted;
+// }, [] as SortingRule[]);
+// }
+
+// @action
+// changeSorting = (col: any) => {
+// this.props.changeColumnSort(col, col.desc === true ? false : col.desc === false ? undefined : true);
+// };
+
+// @action
+// changeTitleMode = () => (this._showTitleDropdown = !this._showTitleDropdown);
+
+// @computed get borderWidth() {
+// return Number(COLLECTION_BORDER_WIDTH);
+// }
+// @computed get tableColumns(): Column<Doc>[] {
+// const possibleKeys = this.props.documentKeys.filter(key => this.props.columns.findIndex(existingKey => existingKey.heading.toUpperCase() === key.toUpperCase()) === -1);
+// const columns: Column<Doc>[] = [];
+// const tableIsFocused = this.props.isFocused(this.props.Document, false);
+// const focusedRow = this._focusedCell.row;
+// const focusedCol = this._focusedCell.col;
+// const isEditable = !this.props.headerIsEditing;
+
+// columns.push({
+// expander: true,
+// Header: '',
+// width: 58,
+// Expander: rowInfo => {
+// return rowInfo.original.type !== DocumentType.COL ? null : (
+// <div className="collectionSchemaView-expander" onClick={action(() => this._openCollections[rowInfo.isExpanded ? 'delete' : 'add'](rowInfo.viewIndex))}>
+// <FontAwesomeIcon icon={rowInfo.isExpanded ? 'caret-down' : 'caret-right'} size="lg" />
+// </div>
+// );
+// },
+// });
+// columns.push(
+// ...this.props.columns.map(col => {
+// const icon: IconProp =
+// this.getColumnType(col) === ColumnType.Number
+// ? 'hashtag'
+// : this.getColumnType(col) === ColumnType.String
+// ? 'font'
+// : this.getColumnType(col) === ColumnType.Boolean
+// ? 'check-square'
+// : this.getColumnType(col) === ColumnType.Doc
+// ? 'file'
+// : this.getColumnType(col) === ColumnType.Image
+// ? 'image'
+// : this.getColumnType(col) === ColumnType.List
+// ? 'list-ul'
+// : this.getColumnType(col) === ColumnType.Date
+// ? 'calendar'
+// : 'align-justify';
+
+// const keysDropdown = (
+// <KeysDropdown
+// keyValue={col.heading}
+// possibleKeys={possibleKeys}
+// existingKeys={this.props.columns.map(c => c.heading)}
+// canAddNew={true}
+// addNew={false}
+// onSelect={this.props.changeColumns}
+// setIsEditing={this.props.setHeaderIsEditing}
+// docs={this.props.childDocs}
+// Document={this.props.Document}
+// dataDoc={this.props.dataDoc}
+// fieldKey={this.props.fieldKey}
+// ContainingCollectionDoc={this.props.ContainingCollectionDoc}
+// ContainingCollectionView={this.props.ContainingCollectionView}
+// active={this.props.active}
+// openHeader={this.props.openHeader}
+// icon={icon}
+// col={col}
+// // try commenting this out
+// width={'100%'}
+// />
+// );
+
+// const sortIcon = col.desc === undefined ? 'caret-right' : col.desc === true ? 'caret-down' : 'caret-up';
+// const header = (
+// <div className="collectionSchemaView-menuOptions-wrapper" style={{ background: col.color, padding: '2px', display: 'flex', cursor: 'default', height: '100%' }}>
+// {keysDropdown}
+// <div onClick={e => this.changeSorting(col)} style={{ width: 21, padding: 1, display: 'inline', zIndex: 1, background: 'inherit', cursor: 'pointer' }}>
+// <FontAwesomeIcon icon={sortIcon} size="lg" />
+// </div>
+// {/* {this.props.Document._chromeHidden || this.props.addDocument == returnFalse ? undefined : <div className="collectionSchemaView-addRow" onClick={this.createRow}>+ new</div>} */}
+// </div>
+// );
+
+// return {
+// Header: <MovableColumn columnRenderer={header} columnValue={col} allColumns={this.props.columns} reorderColumns={this.props.reorderColumns} ScreenToLocalTransform={this.props.ScreenToLocalTransform} />,
+// accessor: (doc: Doc) => (doc ? Field.toString(doc[col.heading] as Field) : 0),
+// id: col.heading,
+// Cell: (rowProps: CellInfo) => {
+// const rowIndex = rowProps.index;
+// const columnIndex = this.props.columns.map(c => c.heading).indexOf(rowProps.column.id!);
+// const isFocused = focusedRow === rowIndex && focusedCol === columnIndex && tableIsFocused;
+
+// const props: CellProps = {
+// row: rowIndex,
+// col: columnIndex,
+// rowProps: rowProps,
+// isFocused: isFocused,
+// changeFocusedCellByIndex: this.changeFocusedCellByIndex,
+// CollectionView: this.props.CollectionView,
+// ContainingCollection: this.props.ContainingCollectionView,
+// Document: this.props.Document,
+// fieldKey: this.props.fieldKey,
+// renderDepth: this.props.renderDepth,
+// addDocTab: this.props.addDocTab,
+// pinToPres: this.props.pinToPres,
+// moveDocument: this.props.moveDocument,
+// setIsEditing: this.setCellIsEditing,
+// isEditable: isEditable,
+// setPreviewDoc: this.props.setPreviewDoc,
+// setComputed: this.setComputed,
+// getField: this.getField,
+// showDoc: this.showDoc,
+// };
+
+// switch (this.getColumnType(col, rowProps.original, rowProps.column.id)) {
+// case ColumnType.Number:
+// return <CollectionSchemaNumberCell {...props} />;
+// case ColumnType.String:
+// return <CollectionSchemaStringCell {...props} />;
+// case ColumnType.Boolean:
+// return <CollectionSchemaCheckboxCell {...props} />;
+// case ColumnType.Doc:
+// return <CollectionSchemaDocCell {...props} />;
+// case ColumnType.Image:
+// return <CollectionSchemaImageCell {...props} />;
+// case ColumnType.List:
+// return <CollectionSchemaListCell {...props} />;
+// case ColumnType.Date:
+// return <CollectionSchemaDateCell {...props} />;
+// default:
+// return <CollectionSchemaCell {...props} />;
+// }
+// },
+// minWidth: 200,
+// };
+// })
+// );
+// columns.push({
+// Header: <CollectionSchemaAddColumnHeader createColumn={this.createColumn} />,
+// accessor: (doc: Doc) => 0,
+// id: 'add',
+// Cell: (rowProps: CellInfo) => {
+// const rowIndex = rowProps.index;
+// const columnIndex = this.props.columns.map(c => c.heading).indexOf(rowProps.column.id!);
+// const isFocused = focusedRow === rowIndex && focusedCol === columnIndex && tableIsFocused;
+// return (
+// <CollectionSchemaButtons
+// {...{
+// row: rowProps.index,
+// col: columnIndex,
+// rowProps: rowProps,
+// isFocused: isFocused,
+// changeFocusedCellByIndex: this.changeFocusedCellByIndex,
+// CollectionView: this.props.CollectionView,
+// ContainingCollection: this.props.ContainingCollectionView,
+// Document: this.props.Document,
+// fieldKey: this.props.fieldKey,
+// renderDepth: this.props.renderDepth,
+// addDocTab: this.props.addDocTab,
+// pinToPres: this.props.pinToPres,
+// moveDocument: this.props.moveDocument,
+// setIsEditing: this.setCellIsEditing,
+// isEditable: isEditable,
+// setPreviewDoc: this.props.setPreviewDoc,
+// setComputed: this.setComputed,
+// getField: this.getField,
+// showDoc: this.showDoc,
+// }}
+// />
+// );
+// },
+// width: 28,
+// resizable: false,
+// });
+// return columns;
+// }
+
+// constructor(props: SchemaTableProps) {
+// super(props);
+// if (this.props.Document._schemaHeaders === undefined) {
+// this.props.Document._schemaHeaders = new List<SchemaHeaderField>([
+// new SchemaHeaderField('title', '#f1efeb'),
+// new SchemaHeaderField('author', '#f1efeb'),
+// new SchemaHeaderField('*lastModified', '#f1efeb', ColumnType.Date),
+// new SchemaHeaderField('text', '#f1efeb', ColumnType.String),
+// new SchemaHeaderField('type', '#f1efeb'),
+// new SchemaHeaderField('context', '#f1efeb', ColumnType.Doc),
+// ]);
+// }
+// }
+
+// componentDidMount() {
+// document.addEventListener('keydown', this.onKeyDown);
+// }
+
+// componentWillUnmount() {
+// document.removeEventListener('keydown', this.onKeyDown);
+// }
+
+// tableAddDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => {
+// const tableDoc = this.props.Document[DataSym];
+// const effectiveAcl = GetEffectiveAcl(tableDoc);
+
+// if (effectiveAcl !== AclPrivate && effectiveAcl !== AclReadonly) {
+// doc.context = this.props.Document;
+// tableDoc[this.props.fieldKey + '-lastModified'] = new DateField(new Date(Date.now()));
+// return Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before);
+// }
+// return false;
+// };
+
+// private getTrProps: ComponentPropsGetterR = (state, rowInfo) => {
+// return !rowInfo
+// ? {}
+// : {
+// ScreenToLocalTransform: this.props.ScreenToLocalTransform,
+// addDoc: this.tableAddDoc,
+// removeDoc: this.props.deleteDocument,
+// rowInfo,
+// rowFocused: !this.props.headerIsEditing && rowInfo.index === this._focusedCell.row && this.props.isFocused(this.props.Document, true),
+// textWrapRow: this.toggleTextWrapRow,
+// rowWrapped: this.textWrappedRows.findIndex(id => rowInfo.original[Id] === id) > -1,
+// dropAction: StrCast(this.props.Document.childDropAction),
+// addDocTab: this.props.addDocTab,
+// };
+// };
+
+// private getTdProps: ComponentPropsGetterR = (state, rowInfo, column, instance) => {
+// if (!rowInfo || column) return {};
+
+// const row = rowInfo.index;
+// //@ts-ignore
+// const col = this.columns.map(c => c.heading).indexOf(column!.id);
+// const isFocused = this._focusedCell.row === row && this._focusedCell.col === col && this.props.isFocused(this.props.Document, true);
+// // TODO: editing border doesn't work :(
+// return {
+// style: { border: !this.props.headerIsEditing && isFocused ? '2px solid rgb(255, 160, 160)' : '1px solid #f1efeb' },
+// };
+// };
+
+// @action setCellIsEditing = (isEditing: boolean) => (this._cellIsEditing = isEditing);
+
+// @action
+// onKeyDown = (e: KeyboardEvent): void => {
+// if (!this._cellIsEditing && !this.props.headerIsEditing && this.props.isFocused(this.props.Document, true)) {
+// // && this.props.isSelected(true)) {
+// const direction = e.key === 'Tab' ? 'tab' : e.which === 39 ? 'right' : e.which === 37 ? 'left' : e.which === 38 ? 'up' : e.which === 40 ? 'down' : '';
+// this._focusedCell = this.changeFocusedCellByDirection(direction, this._focusedCell.row, this._focusedCell.col);
+
+// if (direction) {
+// const pdoc = FieldValue(this.childDocs[this._focusedCell.row]);
+// pdoc && this.props.setPreviewDoc(pdoc);
+// e.stopPropagation();
+// }
+// } else if (e.keyCode === 27) {
+// this.props.setPreviewDoc(undefined);
+// e.stopPropagation(); // stopPropagation for left/right arrows
+// }
+// };
+
+// changeFocusedCellByDirection = (direction: string, curRow: number, curCol: number) => {
+// switch (direction) {
+// case 'tab':
+// return { row: curRow + 1 === this.childDocs.length ? 0 : curRow + 1, col: curCol + 1 === this.props.columns.length ? 0 : curCol + 1 };
+// case 'right':
+// return { row: curRow, col: curCol + 1 === this.props.columns.length ? curCol : curCol + 1 };
+// case 'left':
+// return { row: curRow, col: curCol === 0 ? curCol : curCol - 1 };
+// case 'up':
+// return { row: curRow === 0 ? curRow : curRow - 1, col: curCol };
+// case 'down':
+// return { row: curRow + 1 === this.childDocs.length ? curRow : curRow + 1, col: curCol };
+// }
+// return this._focusedCell;
+// };
+
+// @action
+// changeFocusedCellByIndex = (row: number, col: number): void => {
+// if (this._focusedCell.row !== row || this._focusedCell.col !== col) {
+// this._focusedCell = { row: row, col: col };
+// }
+// this.props.setFocused(this.props.Document);
+// };
+
+// @undoBatch
+// createRow = action(() => {
+// this.props.addDocument?.(Docs.Create.TextDocument('', { title: '', _width: 100, _height: 30 }));
+// this._focusedCell = { row: this.childDocs.length, col: this._focusedCell.col };
+// });
+
+// @undoBatch
+// @action
+// createColumn = () => {
+// const newFieldName = (index: number) => `New field${index ? ` (${index})` : ''}`;
+// for (let index = 0; index < 100; index++) {
+// if (this.props.columns.findIndex(col => col.heading === newFieldName(index)) === -1) {
+// this.props.columns.push(new SchemaHeaderField(newFieldName(index), '#f1efeb'));
+// break;
+// }
+// }
+// };
+
+// @action
+// getColumnType = (column: SchemaHeaderField, doc?: Doc, field?: string): ColumnType => {
+// if (doc && field && column.type === ColumnType.Any) {
+// const val = doc[CollectionSchemaCell.resolvedFieldKey(field, doc)];
+// if (val instanceof ImageField) return ColumnType.Image;
+// if (val instanceof Doc) return ColumnType.Doc;
+// if (val instanceof DateField) return ColumnType.Date;
+// if (val instanceof List) return ColumnType.List;
+// }
+// if (column.type && column.type !== 0) {
+// return column.type;
+// }
+// if (columnTypes.get(column.heading)) {
+// return (column.type = columnTypes.get(column.heading)!);
+// }
+// return (column.type = ColumnType.Any);
+// };
+
+// @undoBatch
+// @action
+// toggleTextwrap = async () => {
+// const textwrappedRows = Cast(this.props.Document.textwrappedSchemaRows, listSpec('string'), []);
+// if (textwrappedRows.length) {
+// this.props.Document.textwrappedSchemaRows = new List<string>([]);
+// } else {
+// const docs = DocListCast(this.props.Document[this.props.fieldKey]);
+// const allRows = docs instanceof Doc ? [docs[Id]] : docs.map(doc => doc[Id]);
+// this.props.Document.textwrappedSchemaRows = new List<string>(allRows);
+// }
+// };
+
+// @action
+// toggleTextWrapRow = (doc: Doc): void => {
+// const textWrapped = this.textWrappedRows;
+// const index = textWrapped.findIndex(id => doc[Id] === id);
+
+// index > -1 ? textWrapped.splice(index, 1) : textWrapped.push(doc[Id]);
+
+// this.textWrappedRows = textWrapped;
+// };
+
+// @computed
+// get reactTable() {
+// const children = this.childDocs;
+// const hasCollectionChild = children.reduce((found, doc) => found || doc.type === DocumentType.COL, false);
+// const expanded: { [name: string]: any } = {};
+// Array.from(this._openCollections.keys()).map(col => (expanded[col.toString()] = true));
+// const rerender = [...this.textWrappedRows]; // TODO: get component to rerender on text wrap change without needign to console.log :((((
+
+// return (
+// <ReactTable
+// style={{ position: 'relative' }}
+// data={children}
+// page={0}
+// pageSize={children.length}
+// showPagination={false}
+// columns={this.tableColumns}
+// getTrProps={this.getTrProps}
+// getTdProps={this.getTdProps}
+// sortable={false}
+// TrComponent={MovableRow}
+// sorted={this.sorted}
+// expanded={expanded}
+// resized={this.resized}
+// onResizedChange={this.props.onResizedChange}
+// // if it has a child, render another table with the children
+// SubComponent={
+// !hasCollectionChild
+// ? undefined
+// : row =>
+// row.original.type !== DocumentType.COL ? null : (
+// <div style={{ paddingLeft: 57 + 'px' }} className="reactTable-sub">
+// <SchemaTable {...this.props} Document={row.original} dataDoc={undefined} childDocs={undefined} />
+// </div>
+// )
+// }
+// />
+// );
+// }
+
+// onContextMenu = (e: React.MouseEvent): void => {
+// ContextMenu.Instance.addItem({ description: 'Toggle text wrapping', event: this.toggleTextwrap, icon: 'table' });
+// };
+
+// getField = (row: number, col?: number) => {
+// const docs = this.childDocs;
+
+// row = row % docs.length;
+// while (row < 0) row += docs.length;
+// const columns = this.props.columns;
+// const doc = docs[row];
+// if (col === undefined) {
+// return doc;
+// }
+// if (col >= 0 && col < columns.length) {
+// const column = this.props.columns[col].heading;
+// return doc[column];
+// }
+// return undefined;
+// };
+
+// createTransformer = (row: number, col: number): Transformer => {
+// const self = this;
+// const captures: { [name: string]: Field } = {};
+
+// const transformer: ts.TransformerFactory<ts.SourceFile> = context => {
+// return root => {
+// function visit(node: ts.Node) {
+// node = ts.visitEachChild(node, visit, context);
+// if (ts.isIdentifier(node)) {
+// const isntPropAccess = !ts.isPropertyAccessExpression(node.parent) || node.parent.expression === node;
+// const isntPropAssign = !ts.isPropertyAssignment(node.parent) || node.parent.name !== node;
+// if (isntPropAccess && isntPropAssign) {
+// if (node.text === '$r') {
+// return ts.createNumericLiteral(row.toString());
+// } else if (node.text === '$c') {
+// return ts.createNumericLiteral(col.toString());
+// } else if (node.text === '$') {
+// if (ts.isCallExpression(node.parent)) {
+// // captures.doc = self.props.Document;
+// // captures.key = self.props.fieldKey;
+// }
+// }
+// }
+// }
+
+// return node;
+// }
+// return ts.visitNode(root, visit);
+// };
+// };
+
+// // const getVars = () => {
+// // return { capturedVariables: captures };
+// // };
+
+// return { transformer /*getVars*/ };
+// };
+
+// setComputed = (script: string, doc: Doc, field: string, row: number, col: number): boolean => {
+// script = `const $ = (row:number, col?:number) => {
+// const rval = (doc as any)[key][row + ${row}];
+// return col === undefined ? rval : rval[(doc as any)._schemaHeaders[col + ${col}].heading];
+// }
+// return ${script}`;
+// const compiled = CompileScript(script, { params: { this: Doc.name }, capturedVariables: { doc: this.props.Document, key: this.props.fieldKey }, typecheck: false, transformer: this.createTransformer(row, col) });
+// if (compiled.compiled) {
+// doc[field] = new ComputedField(compiled);
+// return true;
+// }
+// return false;
+// };
+
+// @action
+// showDoc = (doc: Doc | undefined, dataDoc?: Doc, screenX?: number, screenY?: number) => {
+// this._showDoc = doc;
+// if (dataDoc && screenX && screenY) {
+// this._showDocPos = this.props.ScreenToLocalTransform().transformPoint(screenX, screenY);
+// }
+// };
+
+// onOpenClick = () => {
+// this._showDoc && this.props.addDocTab(this._showDoc, OpenWhere.addRight);
+// };
+
+// getPreviewTransform = (): Transform => {
+// return this.props.ScreenToLocalTransform().translate(-this.borderWidth - 4 - this.tableWidth, -this.borderWidth);
+// };
+
+// render() {
+// const preview = '';
+// return (
+// <div
+// className="collectionSchemaView-table"
+// onPointerDown={this.props.onPointerDown}
+// onClick={this.props.onClick}
+// onWheel={e => this.props.active(true) && e.stopPropagation()}
+// onDrop={e => this.props.onDrop(e, {})}
+// onContextMenu={this.onContextMenu}>
+// {this.reactTable}
+// {this.props.Document._chromeHidden || this.props.addDocument === returnFalse ? undefined : (
+// <div className="collectionSchemaView-addRow" onClick={this.createRow}>
+// + new
+// </div>
+// )}
+// {!this._showDoc ? null : (
+// <div
+// className="collectionSchemaView-documentPreview"
+// ref="overlay"
+// style={{
+// position: 'absolute',
+// width: 150,
+// height: 150,
+// background: 'dimgray',
+// display: 'block',
+// top: 0,
+// left: 0,
+// transform: `translate(${this._showDocPos[0]}px, ${this._showDocPos[1] - 180}px)`,
+// }}>
+// <DocumentView
+// Document={this._showDoc}
+// DataDoc={this._showDataDoc}
+// styleProvider={DefaultStyleProvider}
+// docViewPath={returnEmptyDoclist}
+// focus={DocUtils.DefaultFocus}
+// renderDepth={this.props.renderDepth}
+// rootSelected={returnFalse}
+// isContentActive={returnTrue}
+// isDocumentActive={returnFalse}
+// PanelWidth={() => 150}
+// PanelHeight={() => 150}
+// ScreenToLocalTransform={this.getPreviewTransform}
+// docFilters={returnEmptyFilter}
+// docRangeFilters={returnEmptyFilter}
+// searchFilterDocs={returnEmptyDoclist}
+// ContainingCollectionDoc={this.props.CollectionView?.props.Document}
+// ContainingCollectionView={this.props.CollectionView}
+// moveDocument={this.props.moveDocument}
+// whenChildContentsActiveChanged={emptyFunction}
+// addDocTab={this.props.addDocTab}
+// pinToPres={this.props.pinToPres}
+// bringToFront={returnFalse}></DocumentView>
+// </div>
+// )}
+// </div>
+// );
+// }
+// }
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 569579996..459554ebe 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -44,6 +44,7 @@ import { WebBox } from './WebBox';
import React = require('react');
import XRegExp = require('xregexp');
import { LoadingBox } from './LoadingBox';
+import { SchemaRowBox } from '../collections/collectionSchema/SchemaRowBox';
const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this?
@@ -268,6 +269,7 @@ export class DocumentContentsView extends React.Component<
HTMLtag,
ComparisonBox,
LoadingBox,
+ SchemaRowBox,
}}
bindings={bindings}
jsx={layoutFrame}