aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/CollectionSchemaView.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/collections/CollectionSchemaView.tsx')
-rw-r--r--src/client/views/collections/CollectionSchemaView.tsx169
1 files changed, 79 insertions, 90 deletions
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index b3cc3fbd5..67784fa81 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -5,17 +5,11 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, observable, untracked, runInAction } from "mobx";
import { observer } from "mobx-react";
import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table";
-import { MAX_ROW_HEIGHT } from '../../views/globalCssVariables.scss'
+import { MAX_ROW_HEIGHT } from '../../views/globalCssVariables.scss';
import "react-table/react-table.css";
-import { Document } from "../../../fields/Document";
-import { Field, Opt, FieldWaiting } from "../../../fields/Field";
-import { Key } from "../../../fields/Key";
-import { KeyStore } from "../../../fields/KeyStore";
-import { ListField } from "../../../fields/ListField";
-import { emptyDocFunction, emptyFunction, returnFalse, returnZero } from "../../../Utils";
-import { Server } from "../../Server";
+import { emptyFunction, returnFalse, returnZero } from "../../../Utils";
import { SetupDrag } from "../../util/DragManager";
-import { CompileScript, ToField } from "../../util/Scripting";
+import { CompileScript } from "../../util/Scripting";
import { Transform } from "../../util/Transform";
import { COLLECTION_BORDER_WIDTH } from "../../views/globalCssVariables.scss";
import { anchorPoints, Flyout } from "../DocumentDecorations";
@@ -25,43 +19,46 @@ import { DocumentView } from "../nodes/DocumentView";
import { FieldView, FieldViewProps } from "../nodes/FieldView";
import "./CollectionSchemaView.scss";
import { CollectionSubView } from "./CollectionSubView";
+import { Opt, Field, Doc } from "../../../new_fields/Doc";
+import { Cast, FieldValue, NumCast } from "../../../new_fields/Types";
+import { listSpec } from "../../../new_fields/Schema";
+import { List } from "../../../new_fields/List";
+import { Id } from "../../../new_fields/RefField";
// bcz: need to add drag and drop of rows and columns. This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
@observer
-class KeyToggle extends React.Component<{ keyId: string, checked: boolean, toggle: (key: Key) => void }> {
- @observable key: Key | undefined;
-
+class KeyToggle extends React.Component<{ keyName: string, checked: boolean, toggle: (key: string) => void }> {
constructor(props: any) {
super(props);
- Server.GetField(this.props.keyId, action((field: Opt<Field>) => field instanceof Key && (this.key = field)));
}
render() {
- return !this.key ? (null) :
- (<div key={this.key.Id}>
- <input type="checkbox" checked={this.props.checked} onChange={() => this.key && this.props.toggle(this.key)} />
- {this.key.Name}
- </div>);
+ return (
+ <div key={this.props.keyName}>
+ <input type="checkbox" checked={this.props.checked} onChange={() => this.props.toggle(this.props.keyName)} />
+ {this.props.keyName}
+ </div>
+ );
}
}
@observer
-export class CollectionSchemaView extends CollectionSubView {
+export class CollectionSchemaView extends CollectionSubView(doc => doc) {
private _mainCont?: HTMLDivElement;
private _startSplitPercent = 0;
private DIVIDER_WIDTH = 4;
- @observable _columns: Array<Key> = [KeyStore.Title, KeyStore.Data, KeyStore.Author];
+ @observable _columns: Array<string> = ["title", "data", "author"];
@observable _selectedIndex = 0;
@observable _columnsPercentage = 0;
- @observable _keys: Key[] = [];
+ @observable _keys: string[] = [];
@observable _newKeyName: string = "";
- @computed get splitPercentage() { return this.props.Document.GetNumber(KeyStore.SchemaSplitPercentage, 0); }
- @computed get columns() { return this.props.Document.GetList(KeyStore.ColumnsKey, [] as Key[]); }
+ @computed get splitPercentage() { return NumCast(this.props.Document.schemaSplitPercentage); }
+ @computed get columns() { return Cast(this.props.Document.schemaColumns, listSpec("string"), []); }
@computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
renderCell = (rowProps: CellInfo) => {
@@ -74,7 +71,7 @@ export class CollectionSchemaView extends CollectionSubView {
isTopMost: false,
selectOnLoad: false,
ScreenToLocalTransform: Transform.Identity,
- focus: emptyDocFunction,
+ focus: emptyFunction,
active: returnFalse,
whenActiveChanged: emptyFunction,
PanelHeight: returnZero,
@@ -85,34 +82,27 @@ export class CollectionSchemaView extends CollectionSubView {
);
let reference = React.createRef<HTMLDivElement>();
let onItemDown = SetupDrag(reference, () => props.Document, this.props.moveDocument);
- let applyToDoc = (doc: Document, run: (args?: { [name: string]: any }) => any) => {
+ let applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => {
const res = run({ this: doc });
if (!res.success) return false;
const field = res.result;
- if (field instanceof Field) {
- doc.Set(props.fieldKey, field);
- return true;
- } else {
- let dataField = ToField(field);
- if (dataField) {
- doc.Set(props.fieldKey, dataField);
- return true;
- }
- }
- return false;
+ doc[props.fieldKey] = field;
+ return true;
};
return (
- <div className="collectionSchemaView-cellContents" onPointerDown={onItemDown} key={props.Document.Id} ref={reference}>
+ <div className="collectionSchemaView-cellContents" onPointerDown={onItemDown} key={props.Document[Id]} ref={reference}>
<EditableView
display={"inline"}
contents={contents}
height={Number(MAX_ROW_HEIGHT)}
GetValue={() => {
- let field = props.Document.Get(props.fieldKey);
- if (field && field instanceof Field) {
- return field.ToScriptString();
+ let field = props.Document[props.fieldKey];
+ if (field) {
+ //TODO Types
+ // return field.ToScriptString();
+ return String(field);
}
- return field || "";
+ return "";
}}
SetValue={(value: string) => {
let script = CompileScript(value, { addReturn: true, params: { this: Document.name } });
@@ -128,14 +118,13 @@ export class CollectionSchemaView extends CollectionSubView {
}
const run = script.run;
//TODO This should be able to be refactored to compile the script once
- this.props.Document.GetTAsync<ListField<Document>>(this.props.fieldKey, ListField).then((val) => {
- if (val) {
- val.Data.forEach(doc => applyToDoc(doc, run));
- }
- });
+ const val = Cast(this.props.Document[this.props.fieldKey], listSpec(Doc));
+ if (val) {
+ val.forEach(doc => applyToDoc(doc, run));
+ }
}}>
</EditableView>
- </div>
+ </div >
);
}
@@ -165,41 +154,38 @@ export class CollectionSchemaView extends CollectionSubView {
super.CreateDropTarget(ele);
}
- toggleKey = (key: Key) => {
- this.props.Document.GetTAsync<ListField<Key>>(KeyStore.ColumnsKey, ListField).then(field =>
- runInAction(() => {
- if (field !== FieldWaiting) {
- if (field) {
- const index = field.Data.indexOf(key);
- if (index === -1) {
- this.columns.push(key);
- } else {
- this.columns.splice(index, 1);
- }
- } else {
- this.props.Document.SetData(KeyStore.ColumnsKey, [key], ListField);
- }
- }
- }));
+ @action
+ toggleKey = (key: string) => {
+ let list = Cast(this.props.Document.schemaColumns, listSpec("string"));
+ if (list === undefined) {
+ this.props.Document.schemaColumns = list = new List<string>([key]);
+ } else {
+ const index = list.indexOf(key);
+ if (index === -1) {
+ list.push(key);
+ } else {
+ list.splice(index, 1);
+ }
+ }
}
//toggles preview side-panel of schema
@action
toggleExpander = (event: React.ChangeEvent<HTMLInputElement>) => {
- this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, this.splitPercentage === 0 ? 33 : 0);
+ this.props.Document.schemaSplitPercentage = this.splitPercentage === 0 ? 33 : 0;
}
@action
onDividerMove = (e: PointerEvent): void => {
let nativeWidth = this._mainCont!.getBoundingClientRect();
- this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, Math.max(0, 100 - Math.round((e.clientX - nativeWidth.left) / nativeWidth.width * 100)));
+ this.props.Document.schemaSplitPercentage = Math.max(0, 100 - Math.round((e.clientX - nativeWidth.left) / nativeWidth.width * 100));
}
@action
onDividerUp = (e: PointerEvent): void => {
document.removeEventListener("pointermove", this.onDividerMove);
document.removeEventListener('pointerup', this.onDividerUp);
if (this._startSplitPercent === this.splitPercentage) {
- this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, this.splitPercentage === 0 ? 33 : 0);
+ this.props.Document.schemaSplitPercentage = this.splitPercentage === 0 ? 33 : 0;
}
}
onDividerDown = (e: React.PointerEvent) => {
@@ -212,8 +198,7 @@ export class CollectionSchemaView extends CollectionSubView {
onPointerDown = (e: React.PointerEvent): void => {
if (e.button === 0 && !e.altKey && !e.ctrlKey && !e.metaKey) {
- if (this.props.isSelected())
- e.stopPropagation();
+ if (this.props.isSelected()) e.stopPropagation();
else e.preventDefault();
}
}
@@ -226,7 +211,7 @@ export class CollectionSchemaView extends CollectionSubView {
@action
addColumn = () => {
- this.columns.push(new Key(this._newKeyName));
+ this.columns.push(this._newKeyName);
this._newKeyName = "";
}
@@ -241,21 +226,22 @@ export class CollectionSchemaView extends CollectionSubView {
this.previewScript = e.currentTarget.value;
}
- get previewDocument(): Document | undefined {
- const children = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
- const selected = children.length > this._selectedIndex ? children[this._selectedIndex] : undefined;
- return selected ? (this.previewScript ? selected.Get(new Key(this.previewScript)) as Document : selected) : undefined;
+ get previewDocument(): Doc | undefined {
+ const children = Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), []);
+ const selected = children.length > this._selectedIndex ? FieldValue(children[this._selectedIndex]) : undefined;
+ return selected ? (this.previewScript ? FieldValue(Cast(selected[this.previewScript], Doc)) : selected) : undefined;
}
get tableWidth() { return (this.props.PanelWidth() - 2 * this.borderWidth - this.DIVIDER_WIDTH) * (1 - this.splitPercentage / 100); }
get previewRegionHeight() { return this.props.PanelHeight() - 2 * this.borderWidth; }
get previewRegionWidth() { return (this.props.PanelWidth() - 2 * this.borderWidth - this.DIVIDER_WIDTH) * this.splitPercentage / 100; }
- private previewDocNativeWidth = () => this.previewDocument!.GetNumber(KeyStore.NativeWidth, this.previewRegionWidth);
- private previewDocNativeHeight = () => this.previewDocument!.GetNumber(KeyStore.NativeHeight, this.previewRegionHeight);
+ private previewDocNativeWidth = () => Cast(this.previewDocument!.nativeWidth, "number", this.previewRegionWidth);
+ private previewDocNativeHeight = () => Cast(this.previewDocument!.nativeHeight, "number", this.previewRegionHeight);
private previewContentScaling = () => {
let wscale = this.previewRegionWidth / (this.previewDocNativeWidth() ? this.previewDocNativeWidth() : this.previewRegionWidth);
- if (wscale * this.previewDocNativeHeight() > this.previewRegionHeight)
+ if (wscale * this.previewDocNativeHeight() > this.previewRegionHeight) {
return this.previewRegionHeight / (this.previewDocNativeHeight() ? this.previewDocNativeHeight() : this.previewRegionHeight);
+ }
return wscale;
}
private previewPanelWidth = () => this.previewDocNativeWidth() * this.previewContentScaling();
@@ -263,22 +249,23 @@ export class CollectionSchemaView extends CollectionSubView {
get previewPanelCenteringOffset() { return (this.previewRegionWidth - this.previewDocNativeWidth() * this.previewContentScaling()) / 2; }
getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(
- this.borderWidth - this.DIVIDER_WIDTH - this.tableWidth - this.previewPanelCenteringOffset,
- - this.borderWidth).scale(1 / this.previewContentScaling());
+ - this.borderWidth).scale(1 / this.previewContentScaling())
@computed
get previewPanel() {
// let doc = CompileScript(this.previewScript, { this: selected }, true)();
- return !this.previewDocument ? (null) : (
+ const previewDoc = this.previewDocument;
+ return !previewDoc ? (null) : (
<div className="collectionSchemaView-previewRegion" style={{ width: `${this.previewRegionWidth}px` }}>
<div className="collectionSchemaView-previewDoc" style={{ transform: `translate(${this.previewPanelCenteringOffset}px, 0px)` }}>
- <DocumentView Document={this.previewDocument} isTopMost={false} selectOnLoad={false}
+ <DocumentView Document={previewDoc} isTopMost={false} selectOnLoad={false}
toggleMinimized={emptyFunction}
addDocument={this.props.addDocument} removeDocument={this.props.removeDocument}
ScreenToLocalTransform={this.getPreviewTransform}
ContentScaling={this.previewContentScaling}
PanelWidth={this.previewPanelWidth} PanelHeight={this.previewPanelHeight}
ContainingCollectionView={this.props.CollectionView}
- focus={emptyDocFunction}
+ focus={emptyFunction}
parentActive={this.props.active}
whenActiveChanged={this.props.whenActiveChanged}
/>
@@ -290,24 +277,25 @@ export class CollectionSchemaView extends CollectionSubView {
}
get documentKeysCheckList() {
- const docs = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
- let keys: { [id: string]: boolean } = {};
+ const docs = Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), []);
+ let 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.
- untracked(() => docs.map(doc => doc.GetAllPrototypes().map(proto => proto._proxies.forEach((val: any, key: string) => keys[key] = false))));
+ //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.Id] = true);
+ this.columns.forEach(key => keys[key] = true);
return Array.from(Object.keys(keys)).map(item =>
- (<KeyToggle checked={keys[item]} key={item} keyId={item} toggle={this.toggleKey} />));
+ (<KeyToggle checked={keys[item]} key={item} keyName={item} toggle={this.toggleKey} />));
}
get tableOptionsPanel() {
return !this.props.active() ? (null) :
(<Flyout
- anchorPoint={anchorPoints.LEFT_TOP}
+ anchorPoint={anchorPoints.RIGHT_TOP}
content={<div>
<div id="schema-options-header"><h5><b>Options</b></h5></div>
<div id="options-flyout-div">
@@ -335,16 +323,17 @@ export class CollectionSchemaView extends CollectionSubView {
render() {
library.add(faCog);
library.add(faPlus);
- const children = this.props.Document.GetList(this.props.fieldKey, [] as Document[]);
+ //This can't just pass FieldValue to filter because filter passes other arguments to the passed in function, which end up as default values in FieldValue
+ const children = (this.children || []).filter(doc => FieldValue(doc));
return (
<div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} onWheel={this.onWheel}
onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createTarget}>
<div className="collectionSchemaView-tableContainer" style={{ width: `${this.tableWidth}px` }}>
<ReactTable data={children} page={0} pageSize={children.length} showPagination={false}
columns={this.columns.map(col => ({
- Header: col.Name,
- accessor: (doc: Document) => [doc, col],
- id: col.Id
+ Header: col,
+ accessor: (doc: Doc) => [doc, col],
+ id: col
}))}
column={{ ...ReactTableDefaults.column, Cell: this.renderCell, }}
getTrProps={this.getTrProps}