diff options
Diffstat (limited to 'src/client/views/collections/TreeView.tsx')
-rw-r--r-- | src/client/views/collections/TreeView.tsx | 382 |
1 files changed, 199 insertions, 183 deletions
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 4fd49f8fe..6ea6bbfbd 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -1,44 +1,51 @@ +/* eslint-disable jsx-a11y/no-static-element-interactions */ +/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */ +/* eslint-disable jsx-a11y/click-events-have-key-events */ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { IconButton, Size } from 'browndash-components'; import { IReactionDisposer, action, computed, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { Utils, emptyFunction, lightOrDark, return18, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, returnZero, setupMoveUpEvents, simulateMouseClick } from '../../../Utils'; -import { Doc, DocListCast, Field, FieldResult, Opt, StrListCast } from '../../../fields/Doc'; +import { ClientUtils, lightOrDark, return18, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, returnZero, setupMoveUpEvents, simulateMouseClick } from '../../../ClientUtils'; +import { emptyFunction } from '../../../Utils'; +import { Doc, DocListCast, Field, FieldResult, FieldType, Opt, StrListCast } from '../../../fields/Doc'; import { DocData } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; import { RichTextField } from '../../../fields/RichTextField'; import { listSpec } from '../../../fields/Schema'; import { ComputedField, ScriptField } from '../../../fields/ScriptField'; -import { BoolCast, Cast, DocCast, FieldValue, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; +import { BoolCast, Cast, DocCast, FieldValue, NumCast, ScriptCast, StrCast, toList } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; +import { DocUtils } from '../../documents/DocUtils'; import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; -import { DocUtils, Docs } from '../../documents/Documents'; -import { DocumentManager } from '../../util/DocumentManager'; -import { DragManager, dropActionType } from '../../util/DragManager'; -import { LinkManager } from '../../util/LinkManager'; +import { Docs } from '../../documents/Documents'; +import { DragManager } from '../../util/DragManager'; +import { dropActionType } from '../../util/DropActionTypes'; import { SettingsManager } from '../../util/SettingsManager'; import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from '../../util/Transform'; import { UndoManager, undoBatch, undoable } from '../../util/UndoManager'; import { EditableView } from '../EditableView'; import { ObservableReactComponent } from '../ObservableReactComponent'; -import { StyleProp } from '../StyleProvider'; -import { DocumentView, DocumentViewInternal, OpenWhere } from '../nodes/DocumentView'; +import { StyleProp } from '../StyleProp'; +import { DocumentView, DocumentViewInternal } from '../nodes/DocumentView'; import { FieldViewProps, StyleProviderFuncType } from '../nodes/FieldView'; -import { KeyValueBox } from '../nodes/KeyValueBox'; +import { OpenWhere } from '../nodes/OpenWhere'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; import { RichTextMenu } from '../nodes/formattedText/RichTextMenu'; -import { CollectionTreeView, TreeViewType } from './CollectionTreeView'; +import { CollectionTreeView } from './CollectionTreeView'; +import { TreeViewType } from './CollectionTreeViewType'; import { CollectionView } from './CollectionView'; import { TreeSort } from './TreeSort'; import './TreeView.scss'; + const { TREE_BULLET_WIDTH } = require('../global/globalCssVariables.module.scss'); // prettier-ignore export interface TreeViewProps { treeView: CollectionTreeView; + // eslint-disable-next-line no-use-before-define parentTreeView: TreeView | CollectionTreeView | undefined; observeHeight: (ref: any) => void; unobserveHeight: (ref: any) => void; @@ -48,7 +55,7 @@ export interface TreeViewProps { treeViewParent: Doc; renderDepth: number; dragAction: dropActionType; - addDocTab: (doc: Doc, where: OpenWhere) => boolean; + addDocTab: (doc: Doc | Doc[], where: OpenWhere) => boolean; panelWidth: () => number; panelHeight: () => number; addDocument: (doc: Doc | Doc[], annotationKey?: string, relativeTo?: Doc, before?: boolean) => boolean; @@ -87,6 +94,7 @@ const treeBulletWidth = function () { */ @observer export class TreeView extends ObservableReactComponent<TreeViewProps> { + // eslint-disable-next-line no-use-before-define static _editTitleOnLoad: Opt<{ id: string; parent: TreeView | CollectionTreeView | undefined }>; static _openTitleScript: Opt<ScriptField | undefined>; static _openLevelScript: Opt<ScriptField | undefined>; @@ -101,6 +109,9 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { get treeViewOpenIsTransient() { return this.treeView.Document.treeView_OpenIsTransient || Doc.IsDataProto(this.Document); } + @computed get treeViewOpen() { + return (!this.treeViewOpenIsTransient && Doc.GetT(this.Document, 'treeView_Open', 'boolean', true)) || this._transientOpenState; + } set treeViewOpen(c: boolean) { if (this.treeViewOpenIsTransient) this._transientOpenState = c; else { @@ -137,9 +148,6 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { @computed get Document() { return this._props.Document; } - @computed get treeViewOpen() { - return (!this.treeViewOpenIsTransient && Doc.GetT(this.Document, 'treeView_Open', 'boolean', true)) || this._transientOpenState; - } @computed get treeViewExpandedView() { return this.validExpandViewTypes.includes(StrCast(this.Document.treeView_ExpandedView)) ? StrCast(this.Document.treeView_ExpandedView) : this.defaultExpandedView; } @@ -192,12 +200,13 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { } return false; }; - @undoBatch remove = (doc: Doc | Doc[], key: string) => { + @undoBatch remove = (docIn: Doc | Doc[], key: string) => { + const docs = toList(docIn); this.treeView._props.select(false); - const ind = DocListCast(this.dataDoc[key]).indexOf(doc instanceof Doc ? doc : doc.lastElement()); + const ind = DocListCast(this.dataDoc[key]).indexOf(docs.lastElement()); - const res = (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && Doc.RemoveDocFromList(this.dataDoc, key, doc), true); - res && ind > 0 && DocumentManager.Instance.getDocumentView(DocListCast(this.dataDoc[key])[ind - 1], this.treeView.DocumentView?.())?.select(false); + const res = docs.reduce((flg, doc) => flg && Doc.RemoveDocFromList(this.dataDoc, key, doc), true); + res && ind > 0 && DocumentView.getDocumentView(DocListCast(this.dataDoc[key])[ind - 1], this.treeView.DocumentView?.())?.select(false); return res; }; @@ -221,7 +230,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { this.treeViewOpen = !this.treeViewOpen; } else { // choose an appropriate embedding or make one. --- choose the first embedding that (1) user owns, (2) has no context field ... otherwise make a new embedding - const bestEmbedding = docView.Document.author === Doc.CurrentUserEmail && !Doc.IsDataProto(docView.Document) ? docView.Document : Doc.BestEmbedding(docView.Document); + const bestEmbedding = docView.Document.author === ClientUtils.CurrentUserEmail() && !Doc.IsDataProto(docView.Document) ? docView.Document : Doc.BestEmbedding(docView.Document); this._props.addDocTab(bestEmbedding, OpenWhere.lightbox); } }; @@ -230,7 +239,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { recurToggle = (childList: Doc[]) => { if (childList.length > 0) { childList.forEach(child => { - child.runProcess = !!!child.runProcess; + child.runProcess = !child.runProcess; TreeView.ToggleChildrenRun.get(child)?.(); }); } @@ -273,9 +282,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { this.recurToggle(this.childDocs); }); - TreeView.GetRunningChildren.set(this.Document, () => { - return this.getRunningChildren(this.childDocs); - }); + TreeView.GetRunningChildren.set(this.Document, () => this.getRunningChildren(this.childDocs)); } _treeEle: any; @@ -301,7 +308,9 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { super.componentDidUpdate(prevProps); this._disposers.opening = reaction( () => this.treeViewOpen, - open => !open && (this._renderCount = 20) + open => { + !open && (this._renderCount = 20); + } ); this._props.hierarchyIndex !== undefined && this._props.AddToMap?.(this.Document, this._props.hierarchyIndex); } @@ -310,7 +319,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { this._props.hierarchyIndex !== undefined && this._props.AddToMap?.(this.Document, this._props.hierarchyIndex); } - onDragUp = (e: PointerEvent) => { + onDragUp = () => { document.removeEventListener('pointerup', this.onDragUp, true); document.removeEventListener('pointermove', this.onDragMove, true); }; @@ -324,7 +333,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { document.addEventListener('pointerup', this.onDragUp, true); } }; - onPointerLeave = (e: React.PointerEvent): void => { + onPointerLeave = (): void => { Doc.UnBrushDoc(this.dataDoc); if (this._header.current?.className !== 'treeView-header-editing') { this._header.current!.className = 'treeView-header'; @@ -368,7 +377,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { const bulletData = bullet[DocData]; bulletData.title = ComputedField.MakeFunction('this.text?.Text'); bulletData.data = new List<Doc>([]); - DocumentManager.Instance.AddViewRenderedCb(bullet, dv => dv.ComponentView?.setFocus?.()); + DocumentView.addViewRenderedCb(bullet, dv => dv.ComponentView?.setFocus?.()); return bullet; } @@ -385,7 +394,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { return this.localAdd(folder); }; - preTreeDrop = (e: Event, de: DragManager.DropEvent, docDropAction: dropActionType) => { + preTreeDrop = () => { // fall through and let the CollectionTreeView handle this since treeView items have no special properties of their own }; @@ -395,7 +404,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { if (!this._header.current) return false; const rect = this._header.current.getBoundingClientRect(); const before = pt[1] < rect.top + rect.height / 2; - const inside = this.treeView.fileSysMode && !this.Document.isFolder ? false : pt[0] > rect.left + rect.width * 0.33 || (!before && this.treeViewOpen && this.childDocs?.length ? true : false); + const inside = this.treeView.fileSysMode && !this.Document.isFolder ? false : pt[0] > rect.left + rect.width * 0.33 || !!(!before && this.treeViewOpen && this.childDocs?.length); if (de.complete.linkDragData) { const sourceDoc = de.complete.linkDragData.linkSourceGetAnchor(); const destDoc = this.Document; @@ -403,7 +412,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { e.stopPropagation(); return true; } - const docDragData = de.complete.docDragData; + const { docDragData } = de.complete; if (docDragData && pt[0] < rect.left + rect.width) { if (docDragData.draggedDocuments[0] === this.Document) return true; const added = this.dropDocuments( @@ -423,14 +432,14 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { return false; }; - localAdd = (doc: Doc | Doc[]) => { - const innerAdd = (doc: Doc) => { + localAdd = (docs: Doc | Doc[]): boolean => { + const innerAdd = (doc: Doc): boolean => { const dataIsComputed = ComputedField.WithoutComputed(() => FieldValue(this.dataDoc[this.fieldKey])) instanceof ComputedField; const added = (!dataIsComputed || (this.dropping && this.moving)) && Doc.AddDocToList(this.dataDoc, this.fieldKey, doc); dataIsComputed && Doc.SetContainer(doc, DocCast(this.Document.embedContainer)); return added; }; - return (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && innerAdd(doc), true as boolean); + return toList(docs).reduce((flg, doc) => flg && innerAdd(doc), true as boolean); }; dropping: boolean = false; @@ -462,8 +471,8 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { refTransform = (ref: HTMLDivElement | undefined | null) => { if (!ref) return this.ScreenToLocalTransform(); - const { scale, translateX, translateY } = Utils.GetScreenTransform(ref); - const outerXf = Utils.GetScreenTransform(this.treeView.MainEle()); + const { translateX, translateY } = ClientUtils.GetScreenTransform(ref); + const outerXf = ClientUtils.GetScreenTransform(this.treeView.MainEle()); const offset = this.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY); return this.ScreenToLocalTransform().translate(offset[0], offset[1]); }; @@ -490,29 +499,34 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { const ids: { [key: string]: string } = {}; const rows: JSX.Element[] = []; const doc = this.Document; - doc && Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key)); + doc && + Object.keys(doc).forEach(key => { + !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key); + }); + // eslint-disable-next-line no-restricted-syntax for (const key of Object.keys(ids).slice().sort()) { + // eslint-disable-next-line no-continue if (this._props.skipFields?.includes(key) || key === 'title' || key === 'treeView_Open') continue; const contents = doc[key]; let contentElement: (JSX.Element | null)[] | JSX.Element = []; - let leftOffset = observable({ width: 0 }); + const leftOffset = observable({ width: 0 }); const expandedWidth = () => this._props.panelWidth() - leftOffset.width; if (contents instanceof Doc || (Cast(contents, listSpec(Doc)) && Cast(contents, listSpec(Doc))!.length && Cast(contents, listSpec(Doc))![0] instanceof Doc)) { - const remDoc = (doc: Doc | Doc[]) => this.remove(doc, key); - const moveDoc = (doc: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => this.move(doc, target, addDoc); - const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) => { - const innerAdd = (doc: Doc) => { + const remDoc = (docs: Doc | Doc[]) => this.remove(docs, key); + const moveDoc = (docs: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => this.move(docs, target, addDoc); + const addDoc = (docs: Doc | Doc[], addBefore?: Doc, before?: boolean) => { + const innerAdd = (iDoc: Doc) => { const dataIsComputed = ComputedField.WithoutComputed(() => FieldValue(this.dataDoc[key])) instanceof ComputedField; - const added = (!dataIsComputed || (this.dropping && this.moving)) && Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false, true); - dataIsComputed && Doc.SetContainer(doc, DocCast(this.Document.embedContainer)); + const added = (!dataIsComputed || (this.dropping && this.moving)) && Doc.AddDocToList(this.dataDoc, key, iDoc, addBefore, before, false, true); + dataIsComputed && Doc.SetContainer(iDoc, DocCast(this.Document.embedContainer)); return added; }; - return (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && innerAdd(doc), true as boolean); + return toList(docs).reduce((flg, iDoc) => flg && innerAdd(iDoc), true as boolean); }; contentElement = TreeView.GetChildElements( - contents instanceof Doc ? [contents] : DocListCast(contents), + toList(contents as any), this.treeView, this, doc, @@ -549,11 +563,11 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { contentElement = ( <EditableView key="editableView" - contents={contents !== undefined ? Field.toString(contents as Field) : 'null'} + contents={contents !== undefined ? Field.toString(contents as FieldType) : 'null'} height={13} fontSize={12} GetValue={() => Field.toKeyValueString(doc, key)} - SetValue={(value: string) => KeyValueBox.SetField(doc, key, value, true)} + SetValue={(value: string) => Doc.SetField(doc, key, value, true)} /> ); } @@ -572,20 +586,20 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { ); } rows.push( - <div style={{ display: 'flex', overflow: 'auto' }} key={'newKeyValue'}> + <div style={{ display: 'flex', overflow: 'auto' }} key="newKeyValue"> <EditableView key="editableView" - contents={'+key=value'} + contents="+key=value" height={13} fontSize={12} GetValue={returnEmptyString} SetValue={input => { - const match = input.match(/([a-zA-Z0-9_-]+)(=|=:=)([a-zA-Z,_@\?\+\-\*\/\ 0-9\(\)]+)/); + const match = input.match(/([a-zA-Z0-9_-]+)(=|=:=)([a-zA-Z,_@?+\-*/ 0-9()]+)/); if (match) { const key = match[1]; const assign = match[2]; const val = match[3]; - KeyValueBox.SetField(doc, key, assign + val, false); + Doc.SetField(doc, key, assign + val, false); return true; } return false; @@ -620,7 +634,9 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { const docs = TreeView.sortDocs(this.childDocs || ([] as Doc[]), ordering); doc.zIndex = addBefore ? NumCast(addBefore.zIndex) + (before ? -0.5 : 0.5) : 1000; docs.push(doc); - docs.sort((a, b) => (NumCast(a.zIndex) > NumCast(b.zIndex) ? 1 : -1)).forEach((d, i) => (d.zIndex = i)); + docs.sort((a, b) => (NumCast(a.zIndex) > NumCast(b.zIndex) ? 1 : -1)).forEach((d, i) => { + d.zIndex = i; + }); } const dataIsComputed = ComputedField.WithoutComputed(() => FieldValue(this.dataDoc[key])) instanceof ComputedField; const added = (!dataIsComputed || (this.dropping && this.moving)) && Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false); @@ -628,10 +644,10 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { return added; }; - const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && localAdd(doc, addBefore, before), true); + const addDoc = (docs: Doc | Doc[], addBefore?: Doc, before?: boolean) => toList(docs).reduce((flg, doc) => flg && localAdd(doc, addBefore, before), true); const docs = expandKey === 'embeddings' ? this.childEmbeddings : expandKey === 'links' ? this.childLinks : expandKey === 'annotations' ? this.childAnnos : this.childDocs; - let downX = 0, - downY = 0; + let downX = 0; + let downY = 0; if (docs?.length && this._renderCount < docs?.length) { this._renderTimer && clearTimeout(this._renderTimer); this._renderTimer = setTimeout( @@ -667,7 +683,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { style={{ cursor: 'inherit' }} key={expandKey + 'more'} title={`Sorted by : ${this.Document.treeView_SortCriterion}. click to cycle`} - className="" //this.doc.treeView_HideTitle ? 'no-indent' : ''} + className="" // this.doc.treeView_HideTitle ? 'no-indent' : ''} onPointerDown={e => { downX = e.clientX; downY = e.clientY; @@ -719,7 +735,8 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { </ul> </div> ); - } else if (this.treeViewExpandedView === 'fields') { + } + if (this.treeViewExpandedView === 'fields') { return ( <ul key={this.Document[Id] + this.Document.title} style={{ cursor: 'inherit' }}> <div>{this.expandedField}</div> @@ -804,7 +821,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { @computed get validExpandViewTypes() { const annos = () => (DocListCast(this.Document[this.fieldKey + '_annotations']).length && !this.treeView.dashboardMode ? 'annotations' : ''); - const links = () => (LinkManager.Links(this.Document).length && !this.treeView.dashboardMode ? 'links' : ''); + const links = () => (Doc.Links(this.Document).length && !this.treeView.dashboardMode ? 'links' : ''); const data = () => (this.childDocs || this.treeView.dashboardMode ? this.fieldKey : ''); const embeddings = () => (this.treeView.dashboardMode ? '' : 'embeddings'); const fields = () => (Doc.noviceMode ? '' : 'fields'); @@ -891,14 +908,15 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { titleStyleProvider = (doc: Doc | undefined, props: Opt<FieldViewProps>, property: string): any => { if (!doc || doc !== this.Document) return this._props?.treeView?._props.styleProvider?.(doc, props, property); // properties are inherited from the CollectionTreeView, not the hierarchical parent in the treeView - const treeView = this.treeView; + const { treeView } = this; // prettier-ignore switch (property.split(':')[0]) { case StyleProp.Opacity: return this.treeView.outlineMode ? undefined : 1; - case StyleProp.BackgroundColor: return this.selected ? '#7089bb' : undefined;//StrCast(doc._backgroundColor, StrCast(doc.backgroundColor)); + case StyleProp.BackgroundColor: return this.selected ? '#7089bb' : undefined; // StrCast(doc._backgroundColor, StrCast(doc.backgroundColor)); case StyleProp.Highlighting: if (this.treeView.outlineMode) return undefined; + break; case StyleProp.BoxShadow: return undefined; - case StyleProp.DocContents: + case StyleProp.DocContents: { const highlightIndex = this.treeView.outlineMode ? Doc.DocBrushStatus.unbrushed : Doc.GetBrushHighlightStatus(doc); const highlightColor = ['transparent', 'rgb(68, 118, 247)', 'rgb(68, 118, 247)', 'orange', 'lightBlue'][highlightIndex]; return treeView.outlineMode ? null : ( @@ -917,6 +935,8 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { {StrCast(doc?.title)} </div> ); + } + default: } return treeView._props.styleProvider?.(doc, props, property); }; @@ -924,7 +944,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { if (property.startsWith(StyleProp.Decorations)) return null; return this._props?.treeView?._props.styleProvider?.(doc, props, property); // properties are inherited from the CollectionTreeView, not the hierarchical parent in the treeView }; - onKeyDown = (e: React.KeyboardEvent, fieldProps: FieldViewProps) => { + onKeyDown = (e: React.KeyboardEvent) => { if (this.Document.treeView_HideHeader || (this.Document.treeView_HideHeaderIfTemplate && this.treeView._props.childLayoutTemplate?.()) || this.treeView.outlineMode) { switch (e.key) { case 'Tab': @@ -944,6 +964,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { e.stopPropagation?.(); e.preventDefault?.(); return UndoManager.RunInBatch(this.makeTextCollection, 'bullet'); + default: } } return false; @@ -959,22 +980,24 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { const view = this._editTitle ? ( <EditableView key="_editTitle" - oneLine={true} - display={'inline-block'} + oneLine + display="inline-block" editing={this._editTitle} - background={'#7089bb'} + background="#7089bb" contents={StrCast(this.Document.title)} height={12} - sizeToContent={true} + sizeToContent fontSize={12} - isEditingCallback={action(e => (this._editTitle = e))} + isEditingCallback={action(e => { + this._editTitle = e; + })} GetValue={() => StrCast(this.Document.title)} OnTab={undoBatch((shift?: boolean) => { if (!shift) this._props.indentDocument?.(true); else this._props.outdentDocument?.(true); })} OnEmpty={undoBatch(() => this.treeView.outlineMode && this._props.removeDoc?.(this.Document))} - OnFillDown={val => this.treeView.fileSysMode && this.makeFolder()} + OnFillDown={() => this.treeView.fileSysMode && this.makeFolder()} SetValue={undoBatch((value: string, shiftKey: boolean, enterKey: boolean) => { Doc.SetInPlace(this.Document, 'title', value, false); this.treeView.outlineMode && enterKey && this.makeTextCollection(); @@ -984,7 +1007,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { <DocumentView key="title" ref={action((r: any) => { - this._docRef = r ? r : undefined; + this._docRef = r || undefined; if (this._docRef && TreeView._editTitleOnLoad?.id === this.Document[Id] && TreeView._editTitleOnLoad.parent === this._props.parentTreeView) { this._docRef.select(false); this.setEditTitle(this._docRef); @@ -994,8 +1017,8 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { Document={this.Document} layout_fitWidth={returnTrue} scriptContext={this} - hideDecorations={true} - hideClickBehaviors={true} + hideDecorations + hideClickBehaviors styleProvider={this.titleStyleProvider} onClickScriptDisable="never" // tree docViews have a script to show fields, etc. containerViewPath={this.treeView.childContainerViewPath} @@ -1015,7 +1038,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { PanelHeight={return18} contextMenuItems={this.contextMenuItems} renderDepth={1} - isContentActive={emptyFunction} //this._props.isContentActive} + isContentActive={emptyFunction} // this._props.isContentActive} isDocumentActive={this._props.isContentActive} focus={this.refocus} whenChildContentsActiveChanged={this._props.whenChildContentsActiveChanged} @@ -1045,99 +1068,101 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { }}> {view} </div> - <div className="treeView-rightButtons" ref={action((r: any) => r && (this.headerEleWidth = r.getBoundingClientRect().width))}> + <div + className="treeView-rightButtons" + ref={action((r: any) => { + r && (this.headerEleWidth = r.getBoundingClientRect().width); + })}> {this.titleButtons} </div> </> ); } - renderBulletHeader = (contents: JSX.Element, editing: boolean) => { - return ( - <> + renderBulletHeader = (contents: JSX.Element, editing: boolean) => ( + <> + <div + className={`treeView-header` + (editing ? '-editing' : '')} + key="titleheader" + ref={this._header} + onClick={this.ignoreEvent} + onPointerDown={e => { + this.treeView.isContentActive() && + setupMoveUpEvents( + this, + e, + () => { + (this._dref ?? this._docRef)?.startDragging(e.clientX, e.clientY, '' as any); + return true; + }, + returnFalse, + emptyFunction + ); + }} + onPointerEnter={this.onPointerEnter} + onPointerLeave={this.onPointerLeave}> <div - className={`treeView-header` + (editing ? '-editing' : '')} - key="titleheader" - ref={this._header} - onClick={this.ignoreEvent} - onPointerDown={e => { - this.treeView.isContentActive() && - setupMoveUpEvents( - this, - e, - () => { - (this._dref ?? this._docRef)?.startDragging(e.clientX, e.clientY, '' as any); - return true; - }, - returnFalse, - emptyFunction - ); + className="treeView-background" + style={{ + background: SettingsManager.userColor, }} - onPointerEnter={this.onPointerEnter} - onPointerLeave={this.onPointerLeave}> - <div - className="treeView-background" - style={{ - background: SettingsManager.userColor, - }} - /> - {contents} - </div> - {this.renderBorder} - </> - ); - }; - - fitWidthFilter = (doc: Doc) => (doc.type === DocumentType.IMG ? false : undefined); - renderEmbeddedDocument = (asText: boolean, isActive: () => boolean | undefined) => { - return ( - <div style={{ height: this.embeddedPanelHeight(), width: this.embeddedPanelWidth() }}> - <DocumentView - key={this.Document[Id]} - ref={action((r: DocumentView | null) => (this._dref = r))} - Document={this.Document} - layout_fitWidth={this.fitWidthFilter} - PanelWidth={this.embeddedPanelWidth} - PanelHeight={this.embeddedPanelHeight} - LayoutTemplateString={asText ? FormattedTextBox.LayoutString('text') : undefined} - LayoutTemplate={this.treeView._props.childLayoutTemplate} - isContentActive={isActive} - isDocumentActive={isActive} - styleProvider={asText ? this.titleStyleProvider : this.embeddedStyleProvider} - fitContentsToBox={returnTrue} - hideTitle={asText} - hideDecorations={true} - hideClickBehaviors={true} - hideLinkButton={BoolCast(this.treeView.Document.childHideLinkButton)} - dontRegisterView={BoolCast(this.treeView.Document.childDontRegisterViews, this._props.dontRegisterView)} - ScreenToLocalTransform={this.docTransform} - renderDepth={this._props.renderDepth + 1} - onClickScript={this.onChildClick} - onKey={this.onKeyDown} - containerViewPath={this.treeView.childContainerViewPath} - childFilters={returnEmptyFilter} - childFiltersByRanges={returnEmptyFilter} - searchFilterDocs={returnEmptyDoclist} - focus={this.refocus} - addDocument={this._props.addDocument} - moveDocument={this.move} - removeDocument={this._props.removeDoc} - whenChildContentsActiveChanged={this._props.whenChildContentsActiveChanged} - xPadding={NumCast(this.treeView.Document.childXPadding, this.treeView._props.childXPadding)} - yPadding={NumCast(this.treeView.Document.childYPadding, this.treeView._props.childYPadding)} - addDocTab={this._props.addDocTab} - pinToPres={this.treeView._props.pinToPres} - disableBrushing={this.treeView._props.disableBrushing} - scriptContext={this} /> + {contents} </div> - ); - }; + {this.renderBorder} + </> + ); + + fitWidthFilter = (doc: Doc) => (doc.type === DocumentType.IMG ? false : undefined); + renderEmbeddedDocument = (asText: boolean, isActive: () => boolean | undefined) => ( + <div style={{ height: this.embeddedPanelHeight(), width: this.embeddedPanelWidth() }}> + <DocumentView + key={this.Document[Id]} + ref={action((r: DocumentView | null) => { + this._dref = r; + })} + Document={this.Document} + layout_fitWidth={this.fitWidthFilter} + PanelWidth={this.embeddedPanelWidth} + PanelHeight={this.embeddedPanelHeight} + LayoutTemplateString={asText ? FormattedTextBox.LayoutString('text') : undefined} + LayoutTemplate={this.treeView._props.childLayoutTemplate} + isContentActive={isActive} + isDocumentActive={isActive} + styleProvider={asText ? this.titleStyleProvider : this.embeddedStyleProvider} + fitContentsToBox={returnTrue} + hideTitle={asText} + hideDecorations + hideClickBehaviors + hideLinkButton={BoolCast(this.treeView.Document.childHideLinkButton)} + dontRegisterView={BoolCast(this.treeView.Document.childDontRegisterViews, this._props.dontRegisterView)} + ScreenToLocalTransform={this.docTransform} + renderDepth={this._props.renderDepth + 1} + onClickScript={this.onChildClick} + onKey={this.onKeyDown} + containerViewPath={this.treeView.childContainerViewPath} + childFilters={returnEmptyFilter} + childFiltersByRanges={returnEmptyFilter} + searchFilterDocs={returnEmptyDoclist} + focus={this.refocus} + addDocument={this._props.addDocument} + moveDocument={this.move} + removeDocument={this._props.removeDoc} + whenChildContentsActiveChanged={this._props.whenChildContentsActiveChanged} + xPadding={NumCast(this.treeView.Document.childXPadding, this.treeView._props.childXPadding)} + yPadding={NumCast(this.treeView.Document.childYPadding, this.treeView._props.childYPadding)} + addDocTab={this._props.addDocTab} + pinToPres={this.treeView._props.pinToPres} + disableBrushing={this.treeView._props.disableBrushing} + scriptContext={this} + /> + </div> + ); // renders the text version of a document as the header. This is used in the file system mode and in other vanilla tree views. @computed get renderTitleAsHeader() { return this.treeView.Document.treeView_HideUnrendered && this.Document.layout_unrendered && !this.Document.treeView_FieldKey ? ( - <div></div> + <div /> ) : ( <> {this.renderBullet} @@ -1147,14 +1172,12 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { } // renders the document in the header field instead of a text proxy. - renderDocumentAsHeader = (asText: boolean) => { - return ( - <> - {this.renderBullet} - {this.renderEmbeddedDocument(asText, this._props.isContentActive)} - </> - ); - }; + renderDocumentAsHeader = (asText: boolean) => ( + <> + {this.renderBullet} + {this.renderEmbeddedDocument(asText, this._props.isContentActive)} + </> + ); @computed get renderBorder() { const sorting = StrCast(this.Document.treeView_SortCriterion, TreeSort.WhenAdded); @@ -1170,7 +1193,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { const pt = [de.clientX, de.clientY]; const rect = this._header.current!.getBoundingClientRect(); const before = pt[1] < rect.top + rect.height / 2; - const inside = this.treeView.fileSysMode && !this.Document.isFolder ? false : pt[0] > rect.left + rect.width * 0.33 || (!before && this.treeViewOpen && this.childDocs?.length ? true : false); + const inside = this.treeView.fileSysMode && !this.Document.isFolder ? false : pt[0] > rect.left + rect.width * 0.33 || !!(!before && this.treeViewOpen && this.childDocs?.length); this.treeView.onTreeDrop(de, (docs: Doc[]) => this.dropDocuments(docs, before, inside, dropActionType.copy, undefined, undefined, false, false)); }; @@ -1185,7 +1208,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { className={`treeView-container${this._props.isContentActive() ? '-active' : ''}`} ref={this.createTreeDropTarget} 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 + // onPointerDown={e => this._props.isContentActive(true) && DocumentView.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"> @@ -1209,11 +1232,10 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { const aN = parseInt(a.match(reN)![0], 10); const bN = parseInt(b.match(reN)![0], 10); return aN === bN ? 0 : aN > bN ? 1 : -1; - } else { - return aA > bA ? 1 : -1; } + return aA > bA ? 1 : -1; }; - docs.sort(function (d1, d2): 0 | 1 | -1 { + docs.sort((d1, d2): 0 | 1 | -1 => { const a = criterion === TreeSort.AlphaUp ? d2 : d1; const b = criterion === TreeSort.AlphaUp ? d1 : d2; const first = a[criterion === TreeSort.Zindex ? 'zIndex' : 'title']; @@ -1230,7 +1252,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { childDocs: Doc[], treeView: CollectionTreeView, parentTreeView: CollectionTreeView | TreeView | undefined, - treeView_Parent: Doc, + treeViewParent: Doc, dataDoc: Doc | undefined, parentCollectionDoc: Doc | undefined, containerPrevSibling: Doc | undefined, @@ -1238,13 +1260,13 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { remove: undefined | ((doc: Doc | Doc[]) => boolean), move: DragManager.MoveFunction, dragAction: dropActionType, - addDocTab: (doc: Doc, where: OpenWhere) => boolean, + addDocTab: (doc: Doc | Doc[], where: OpenWhere) => boolean, styleProvider: undefined | StyleProviderFuncType, screenToLocalXf: () => Transform, isContentActive: (outsideReaction?: boolean) => boolean, panelWidth: () => number, renderDepth: number, - treeView_HideHeaderFields: () => boolean, + treeViewHideHeaderFields: () => boolean, renderedIds: string[], onCheckedClick: undefined | (() => ScriptField), onChildClick: undefined | (() => ScriptField), @@ -1261,19 +1283,14 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { hierarchyIndex?: number[], renderCount?: number ) { - const viewSpecScript = Cast(treeView_Parent.viewSpecScript, ScriptField); - if (viewSpecScript) { - childDocs = childDocs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result); - } - - const docs = TreeView.sortDocs(childDocs, StrCast(treeView_Parent.treeView_SortCriterion, TreeSort.WhenAdded)); + const docs = TreeView.sortDocs(childDocs, StrCast(treeViewParent.treeView_SortCriterion, TreeSort.WhenAdded)); const rowWidth = () => panelWidth() - treeBulletWidth() * (treeView._props.NativeDimScaling?.() || 1); - const treeView_Refs = new Map<Doc, TreeView | undefined>(); + const treeViewRefs = new Map<Doc, TreeView | undefined>(); return docs .filter(child => child instanceof Doc) .map((child, i) => { if (renderCount && i > renderCount) return null; - const pair = Doc.GetLayoutDataDocPair(treeView_Parent, dataDoc, child); + const pair = Doc.GetLayoutDataDocPair(treeViewParent, dataDoc, child); if (!pair.layout || pair.data instanceof Promise) { return null; } @@ -1283,14 +1300,14 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { const fieldKey = Doc.LayoutFieldKey(newParent); if (remove && fieldKey && Cast(newParent[fieldKey], listSpec(Doc)) !== undefined) { remove(child); - FormattedTextBox.SetSelectOnLoad(child); + Doc.SetSelectOnLoad(child); TreeView._editTitleOnLoad = editTitle ? { id: child[Id], parent } : undefined; Doc.AddDocToList(newParent, fieldKey, child, addAfter, false); newParent.treeView_Open = true; Doc.SetContainer(child, treeView.Document); } }; - const indent = i === 0 ? undefined : (editTitle: boolean) => dentDoc(editTitle, docs[i - 1], undefined, treeView_Refs.get(docs[i - 1])); + const indent = i === 0 ? undefined : (editTitle: boolean) => dentDoc(editTitle, docs[i - 1], undefined, treeViewRefs.get(docs[i - 1])); const outdent = !parentCollectionDoc ? undefined : (editTitle: boolean) => dentDoc(editTitle, parentCollectionDoc, containerPrevSibling, parentTreeView instanceof TreeView ? parentTreeView._props.parentTreeView : undefined); const addDocument = (doc: Doc | Doc[], annotationKey?: string, relativeTo?: Doc, before?: boolean) => add(doc, relativeTo ?? docs[i], before !== undefined ? before : false); const childLayout = Doc.Layout(pair.layout); @@ -1301,12 +1318,11 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { return ( <TreeView key={child[Id]} - ref={r => treeView_Refs.set(child, r ? r : undefined)} + ref={r => treeViewRefs.set(child, r || undefined)} Document={pair.layout} dataDoc={pair.data} - treeViewParent={treeView_Parent} + treeViewParent={treeViewParent} prevSibling={docs[i]} - // TODO: [AL] add these hierarchyIndex={hierarchyIndex ? [...hierarchyIndex, i + 1] : undefined} AddToMap={AddToMap} RemFromMap={RemFromMap} @@ -1316,7 +1332,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { onCheckedClick={onCheckedClick} onChildClick={onChildClick} renderDepth={renderDepth} - removeDoc={StrCast(treeView_Parent.treeView_FreezeChildren).includes('remove') ? undefined : remove} + removeDoc={StrCast(treeViewParent.treeView_FreezeChildren).includes('remove') ? undefined : remove} addDocument={addDocument} styleProvider={styleProvider} panelWidth={rowWidth} @@ -1327,7 +1343,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> { addDocTab={addDocTab} ScreenToLocalTransform={screenToLocalXf} isContentActive={isContentActive} - treeViewHideHeaderFields={treeView_HideHeaderFields} + treeViewHideHeaderFields={treeViewHideHeaderFields} renderedIds={renderedIds} skipFields={skipFields} firstLevel={firstLevel} |