aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/CollectionSchemaView.tsx
diff options
context:
space:
mode:
authorlaurawilsonri <laura_wilson@brown.edu>2019-03-18 18:14:27 -0400
committerlaurawilsonri <laura_wilson@brown.edu>2019-03-18 18:14:27 -0400
commit9d939c1190ef86e456cf26e9f5cb84743279f7a6 (patch)
tree24d72d918f2becf6762ea30b92da7339957eedbd /src/client/views/collections/CollectionSchemaView.tsx
parent67170e521366f8178645cc85aaf377e53b1a6f21 (diff)
parentf70ad315167b714f11f7d68f35a46abe9e525a4d (diff)
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web into editableSchema
Diffstat (limited to 'src/client/views/collections/CollectionSchemaView.tsx')
-rw-r--r--src/client/views/collections/CollectionSchemaView.tsx230
1 files changed, 188 insertions, 42 deletions
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 7c87ef744..2598dd3a9 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -1,11 +1,16 @@
+<<<<<<< HEAD
import React = require("react");
import { action, observable } from "mobx";
+=======
+import React = require("react")
+import { action, observable, ObservableMap, computed } from "mobx";
+>>>>>>> f70ad315167b714f11f7d68f35a46abe9e525a4d
import { observer } from "mobx-react";
import Measure from "react-measure";
import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table";
import "react-table/react-table.css";
import { Document } from "../../../fields/Document";
-import { Field } from "../../../fields/Field";
+import { Field, Opt } from "../../../fields/Field";
import { KeyStore } from "../../../fields/KeyStore";
import { CompileScript, ToField } from "../../util/Scripting";
import { Transform } from "../../util/Transform";
@@ -14,9 +19,10 @@ import { EditableView } from "../EditableView";
import { DocumentView } from "../nodes/DocumentView";
import { FieldView, FieldViewProps } from "../nodes/FieldView";
import "./CollectionSchemaView.scss";
-import { COLLECTION_BORDER_WIDTH } from "./CollectionView";
+import { COLLECTION_BORDER_WIDTH, CollectionView } from "./CollectionView";
import { CollectionViewBase } from "./CollectionViewBase";
import { setupDrag } from "../../util/DragManager";
+<<<<<<< HEAD
import '../DocumentDecorations.scss';
import { Flyout, anchorPoints } from "../DocumentDecorations";
import { DropdownButton, Dropdown } from 'react-bootstrap';
@@ -27,21 +33,53 @@ import { Key } from "../../../fields/Key";
import { Server } from "../../Server";
//import { MenuItem } from 'react-bootstrap';
+=======
+import { Key } from "./../../../fields/Key";
+import { Server } from "../../Server";
+import { ListField } from "../../../fields/ListField";
+
+>>>>>>> f70ad315167b714f11f7d68f35a46abe9e525a4d
// 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;
+
+ componentWillReceiveProps() {
+ Server.GetField(this.props.keyId, action((field: Opt<Field>) => {
+ if (field instanceof Key) {
+ this.key = field;
+ }
+ }))
+ }
+
+ render() {
+ if (this.key) {
+ return (<div key={this.key.Id}>
+ <input type="checkbox" checked={this.props.checked} onChange={() => this.key && this.props.toggle(this.key)} />{this.key.Name}
+ </div>)
+ } else {
+ return <div></div>
+ }
+ }
+}
+
+@observer
export class CollectionSchemaView extends CollectionViewBase {
private _mainCont = React.createRef<HTMLDivElement>();
- private DIVIDER_WIDTH = 5;
+ private DIVIDER_WIDTH = 4;
+ @observable _columns: Array<Key> = [KeyStore.Title, KeyStore.Data, KeyStore.Author];
@observable _contentScaling = 1; // used to transfer the dimensions of the content pane in the DOM to the ContentScaling prop of the DocumentView
@observable _dividerX = 0;
@observable _panelWidth = 0;
@observable _panelHeight = 0;
@observable _selectedIndex = 0;
- @observable _splitPercentage: number = 50;
+ @observable _columnsPercentage = 0;
+ @computed get splitPercentage() { return this.props.Document.GetNumber(KeyStore.SchemaSplitPercentage, 0); }
renderCell = (rowProps: CellInfo) => {
let props: FieldViewProps = {
@@ -57,10 +95,12 @@ export class CollectionSchemaView extends CollectionViewBase {
<FieldView {...props} />
)
let reference = React.createRef<HTMLDivElement>();
- let onItemDown = setupDrag(reference, () => props.doc);
+ let onItemDown = setupDrag(reference, () => props.doc, (containingCollection: CollectionView) => this.props.removeDocument(props.doc));
return (
- <div onPointerDown={onItemDown} key={props.doc.Id} ref={reference}>
- <EditableView contents={contents}
+ <div className="collectionSchemaView-cellContents" onPointerDown={onItemDown} style={{ height: "36px" }} key={props.doc.Id} ref={reference}>
+ <EditableView
+ display={"inline"}
+ contents={contents}
height={36} GetValue={() => {
let field = props.doc.Get(props.fieldKey);
if (field && field instanceof Field) {
@@ -69,7 +109,7 @@ export class CollectionSchemaView extends CollectionViewBase {
return field || "";
}}
SetValue={(value: string) => {
- let script = CompileScript(value, undefined, true);
+ let script = CompileScript(value);
if (!script.compiled) {
return false;
}
@@ -99,7 +139,8 @@ export class CollectionSchemaView extends CollectionViewBase {
return {
onClick: action((e: React.MouseEvent, handleOriginal: Function) => {
that._selectedIndex = rowInfo.index;
- this._splitPercentage += 0.05; // bcz - ugh - needed to force Measure to do its thing and call onResize
+ // bcz - ugh - needed to force Measure to do its thing and call onResize
+ this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, this.splitPercentage - 0.05)
if (handleOriginal) {
handleOriginal()
@@ -112,27 +153,83 @@ export class CollectionSchemaView extends CollectionViewBase {
};
}
+ get columns() {
+ return this.props.Document.GetList<Key>(KeyStore.ColumnsKey, []);
+ }
+
+ @action
+ toggleKey = (key: Key) => {
+ this.props.Document.GetOrCreateAsync<ListField<Key>>(KeyStore.ColumnsKey, ListField,
+ (field) => {
+ const index = field.Data.indexOf(key);
+ if (index === -1) {
+ this.columns.push(key);
+ } else {
+ this.columns.splice(index, 1);
+ }
+
+ })
+ }
+
+ @observable keys: Key[] = [];
+
+ findAllDocumentKeys = (): { [id: string]: boolean } => {
+ const docs = this.props.Document.GetList<Document>(this.props.fieldKey, []);
+ let keys: { [id: string]: boolean } = {}
+ docs.forEach(doc => {
+ let protos = doc.GetAllPrototypes();
+ for (const proto of protos) {
+ proto._proxies.forEach((val: any, key: string) => {
+ keys[key] = false
+ })
+ }
+ })
+ this.columns.forEach(key => {
+ keys[key.Id] = true;
+ })
+ return keys;
+ }
+
_startSplitPercent = 0;
@action
onDividerMove = (e: PointerEvent): void => {
let nativeWidth = this._mainCont.current!.getBoundingClientRect();
- this._splitPercentage = Math.round((e.clientX - nativeWidth.left) / nativeWidth.width * 100);
+ this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, 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._splitPercentage = this._splitPercentage == 1 ? 66 : 100;
+ if (this._startSplitPercent == this.splitPercentage) {
+ this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, this.splitPercentage == 0 ? 33 : 0);
}
}
onDividerDown = (e: React.PointerEvent) => {
- this._startSplitPercent = this._splitPercentage;
+ this._startSplitPercent = this.splitPercentage;
e.stopPropagation();
e.preventDefault();
document.addEventListener("pointermove", this.onDividerMove);
document.addEventListener('pointerup', this.onDividerUp);
}
+
+
+ @action
+ onColDividerMove = (e: PointerEvent): void => {
+ let nativeWidth = this._mainCont.current!.getBoundingClientRect();
+ this._columnsPercentage = 100 - (e.clientY - nativeWidth.top) / nativeWidth.height * 100;
+ }
+ @action
+ onColDividerUp = (e: PointerEvent): void => {
+ document.removeEventListener("pointermove", this.onColDividerMove);
+ document.removeEventListener('pointerup', this.onColDividerUp);
+ }
+ onColDividerDown = (e: React.PointerEvent) => {
+ e.stopPropagation();
+ e.preventDefault();
+ document.addEventListener("pointermove", this.onColDividerMove);
+ document.addEventListener('pointerup', this.onColDividerUp);
+ }
+
@action
onExpanderMove = (e: PointerEvent): void => {
e.stopPropagation();
@@ -144,12 +241,12 @@ export class CollectionSchemaView extends CollectionViewBase {
e.preventDefault();
document.removeEventListener("pointermove", this.onExpanderMove);
document.removeEventListener('pointerup', this.onExpanderUp);
- if (this._startSplitPercent == this._splitPercentage) {
- this._splitPercentage = this._splitPercentage == 100 ? 66 : 100;
+ if (this._startSplitPercent == this.splitPercentage) {
+ this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, this.splitPercentage == 0 ? 33 : 0);
}
}
onExpanderDown = (e: React.PointerEvent) => {
- this._startSplitPercent = this._splitPercentage;
+ this._startSplitPercent = this.splitPercentage;
e.stopPropagation();
e.preventDefault();
document.addEventListener("pointermove", this.onExpanderMove);
@@ -162,15 +259,36 @@ export class CollectionSchemaView extends CollectionViewBase {
// e.preventDefault();
// } else
{
- if (e.buttons === 1) {
- if (this.props.isSelected()) {
- e.stopPropagation();
- }
- }
+ // if (e.buttons === 1) {
+ // if (this.props.isSelected()) {
+ // e.stopPropagation();
+ // }
+ // }
}
}
@action
+ onColumnsMove = (e: PointerEvent): void => {
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ @action
+ onColumnsUp = (e: PointerEvent): void => {
+ e.stopPropagation();
+ e.preventDefault();
+ document.removeEventListener("pointermove", this.onColumnsMove);
+ document.removeEventListener('pointerup', this.onColumnsUp);
+ this._columnsPercentage = this._columnsPercentage ? 0 : 50;
+ }
+ onColumnsDown = (e: React.PointerEvent) => {
+ this._startSplitPercent = this.splitPercentage;
+ e.stopPropagation();
+ e.preventDefault();
+ document.addEventListener("pointermove", this.onColumnsMove);
+ document.addEventListener('pointerup', this.onColumnsUp);
+ }
+
+ @action
setScaling = (r: any) => {
const children = this.props.Document.GetList<Document>(this.props.fieldKey, []);
const selected = children.length > this._selectedIndex ? children[this._selectedIndex] : undefined;
@@ -202,9 +320,10 @@ export class CollectionSchemaView extends CollectionViewBase {
}
render() {
- const columns = this.props.Document.GetList(KeyStore.ColumnsKey, [KeyStore.Title, KeyStore.Data, KeyStore.Author])
+ const columns = this.columns;
const children = this.props.Document.GetList<Document>(this.props.fieldKey, []);
const selected = children.length > this._selectedIndex ? children[this._selectedIndex] : undefined;
+ const allKeys = this.findAllDocumentKeys();
let content = this._selectedIndex == -1 || !selected ? (null) : (
<Measure onResize={this.setScaling}>
{({ measureRef }) =>
@@ -226,8 +345,11 @@ export class CollectionSchemaView extends CollectionViewBase {
)
let previewHandle = !this.props.active() ? (null) : (
<div className="collectionSchemaView-previewHandle" onPointerDown={this.onExpanderDown} />);
- let dividerDragger = this._splitPercentage == 100 ? (null) :
+ let columnsHandle = !this.props.active() ? (null) : (
+ <div className="collectionSchemaView-columnsHandle" onPointerDown={this.onColumnsDown} />);
+ let dividerDragger = this.splitPercentage == 0 ? (null) :
<div className="collectionSchemaView-dividerDragger" onPointerDown={this.onDividerDown} style={{ width: `${this.DIVIDER_WIDTH}px` }} />
+<<<<<<< HEAD
//get the union of all childrens' keys
let addFields: { id: string, name: string }[] = [];
@@ -268,6 +390,10 @@ export class CollectionSchemaView extends CollectionViewBase {
}
+=======
+ let colDividerDragger = this._columnsPercentage == 0 ? (null) :
+ <div className="collectionSchemaView-colDividerDragger" onPointerDown={this.onColDividerDown} style={{ height: `${this.DIVIDER_WIDTH}px` }} />
+>>>>>>> f70ad315167b714f11f7d68f35a46abe9e525a4d
return (
<div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} ref={this._mainCont} style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }} >
@@ -277,33 +403,53 @@ export class CollectionSchemaView extends CollectionViewBase {
this._panelHeight = r.entry.height;
})}>
{({ measureRef }) =>
- <div ref={measureRef} className="collectionSchemaView-tableContainer" style={{ width: `${this._splitPercentage}%` }}>
- <ReactTable
- data={children}
- pageSize={children.length}
- page={0}
- showPagination={false}
- columns={columns.map(col => ({
- Header: col.Name,
- accessor: (doc: Document) => [doc, col],
- id: col.Id
- }))}
- column={{
- ...ReactTableDefaults.column,
- Cell: this.renderCell,
-
- }}
- getTrProps={this.getTrProps}
- />
+ <div ref={measureRef} className="collectionSchemaView-tableContainer"
+ style={{ width: `calc(100% - ${this.splitPercentage}%)` }}>
+ <div className="collectionSchemaView-reactContainer" style={{ height: `calc(100% - ${this._columnsPercentage}%)` }}>
+ <ReactTable
+ data={children}
+ pageSize={children.length}
+ page={0}
+ showPagination={false}
+ columns={columns.map(col => ({
+ Header: col.Name,
+ accessor: (doc: Document) => [doc, col],
+ id: col.Id
+ }))}
+ column={{
+ ...ReactTableDefaults.column,
+ Cell: this.renderCell,
+
+ }}
+ getTrProps={this.getTrProps}
+ />
+ </div>
+ {colDividerDragger}
+ <div className="collectionSchemaView-addColumn" style={{ height: `${this._columnsPercentage}%` }} >
+ {/* <input type="checkbox" id="addColumn-toggle" />
+ <label htmlFor="addColumn-toggle" title="Add Column"><p>+</p></label> */}
+
+ <div className="addColumn-options">
+ <ul style={{ overflow: "scroll" }}>
+ {Array.from(Object.keys(allKeys)).map(item => {
+ return (<KeyToggle checked={allKeys[item]} key={item} keyId={item} toggle={this.toggleKey} />)
+ })}
+ </ul>
+ </div>
+ </div>
</div>
}
</Measure>
{dividerDragger}
- <div className="collectionSchemaView-previewRegion" style={{ width: `calc(${100 - this._splitPercentage}% - ${this.DIVIDER_WIDTH}px)` }}>
+ <div className="collectionSchemaView-previewRegion" style={{ width: `calc(${this.props.Document.GetNumber(KeyStore.SchemaSplitPercentage, 0)}% - ${this.DIVIDER_WIDTH}px)` }}>
{content}
</div>
{previewHandle}
+<<<<<<< HEAD
{optionsMenu}
+=======
+ {columnsHandle}
+>>>>>>> f70ad315167b714f11f7d68f35a46abe9e525a4d
</div>
</div >