diff options
Diffstat (limited to 'src/client/views/collections/TreeView.tsx')
-rw-r--r-- | src/client/views/collections/TreeView.tsx | 73 |
1 files changed, 61 insertions, 12 deletions
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 70ad23f41..09f05f69a 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -1,6 +1,6 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, IReactionDisposer, observable, reaction } from "mobx"; +import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; import { DataSym, Doc, DocListCast, DocListCastOrNull, Field, HeightSym, Opt, StrListCast, WidthSym } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; @@ -14,7 +14,7 @@ import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentType } from "../../documents/DocumentTypes"; import { CurrentUserUtils } from '../../util/CurrentUserUtils'; -import { DocumentManager } from '../../util/DocumentManager'; +import { DocumentManager, DocFocusOrOpen } from '../../util/DocumentManager'; import { DragManager, dropActionType } from "../../util/DragManager"; import { SelectionManager } from '../../util/SelectionManager'; import { SnappingManager } from '../../util/SnappingManager'; @@ -64,6 +64,10 @@ export interface TreeViewProps { onChildClick?: () => ScriptField; skipFields?: string[]; firstLevel: boolean; + // TODO: [AL] add these + AddToMap?: (treeViewDoc: Doc, index: number[]) => Doc[]; + RemFromMap?: (treeViewDoc: Doc, index: number[]) => Doc[]; + hierarchyIndex?: number[]; } const treeBulletWidth = function () { return Number(TREE_BULLET_WIDTH.replace("px", "")); }; @@ -109,7 +113,7 @@ export class TreeView extends React.Component<TreeViewProps> { get defaultExpandedView() { return this.doc.viewType === CollectionViewType.Docking ? this.fieldKey : this.props.treeView.dashboardMode ? this.fieldKey : - this.props.treeView.fileSysMode ? (this.doc.isFolder ? this.fieldKey : "aliases") : + this.props.treeView.fileSysMode ? (this.doc.isFolder ? this.fieldKey : "aliases") : // for displaying this.props.treeView.outlineMode || this.childDocs ? this.fieldKey : Doc.UserDoc().noviceMode ? "layout" : StrCast(this.props.treeView.doc.treeViewExpandedView, "fields"); } @@ -127,6 +131,16 @@ export class TreeView extends React.Component<TreeViewProps> { @computed get selected() { return SelectionManager.IsSelected(this._docRef); } // SelectionManager.Views().lastElement()?.props.Document === this.props.document; } + @observable _presTimer!: NodeJS.Timeout; + @observable _presKeyEventsActive: boolean = false; + + @observable _selectedArray: ObservableMap = new ObservableMap<Doc, any>(); + // the selected item's index + @computed get itemIndex() { return NumCast(this.doc._itemIndex); } + // the item that's active + @computed get activeItem() { return this.childDocs ? Cast(this.childDocs[NumCast(this.doc._itemIndex)], Doc, null) : undefined; } + @computed get targetDoc() { return Cast(this.activeItem?.presentationTargetDoc, Doc, null); } + childDocList(field: string) { const layout = Cast(Doc.LayoutField(this.doc), Doc, null); return (this.props.dataDoc ? DocListCastOrNull(this.props.dataDoc[field]) : undefined) || // if there's a data doc for an expanded template, use it's data field @@ -169,7 +183,7 @@ export class TreeView extends React.Component<TreeViewProps> { this.treeViewOpen = !this.treeViewOpen; } else { // choose an appropriate alias or make one. --- choose the first alias that (1) user owns, (2) has no context field ... otherwise make a new alias - const bestAlias = docView.props.Document.author === Doc.CurrentUserEmail ? docView.props.Document : DocListCast(this.props.document.aliases).find(doc => !doc.context && doc.author === Doc.CurrentUserEmail); + const bestAlias = docView.props.Document.author === Doc.CurrentUserEmail && !Doc.IsPrototype(docView.props.Document) ? docView.props.Document : DocListCast(this.props.document.aliases).find(doc => !doc.context && doc.author === Doc.CurrentUserEmail); const nextBestAlias = DocListCast(this.props.document.aliases).find(doc => doc.author === Doc.CurrentUserEmail); this.props.addDocTab(bestAlias ?? nextBestAlias ?? Doc.MakeAlias(this.props.document), "lightbox"); } @@ -198,6 +212,16 @@ export class TreeView extends React.Component<TreeViewProps> { this._treeEle && this.props.unobserveHeight(this._treeEle); document.removeEventListener("pointermove", this.onDragMove, true); document.removeEventListener("pointermove", this.onDragUp, true); + // TODO: [AL] add these + this.props.hierarchyIndex !== undefined && this.props.RemFromMap?.(this.doc, this.props.hierarchyIndex); + } + + componentDidUpdate() { + this.props.hierarchyIndex !== undefined && this.props.AddToMap?.(this.doc, this.props.hierarchyIndex); + } + + componentDidMount() { + this.props.hierarchyIndex !== undefined && this.props.AddToMap?.(this.doc, this.props.hierarchyIndex); } onDragUp = (e: PointerEvent) => { @@ -272,7 +296,8 @@ export class TreeView extends React.Component<TreeViewProps> { @undoBatch treeDrop = (e: Event, de: DragManager.DropEvent) => { const pt = [de.x, de.y]; - const rect = this._header.current!.getBoundingClientRect(); + if (!this._header.current) return; + const rect = this._header.current.getBoundingClientRect(); const before = pt[1] < rect.top + rect.height / 2; const inside = this.props.treeView.fileSysMode && !this.doc.isFolder ? false : pt[0] > Math.min(rect.left + 75, rect.left + rect.width * .75) || (!before && this.treeViewOpen && this.childDocList.length); if (de.complete.linkDragData) { @@ -364,7 +389,12 @@ export class TreeView extends React.Component<TreeViewProps> { this.props.dropAction, this.props.addDocTab, this.titleStyleProvider, this.props.ScreenToLocalTransform, this.props.isContentActive, this.props.panelWidth, this.props.renderDepth, this.props.treeViewHideHeaderFields, [...this.props.renderedIds, doc[Id]], this.props.onCheckedClick, this.props.onChildClick, this.props.skipFields, false, this.props.whenChildContentsActiveChanged, - this.props.dontRegisterView, emptyFunction, emptyFunction, this.childContextMenuItems()); + this.props.dontRegisterView, emptyFunction, emptyFunction, this.childContextMenuItems(), + // TODO: [AL] Add these + this.props.AddToMap, + this.props.RemFromMap, + this.props.hierarchyIndex + ); } else { contentElement = <EditableView key="editableView" contents={contents !== undefined ? Field.toString(contents as Field) : "null"} @@ -441,7 +471,7 @@ export class TreeView extends React.Component<TreeViewProps> { const docs = expandKey === "aliases" ? this.childAliases : expandKey === "links" ? this.childLinks : expandKey === "annotations" ? this.childAnnos : this.childDocs; let downX = 0, downY = 0; return <> - {!docs?.length ? (null) : <div className={'treeView-sorting'} style={{ background: sortings[sorting]?.color }} > + {!docs?.length || this.props.AddToMap /* hack to identify pres box trees */ ? (null) : <div className={'treeView-sorting'} style={{ background: sortings[sorting]?.color }} > {sortings[sorting]?.label} </div>} <ul key={expandKey + "more"} title="click to change sort order" className={this.doc.treeViewHideTitle ? "no-indent" : ""} @@ -458,7 +488,11 @@ export class TreeView extends React.Component<TreeViewProps> { StrCast(this.doc.childDropAction, this.props.dropAction) as dropActionType, this.props.addDocTab, this.titleStyleProvider, this.props.ScreenToLocalTransform, this.props.isContentActive, this.props.panelWidth, this.props.renderDepth, this.props.treeViewHideHeaderFields, [...this.props.renderedIds, this.doc[Id]], this.props.onCheckedClick, this.props.onChildClick, this.props.skipFields, false, this.props.whenChildContentsActiveChanged, - this.props.dontRegisterView, emptyFunction, emptyFunction, this.childContextMenuItems())} + this.props.dontRegisterView, emptyFunction, emptyFunction, this.childContextMenuItems(), + // TODO: [AL] add these + this.props.AddToMap, + this.props.RemFromMap, + this.props.hierarchyIndex)} </ul > </>; } else if (this.treeViewExpandedView === "fields") { @@ -468,7 +502,7 @@ export class TreeView extends React.Component<TreeViewProps> { </div> </ul>; } - return <ul onPointerDown={e => { e.preventDefault(); e.stopPropagation(); }}>{this.renderEmbeddedDocument(false, returnFalse)}</ul>; // "layout" + return <ul onPointerDown={e => { e.preventDefault(); e.stopPropagation(); }}>{this.renderEmbeddedDocument(false, this.props.treeView.props.childDocumentsActive ?? returnFalse)}</ul>; // "layout" } get onCheckedClick() { return this.doc.type === DocumentType.COL ? undefined : this.props.onCheckedClick?.() ?? ScriptCast(this.doc.onCheckedClick); } @@ -574,7 +608,10 @@ export class TreeView extends React.Component<TreeViewProps> { const icons = StrListCast(this.doc.childContextMenuIcons); return StrListCast(this.doc.childContextMenuLabels).map((label, i) => ({ script: customScripts[i], filter: customFilters[i], icon: icons[i], label })); } - onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptCast(this.doc.treeChildClick)); + + onChildClick = () => { + return this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!); + } onChildDoubleClick = () => (!this.props.treeView.outlineMode && this._openScript?.()) || ScriptCast(this.doc.treeChildDoubleClick); @@ -762,6 +799,7 @@ export class TreeView extends React.Component<TreeViewProps> { fitContentsToDoc={returnTrue} hideDecorationTitle={this.props.treeView.outlineMode} hideResizeHandles={this.props.treeView.outlineMode} + onClick={this.onChildClick} focus={this.refocus} ContentScaling={returnOne} onKey={this.onKeyDown} @@ -828,7 +866,10 @@ export class TreeView extends React.Component<TreeViewProps> { return this.props.renderedIds.indexOf(this.doc[Id]) !== -1 ? "<" + this.doc.title + ">" : // just print the title of documents we've previously rendered in this hierarchical path to avoid cycles <div className={`treeView-container${this.props.isContentActive() ? "-active" : ""}`} ref={this.createTreeDropTarget} - onDrop={this.onTreeDrop}> + onDrop={this.onTreeDrop} + //onPointerDown={e => this.props.isContentActive(true) && SelectionManager.DeselectAll()} // bcz: this breaks entering a text filter in a filterBox since it deselects the filter's target document + // onKeyDown={this.onKeyDown} + > <li className="collection-child"> {hideTitle && this.doc.type !== DocumentType.RTF && !this.doc.treeViewRenderAsBulletHeader ? // should test for prop 'treeViewRenderDocWithBulletAsHeader" this.renderEmbeddedDocument(false, returnFalse) : @@ -893,7 +934,11 @@ export class TreeView extends React.Component<TreeViewProps> { dontRegisterView: boolean | undefined, observerHeight: (ref: any) => void, unobserveHeight: (ref: any) => void, - contextMenuItems: ({ script: ScriptField, filter: ScriptField, label: string, icon: string }[]) + contextMenuItems: ({ script: ScriptField, filter: ScriptField, label: string, icon: string }[]), + // TODO: [AL] add these + AddToMap?: (treeViewDoc: Doc, index: number[]) => Doc[], + RemFromMap?: (treeViewDoc: Doc, index: number[]) => Doc[], + hierarchyIndex?: number[], ) { const viewSpecScript = Cast(containerCollection.viewSpecScript, ScriptField); if (viewSpecScript) { @@ -934,6 +979,10 @@ export class TreeView extends React.Component<TreeViewProps> { dataDoc={pair.data} containerCollection={containerCollection} prevSibling={docs[i]} + // TODO: [AL] add these + hierarchyIndex={hierarchyIndex ? [...hierarchyIndex, i + 1] : undefined} + AddToMap={AddToMap} + RemFromMap={RemFromMap} treeView={treeView} indentDocument={indent} outdentDocument={outdent} |