diff options
| author | Tyler Schicke <tyler_schicke@brown.edu> | 2019-03-02 23:10:01 -0500 |
|---|---|---|
| committer | Tyler Schicke <tyler_schicke@brown.edu> | 2019-03-02 23:10:01 -0500 |
| commit | fd77567ca4cb2afbaa9c2df1a71f8ae728369bb1 (patch) | |
| tree | 123b826150a9714b4431a2a55ba948e13608099f /src/client/views/collections/CollectionTreeView.tsx | |
| parent | 6d456bbe4a2de50abe1a4b338d1f446d3123b321 (diff) | |
| parent | f1be2fc29ea59c05a3ece851df3ed72adb07a0c2 (diff) | |
Merge branch 'master' of github-tsch-brown:browngraphicslab/Dash-Web into contextMenu
Diffstat (limited to 'src/client/views/collections/CollectionTreeView.tsx')
| -rw-r--r-- | src/client/views/collections/CollectionTreeView.tsx | 165 |
1 files changed, 118 insertions, 47 deletions
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 52e853bf7..8b06d9ac4 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -7,9 +7,20 @@ import React = require("react") import { TextField } from "../../../fields/TextField"; import { observable, action } from "mobx"; import "./CollectionTreeView.scss"; +import { EditableView } from "../EditableView"; +import { setupDrag } from "../../util/DragManager"; +import { FieldWaiting } from "../../../fields/Field"; +import { COLLECTION_BORDER_WIDTH } from "./CollectionView"; export interface TreeViewProps { document: Document; + deleteDoc: (doc: Document) => void; +} + +export enum BulletType { + Collapsed, + Collapsible, + List } @observer @@ -21,61 +32,100 @@ class TreeView extends React.Component<TreeViewProps> { @observable collapsed: boolean = false; + delete = () => { + this.props.deleteDoc(this.props.document); + } + + + @action + remove = (document: Document) => { + var children = this.props.document.GetT<ListField<Document>>(KeyStore.Data, ListField); + if (children && children !== FieldWaiting) { + children.Data.splice(children.Data.indexOf(document), 1); + } + } + + renderBullet(type: BulletType) { + let onClicked = action(() => this.collapsed = !this.collapsed); + + switch (type) { + case BulletType.Collapsed: + return <div className="bullet" onClick={onClicked}>▶</div> + case BulletType.Collapsible: + return <div className="bullet" onClick={onClicked}>▼</div> + case BulletType.List: + return <div className="bullet">—</div> + } + } + /** - * Renders a single child document. If this child is a collection, it will call renderTreeView again. Otherwise, it will just append a list element. - * @param document The document to render. + * Renders the EditableView title element for placement into the tree. */ - renderChild(document: Document) { - var children = document.GetT<ListField<Document>>(KeyStore.Data, ListField); - let title = document.GetT<TextField>(KeyStore.Title, TextField); + renderTitle() { + let title = this.props.document.GetT<TextField>(KeyStore.Title, TextField); // if the title hasn't loaded, immediately return the div if (!title || title === "<Waiting>") { - return <div key={document.Id}></div>; + return <div key={this.props.document.Id}></div>; } - // otherwise, check if it's a collection. - else if (children && children !== "<Waiting>") { - // if it's not collapsed, then render the full TreeView. + return <div className="docContainer"> <EditableView contents={title.Data} + height={36} GetValue={() => { + let title = this.props.document.GetT<TextField>(KeyStore.Title, TextField); + if (title && title !== "<Waiting>") + return title.Data; + return ""; + }} SetValue={(value: string) => { + this.props.document.SetData(KeyStore.Title, value, TextField); + return true; + }} /> + <div className="delete-button" onClick={this.delete}>x</div> + </div > + } + + render() { + var children = this.props.document.GetT<ListField<Document>>(KeyStore.Data, ListField); + + let reference = React.createRef<HTMLDivElement>(); + let onItemDown = setupDrag(reference, () => this.props.document); + let titleElement = this.renderTitle(); + + // check if this document is a collection + if (children && children !== FieldWaiting) { + let subView; + + // if uncollapsed, then add the children elements if (!this.collapsed) { - return ( - <li className="uncollapsed" key={document.Id} onClick={action(() => this.collapsed = true)} > - {title.Data} - <ul key={document.Id}> - <TreeView - document={document} - /> + // render all children elements + let childrenElement = (children.Data.map(value => + <TreeView document={value} deleteDoc={this.remove} />) + ) + subView = + <li key={this.props.document.Id} > + {this.renderBullet(BulletType.Collapsible)} + {titleElement} + <ul key={this.props.document.Id}> + {childrenElement} </ul> </li> - ); } else { - return <li className="collapsed" key={document.Id} onClick={action(() => this.collapsed = false)}>{title.Data}</li> + subView = <li key={this.props.document.Id}> + {this.renderBullet(BulletType.Collapsed)} + {titleElement} + </li> } - } - // finally, if it's a normal document, then render it as such. - else { - return <li key={document.Id}>{title.Data}</li>; + return <div className="treeViewItem-container" onPointerDown={onItemDown} ref={reference}> + {subView} + </div> } - } - - render() { - var children = this.props.document.GetT<ListField<Document>>(KeyStore.Data, ListField); - if (children && children !== "<Waiting>") { - return (<div> - {children.Data.map(value => this.renderChild(value))} - </div>) - // let results: JSX.Element[] = []; - - // // append a list item for each child in the collection - // children.Data.forEach((value) => { - // results.push(this.renderChild(value)); - // }) - - // return results; - } else { - return <div></div>; + // otherwise this is a normal leaf node + else { + return <li key={this.props.document.Id}> + {this.renderBullet(BulletType.List)} + {titleElement} + </li>; } } } @@ -84,21 +134,42 @@ class TreeView extends React.Component<TreeViewProps> { @observer export class CollectionTreeView extends CollectionViewBase { + @action + remove = (document: Document) => { + var children = this.props.Document.GetT<ListField<Document>>(KeyStore.Data, ListField); + if (children && children !== FieldWaiting) { + children.Data.splice(children.Data.indexOf(document), 1); + } + } + render() { let titleStr = ""; let title = this.props.Document.GetT<TextField>(KeyStore.Title, TextField); - if (title && title !== "<Waiting>") { + if (title && title !== FieldWaiting) { titleStr = title.Data; } + + var children = this.props.Document.GetT<ListField<Document>>(KeyStore.Data, ListField); + let childrenElement = !children || children === FieldWaiting ? (null) : + (children.Data.map(value => + <TreeView document={value} key={value.Id} deleteDoc={this.remove} />) + ) + return ( - <div> - <h3>{titleStr}</h3> + <div id="body" className="collectionTreeView-dropTarget" onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createDropTarget} style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }}> + <h3> + <EditableView contents={titleStr} + height={72} GetValue={() => { + return this.props.Document.Title; + }} SetValue={(value: string) => { + this.props.Document.SetData(KeyStore.Title, value, TextField); + return true; + }} /> + </h3> <ul className="no-indent"> - <TreeView - document={this.props.Document} - /> + {childrenElement} </ul> - </div> + </div > ); } }
\ No newline at end of file |
