aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/CollectionTreeView.tsx
diff options
context:
space:
mode:
authorusodhi <61431818+usodhi@users.noreply.github.com>2021-04-04 13:38:55 -0400
committerusodhi <61431818+usodhi@users.noreply.github.com>2021-04-04 13:38:55 -0400
commit15c1c952c50bb2de972c614e46c5f33c2b2952cc (patch)
treee8d7330336b80939e82749290c22ef5a05b01224 /src/client/views/collections/CollectionTreeView.tsx
parent479dff344ff2cf92ace9c68c3ce6d03e6e6dce22 (diff)
parentee17752109ba1238d645a4df7cee1cf60855f8df (diff)
merging
Diffstat (limited to 'src/client/views/collections/CollectionTreeView.tsx')
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx198
1 files changed, 100 insertions, 98 deletions
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index f5eb534aa..37600fa4d 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -27,6 +27,8 @@ import { TreeView } from "./TreeView";
import React = require("react");
export type collectionTreeViewProps = {
+ treeViewExpandedView?: "fields" | "layout" | "links" | "data";
+ treeViewOpen?: boolean;
treeViewHideTitle?: boolean;
treeViewHideHeaderFields?: boolean;
treeViewSkipFields?: string[]; // prevents specific fields from being displayed (see LinkBox)
@@ -38,12 +40,19 @@ export type collectionTreeViewProps = {
export class
CollectionTreeView extends CollectionSubView<Document, Partial<collectionTreeViewProps>>(Document) {
private treedropDisposer?: DragManager.DragDropDisposer;
- private _isChildActive = false;
private _mainEle?: HTMLDivElement;
- public _uniqueId = Utils.GenerateGuid();
-
- @computed get doc() { TraceMobx(); return this.props.Document; }
+ MainEle = () => this._mainEle;
+ @computed get doc() { return this.props.Document; }
@computed get dataDoc() { return this.props.DataDoc || this.doc; }
+ @computed get treeViewtruncateTitleWidth() { return NumCast(this.doc.treeViewTruncateTitleWidth, this.panelWidth()); }
+ @computed get treeChildren() { return this.props.childDocuments || this.childDocs; }
+ @computed get outlineMode() { return this.doc.treeViewType === "outline"; }
+ @computed get fileSysMode() { return this.doc.treeViewType === "fileSystem"; }
+
+ componentWillUnmount() {
+ super.componentWillUnmount();
+ this.treedropDisposer?.();
+ }
protected createTreeDropTarget = (ele: HTMLDivElement) => {
this.treedropDisposer?.();
@@ -53,19 +62,13 @@ export class
protected onInternalPreDrop = (e: Event, de: DragManager.DropEvent, targetAction: dropActionType) => {
const dragData = de.complete.docDragData;
if (dragData) {
- if (targetAction && !dragData.draggedDocuments.some(d => d.context === this.doc && this.childDocs.includes(d))) {
- dragData.dropAction = targetAction;
- } else dragData.dropAction = this.doc === dragData?.treeViewDoc ? "same" : dragData.dropAction;
+ const isInTree = () => dragData.draggedDocuments.some(d => d.context === this.doc && this.childDocs.includes(d));
+ dragData.dropAction = targetAction && !isInTree() ? targetAction : this.doc === dragData?.treeViewDoc ? "same" : dragData.dropAction;
}
}
- componentWillUnmount() {
- super.componentWillUnmount();
- this.treedropDisposer?.();
- }
-
- @undoBatch
- remove = action((doc: Doc | Doc[]): boolean => {
+ @action
+ remove = (doc: Doc | Doc[]): boolean => {
const docs = doc instanceof Doc ? [doc] : doc;
const targetDataDoc = this.doc[DataSym];
const value = DocListCast(targetDataDoc[this.props.fieldKey]);
@@ -83,27 +86,24 @@ export class
return true;
}
return false;
- });
+ }
+
@action
- addDoc = (doc: Doc | Doc[], relativeTo: Opt<Doc>, before?: boolean): boolean => {
+ addDoc = (docs: Doc | Doc[], relativeTo: Opt<Doc>, before?: boolean): boolean => {
const doAddDoc = (doc: Doc | Doc[]) =>
- (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) =>
- flg && Doc.AddDocToList(this.doc[DataSym], this.props.fieldKey, doc, relativeTo, before, false, false, false), true);
- if (this.doc.resolvedDataDoc instanceof Promise) {
- this.doc.resolvedDataDoc.then((resolved: any) => doAddDoc(doc));
- } else if (relativeTo === undefined) {
- this.props.addDocument?.(doc);
- } else {
- doAddDoc(doc);
- (doc instanceof Doc ? [doc] : doc).forEach(d => d.context = this.props.Document);
- }
- return true;
+ (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => {
+ const res = flg && Doc.AddDocToList(this.doc[DataSym], this.props.fieldKey, doc, relativeTo, before);
+ res && (doc.context = this.props.Document);
+ return res;
+ }, true);
+ if (this.doc.resolvedDataDoc instanceof Promise) return false;
+ return relativeTo === undefined ? this.props.addDocument?.(docs) || false : doAddDoc(docs);
}
onContextMenu = (e: React.MouseEvent): void => {
// need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout
if (!Doc.UserDoc().noviceMode) {
const layoutItems: ContextMenuProps[] = [];
- layoutItems.push({ description: (this.doc.treeViewPreventOpen ? "Persist" : "Abandon") + "Treeview State", event: () => this.doc.treeViewPreventOpen = !this.doc.treeViewPreventOpen, icon: "paint-brush" });
+ layoutItems.push({ description: "Make tree state " + (this.doc.treeViewOpenIsTransient ? "persistent" : "transient"), event: () => this.doc.treeViewOpenIsTransient = !this.doc.treeViewOpenIsTransient, icon: "paint-brush" });
layoutItems.push({ description: (this.doc.treeViewHideHeaderFields ? "Show" : "Hide") + " Header Fields", event: () => this.doc.treeViewHideHeaderFields = !this.doc.treeViewHideHeaderFields, icon: "paint-brush" });
layoutItems.push({ description: (this.doc.treeViewHideTitle ? "Show" : "Hide") + " Title", event: () => this.doc.treeViewHideTitle = !this.doc.treeViewHideTitle, icon: "paint-brush" });
ContextMenu.Instance.addItem({ description: "Options...", subitems: layoutItems, icon: "eye" });
@@ -113,50 +113,30 @@ export class
!existingOnClick && ContextMenu.Instance.addItem({ description: "OnClick...", noexpand: true, subitems: onClicks, icon: "mouse-pointer" });
}
}
- outerXf = () => Utils.GetScreenTransform(this._mainEle!);
onTreeDrop = (e: React.DragEvent) => this.onExternalDrop(e, {});
- @computed get renderClearButton() {
- return !this.doc.allowClear ? (null) : <div key="toolbar">
- <button className="toolbar-button round-button" title="Empty" onClick={undoBatch(action(() => Doc.GetProto(this.doc)[this.props.fieldKey] = undefined))}>
- <FontAwesomeIcon icon={"trash"} size="sm" />
- </button>
- </div >;
- }
-
@undoBatch
- makeTextCollection = action((childDocs: Doc[]) => {
- Doc.SetInPlace(this.doc, "editTitle", undefined, false);
- const bullet = TreeView.makeTextBullet();
- bullet.context = this.doc;
- this.addDoc(bullet, childDocs.length ? childDocs[0] : undefined, true);
- });
+ makeTextCollection = (childDocs: Doc[]) => {
+ this.addDoc(TreeView.makeTextBullet(), childDocs.length ? childDocs[0] : undefined, true);
+ }
editableTitle = (childDocs: Doc[]) => {
- return !this.dataDoc ? (null) : <EditableView
- contents={this.dataDoc.title}
- editing={false}
- display={"block"}
- maxHeight={72}
- height={"auto"}
- GetValue={() => StrCast(this.dataDoc.title)}
- SetValue={undoBatch((value: string, shift: boolean, enter: boolean) => {
- if (enter) {
- switch (this.props.Document.treeViewType) {
- case "outline": this.makeTextCollection(childDocs); break;
- case "fileSystem": break;
- }
- }
- return Doc.SetInPlace(this.dataDoc, "title", value, false);
- })} />;
+ return !this.dataDoc ? (null) :
+ <EditableView
+ contents={this.dataDoc.title}
+ display={"block"}
+ maxHeight={72}
+ height={"auto"}
+ GetValue={() => StrCast(this.dataDoc.title)}
+ SetValue={undoBatch((value: string, shift: boolean, enter: boolean) => {
+ if (enter && this.props.Document.treeViewType === "outline") this.makeTextCollection(childDocs);
+ this.dataDoc.title = value;
+ return true;
+ })} />;
}
-
- rtfWidth = () => Math.min(this.layoutDoc?.[WidthSym](), this.props.PanelWidth() - 20);
- rtfOutlineHeight = () => Math.min(this.layoutDoc?.[HeightSym](), (StrCast(this.layoutDoc?._fontSize) ? Number(StrCast(this.layoutDoc?._fontSize, "32px").replace("px", "")) : NumCast(this.layoutDoc?._fontSize)) * 2);
- titleTransform = () => this.props.ScreenToLocalTransform().translate(-NumCast(this.doc._xPadding, 10), -NumCast(this.doc._yPadding, 20));
documentTitle = (childDocs: Doc[]) => {
- return <div style={{ display: "inline-block", width: "100%", height: this.rtfOutlineHeight() }} key={this.doc[Id]}
+ return <div style={{ display: "inline-block", width: "100%", height: this.documentTitleHeight() }} key={this.doc[Id]}
onKeyDown={e => {
e.stopPropagation();
e.key === "Enter" && this.makeTextCollection(childDocs);
@@ -166,15 +146,15 @@ export class
DataDoc={undefined}
LayoutTemplateString={FormattedTextBox.LayoutString("text")}
renderDepth={this.props.renderDepth + 1}
+ isContentActive={this.isContentActive}
rootSelected={returnTrue}
- //dontRegisterView={true}
docViewPath={this.props.docViewPath}
styleProvider={this.props.styleProvider}
layerProvider={this.props.layerProvider}
- PanelWidth={this.rtfWidth}
- PanelHeight={this.rtfOutlineHeight}
- NativeWidth={this.rtfWidth}
- NativeHeight={this.rtfOutlineHeight}
+ PanelWidth={this.documentTitleWidth}
+ PanelHeight={this.documentTitleHeight}
+ NativeWidth={this.documentTitleWidth}
+ NativeHeight={this.documentTitleHeight}
focus={this.props.focus}
ScreenToLocalTransform={this.titleTransform}
docFilters={returnEmptyFilter}
@@ -185,54 +165,77 @@ export class
addDocument={this.props.addDocument}
moveDocument={returnFalse}
removeDocument={returnFalse}
- parentActive={this.props.active}
- whenActiveChanged={this.props.whenActiveChanged}
+ whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged}
addDocTab={this.props.addDocTab}
pinToPres={this.props.pinToPres}
bringToFront={returnFalse}
/>
</div>;
}
- @computed get treeViewtruncateTitleWidth() { return NumCast(this.doc.treeViewTruncateTitleWidth, this.panelWidth()); }
- truncateTitleWidth = () => this.treeViewtruncateTitleWidth;
- @computed get outlineMode() { return this.doc.treeViewType === "outline"; }
- @computed get fileSysMode() { return this.doc.treeViewType === "fileSystem"; }
- onChildClick = () => this.props.onChildClick?.() || ScriptCast(this.doc.onChildClick);
- whenActiveChanged = (isActive: boolean) => { this.props.whenActiveChanged(this._isChildActive = isActive); };
- active = (outsideReaction: boolean | undefined) => this.props.active(outsideReaction) || this._isChildActive;
- panelWidth = () => this.props.PanelWidth() - 20; // bcz: 20 is the 10 + 10 for the left and right padding.
- @computed get treeChildren() {
- TraceMobx();
- return this.props.childDocuments || this.childDocs;
- }
@computed get treeViewElements() {
TraceMobx();
const dropAction = StrCast(this.doc.childDropAction) as dropActionType;
const addDoc = (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => this.addDoc(doc, relativeTo, before);
const moveDoc = (d: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => this.props.moveDocument?.(d, target, addDoc) || false;
- return TreeView.GetChildElements(this.treeChildren, this, this.doc, this.props.DataDoc, this.props.fieldKey, this.props.ContainingCollectionDoc, undefined, addDoc, this.remove,
- moveDoc, dropAction, this.props.addDocTab, this.props.pinToPres, this.props.styleProvider, returnTrue, this.props.ScreenToLocalTransform,
- this.outerXf, this.active, this.panelWidth, this.props.renderDepth, () => this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeViewHideHeaderFields),
- BoolCast(this.doc.treeViewPreventOpen), [], this.props.onCheckedClick,
- this.onChildClick, this.props.treeViewSkipFields, true, this.whenActiveChanged, this.props.dontRegisterView || Cast(this.props.Document.childDontRegisterViews, "boolean", null), this);
+ return TreeView.GetChildElements(
+ this.treeChildren,
+ this,
+ this,
+ this.doc,
+ this.props.DataDoc,
+ this.props.ContainingCollectionDoc,
+ undefined,
+ addDoc,
+ this.remove,
+ moveDoc,
+ dropAction,
+ this.props.addDocTab,
+ this.props.styleProvider,
+ this.props.ScreenToLocalTransform,
+ this.props.isContentActive,
+ this.panelWidth,
+ this.props.renderDepth,
+ () => this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeViewHideHeaderFields),
+ [],
+ this.props.onCheckedClick,
+ this.onChildClick,
+ this.props.treeViewSkipFields,
+ true,
+ this.props.whenChildContentsActiveChanged,
+ this.props.dontRegisterView || Cast(this.props.Document.childDontRegisterViews, "boolean", null));
}
@computed get titleBar() {
const hideTitle = this.props.treeViewHideTitle || this.doc.treeViewHideTitle;
return hideTitle ? (null) : (this.doc.treeViewType === "outline" ? this.documentTitle : this.editableTitle)(this.treeChildren);
}
+
+ @computed get renderClearButton() {
+ return !this.doc.treeViewShowClearButton ? (null) : <div key="toolbar">
+ <button className="toolbar-button round-button" title="Empty" onClick={undoBatch(action(() => Doc.GetProto(this.doc)[this.props.fieldKey] = undefined))}>
+ <FontAwesomeIcon icon={"trash"} size="sm" />
+ </button>
+ </div >;
+ }
+
+ paddingX = () => NumCast(this.doc._xPadding, 15);
+ documentTitleWidth = () => Math.min(this.layoutDoc?.[WidthSym](), this.panelWidth());
+ documentTitleHeight = () => Math.min(this.layoutDoc?.[HeightSym](), (StrCast(this.layoutDoc?._fontSize) ? Number(StrCast(this.layoutDoc?._fontSize, "32px").replace("px", "")) : NumCast(this.layoutDoc?._fontSize)) * 2);
+ titleTransform = () => this.props.ScreenToLocalTransform().translate(-NumCast(this.doc._xPadding, 10), -NumCast(this.doc._yPadding, 20));
+ truncateTitleWidth = () => this.treeViewtruncateTitleWidth;
+ onChildClick = () => this.props.onChildClick?.() || ScriptCast(this.doc.onChildClick);
+ panelWidth = () => this.props.PanelWidth() - 2 * this.paddingX();
+ isContentActive = () => this.props.isContentActive() || this.props.isSelected();
render() {
TraceMobx();
- if (!(this.doc instanceof Doc)) return (null);
- const background = this.props.treeViewHideTitle && this.props.treeViewHideHeaderFields ? "#9F9F9F" : this.props.styleProvider?.(this.doc, this.props, StyleProp.BackgroundColor);
- const paddingX = `${NumCast(this.doc._xPadding, 15)}px`;
- const paddingTop = `${NumCast(this.doc._yPadding, 20)}px`;
- const pointerEvents = !this.props.active() && !SnappingManager.GetIsDragging() && !this._isChildActive ? "none" : undefined;
+ const background = () => this.props.styleProvider?.(this.doc, this.props, StyleProp.BackgroundColor);
+ const paddingTop = () => `${NumCast(this.doc._yPadding, 20)}px`;
+ const pointerEvents = () => !this.props.isContentActive() && !SnappingManager.GetIsDragging() ? "none" : undefined;
- return !this.treeChildren ? (null) : (
+ return !(this.doc instanceof Doc) || !this.treeChildren ? (null) :
<div className="collectionTreeView-container" onContextMenu={this.onContextMenu}>
<div className="collectionTreeView-dropTarget"
- style={{ background, paddingLeft: paddingX, paddingRight: paddingX, paddingTop, pointerEvents }}
- onWheel={(e) => this._mainEle && this._mainEle.scrollHeight > this._mainEle.clientHeight && e.stopPropagation()}
+ style={{ background: background(), paddingLeft: `${this.paddingX()}px`, paddingRight: `${this.paddingX()}px`, paddingTop: paddingTop(), pointerEvents: pointerEvents() }}
+ onWheel={e => e.stopPropagation()}
onDrop={this.onTreeDrop}
ref={this.createTreeDropTarget}>
{this.titleBar}
@@ -241,7 +244,6 @@ export class
{this.treeViewElements}
</ul>
</div >
- </div>
- );
+ </div>;
}
} \ No newline at end of file