aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2023-08-27 12:14:02 -0400
committerbobzel <zzzman@gmail.com>2023-08-27 12:14:02 -0400
commit2bf684f3f7960b92fb052d746cb25c11b603b190 (patch)
tree742aff58e4f0879574bc5cd1ce3935208c30209e /src/client/views/collections
parent68ddebab45946697270c5f291ff9fdd044b6e83d (diff)
parentbf1777b93be0707e17e3b3c0ca6c965facebfe14 (diff)
Merge branch 'master' into secondpropertiesmenu-emily
Diffstat (limited to 'src/client/views/collections')
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx4
-rw-r--r--src/client/views/collections/CollectionStackedTimeline.tsx2
-rw-r--r--src/client/views/collections/CollectionSubView.tsx6
-rw-r--r--src/client/views/collections/CollectionTimeView.tsx6
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx23
-rw-r--r--src/client/views/collections/CollectionView.tsx2
-rw-r--r--src/client/views/collections/TabDocView.tsx51
-rw-r--r--src/client/views/collections/TreeView.tsx109
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx15
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss7
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx65
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx64
-rw-r--r--src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.scss6
-rw-r--r--src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx7
14 files changed, 203 insertions, 164 deletions
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 0052c4196..e15d57306 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -498,6 +498,7 @@ export class CollectionDockingView extends CollectionSubView() {
_layout_fitWidth: true,
title: `Untitled Tab ${NumCast(dashboard['pane-count'])}`,
});
+ Doc.AddDocToList(Doc.MyHeaderBar, 'data', docToAdd);
inheritParentAcls(this.rootDoc, docToAdd, false);
CollectionDockingView.AddSplit(docToAdd, OpenWhereMod.none, stack);
}
@@ -541,6 +542,7 @@ export class CollectionDockingView extends CollectionSubView() {
_freeform_backgroundGrid: true,
title: `Untitled Tab ${NumCast(dashboard['pane-count'])}`,
});
+ Doc.AddDocToList(Doc.MyHeaderBar, 'data', docToAdd);
inheritParentAcls(this.dataDoc, docToAdd, false);
CollectionDockingView.AddSplit(docToAdd, OpenWhereMod.none, stack);
}
@@ -549,7 +551,7 @@ export class CollectionDockingView extends CollectionSubView() {
};
render() {
- const href = ImageCast(this.rootDoc.thumb)?.url.href;
+ const href = ImageCast(this.rootDoc.thumb)?.url?.href;
return this.props.renderDepth > -1 ? (
<div>
{href ? (
diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx
index ad84d859d..de58e1fe7 100644
--- a/src/client/views/collections/CollectionStackedTimeline.tsx
+++ b/src/client/views/collections/CollectionStackedTimeline.tsx
@@ -716,7 +716,7 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps>
this._disposer = reaction(
() => this.props.currentTimecode(),
time => {
- const dictationDoc = Cast(this.props.layoutDoc['data-dictation'], Doc, null);
+ const dictationDoc = Cast(this.props.layoutDoc.data_dictation, Doc, null);
const isDictation = dictationDoc && LinkManager.Links(this.props.mark).some(link => Cast(link.link_anchor_1, Doc, null)?.annotationOn === dictationDoc);
if (
!LightboxView.LightboxDoc &&
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index c189ef126..eb4685834 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -298,7 +298,11 @@ export function CollectionSubView<X>(moreProps?: X) {
let source = split;
if (split.startsWith('data:image') && split.includes('base64')) {
const [{ accessPaths }] = await Networking.PostToServer('/uploadRemoteImage', { sources: [split] });
- source = Utils.prepend(accessPaths.agnostic.client);
+ if (accessPaths.agnostic.client.indexOf("dashblobstore") === -1) {
+ source = Utils.prepend(accessPaths.agnostic.client);
+ } else {
+ source = accessPaths.agnostic.client;
+ }
}
if (source.startsWith('http')) {
const doc = Docs.Create.ImageDocument(source, { ...options, _width: 300 });
diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx
index 192d48c64..a8f5345b7 100644
--- a/src/client/views/collections/CollectionTimeView.tsx
+++ b/src/client/views/collections/CollectionTimeView.tsx
@@ -65,9 +65,9 @@ export class CollectionTimeView extends CollectionSubView() {
@action
scrollPreview = (docView: DocumentView, anchor: Doc, focusSpeed: number, options: DocFocusOptions) => {
// if in preview, then override document's fields with view spec
- this._focusFilters = StrListCast(anchor.presDocFilters);
- this._focusRangeFilters = StrListCast(anchor.presPinDocRangeFilters);
- this._focusPivotField = StrCast(anchor.presPivotField);
+ this._focusFilters = StrListCast(anchor.config_docFilters);
+ this._focusRangeFilters = StrListCast(anchor.config_docRangeFilters);
+ this._focusPivotField = StrCast(anchor.config_pivotField);
return undefined;
};
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index ea3b5065f..eed04b3ee 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -66,17 +66,17 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
return this.props.DataDoc || this.doc;
}
@computed get treeViewtruncateTitleWidth() {
- return NumCast(this.doc.treeViewTruncateTitleWidth, this.panelWidth());
+ return NumCast(this.doc.treeView_TruncateTitleWidth, this.panelWidth());
}
@computed get treeChildren() {
TraceMobx();
return this.props.childDocuments || this.childDocs;
}
@computed get outlineMode() {
- return this.doc.treeViewType === TreeViewType.outline;
+ return this.doc.treeView_Type === TreeViewType.outline;
}
@computed get fileSysMode() {
- return this.doc.treeViewType === TreeViewType.fileSystem;
+ return this.doc.treeView_Type === TreeViewType.fileSystem;
}
@computed get dashboardMode() {
return this.doc === Doc.MyDashboards;
@@ -191,9 +191,9 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
// need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout
if (!Doc.noviceMode) {
const layoutItems: ContextMenuProps[] = [];
- 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' });
+ layoutItems.push({ description: 'Make tree state ' + (this.doc.treeView_OpenIsTransient ? 'persistent' : 'transient'), event: () => (this.doc.treeView_OpenIsTransient = !this.doc.treeView_OpenIsTransient), icon: 'paint-brush' });
+ layoutItems.push({ description: (this.doc.treeView_HideHeaderFields ? 'Show' : 'Hide') + ' Header Fields', event: () => (this.doc.treeView_HideHeaderFields = !this.doc.treeView_HideHeaderFields), icon: 'paint-brush' });
+ layoutItems.push({ description: (this.doc.treeView_HideTitle ? 'Show' : 'Hide') + ' Title', event: () => (this.doc.treeView_HideTitle = !this.doc.treeView_HideTitle), icon: 'paint-brush' });
ContextMenu.Instance.addItem({ description: 'Options...', subitems: layoutItems, icon: 'eye' });
const existingOnClick = ContextMenu.Instance.findByDescription('OnClick...');
const onClicks: ContextMenuProps[] = existingOnClick && 'subitems' in existingOnClick ? existingOnClick.subitems : [];
@@ -215,7 +215,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
height={'auto'}
GetValue={() => StrCast(this.dataDoc.title)}
SetValue={undoBatch((value: string, shift: boolean, enter: boolean) => {
- if (enter && this.props.Document.treeViewType === TreeViewType.outline) this.makeTextCollection(this.treeChildren);
+ if (enter && this.props.Document.treeView_Type === TreeViewType.outline) this.makeTextCollection(this.treeChildren);
this.dataDoc.title = value;
return true;
})}
@@ -261,7 +261,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
const icons = StrListCast(this.doc.childContextMenuIcons);
return StrListCast(this.doc.childContextMenuLabels).map((label, i) => ({ script: customScripts[i], filter: customFilters[i], icon: icons[i], label }));
};
- headerFields = () => this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeViewHideHeaderFields);
+ headerFields = () => this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeView_HideHeaderFields);
@observable _renderCount = 1;
@computed get treeViewElements() {
TraceMobx();
@@ -389,7 +389,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
const background = () => this.props.styleProvider?.(this.doc, this.props, StyleProp.BackgroundColor);
const color = () => this.props.styleProvider?.(this.doc, this.props, StyleProp.Color);
const pointerEvents = () => (this.props.isContentActive() === false ? 'none' : undefined);
- const titleBar = this.props.treeViewHideTitle || this.doc.treeViewHideTitle ? null : this.titleBar;
+ const titleBar = this.props.treeViewHideTitle || this.doc.treeView_HideTitle ? null : this.titleBar;
return (
<div style={{ display: 'flex', flexDirection: 'column', height: '100%', pointerEvents: 'all' }}>
{!this.buttonMenu && !this.noviceExplainer ? null : (
@@ -401,7 +401,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
<div
className="collectionTreeView-contents"
key="tree"
- ref={r => !this.doc.treeViewHasOverlay && r && this.createTreeDropTarget(r)}
+ ref={r => !this.doc.treeView_HasOverlay && r && this.createTreeDropTarget(r)}
style={{
...(!titleBar ? { marginLeft: this.marginX(), paddingTop: this.marginTop() } : {}),
color: color(),
@@ -426,6 +426,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
minHeight: '100%',
}}
onWheel={e => e.stopPropagation()}
+ onClick={e => (!this.layoutDoc.forceActive ? this.props.select(false) : SelectionManager.DeselectAll())}
onDrop={this.onTreeDrop}>
<ul className={`no-indent${this.outlineMode ? '-outline' : ''}`}>{this.treeViewElements}</ul>
</div>
@@ -440,7 +441,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
const scale = (this.props.NativeDimScaling?.() || 1) * NumCast(this.layoutDoc._freeform_scale, 1) || 1;
return (
<div style={{ transform: `scale(${scale})`, transformOrigin: 'top left', width: `${100 / scale}%`, height: `${100 / scale}%` }}>
- {!(this.doc instanceof Doc) || !this.treeChildren ? null : this.doc.treeViewHasOverlay ? (
+ {!(this.doc instanceof Doc) || !this.treeChildren ? null : this.doc.treeView_HasOverlay ? (
<CollectionFreeFormView
{...this.props}
setContentView={emptyFunction}
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index c33519afb..88f892efc 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -41,7 +41,7 @@ interface CollectionViewProps_ extends FieldViewProps {
isAnnotationOverlayScrollable?: boolean; // whether the annotation overlay can be vertically scrolled (just for tree views, currently)
layoutEngine?: () => string;
setPreviewCursor?: (func: (x: number, y: number, drag: boolean, hide: boolean) => void) => void;
- setBrushViewer?: (func?: (view: { width: number; height: number; panX: number; panY: number }) => void) => void;
+ setBrushViewer?: (func?: (view: { width: number; height: number; panX: number; panY: number }, transTime: number) => void) => void;
ignoreUnrendered?: boolean;
// property overrides for child documents
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index d787f5262..f379d09ff 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -137,7 +137,11 @@ export class TabDocView extends React.Component<TabDocViewProps> {
setupMoveUpEvents(
this,
e,
- e => !e.defaultPrevented && DragManager.StartDocumentDrag([iconWrap], new DragManager.DocumentDragData([doc], doc.dropAction as dropActionType), e.clientX, e.clientY),
+ e =>
+ !e.defaultPrevented &&
+ DragManager.StartDocumentDrag([iconWrap], new DragManager.DocumentDragData([doc], doc.dropAction as dropActionType), e.clientX, e.clientY, undefined, () => {
+ CollectionDockingView.CloseSplit(doc);
+ }),
returnFalse,
action(e => {
if (this.view) {
@@ -256,46 +260,47 @@ export class TabDocView extends React.Component<TabDocViewProps> {
return;
}
const anchorDoc = DocumentManager.Instance.getDocumentView(doc)?.ComponentView?.getAnchor?.(false, pinProps);
- const pinDoc = Doc.MakeDelegate(anchorDoc && anchorDoc !== doc ? anchorDoc : doc);
- pinDoc.presentationTargetDoc = anchorDoc ?? doc;
+ const pinDoc = anchorDoc?.type === DocumentType.CONFIG ? anchorDoc : Doc.MakeDelegate(anchorDoc && anchorDoc !== doc ? anchorDoc : doc);
+ pinDoc.presentation_targetDoc = anchorDoc ?? doc;
pinDoc.title = doc.title + ' - Slide';
pinDoc.data = new List<Doc>(); // the children of the embedding's layout are the presentation slide children. the embedding's data field might be children of a collection, PDF data, etc -- in any case we don't want the tree view to "see" this data
- pinDoc.presMovement = doc.type === DocumentType.SCRIPTING || pinProps?.pinDocLayout ? PresMovement.None : PresMovement.Zoom;
- pinDoc.presDuration = pinDoc.presDuration ?? 1000;
- pinDoc.groupWithUp = false;
+ pinDoc.presentation_movement = doc.type === DocumentType.SCRIPTING || pinProps?.pinDocLayout ? PresMovement.None : PresMovement.Zoom;
+ pinDoc.presentation_duration = pinDoc.presentation_duration ?? 1000;
+ pinDoc.presentation_groupWithUp = false;
Doc.SetContainer(pinDoc, curPres);
// these should potentially all be props passed down by the CollectionTreeView to the TreeView elements. That way the PresBox could configure all of its children at render time
- pinDoc.treeViewRenderAsBulletHeader = true; // forces a tree view to render the document next to the bullet in the header area
- pinDoc.treeViewHeaderWidth = '100%'; // forces the header to grow to be the same size as its largest sibling.
- pinDoc.treeViewChildrenOnRoot = true; // tree view will look for hierarchical children on the root doc, not the data doc.
- pinDoc.treeViewFieldKey = 'data'; // tree view will treat the 'data' field as the field where the hierarchical children are located instead of using the document's layout string field
- pinDoc.treeViewExpandedView = 'data'; // in case the data doc has an expandedView set, this will mask that field and use the 'data' field when expanding the tree view
- pinDoc.treeViewHideHeaderIfTemplate = true; // this will force the document to render itself as the tree view header
+ pinDoc.treeView = ''; // not really needed, but makes key value pane look better
+ pinDoc.treeView_RenderAsBulletHeader = true; // forces a tree view to render the document next to the bullet in the header area
+ pinDoc.treeView_HeaderWidth = '100%'; // forces the header to grow to be the same size as its largest sibling.
+ pinDoc.treeView_ChildrenOnRoot = true; // tree view will look for hierarchical children on the root doc, not the data doc.
+ pinDoc.treeView_FieldKey = 'data'; // tree view will treat the 'data' field as the field where the hierarchical children are located instead of using the document's layout string field
+ pinDoc.treeView_ExpandedView = 'data'; // in case the data doc has an expandedView set, this will mask that field and use the 'data' field when expanding the tree view
+ pinDoc.treeView_HideHeaderIfTemplate = true; // this will force the document to render itself as the tree view header
const duration = NumCast(doc[`${Doc.LayoutFieldKey(pinDoc)}_duration`], null);
if (pinProps.pinViewport) PresBox.pinDocView(pinDoc, pinProps, anchorDoc ?? doc);
if (!pinProps?.audioRange && duration !== undefined) {
pinDoc.mediaStart = 'manual';
pinDoc.mediaStop = 'manual';
- pinDoc.presStartTime = NumCast(doc.clipStart);
- pinDoc.presEndTime = NumCast(doc.clipEnd, duration);
+ pinDoc.config_clipStart = NumCast(doc.clipStart);
+ pinDoc.config_clipEnd = NumCast(doc.clipEnd, duration);
}
if (pinProps?.activeFrame !== undefined) {
- pinDoc.presActiveFrame = pinProps?.activeFrame;
+ pinDoc.config_activeFrame = pinProps?.activeFrame;
pinDoc.title = doc.title + ' (move)';
- pinDoc.presMovement = PresMovement.Pan;
+ pinDoc.presentation_movement = PresMovement.Pan;
}
if (pinProps?.currentFrame !== undefined) {
- pinDoc.presCurrentFrame = pinProps?.currentFrame;
+ pinDoc.config_currentFrame = pinProps?.currentFrame;
pinDoc.title = doc.title + ' (move)';
- pinDoc.presMovement = PresMovement.Pan;
+ pinDoc.presentation_movement = PresMovement.Pan;
}
if (pinDoc.stroke_isInkMask) {
- pinDoc.presHideAfter = true;
- pinDoc.presHideBefore = true;
- pinDoc.presMovement = PresMovement.None;
+ pinDoc.presentation_hideAfter = true;
+ pinDoc.presentation_hideBefore = true;
+ pinDoc.presentation_movement = PresMovement.None;
}
- if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true;
+ if (curPres.expandBoolean) pinDoc.presentation_expandInlineButton = true;
Doc.AddDocToList(curPres, 'data', pinDoc, PresBox.Instance?.sortArray()?.lastElement());
PresBox.Instance?.clearSelectedArray();
pinDoc && PresBox.Instance?.addToSelectedArray(pinDoc); //Update selected array
@@ -393,7 +398,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
};
getCurrentFrame = () => {
- return NumCast(Cast(PresBox.Instance.activeItem.presentationTargetDoc, Doc, null)._currentFrame);
+ return NumCast(Cast(PresBox.Instance.activeItem.presentation_targetDoc, Doc, null)._currentFrame);
};
static Activate = (tabDoc: Doc) => {
const tab = Array.from(CollectionDockingView.Instance?.tabMap!).find(tab => tab.DashDoc === tabDoc && !tab.contentItem.config.props.keyValue);
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 25a547066..3402a8c8d 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -78,17 +78,17 @@ const treeBulletWidth = function () {
};
export enum TreeSort {
- Up = 'up',
- Down = 'down',
- Zindex = 'z',
- None = 'none',
+ AlphaUp = 'alphabetical from z',
+ AlphaDown = 'alphabetical from A',
+ Zindex = 'by Z index',
+ WhenAdded = 'when added',
}
/**
* Renders a treeView of a collection of documents
*
* special fields:
- * treeViewOpen : flag denoting whether the documents sub-tree (contents) is visible or hidden
- * treeViewExpandedView : name of field whose contents are being displayed as the document's subtree
+ * treeView_Open : flag denoting whether the documents sub-tree (contents) is visible or hidden
+ * treeView_ExpandedView : name of field whose contents are being displayed as the document's subtree
*/
@observer
export class TreeView extends React.Component<TreeViewProps> {
@@ -104,16 +104,16 @@ export class TreeView extends React.Component<TreeViewProps> {
private _treedropDisposer?: DragManager.DragDropDisposer;
get treeViewOpenIsTransient() {
- return this.props.treeView.doc.treeViewOpenIsTransient || Doc.IsDataProto(this.doc);
+ return this.props.treeView.doc.treeView_OpenIsTransient || Doc.IsDataProto(this.doc);
}
set treeViewOpen(c: boolean) {
if (this.treeViewOpenIsTransient) this._transientOpenState = c;
else {
- this.doc.treeViewOpen = c;
+ this.doc.treeView_Open = c;
this._transientOpenState = false;
}
}
- @observable _transientOpenState = false; // override of the treeViewOpen field allowing the display state to be independent of the document's state
+ @observable _transientOpenState = false; // override of the treeView_Open field allowing the display state to be independent of the document's state
@observable _editTitle: boolean = false;
@observable _dref: DocumentView | undefined | null;
get displayName() {
@@ -132,29 +132,29 @@ export class TreeView extends React.Component<TreeViewProps> {
? this.fieldKey
: Doc.noviceMode
? 'layout'
- : StrCast(this.props.treeView.doc.treeViewExpandedView, 'fields');
+ : StrCast(this.props.treeView.doc.treeView_ExpandedView, 'fields');
}
@computed get doc() {
return this.props.document;
}
@computed get treeViewOpen() {
- return (!this.treeViewOpenIsTransient && Doc.GetT(this.doc, 'treeViewOpen', 'boolean', true)) || this._transientOpenState;
+ return (!this.treeViewOpenIsTransient && Doc.GetT(this.doc, 'treeView_Open', 'boolean', true)) || this._transientOpenState;
}
@computed get treeViewExpandedView() {
- return this.validExpandViewTypes.includes(StrCast(this.doc.treeViewExpandedView)) ? StrCast(this.doc.treeViewExpandedView) : this.defaultExpandedView;
+ return this.validExpandViewTypes.includes(StrCast(this.doc.treeView_ExpandedView)) ? StrCast(this.doc.treeView_ExpandedView) : this.defaultExpandedView;
}
@computed get MAX_EMBED_HEIGHT() {
return NumCast(this.props.treeViewParent.maxEmbedHeight, 200);
}
@computed get dataDoc() {
- return this.props.document.treeViewChildrenOnRoot ? this.doc : this.doc[DocData];
+ return this.props.document.treeView_ChildrenOnRoot ? this.doc : this.doc[DocData];
}
@computed get layoutDoc() {
return Doc.Layout(this.doc);
}
@computed get fieldKey() {
- return StrCast(this.doc._treeViewFieldKey, Doc.LayoutFieldKey(this.doc));
+ return StrCast(this.doc._treeView_FieldKey, Doc.LayoutFieldKey(this.doc));
}
@computed get childDocs() {
return this.childDocList(this.fieldKey);
@@ -308,13 +308,13 @@ export class TreeView extends React.Component<TreeViewProps> {
const bullet = Docs.Create.TextDocument('', {
layout: CollectionView.LayoutString('data'),
title: '-title-',
- treeViewExpandedViewLock: true,
- treeViewExpandedView: 'data',
+ treeView_ExpandedViewLock: true,
+ treeView_ExpandedView: 'data',
_type_collection: CollectionViewType.Tree,
layout_hideLinkButton: true,
_layout_showSidebar: true,
_layout_fitWidth: true,
- treeViewType: TreeViewType.outline,
+ treeView_Type: TreeViewType.outline,
x: 0,
y: 0,
_xMargin: 0,
@@ -395,7 +395,7 @@ export class TreeView extends React.Component<TreeViewProps> {
};
const addDoc = inside ? localAdd : parentAddDoc;
const move = (!dropAction || dropAction === 'proto' || dropAction === 'move' || dropAction === 'same') && moveDocument;
- const canAdd = (!this.props.treeView.outlineMode && !StrCast((inside ? this.props.document : this.props.treeViewParent)?.treeViewFreezeChildren).includes('add')) || forceAdd;
+ const canAdd = (!this.props.treeView.outlineMode && !StrCast((inside ? this.props.document : this.props.treeViewParent)?.treeView_FreezeChildren).includes('add')) || forceAdd;
if (canAdd) {
this.props.parentTreeView instanceof TreeView && (this.props.parentTreeView.dropping = true);
const res = droppedDocuments.reduce((added, d) => (move ? move(d, undefined, addDoc) || (dropAction === 'proto' ? addDoc(d) : false) : addDoc(d)) || added, false);
@@ -438,7 +438,7 @@ export class TreeView extends React.Component<TreeViewProps> {
doc && Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key));
for (const key of Object.keys(ids).slice().sort()) {
- if (this.props.skipFields?.includes(key) || key === 'title' || key === 'treeViewOpen') continue;
+ if (this.props.skipFields?.includes(key) || key === 'title' || key === 'treeView_Open') continue;
const contents = doc[key];
let contentElement: (JSX.Element | null)[] | JSX.Element = [];
@@ -538,7 +538,7 @@ export class TreeView extends React.Component<TreeViewProps> {
const expandKey = this.treeViewExpandedView;
const sortings = (this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewSortings) as { [key: string]: { color: string; icon: JSX.Element | string } }) ?? {};
if (['links', 'annotations', 'embeddings', this.fieldKey].includes(expandKey)) {
- const sorting = StrCast(this.doc.treeViewSortCriterion, TreeSort.None);
+ const sorting = StrCast(this.doc.treeView_SortCriterion, TreeSort.WhenAdded);
const sortKeys = Object.keys(sortings);
const curSortIndex = Math.max(
0,
@@ -550,7 +550,7 @@ export class TreeView extends React.Component<TreeViewProps> {
const localAdd = (doc: Doc, addBefore?: Doc, before?: boolean) => {
// if there's a sort ordering specified that can be modified on drop (eg, zorder can be modified, alphabetical can't),
// then the modification would be done here
- const ordering = StrCast(this.doc.treeViewSortCriterion);
+ const ordering = StrCast(this.doc.treeView_SortCriterion);
if (ordering === TreeSort.Zindex) {
const docs = TreeView.sortDocs(this.childDocs || ([] as Doc[]), ordering);
doc.zIndex = addBefore ? NumCast(addBefore.zIndex) + (before ? -0.5 : 0.5) : 1000;
@@ -578,10 +578,11 @@ export class TreeView extends React.Component<TreeViewProps> {
return (
<div>
{!docs?.length || this.props.AddToMap /* hack to identify pres box trees */ ? null : (
- <div className={'treeView-sorting'}>
+ <div className='treeView-sorting'>
<IconButton
color={sortings[sorting]?.color}
size={Size.XSMALL}
+ tooltip={`Sorted by : ${this.doc.treeView_SortCriterion}. click to cycle`}
icon={sortings[sorting]?.icon}
onPointerDown={e => {
downX = e.clientX;
@@ -590,7 +591,7 @@ export class TreeView extends React.Component<TreeViewProps> {
}}
onClick={undoable(e => {
if (this.props.isContentActive() && Math.abs(e.clientX - downX) < 3 && Math.abs(e.clientY - downY) < 3) {
- !this.props.treeView.outlineMode && (this.doc.treeViewSortCriterion = sortKeys[(curSortIndex + 1) % sortKeys.length]);
+ !this.props.treeView.outlineMode && (this.doc.treeView_SortCriterion = sortKeys[(curSortIndex + 1) % sortKeys.length]);
e.stopPropagation();
}
}, 'sort order')}
@@ -600,8 +601,8 @@ export class TreeView extends React.Component<TreeViewProps> {
<ul
style={{ cursor: 'inherit' }}
key={expandKey + 'more'}
- title="click to change sort order"
- className={''} //this.doc.treeViewHideTitle ? 'no-indent' : ''}
+ title={`Sorted by : ${this.doc.treeView_SortCriterion}. click to cycle`}
+ className='' //this.doc.treeView_HideTitle ? 'no-indent' : ''}
onPointerDown={e => {
downX = e.clientX;
downY = e.clientY;
@@ -609,7 +610,7 @@ export class TreeView extends React.Component<TreeViewProps> {
}}
onClick={undoable(e => {
if (this.props.isContentActive() && Math.abs(e.clientX - downX) < 3 && Math.abs(e.clientY - downY) < 3) {
- !this.props.treeView.outlineMode && (this.doc.treeViewSortCriterion = sortKeys[(curSortIndex + 1) % sortKeys.length]);
+ !this.props.treeView.outlineMode && (this.doc.treeView_SortCriterion = sortKeys[(curSortIndex + 1) % sortKeys.length]);
e.stopPropagation();
}
}, 'sort order')}>
@@ -683,7 +684,7 @@ export class TreeView extends React.Component<TreeViewProps> {
{
this: this.doc.isTemplateForField && this.props.dataDoc ? this.props.dataDoc : this.doc,
heading: this.props.treeViewParent.title,
- checked: this.doc.treeViewChecked === 'check' ? 'x' : this.doc.treeViewChecked === 'x' ? 'remove' : 'check',
+ checked: this.doc.treeView_Checked === 'check' ? 'x' : this.doc.treeView_Checked === 'x' ? 'remove' : 'check',
containingTreeView: this.props.treeView.props.Document,
},
console.log
@@ -698,7 +699,7 @@ export class TreeView extends React.Component<TreeViewProps> {
TraceMobx();
const iconType = this.props.treeView.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewIcon + (this.treeViewOpen ? ':open' : !this.childDocs.length ? ':empty' : '')) || 'question';
const color = StrCast(Doc.UserDoc().userColor);
- const checked = this.onCheckedClick ? this.doc.treeViewChecked ?? 'unchecked' : undefined;
+ const checked = this.onCheckedClick ? this.doc.treeView_Checked ?? 'unchecked' : undefined;
return (
<div
className={`bullet${this.props.treeView.outlineMode ? '-outline' : ''}`}
@@ -748,9 +749,9 @@ export class TreeView extends React.Component<TreeViewProps> {
}
@action
expandNextviewType = () => {
- if (this.treeViewOpen && !this.doc.isFolder && !this.props.treeView.outlineMode && !this.doc.treeViewExpandedViewLock) {
+ if (this.treeViewOpen && !this.doc.isFolder && !this.props.treeView.outlineMode && !this.doc.treeView_ExpandedViewLock) {
const next = (modes: any[]) => modes[(modes.indexOf(StrCast(this.treeViewExpandedView)) + 1) % modes.length];
- this.doc.treeViewExpandedView = next(this.validExpandViewTypes);
+ this.doc.treeView_ExpandedView = next(this.validExpandViewTypes);
}
this.treeViewOpen = true;
};
@@ -759,7 +760,7 @@ export class TreeView extends React.Component<TreeViewProps> {
@computed get titleButtons() {
const customHeaderButtons = this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.Decorations);
const color = StrCast(Doc.UserDoc().userColor);
- return this.props.treeViewHideHeaderFields() || this.doc.treeViewHideHeaderFields ? null : (
+ return this.props.treeViewHideHeaderFields() || this.doc.treeView_HideHeaderFields ? null : (
<>
{customHeaderButtons} {/* e.g.,. hide button is set by dashboardStyleProvider */}
<IconButton
@@ -771,7 +772,7 @@ export class TreeView extends React.Component<TreeViewProps> {
e.stopPropagation();
}}
/>
- {Doc.noviceMode ? null : this.doc.treeViewExpandedViewLock || Doc.IsSystem(this.doc) ? null : (
+ {Doc.noviceMode ? null : this.doc.treeView_ExpandedViewLock || Doc.IsSystem(this.doc) ? null : (
<span className="collectionTreeView-keyHeader" title="type of expanded data" key={this.treeViewExpandedView} onPointerDown={this.expandNextviewType}>
{this.treeViewExpandedView}
</span>
@@ -815,7 +816,7 @@ export class TreeView extends React.Component<TreeViewProps> {
onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!);
- onChildDoubleClick = () => ScriptCast(this.props.treeView.Document.treeViewChildDoubleClick, !this.props.treeView.outlineMode ? this._openScript?.() : null);
+ onChildDoubleClick = () => ScriptCast(this.props.treeView.Document.treeView_ChildDoubleClick, !this.props.treeView.outlineMode ? this._openScript?.() : null);
refocus = () => this.props.treeView.props.focus(this.props.treeView.props.Document, {});
ignoreEvent = (e: any) => {
@@ -861,7 +862,7 @@ export class TreeView extends React.Component<TreeViewProps> {
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) => {
- if (this.doc.treeViewHideHeader || (this.doc.treeViewHideHeaderIfTemplate && this.props.treeView.props.childLayoutTemplate?.()) || this.props.treeView.outlineMode) {
+ if (this.doc.treeView_HideHeader || (this.doc.treeView_HideHeaderIfTemplate && this.props.treeView.props.childLayoutTemplate?.()) || this.props.treeView.outlineMode) {
switch (e.key) {
case 'Tab':
e.stopPropagation?.();
@@ -1068,7 +1069,7 @@ export class TreeView extends React.Component<TreeViewProps> {
// 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.props.treeView.Document.treeViewHideUnrendered && this.doc.layout_unrendered && !this.doc.treeViewFieldKey ? (
+ return this.props.treeView.Document.treeView_HideUnrendered && this.doc.layout_unrendered && !this.doc.treeView_FieldKey ? (
<div></div>
) : (
<>
@@ -1089,7 +1090,7 @@ export class TreeView extends React.Component<TreeViewProps> {
};
@computed get renderBorder() {
- const sorting = StrCast(this.doc.treeViewSortCriterion, TreeSort.None);
+ const sorting = StrCast(this.doc.treeView_SortCriterion, TreeSort.WhenAdded);
const sortings = (this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewSortings) ?? {}) as { [key: string]: { color: string; label: string } };
return (
<div className={`treeView-border${this.props.treeView.outlineMode ? TreeViewType.outline : ''}`} style={{ borderColor: sortings[sorting]?.color }}>
@@ -1109,7 +1110,7 @@ export class TreeView extends React.Component<TreeViewProps> {
render() {
TraceMobx();
- const hideTitle = this.doc.treeViewHideHeader || (this.doc.treeViewHideHeaderIfTemplate && this.props.treeView.props.childLayoutTemplate?.()) || this.props.treeView.outlineMode;
+ const hideTitle = this.doc.treeView_HideHeader || (this.doc.treeView_HideHeaderIfTemplate && this.props.treeView.props.childLayoutTemplate?.()) || this.props.treeView.outlineMode;
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
) : (
@@ -1121,9 +1122,9 @@ export class TreeView extends React.Component<TreeViewProps> {
// onKeyDown={this.onKeyDown}
>
<li className="collection-child">
- {hideTitle && this.doc.type !== DocumentType.RTF && !this.doc.treeViewRenderAsBulletHeader // should test for prop 'treeViewRenderDocWithBulletAsHeader"
+ {hideTitle && this.doc.type !== DocumentType.RTF && !this.doc.treeView_RenderAsBulletHeader // should test for prop 'treeView_RenderDocWithBulletAsHeader"
? this.renderEmbeddedDocument(false, returnFalse)
- : this.renderBulletHeader(hideTitle ? this.renderDocumentAsHeader(!this.doc.treeViewRenderAsBulletHeader) : this.renderTitleAsHeader, this._editTitle)}
+ : this.renderBulletHeader(hideTitle ? this.renderDocumentAsHeader(!this.doc.treeView_RenderAsBulletHeader) : this.renderTitleAsHeader, this._editTitle)}
</li>
</div>
);
@@ -1131,7 +1132,7 @@ export class TreeView extends React.Component<TreeViewProps> {
public static sortDocs(childDocs: Doc[], criterion: string | undefined) {
const docs = childDocs.slice();
- if (criterion !== TreeSort.None) {
+ if (criterion !== TreeSort.WhenAdded) {
const sortAlphaNum = (a: string, b: string): 0 | 1 | -1 => {
const reN = /[0-9]*$/;
const aA = a.replace(reN, '') ? a.replace(reN, '') : +a; // get rid of trailing numbers
@@ -1146,8 +1147,8 @@ export class TreeView extends React.Component<TreeViewProps> {
}
};
docs.sort(function (d1, d2): 0 | 1 | -1 {
- const a = criterion === TreeSort.Up ? d2 : d1;
- const b = criterion === TreeSort.Up ? d1 : d2;
+ const a = criterion === TreeSort.AlphaUp ? d2 : d1;
+ const b = criterion === TreeSort.AlphaUp ? d1 : d2;
const first = a[criterion === TreeSort.Zindex ? 'zIndex' : 'title'];
const second = b[criterion === TreeSort.Zindex ? 'zIndex' : 'title'];
if (typeof first === 'number' && typeof second === 'number') return first - second > 0 ? 1 : -1;
@@ -1162,7 +1163,7 @@ export class TreeView extends React.Component<TreeViewProps> {
childDocs: Doc[],
treeView: CollectionTreeView,
parentTreeView: CollectionTreeView | TreeView | undefined,
- treeViewParent: Doc,
+ treeView_Parent: Doc,
dataDoc: Doc | undefined,
parentCollectionDoc: Doc | undefined,
containerPrevSibling: Doc | undefined,
@@ -1176,7 +1177,7 @@ export class TreeView extends React.Component<TreeViewProps> {
isContentActive: (outsideReaction?: boolean) => boolean,
panelWidth: () => number,
renderDepth: number,
- treeViewHideHeaderFields: () => boolean,
+ treeView_HideHeaderFields: () => boolean,
renderedIds: string[],
onCheckedClick: undefined | (() => ScriptField),
onChildClick: undefined | (() => ScriptField),
@@ -1193,19 +1194,19 @@ export class TreeView extends React.Component<TreeViewProps> {
hierarchyIndex?: number[],
renderCount?: number
) {
- const viewSpecScript = Cast(treeViewParent.viewSpecScript, ScriptField);
+ 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(treeViewParent.treeViewSortCriterion, TreeSort.None));
+ const docs = TreeView.sortDocs(childDocs, StrCast(treeView_Parent.treeView_SortCriterion, TreeSort.WhenAdded));
const rowWidth = () => panelWidth() - treeBulletWidth() * (treeView.props.NativeDimScaling?.() || 1);
- const treeViewRefs = new Map<Doc, TreeView | undefined>();
+ const treeView_Refs = 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(treeViewParent, dataDoc, child);
+ const pair = Doc.GetLayoutDataDocPair(treeView_Parent, dataDoc, child);
if (!pair.layout || pair.data instanceof Promise) {
return null;
}
@@ -1218,11 +1219,11 @@ export class TreeView extends React.Component<TreeViewProps> {
FormattedTextBox.SelectOnLoad = child[Id];
TreeView._editTitleOnLoad = editTitle ? { id: child[Id], parent } : undefined;
Doc.AddDocToList(newParent, fieldKey, child, addAfter, false);
- newParent.treeViewOpen = true;
+ newParent.treeView_Open = true;
Doc.SetContainer(child, treeView.Document);
}
};
- const indent = i === 0 ? undefined : (editTitle: boolean) => dentDoc(editTitle, docs[i - 1], undefined, treeViewRefs.get(docs[i - 1]));
+ const indent = i === 0 ? undefined : (editTitle: boolean) => dentDoc(editTitle, docs[i - 1], undefined, treeView_Refs.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);
@@ -1233,10 +1234,10 @@ export class TreeView extends React.Component<TreeViewProps> {
return (
<TreeView
key={child[Id]}
- ref={r => treeViewRefs.set(child, r ? r : undefined)}
+ ref={r => treeView_Refs.set(child, r ? r : undefined)}
document={pair.layout}
dataDoc={pair.data}
- treeViewParent={treeViewParent}
+ treeViewParent={treeView_Parent}
prevSibling={docs[i]}
// TODO: [AL] add these
hierarchyIndex={hierarchyIndex ? [...hierarchyIndex, i + 1] : undefined}
@@ -1248,7 +1249,7 @@ export class TreeView extends React.Component<TreeViewProps> {
onCheckedClick={onCheckedClick}
onChildClick={onChildClick}
renderDepth={renderDepth}
- removeDoc={StrCast(treeViewParent.treeViewFreezeChildren).includes('remove') ? undefined : remove}
+ removeDoc={StrCast(treeView_Parent.treeView_FreezeChildren).includes('remove') ? undefined : remove}
addDocument={addDocument}
styleProvider={styleProvider}
panelWidth={rowWidth}
@@ -1259,7 +1260,7 @@ export class TreeView extends React.Component<TreeViewProps> {
addDocTab={addDocTab}
ScreenToLocalTransform={screenToLocalXf}
isContentActive={isContentActive}
- treeViewHideHeaderFields={treeViewHideHeaderFields}
+ treeViewHideHeaderFields={treeView_HideHeaderFields}
renderedIds={renderedIds}
skipFields={skipFields}
firstLevel={firstLevel}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
index fb8ec93b2..89deb733a 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
@@ -21,6 +21,8 @@ export interface CollectionFreeFormLinkViewProps {
LinkDocs: Doc[];
}
+// props.screentolocatransform
+
@observer
export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFormLinkViewProps> {
@observable _opacity: number = 0;
@@ -59,7 +61,7 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
0
); // since the render code depends on querying the Dom through getBoudndingClientRect, we need to delay triggering render()
setTimeout(
- action(() => (!LinkDocs.length || !linkDoc.link_displayLine) && (this._opacity = 0.05)),
+ action(() => (!LinkDocs.length || !(linkDoc.link_displayLine || Doc.UserDoc().showLinkLines)) && (this._opacity = 0.05)),
750
); // this will unhighlight the link line.
const a = A.ContentDiv.getBoundingClientRect();
@@ -235,11 +237,12 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
bActive,
textX,
textY,
- // pt1,
- // pt2,
+ // fully connected
+ pt1,
+ pt2,
// this code adds space between links
- pt1: [pt1[0] + pt1normalized[0] * 13, pt1[1] + pt1normalized[1] * 13],
- pt2: [pt2[0] + pt2normalized[0] * 13, pt2[1] + pt2normalized[1] * 13],
+ // pt1: [pt1[0] + pt1normalized[0] * 13, pt1[1] + pt1normalized[1] * 13],
+ // pt2: [pt2[0] + pt2normalized[0] * 13, pt2[1] + pt2normalized[1] * 13],
};
}
@@ -269,7 +272,7 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
link.link_displayArrow = false;
}
- return link.opacity === 0 || !a.width || !b.width || (!link.link_displayLine && !aActive && !bActive) ? null : (
+ return link.opacity === 0 || !a.width || !b.width || (!(Doc.UserDoc().showLinkLines || link.link_displayLine) && !aActive && !bActive) ? null : (
<>
<defs>
<marker id={`${link[Id] + 'arrowhead'}`} markerWidth="4" markerHeight="3" refX="0" refY="1.5" orient="auto">
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
index c6419885b..e4ae251c8 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
@@ -153,7 +153,12 @@
overflow-y: auto;
overflow-x: hidden;
}
-
+.collectionFreeFormView-brushView {
+ pointer-events: none;
+ position: absolute;
+ transition: opacity 0.5s;
+ z-index: 1000;
+}
.collectionfreeformview-container {
// touch action none means that the browser will handle none of the touch actions. this allows us to implement our own actions.
touch-action: none;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index e1455525e..f5cc1eb53 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -237,7 +237,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
onChildClickHandler = () => this.props.childClickScript || ScriptCast(this.Document.onChildClick);
onChildDoubleClickHandler = () => this.props.childDoubleClickScript || ScriptCast(this.Document.onChildDoubleClick);
elementFunc = () => this._layoutElements;
- shrinkWrap = () => {
+ fitContentOnce = () => {
if (this.props.DocumentView?.().nativeWidth) return;
const vals = this.fitToContentVals;
this.layoutDoc._freeform_panX = vals.bounds.cx;
@@ -319,7 +319,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
// focus on the document in the collection
const didMove = !cantTransform && !anchor.z && (panX !== savedState.panX || panY !== savedState.panY || scale !== savedState.scale);
if (didMove) options.didMove = true;
- // glr: freeform transform speed can be set by adjusting presTransition field - needs a way of knowing when presentation is not active...
+ // glr: freeform transform speed can be set by adjusting presentation_transition field - needs a way of knowing when presentation is not active...
if (didMove) {
const focusTime = options?.instant ? 0 : options.zoomTime ?? 500;
(options.zoomScale ?? options.willZoomCentered) && scale && (this.Document[this.scaleFieldKey] = scale);
@@ -681,6 +681,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
case GestureUtils.Gestures.Stroke:
const points = ge.points;
const B = this.getTransform().transformBounds(ge.bounds.left, ge.bounds.top, ge.bounds.width, ge.bounds.height);
+ console.log(ge.bounds.left, ge.bounds.top, ge.bounds.width, ge.bounds.height);
const inkDoc = Docs.Create.InkDocument(
ActiveInkColor(),
ActiveInkWidth() * this.props.ScreenToLocalTransform().Scale,
@@ -1050,7 +1051,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
onPointerWheel = (e: React.WheelEvent): void => {
if (this.Document._isGroup || !this.isContentActive()) return; // group style collections neither pan nor zoom
PresBox.Instance?.pauseAutoPres();
- if (this.layoutDoc._Transform || this.props.Document.treeViewOutlineMode === TreeViewType.outline) return;
+ if (this.layoutDoc._Transform || this.props.Document.treeView_OutlineMode === TreeViewType.outline) return;
e.stopPropagation();
const docHeight = NumCast(this.rootDoc[Doc.LayoutFieldKey(this.rootDoc) + '_nativeHeight'], this.nativeHeight);
const scrollable = NumCast(this.layoutDoc[this.scaleFieldKey], 1) === 1 && docHeight > this.props.PanelHeight() / this.nativeDimScaling + 1e-4;
@@ -1318,7 +1319,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
layout_showTitle={this.props.childlayout_showTitle}
dontRegisterView={this.props.dontRenderDocuments || this.props.dontRegisterView}
pointerEvents={this.pointerEvents}
- //fitContentsToBox={this.props.fitContentsToBox || BoolCast(this.props.treeViewFreezeChildDimensions)} // bcz: check this
+ //fitContentsToBox={this.props.fitContentsToBox || BoolCast(this.props.treeView_FreezeChildDimensions)} // bcz: check this
/>
);
}
@@ -1537,7 +1538,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => {
// create an anchor that saves information about the current state of the freeform view (pan, zoom, view type)
- const anchor = Docs.Create.ConfigDocument({ title: 'ViewSpec - ' + StrCast(this.layoutDoc._type_collection), layout_unrendered: true, presTransition: 500, annotationOn: this.rootDoc });
+ const anchor = Docs.Create.ConfigDocument({ title: 'ViewSpec - ' + StrCast(this.layoutDoc._type_collection), layout_unrendered: true, presentation_transition: 500, annotationOn: this.rootDoc });
PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), pannable: !this.Document._isGroup, type_collection: true, filters: true } }, this.rootDoc);
if (addAsAnnotation) {
@@ -1594,6 +1595,15 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
elements => (this._layoutElements = elements || []),
{ fireImmediately: true, name: 'doLayout' }
);
+
+ this._disposers.fitContent = reaction(
+ () => this.rootDoc.fitContentOnce,
+ fitContentOnce => {
+ if (fitContentOnce) this.fitContentOnce();
+ this.rootDoc.fitContentOnce = undefined;
+ },
+ { fireImmediately: true, name: 'fitContent' }
+ );
})
);
}
@@ -1784,6 +1794,14 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
!Doc.noviceMode &&
optionItems.push({ description: (this._showAnimTimeline ? 'Close' : 'Open') + ' Animation Timeline', event: action(() => (this._showAnimTimeline = !this._showAnimTimeline)), icon: 'eye' });
this.props.renderDepth && optionItems.push({ description: 'Use Background Color as Default', event: () => (Cast(Doc.UserDoc().emptyCollection, Doc, null)._backgroundColor = StrCast(this.layoutDoc._backgroundColor)), icon: 'palette' });
+ this.props.renderDepth &&
+ optionItems.push({
+ description: 'Fit Content Once',
+ event: () => {
+ this.fitContentOnce();
+ },
+ icon: 'object-group',
+ });
if (!Doc.noviceMode) {
optionItems.push({ description: (!Doc.NativeWidth(this.layoutDoc) || !Doc.NativeHeight(this.layoutDoc) ? 'Freeze' : 'Unfreeze') + ' Aspect', event: this.toggleNativeDimensions, icon: 'snowflake' });
}
@@ -1866,6 +1884,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
showPresPaths = () => (CollectionFreeFormView.ShowPresPaths ? PresBox.Instance.getPaths(this.rootDoc) : null);
+ brushedView = () => this._brushedView;
@computed get marqueeView() {
TraceMobx();
return (
@@ -1908,13 +1927,13 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
</div>
) : null}
<CollectionFreeFormViewPannableContents
- brushView={this._brushedView}
+ brushedView={this.brushedView}
isAnnotationOverlay={this.isAnnotationOverlay}
isAnnotationOverlayScrollable={this.props.isAnnotationOverlayScrollable}
transform={this.contentTransform}
zoomScaling={this.zoomScaling}
presPaths={this.showPresPaths}
- presPinView={BoolCast(this.Document.presPinView)}
+ presPinView={BoolCast(this.Document.config_pinView)}
transition={this._panZoomTransition ? `transform ${this._panZoomTransition}ms` : Cast(this.layoutDoc._viewTransition, 'string', Cast(this.props.DocumentView?.()?.rootDoc._viewTransition, 'string', null))}
viewDefDivClick={this.props.viewDefDivClick}>
{this.children}
@@ -1945,19 +1964,19 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
};
@action
- brushView = (viewport: { width: number; height: number; panX: number; panY: number }) => {
- this._brushedView = { ...viewport, panX: viewport.panX - viewport.width / 2, panY: viewport.panY - viewport.height / 2, opacity: 1 };
+ brushView = (viewport: { width: number; height: number; panX: number; panY: number }, transTime: number) => {
this._brushtimer1 && clearTimeout(this._brushtimer1);
this._brushtimer && clearTimeout(this._brushtimer);
+ this._brushedView = { width: 0, height: 0, panX: 0, panY: 0, opacity: 0 };
this._brushtimer1 = setTimeout(
action(() => {
- this._brushedView.opacity = 0;
+ this._brushedView = { ...viewport, panX: viewport.panX - viewport.width / 2, panY: viewport.panY - viewport.height / 2, opacity: 1 };
this._brushtimer = setTimeout(
- action(() => (this._brushedView = { width: 0, height: 0, panX: 0, panY: 0, opacity: 0 })),
- 500
+ action(() => (this._brushedView.opacity = 0)),
+ 2500
);
}),
- 1000
+ transTime + 1
);
};
lightboxPanelWidth = () => Math.max(0, this.props.PanelWidth() - 30);
@@ -2084,7 +2103,7 @@ interface CollectionFreeFormViewPannableContentsProps {
presPinView?: boolean;
isAnnotationOverlay: boolean | undefined;
isAnnotationOverlayScrollable: boolean | undefined;
- brushView: { panX: number; panY: number; width: number; height: number; opacity: number };
+ brushedView: () => { panX: number; panY: number; width: number; height: number; opacity: number };
}
@observer
@@ -2156,6 +2175,7 @@ class CollectionFreeFormViewPannableContents extends React.Component<CollectionF
}
render() {
+ const brushedView = this.props.brushedView();
return (
<div
className={'collectionfreeformview' + (this.props.viewDefDivClick ? '-viewDef' : '-none')}
@@ -2173,21 +2193,18 @@ class CollectionFreeFormViewPannableContents extends React.Component<CollectionF
//willChange: "transform"
}}>
{this.props.children}
- {!this.props.brushView.width ? null : (
+ {
<div
className="collectionFreeFormView-brushView"
style={{
- zIndex: 1000,
- opacity: this.props.brushView.opacity,
- border: 'orange solid 2px',
- position: 'absolute',
- transform: `translate(${this.props.brushView.panX}px, ${this.props.brushView.panY}px)`,
- width: this.props.brushView.width,
- height: this.props.brushView.height,
- transition: 'opacity 2s',
+ opacity: brushedView.opacity,
+ transform: `translate(${brushedView.panX}px, ${brushedView.panY}px)`,
+ width: brushedView.width,
+ height: brushedView.height,
+ border: `orange solid ${brushedView.width * 0.005}px`,
}}
/>
- )}
+ }
{this.presPaths}
</div>
);
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 7c53bfdbe..1c3da1dc5 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -170,7 +170,15 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
TreeView._editTitleOnLoad = { id: slide[Id], parent: undefined };
this.props.addDocument?.(slide);
e.stopPropagation();
- }*/ else if (!e.ctrlKey && !e.metaKey && SelectionManager.Views().length < 2) {
+ }*/ else if (e.key === 'p' && e.ctrlKey) {
+ e.preventDefault();
+ (async () => {
+ const text: string = await navigator.clipboard.readText();
+ const ns = text.split('\n').filter(t => t.trim() !== '\r' && t.trim() !== '');
+ this.pasteTable(ns, x, y);
+ })();
+ e.stopPropagation();
+ } else if (!e.ctrlKey && !e.metaKey && SelectionManager.Views().length < 2) {
FormattedTextBox.SelectOnLoadChar = Doc.UserDoc().defaultTextLayout && !this.props.childLayoutString ? e.key : '';
FormattedTextBox.LiveTextUndo = UndoManager.StartBatch('type new note');
this.props.addLiveTextDocument(DocUtils.GetNewTextDoc('-typed text-', x, y, 200, 100, this.props.xPadding === 0));
@@ -185,44 +193,26 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
// any row that has only one column is a section header-- this header is then added as a column to subsequent rows until the next header
// assumes each cell is a string or a number
pasteTable(ns: string[], x: number, y: number) {
- while (ns.length > 0 && ns[0].split('\t').length < 2) {
- ns.splice(0, 1);
- }
- if (ns.length > 0) {
- const columns = ns[0].split('\t');
- const docList: Doc[] = [];
- let groupAttr: string | number = '';
- const rowProto = new Doc();
- rowProto.title = rowProto.Id;
- rowProto._width = 200;
- rowProto.isDataDoc = true;
- for (let i = 1; i < ns.length - 1; i++) {
- const values = ns[i].split('\t');
- if (values.length === 1 && columns.length > 1) {
- groupAttr = values[0];
- continue;
- }
- const docDataProto = Doc.MakeDelegate(rowProto);
- docDataProto.isDataDoc = true;
- columns.forEach((col, i) => (docDataProto[columns[i]] = values.length > i ? (values[i].indexOf(Number(values[i]).toString()) !== -1 ? Number(values[i]) : values[i]) : undefined));
- if (groupAttr) {
- docDataProto._group = groupAttr;
- }
- docDataProto.title = i.toString();
- const doc = Doc.MakeDelegate(docDataProto);
- doc._width = 200;
- docList.push(doc);
+ let csvRows = [];
+ const headers = ns[0].split('\t');
+ csvRows.push(headers.join(','));
+ ns[0] = '';
+ const eachCell = ns.join('\t').split('\t')
+ let eachRow = []
+ for (let i=1; i<eachCell.length; i++){
+ eachRow.push(eachCell[i].replace(/\,/g, ''));
+ if (i % headers.length == 0){
+ csvRows.push(eachRow)
+ eachRow = [];
}
- const newCol = Docs.Create.SchemaDocument([...(groupAttr ? [new SchemaHeaderField('_group', '#f1efeb')] : []), ...columns.filter(c => c).map(c => new SchemaHeaderField(c, '#f1efeb'))], docList, {
- x: x,
- y: y,
- title: 'droppedTable',
- _width: 300,
- _height: 100,
- });
-
- this.props.addDocument?.(newCol);
}
+
+ const blob = new Blob([csvRows.join('\n')], {type: 'text/csv'})
+ const options = { x: x, y: y, title: 'droppedTable', _width: 300, _height: 100, type:'text/csv'}
+ const file = new File([blob], 'droppedTable', options);
+ const loading = Docs.Create.LoadingDocument(file, options);
+ DocUtils.uploadFileToDoc(file, {}, loading);
+ this.props.addDocument?.(loading);
}
@action
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.scss b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.scss
index f87a06033..cb0d5e03f 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.scss
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.scss
@@ -9,6 +9,12 @@
flex-direction: column;
width: 100%;
align-items: center;
+ position: relative;
+ > .iconButton-container {
+ top: 0;
+ left: 0;
+ position: absolute;
+ }
.contentFittingDocumentView {
width: unset;
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
index 10532b9d9..80da4e1a2 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
@@ -1,3 +1,5 @@
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { Button } from 'browndash-components';
import { action, computed } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
@@ -6,7 +8,7 @@ import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types
import { returnFalse } from '../../../../Utils';
import { DragManager, dropActionType } from '../../../util/DragManager';
import { Transform } from '../../../util/Transform';
-import { undoBatch } from '../../../util/UndoManager';
+import { undoable, undoBatch } from '../../../util/UndoManager';
import { DocumentView } from '../../nodes/DocumentView';
import { CollectionSubView } from '../CollectionSubView';
import './CollectionMulticolumnView.scss';
@@ -301,6 +303,9 @@ export class CollectionMulticolumnView extends CollectionSubView() {
collector.push(
<div className="document-wrapper" key={'wrapper' + i} style={{ width: width() }}>
{this.getDisplayDoc(layout, dxf, docwidth, docheight, shouldNotScale)}
+ <Button icon={<FontAwesomeIcon icon={'times'} size={'lg'} />} onClick={undoable(e => {
+ this.props.removeDocument?.(layout);
+ }, "close doc")} color={StrCast(Doc.UserDoc().userColor)} />
<WidthLabel layout={layout} collectionDoc={Document} />
</div>,
<ResizeBar