diff options
| author | monikahedman <monika_hedman@brown.edu> | 2019-07-14 17:08:03 -0400 |
|---|---|---|
| committer | monikahedman <monika_hedman@brown.edu> | 2019-07-14 17:08:03 -0400 |
| commit | 7f011d633021fece4d071b741f8571440236ea71 (patch) | |
| tree | ce2e7dc7c29a2a2ebab57efbc8001b2d753819d8 /src/client/views/collections/CollectionTreeView.tsx | |
| parent | 2575564d70828820521074455383e940d521cca8 (diff) | |
| parent | 7d9e29690956327d1ed9981cd2882d08b72b5c86 (diff) | |
pulled from master
Diffstat (limited to 'src/client/views/collections/CollectionTreeView.tsx')
| -rw-r--r-- | src/client/views/collections/CollectionTreeView.tsx | 73 |
1 files changed, 45 insertions, 28 deletions
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index c83a2d2c6..0196fecff 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -1,7 +1,7 @@ import { library } from '@fortawesome/fontawesome-svg-core'; -import { faAngleRight, faCamera, faExpand, faBell, faCaretDown, faCaretRight, faCaretSquareDown, faCaretSquareRight, faTrashAlt } from '@fortawesome/free-solid-svg-icons'; +import { faAngleRight, faCamera, faExpand, faTrash, faBell, faCaretDown, faCaretRight, faCaretSquareDown, faCaretSquareRight, faTrashAlt } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, observable, trace } from "mobx"; +import { action, computed, observable, trace, untracked } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast, HeightSym, WidthSym, Opt } from '../../../new_fields/Doc'; import { Id } from '../../../new_fields/FieldSymbols'; @@ -9,7 +9,7 @@ import { List } from '../../../new_fields/List'; import { Document, listSpec } from '../../../new_fields/Schema'; import { BoolCast, Cast, NumCast, StrCast } from '../../../new_fields/Types'; import { emptyFunction, Utils } from '../../../Utils'; -import { Docs, DocUtils, DocTypes } from '../../documents/Documents'; +import { Docs, DocUtils, DocumentType } from '../../documents/Documents'; import { DocumentManager } from '../../util/DocumentManager'; import { DragManager, dropActionType, SetupDrag } from "../../util/DragManager"; import { SelectionManager } from '../../util/SelectionManager'; @@ -51,6 +51,7 @@ export interface TreeViewProps { library.add(faTrashAlt); library.add(faAngleRight); library.add(faBell); +library.add(faTrash); library.add(faCamera); library.add(faExpand); library.add(faCaretDown); @@ -72,9 +73,10 @@ class TreeView extends React.Component<TreeViewProps> { @observable _collapsed: boolean = true; @computed get fieldKey() { - let keys = Array.from(Object.keys(this.resolvedDataDoc)); + let keys = Array.from(Object.keys(this.resolvedDataDoc)); // bcz: Argh -- make untracked to avoid this rerunning whenever 'libraryBrush' is set if (this.resolvedDataDoc.proto instanceof Doc) { - keys.push(...Array.from(Object.keys(this.resolvedDataDoc.proto))); + let arr = Array.from(Object.keys(this.resolvedDataDoc.proto));// bcz: Argh -- make untracked to avoid this rerunning whenever 'libraryBrush' is set + keys.push(...arr); while (keys.indexOf("proto") !== -1) keys.splice(keys.indexOf("proto"), 1); } let keyList: string[] = []; @@ -112,12 +114,12 @@ class TreeView extends React.Component<TreeViewProps> { } } onPointerLeave = (e: React.PointerEvent): void => { - this.props.document.libraryBrush = false; + this.props.document.libraryBrush = undefined; this._header!.current!.className = "treeViewItem-header"; document.removeEventListener("pointermove", this.onDragMove, true); } onDragMove = (e: PointerEvent): void => { - this.props.document.libraryBrush = false; + this.props.document.libraryBrush = undefined; let x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY); let rect = this._header!.current!.getBoundingClientRect(); let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2); @@ -151,7 +153,8 @@ class TreeView extends React.Component<TreeViewProps> { let docList = Cast(this.resolvedDataDoc[this.fieldKey], listSpec(Doc)); let doc = Cast(this.resolvedDataDoc[this.fieldKey], Doc); let isDoc = doc instanceof Doc || docList; - return <div className="bullet" onClick={action(() => this._collapsed = !this._collapsed)}> + let c + return <div className="bullet" onClick={action(() => this._collapsed = !this._collapsed)} style={{ color: StrCast(this.props.document.color, "black"), opacity: 0.4 }}> {<FontAwesomeIcon icon={this._collapsed ? (isDoc ? "caret-square-right" : "caret-right") : (isDoc ? "caret-square-down" : "caret-down")} />} </div>; } @@ -169,7 +172,7 @@ class TreeView extends React.Component<TreeViewProps> { SetValue={(value: string) => (Doc.GetProto(this.resolvedDataDoc)[key] = value) ? true : true} OnFillDown={(value: string) => { Doc.GetProto(this.resolvedDataDoc)[key] = value; - let doc = Docs.FreeformDocument([], { title: "", x: 0, y: 0, width: 100, height: 25, templates: new List<string>([Templates.Title.Layout]) }); + let doc = Docs.Create.FreeformDocument([], { title: "", x: 0, y: 0, width: 100, height: 25, templates: new List<string>([Templates.Title.Layout]) }); TreeView.loadId = doc[Id]; return this.props.addDocument(doc); }} @@ -202,7 +205,7 @@ class TreeView extends React.Component<TreeViewProps> { let onItemDown = SetupDrag(reference, () => this.resolvedDataDoc, this.move, this.props.dropAction, this.props.treeViewId, true); let headerElements = ( - <span className="collectionTreeView-keyHeader" key={this._chosenKey} + <span className="collectionTreeView-keyHeader" key={this._chosenKey + "chosen"} onPointerDown={action(() => { let ind = this.keyList.indexOf(this._chosenKey); ind = (ind + 1) % this.keyList.length; @@ -218,8 +221,8 @@ class TreeView extends React.Component<TreeViewProps> { return <> <div className="docContainer" id={`docContainer-${this.props.parentKey}`} ref={reference} onPointerDown={onItemDown} style={{ - background: BoolCast(this.props.document.libraryBrush, false) ? "#06121212" : "0", - outline: BoolCast(this.props.document.workspaceBrush, false) ? "dashed 1px #06123232" : undefined, + background: BoolCast(this.props.document.libraryBrush) ? "#06121212" : "0", + outline: BoolCast(this.props.document.workspaceBrush) ? "dashed 1px #06123232" : undefined, pointerEvents: this.props.active() || SelectionManager.GetIsDragging() ? "all" : "none" }} > @@ -245,7 +248,7 @@ class TreeView extends React.Component<TreeViewProps> { ContextMenu.Instance.addItem({ description: "Open as Workspace", event: undoBatch(() => MainView.Instance.openWorkspace(this.resolvedDataDoc)), icon: "caret-square-right" }); ContextMenu.Instance.addItem({ description: "Delete Workspace", event: undoBatch(() => this.props.deleteDoc(this.props.document)), icon: "trash-alt" }); } - ContextMenu.Instance.addItem({ description: "Open Fields", event: () => { let kvp = Docs.KVPDocument(this.props.document, { width: 300, height: 300 }); this.props.addDocTab(kvp, this.props.dataDoc ? this.props.dataDoc : kvp, "onRight"); }, icon: "layer-group" }); + ContextMenu.Instance.addItem({ description: "Open Fields", event: () => { let kvp = Docs.Create.KVPDocument(this.props.document, { width: 300, height: 300 }); this.props.addDocTab(kvp, this.props.dataDoc ? this.props.dataDoc : kvp, "onRight"); }, icon: "layer-group" }); ContextMenu.Instance.displayMenu(e.pageX > 156 ? e.pageX - 156 : 0, e.pageY - 15); e.stopPropagation(); e.preventDefault(); @@ -299,7 +302,14 @@ class TreeView extends React.Component<TreeViewProps> { let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.props.document, this._chosenKey, doc, addBefore, before); let groups = LinkManager.Instance.getRelatedGroupedLinks(this.props.document); groups.forEach((groupLinkDocs, groupType) => { - let destLinks = groupLinkDocs.map(d => LinkManager.Instance.getOppositeAnchor(d, this.props.document)); + // let destLinks = groupLinkDocs.map(d => LinkManager.Instance.getOppositeAnchor(d, this.props.document)); + let destLinks: Doc[] = []; + groupLinkDocs.forEach((doc) => { + let opp = LinkManager.Instance.getOppositeAnchor(doc, this.props.document); + if (opp) { + destLinks.push(opp); + } + }); ele.push( <div key={"treeviewlink-" + groupType + "subtitle"}> <div className="collectionTreeView-subtitle">{groupType}:</div> @@ -313,10 +323,10 @@ class TreeView extends React.Component<TreeViewProps> { return ele; } - @computed get docBounds() { - if (StrCast(this.props.document.type).indexOf(DocTypes.COL) === -1) return undefined; + @computed get boundsOfCollectionDocument() { + if (StrCast(this.props.document.type).indexOf(DocumentType.COL) === -1) return undefined; let layoutDoc = Doc.expandTemplateLayout(this.props.document, this.props.dataDoc); - return Doc.ComputeContentBounds(layoutDoc); + return Doc.ComputeContentBounds(DocListCast(layoutDoc.data)); } docWidth = () => { let aspect = NumCast(this.props.document.nativeHeight) / NumCast(this.props.document.nativeWidth); @@ -324,7 +334,7 @@ class TreeView extends React.Component<TreeViewProps> { return NumCast(this.props.document.nativeWidth) ? Math.min(this.props.document[WidthSym](), this.props.panelWidth() - 5) : this.props.panelWidth() - 5; } docHeight = () => { - let bounds = this.docBounds; + let bounds = this.boundsOfCollectionDocument; return Math.min(this.MAX_EMBED_HEIGHT, (() => { let aspect = NumCast(this.props.document.nativeHeight) / NumCast(this.props.document.nativeWidth); if (aspect) return this.docWidth() * aspect; @@ -332,10 +342,6 @@ class TreeView extends React.Component<TreeViewProps> { return NumCast(this.props.document.height) ? NumCast(this.props.document.height) : 50; })()); } - fitToBox = () => { - let bounds = this.docBounds!; - return [(bounds.x + bounds.r) / 2, (bounds.y + bounds.b) / 2, Math.min(this.docHeight() / (bounds.b - bounds.y), this.docWidth() / (bounds.r - bounds.x))]; - } render() { let contentElement: (JSX.Element | null) = null; @@ -353,12 +359,12 @@ class TreeView extends React.Component<TreeViewProps> { </ul >; } else { let layoutDoc = Doc.expandTemplateLayout(this.props.document, this.props.dataDoc); - contentElement = <div ref={this._dref} style={{ display: "inline-block", height: this.docHeight() }} key={this.props.document[Id]}> + contentElement = <div ref={this._dref} style={{ display: "inline-block", height: this.docHeight() }} key={this.props.document[Id] + this.props.document.title}> <CollectionSchemaPreview Document={layoutDoc} DataDocument={this.resolvedDataDoc} renderDepth={this.props.renderDepth} - fitToBox={this.docBounds && !NumCast(this.props.document.nativeWidth) ? this.fitToBox : undefined} + fitToBox={this.boundsOfCollectionDocument !== undefined} width={this.docWidth} height={this.docHeight} getTransform={this.docTransform} @@ -426,7 +432,7 @@ class TreeView extends React.Component<TreeViewProps> { dataDoc={dataDoc} containingCollection={containingCollection} treeViewId={treeViewId} - key={child[Id]} + key={child[Id] + "child " + i} indentDocument={indent} renderDepth={renderDepth} deleteDoc={remove} @@ -509,15 +515,25 @@ export class CollectionTreeView extends CollectionSubView(Document) { </div> </div >; } + @computed get clearButton() { + return <div id="toolbar" key="toolbar"> + <div > + <button className="toolbar-button round-button" title="Notifs" + onClick={undoBatch(action(() => Doc.GetProto(this.props.Document)[this.props.fieldKey] = undefined))}> + <FontAwesomeIcon icon={faTrash} size="sm" /> + </button> + </div> + </div >; + } + render() { let dropAction = StrCast(this.props.Document.dropAction) as dropActionType; let addDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before); let moveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc); - return !this.childDocs ? (null) : ( <div id="body" className="collectionTreeView-dropTarget" - style={{ overflow: "auto" }} + style={{ overflow: "auto", background: StrCast(this.props.Document.backgroundColor, "lightgray") }} onContextMenu={this.onContextMenu} onWheel={(e: React.WheelEvent) => (e.target as any).scrollHeight > (e.target as any).clientHeight && e.stopPropagation()} onDrop={this.onTreeDrop} @@ -530,11 +546,12 @@ export class CollectionTreeView extends CollectionSubView(Document) { SetValue={(value: string) => (Doc.GetProto(this.resolvedDataDoc).title = value) ? true : true} OnFillDown={(value: string) => { Doc.GetProto(this.props.Document).title = value; - let doc = Docs.FreeformDocument([], { title: "", x: 0, y: 0, width: 100, height: 25, templates: new List<string>([Templates.Title.Layout]) }); + let doc = Docs.Create.FreeformDocument([], { title: "", x: 0, y: 0, width: 100, height: 25, templates: new List<string>([Templates.Title.Layout]) }); TreeView.loadId = doc[Id]; Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, this.childDocs.length ? this.childDocs[0] : undefined, true); }} /> {this.props.Document.workspaceLibrary ? this.notifsButton : (null)} + {this.props.Document.allowClear ? this.clearButton : (null)} <ul className="no-indent" style={{ width: "max-content" }} > { TreeView.GetChildElements(this.childDocs, this.props.Document[Id], this.props.Document, this.props.DataDoc, this.props.fieldKey, addDoc, this.remove, |
