aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/collections')
-rw-r--r--src/client/views/collections/CollectionCarousel3DView.scss14
-rw-r--r--src/client/views/collections/CollectionCarousel3DView.tsx38
-rw-r--r--src/client/views/collections/CollectionCarouselView.tsx23
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx96
-rw-r--r--src/client/views/collections/CollectionMasonryViewFieldRow.tsx49
-rw-r--r--src/client/views/collections/CollectionMenu.tsx110
-rw-r--r--src/client/views/collections/CollectionNoteTakingView.tsx187
-rw-r--r--src/client/views/collections/CollectionNoteTakingViewColumn.tsx28
-rw-r--r--src/client/views/collections/CollectionPileView.tsx38
-rw-r--r--src/client/views/collections/CollectionStackedTimeline.tsx56
-rw-r--r--src/client/views/collections/CollectionStackingView.scss6
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx107
-rw-r--r--src/client/views/collections/CollectionStackingViewFieldColumn.tsx34
-rw-r--r--src/client/views/collections/CollectionSubView.tsx65
-rw-r--r--src/client/views/collections/CollectionTimeView.tsx30
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx59
-rw-r--r--src/client/views/collections/CollectionView.tsx26
-rw-r--r--src/client/views/collections/TabDocView.tsx83
-rw-r--r--src/client/views/collections/TreeView.tsx117
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx11
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx67
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx309
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx69
-rw-r--r--src/client/views/collections/collectionLinear/CollectionLinearView.tsx46
-rw-r--r--src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx4
-rw-r--r--src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx4
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaView.scss6
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaView.tsx163
-rw-r--r--src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx6
-rw-r--r--src/client/views/collections/collectionSchema/SchemaRowBox.tsx30
-rw-r--r--src/client/views/collections/collectionSchema/SchemaTableCell.tsx109
31 files changed, 1030 insertions, 960 deletions
diff --git a/src/client/views/collections/CollectionCarousel3DView.scss b/src/client/views/collections/CollectionCarousel3DView.scss
index 5c8b491eb..6bd1d9f5f 100644
--- a/src/client/views/collections/CollectionCarousel3DView.scss
+++ b/src/client/views/collections/CollectionCarousel3DView.scss
@@ -1,3 +1,4 @@
+@import '../global/globalCssVariables';
.collectionCarousel3DView-outer {
height: 100%;
position: relative;
@@ -7,8 +8,8 @@
.carousel-wrapper {
display: flex;
position: absolute;
- top: 15%;
- height: 60%;
+ top: $CAROUSEL3D_TOP * 1%;
+ height: ($CAROUSEL3D_SIDE_SCALE * 100) * 1%;
align-items: center;
transition: transform 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955);
@@ -17,10 +18,17 @@
flex: 1;
transition: opacity 0.3s linear, transform 0.5s cubic-bezier(0.455, 0.03, 0.515, 0.955);
pointer-events: none;
+ opacity: 0.5;
+ z-index: 1;
+ transform: scale($CAROUSEL3D_SIDE_SCALE);
+ user-select: none;
}
.collectionCarousel3DView-item-active {
pointer-events: unset;
+ opacity: 1;
+ z-index: 2;
+ transform: scale($CAROUSEL3D_CENTER_SCALE);
}
}
@@ -105,4 +113,4 @@
.carousel3DView-back-scroll:hover,
.carousel3DView-fwd-scroll:hover {
background: lightgray;
-} \ No newline at end of file
+}
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index a266c9207..d94e552b4 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -7,6 +7,8 @@ import { Id } from '../../../fields/FieldSymbols';
import { NumCast, ScriptCast, StrCast } from '../../../fields/Types';
import { returnFalse, returnZero, Utils } from '../../../Utils';
import { DragManager } from '../../util/DragManager';
+import { SelectionManager } from '../../util/SelectionManager';
+import { CAROUSEL3D_CENTER_SCALE, CAROUSEL3D_SIDE_SCALE, CAROUSEL3D_TOP } from '../global/globalCssVariables.scss';
import { DocumentView } from '../nodes/DocumentView';
import { StyleProp } from '../StyleProvider';
import './CollectionCarousel3DView.scss';
@@ -32,27 +34,34 @@ export class CollectionCarousel3DView extends CollectionSubView() {
}
};
+ centerScale = Number(CAROUSEL3D_CENTER_SCALE);
panelWidth = () => this.props.PanelWidth() / 3;
- panelHeight = () => this.props.PanelHeight() * 0.6;
+ panelHeight = () => this.props.PanelHeight() * Number(CAROUSEL3D_SIDE_SCALE);
onChildDoubleClick = () => ScriptCast(this.layoutDoc.onChildDoubleClick);
isContentActive = () => this.props.isSelected() || this.props.isContentActive() || this.props.isAnyChildContentActive();
isChildContentActive = () => (this.isContentActive() ? true : false);
+ childScreenToLocal = () =>
+ this.props // document's left is the panel shifted by the doc's index * panelWidth/#docs. But it scales by centerScale around its center, so it's left moves left by the distance of the left from the center (panelwidth/2) * the scale delta (centerScale-1)
+ .ScreenToLocalTransform() // the top behaves the same way ecept it's shifted by the 'top' amount specified for the panel in css and then by the scale factor.
+ .translate(-this.panelWidth() + ((this.centerScale - 1) * this.panelWidth()) / 2, -((Number(CAROUSEL3D_TOP) / 100) * this.props.PanelHeight()) + ((this.centerScale - 1) * this.panelHeight()) / 2)
+ .scale(1 / this.centerScale);
@computed get content() {
- const currentIndex = NumCast(this.layoutDoc._itemIndex);
+ const currentIndex = NumCast(this.layoutDoc._carousel_index);
const displayDoc = (childPair: { layout: Doc; data: Doc }) => {
return (
<DocumentView
{...this.props}
NativeWidth={returnZero}
NativeHeight={returnZero}
- suppressSetHeight={true}
+ //suppressSetHeight={true}
onDoubleClick={this.onChildDoubleClick}
renderDepth={this.props.renderDepth + 1}
LayoutTemplate={this.props.childLayoutTemplate}
LayoutTemplateString={this.props.childLayoutString}
Document={childPair.layout}
DataDoc={childPair.data}
+ ScreenToLocalTransform={this.childScreenToLocal}
isContentActive={this.isChildContentActive}
isDocumentActive={this.props.childDocumentsActive?.() || this.Document._childDocumentsActive ? this.props.isDocumentActive : this.isContentActive}
PanelWidth={this.panelWidth}
@@ -64,10 +73,7 @@ export class CollectionCarousel3DView extends CollectionSubView() {
return this.childLayoutPairs.map((childPair, index) => {
return (
- <div
- key={childPair.layout[Id]}
- className={`collectionCarousel3DView-item${index === currentIndex ? '-active' : ''} ${index}`}
- style={index === currentIndex ? { opacity: '1', transform: 'scale(1.3)', width: this.panelWidth() } : { opacity: '0.5', transform: 'scale(0.6)', userSelect: 'none', width: this.panelWidth() }}>
+ <div key={childPair.layout[Id]} className={`collectionCarousel3DView-item${index === currentIndex ? '-active' : ''} ${index}`} style={{ width: this.panelWidth() }}>
{displayDoc(childPair)}
</div>
);
@@ -75,7 +81,8 @@ export class CollectionCarousel3DView extends CollectionSubView() {
}
changeSlide = (direction: number) => {
- this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) + direction + this.childLayoutPairs.length) % this.childLayoutPairs.length;
+ SelectionManager.DeselectAll();
+ this.layoutDoc._carousel_index = (NumCast(this.layoutDoc._carousel_index) + direction + this.childLayoutPairs.length) % this.childLayoutPairs.length;
};
onArrowClick = (e: React.MouseEvent, direction: number) => {
@@ -114,10 +121,10 @@ export class CollectionCarousel3DView extends CollectionSubView() {
return (
<div className="arrow-buttons">
<div key="back" className="carousel3DView-back" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }} onClick={e => this.onArrowClick(e, -1)}>
- <FontAwesomeIcon icon={'angle-left'} size={'2x'} />
+ <FontAwesomeIcon icon="angle-left" size={'2x'} />
</div>
<div key="fwd" className="carousel3DView-fwd" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }} onClick={e => this.onArrowClick(e, 1)}>
- <FontAwesomeIcon icon={'angle-right'} size={'2x'} />
+ <FontAwesomeIcon icon="angle-right" size={'2x'} />
</div>
{this.autoScrollButton}
</div>
@@ -139,13 +146,14 @@ export class CollectionCarousel3DView extends CollectionSubView() {
}
@computed get dots() {
- return this.childLayoutPairs.map((_child, index) => <div key={Utils.GenerateGuid()} className={`dot${index === NumCast(this.layoutDoc._itemIndex) ? '-active' : ''}`} onClick={() => (this.layoutDoc._itemIndex = index)} />);
+ return this.childLayoutPairs.map((_child, index) => <div key={Utils.GenerateGuid()} className={`dot${index === NumCast(this.layoutDoc._carousel_index) ? '-active' : ''}`} onClick={() => (this.layoutDoc._carousel_index = index)} />);
+ }
+ @computed get translateX() {
+ const index = NumCast(this.layoutDoc._carousel_index);
+ return this.panelWidth() * (1 - index);
}
render() {
- const index = NumCast(this.layoutDoc._itemIndex);
- const translateX = this.panelWidth() * (1 - index);
-
return (
<div
className="collectionCarousel3DView-outer"
@@ -154,7 +162,7 @@ export class CollectionCarousel3DView extends CollectionSubView() {
background: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor),
color: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Color),
}}>
- <div className="carousel-wrapper" style={{ transform: `translateX(${translateX}px)` }}>
+ <div className="carousel-wrapper" style={{ transform: `translateX(${this.translateX}px)` }}>
{this.content}
</div>
{this.props.Document._chromeHidden ? null : this.buttons}
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index 0e4556eb4..0eb61a0b2 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -4,7 +4,7 @@ import { observer } from 'mobx-react';
import * as React from 'react';
import { Doc, Opt } from '../../../fields/Doc';
import { NumCast, ScriptCast, StrCast } from '../../../fields/Types';
-import { emptyFunction, returnFalse, returnZero } from '../../../Utils';
+import { returnFalse, returnZero, StopEvent } from '../../../Utils';
import { DragManager } from '../../util/DragManager';
import { DocumentView, DocumentViewProps } from '../nodes/DocumentView';
import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
@@ -30,27 +30,27 @@ export class CollectionCarouselView extends CollectionSubView() {
advance = (e: React.MouseEvent) => {
e.stopPropagation();
- this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) + 1) % this.childLayoutPairs.length;
+ this.layoutDoc._carousel_index = (NumCast(this.layoutDoc._carousel_index) + 1) % this.childLayoutPairs.length;
};
goback = (e: React.MouseEvent) => {
e.stopPropagation();
- this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
+ this.layoutDoc._carousel_index = (NumCast(this.layoutDoc._carousel_index) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
};
captionStyleProvider = (doc: Doc | undefined, captionProps: Opt<DocumentViewProps>, property: string): any => {
// first look for properties on the document in the carousel, then fallback to properties on the container
const childValue = doc?.['caption-' + property] ? this.props.styleProvider?.(doc, captionProps, property) : undefined;
return childValue ?? this.props.styleProvider?.(this.layoutDoc, captionProps, property);
};
- panelHeight = () => this.props.PanelHeight() - (StrCast(this.layoutDoc._showCaption) ? 50 : 0);
+ panelHeight = () => this.props.PanelHeight() - (StrCast(this.layoutDoc._layout_showCaption) ? 50 : 0);
onContentDoubleClick = () => ScriptCast(this.layoutDoc.onChildDoubleClick);
onContentClick = () => ScriptCast(this.layoutDoc.onChildClick);
@computed get content() {
- const index = NumCast(this.layoutDoc._itemIndex);
+ const index = NumCast(this.layoutDoc._carousel_index);
const curDoc = this.childLayoutPairs?.[index];
const captionProps = { ...this.props, fieldKey: 'caption', setHeight: undefined };
- const marginX = NumCast(this.layoutDoc['caption-xMargin']);
- const marginY = NumCast(this.layoutDoc['caption-yMargin']);
- const showCaptions = StrCast(this.layoutDoc._showCaption);
+ const marginX = NumCast(this.layoutDoc['caption_xMargin']);
+ const marginY = NumCast(this.layoutDoc['caption_yMargin']);
+ const show_captions = StrCast(this.layoutDoc._layout_showCaption);
return !(curDoc?.layout instanceof Doc) ? null : (
<>
<div className="collectionCarouselView-image" key="image">
@@ -60,7 +60,7 @@ export class CollectionCarouselView extends CollectionSubView() {
NativeHeight={returnZero}
onDoubleClick={this.onContentDoubleClick}
onClick={this.onContentClick}
- hideCaptions={showCaptions ? true : false}
+ hideCaptions={show_captions ? true : false}
renderDepth={this.props.renderDepth + 1}
LayoutTemplate={this.props.childLayoutTemplate}
LayoutTemplateString={this.props.childLayoutString}
@@ -73,14 +73,15 @@ export class CollectionCarouselView extends CollectionSubView() {
<div
className="collectionCarouselView-caption"
key="caption"
+ onWheel={StopEvent}
style={{
- display: showCaptions ? undefined : 'none',
+ display: show_captions ? undefined : 'none',
borderRadius: this.props.styleProvider?.(this.layoutDoc, captionProps, StyleProp.BorderRounding),
marginRight: marginX,
marginLeft: marginX,
width: `calc(100% - ${marginX * 2}px)`,
}}>
- <FormattedTextBox key={index} {...captionProps} fieldKey={showCaptions} styleProvider={this.captionStyleProvider} Document={curDoc.layout} DataDoc={undefined} />
+ <FormattedTextBox key={index} {...captionProps} allowScroll={true} fieldKey={show_captions} styleProvider={this.captionStyleProvider} Document={curDoc.layout} DataDoc={undefined} />
</div>
</>
);
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index bb1f788d4..e9cc2c894 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -6,7 +6,7 @@ import { Doc, DocListCast, Opt } from '../../../fields/Doc';
import { Id } from '../../../fields/FieldSymbols';
import { InkTool } from '../../../fields/InkField';
import { List } from '../../../fields/List';
-import { Cast, ImageCast, NumCast, StrCast } from '../../../fields/Types';
+import { ImageCast, NumCast, StrCast } from '../../../fields/Types';
import { ImageField } from '../../../fields/URLField';
import { inheritParentAcls } from '../../../fields/util';
import { emptyFunction, incrementTitleCopy } from '../../../Utils';
@@ -20,14 +20,15 @@ import { SelectionManager } from '../../util/SelectionManager';
import { undoBatch, UndoManager } from '../../util/UndoManager';
import { DashboardView } from '../DashboardView';
import { LightboxView } from '../LightboxView';
+import { OpenWhere, OpenWhereMod } from '../nodes/DocumentView';
+import { OverlayView } from '../OverlayView';
+import { ScriptingRepl } from '../ScriptingRepl';
+import { UndoStack } from '../UndoStack';
import './CollectionDockingView.scss';
import { CollectionFreeFormView } from './collectionFreeForm';
import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
import { TabDocView } from './TabDocView';
import React = require('react');
-import { OpenWhere, OpenWhereMod } from '../nodes/DocumentView';
-import { OverlayView } from '../OverlayView';
-import { ScriptingRepl } from '../ScriptingRepl';
const _global = (window /* browser */ || global) /* node */ as any;
@observer
@@ -85,6 +86,7 @@ export class CollectionDockingView extends CollectionSubView() {
tabItemDropped = () => DragManager.CompleteWindowDrag?.(false);
tabDragStart = (proxy: any, finishDrag?: (aborted: boolean) => void) => {
+ this._flush = this._flush ?? UndoManager.StartBatch('tab move');
const dashDoc = proxy?._contentItem?.tab?.DashDoc as Doc;
dashDoc && (DragManager.DocDragData = new DragManager.DocumentDragData([proxy._contentItem.tab.DashDoc]));
DragManager.CompleteWindowDrag = (aborted: boolean) => {
@@ -92,12 +94,12 @@ export class CollectionDockingView extends CollectionSubView() {
proxy._dragListener.AbortDrag();
if (this._flush) {
this._flush.cancel(); // cancel the undo change being logged
- this._flush = undefined;
this.setupGoldenLayout(); // restore golden layout to where it was before the drag (this is a no-op when using StartOtherDrag because the proxy dragged item was never in the golden layout)
}
DragManager.CompleteWindowDrag = undefined;
}
finishDrag?.(aborted);
+ setTimeout(this.endUndoBatch, 100);
};
};
@undoBatch
@@ -127,12 +129,12 @@ export class CollectionDockingView extends CollectionSubView() {
SelectionManager.DeselectAll();
const instance = CollectionDockingView.Instance;
if (instance) {
- if (doc._viewType === CollectionViewType.Docking && doc.layoutKey === 'layout') {
+ if (doc._type_collection === CollectionViewType.Docking && doc.layout_fieldKey === 'layout') {
return DashboardView.openDashboard(doc);
}
const newItemStackConfig = {
type: 'stack',
- content: [CollectionDockingView.makeDocumentConfig(Doc.MakeAlias(doc))],
+ content: [CollectionDockingView.makeDocumentConfig(Doc.MakeEmbedding(doc))],
};
const docconfig = instance._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout);
instance._goldenLayout.root.contentItems[0].addChild(docconfig);
@@ -180,10 +182,9 @@ export class CollectionDockingView extends CollectionSubView() {
//
// Creates a split on any side of the docking view based on the passed input pullSide and then adds the Document to the requested side
//
- @undoBatch
@action
public static AddSplit(document: Doc, pullSide: OpenWhereMod, stack?: any, panelName?: string, keyValue?: boolean) {
- if (document?._viewType === CollectionViewType.Docking) return DashboardView.openDashboard(document);
+ if (document?._type_collection === CollectionViewType.Docking) return DashboardView.openDashboard(document);
if (!CollectionDockingView.Instance) return false;
const tab = Array.from(CollectionDockingView.Instance.tabMap).find(tab => tab.DashDoc === document && !keyValue);
if (tab) {
@@ -195,6 +196,8 @@ export class CollectionDockingView extends CollectionSubView() {
if (!instance) return false;
const docContentConfig = CollectionDockingView.makeDocumentConfig(document, panelName, undefined, keyValue);
+ CollectionDockingView.Instance._flush = CollectionDockingView.Instance._flush ?? UndoManager.StartBatch('Add Split');
+ setTimeout(CollectionDockingView.Instance.endUndoBatch, 100);
if (!pullSide && stack) {
stack.addChild(docContentConfig, undefined);
setTimeout(() => stack.setActiveContentItem(stack.contentItems[stack.contentItems.length - 1]));
@@ -370,16 +373,30 @@ export class CollectionDockingView extends CollectionSubView() {
!LightboxView.LightboxDoc && cur && this._goldenLayout?.updateSize(cur.getBoundingClientRect().width, cur.getBoundingClientRect().height);
};
+ endUndoBatch = () => {
+ const json = JSON.stringify(this._goldenLayout.toConfig());
+ const matches = json.match(/\"documentId\":\"[a-z0-9-]+\"/g);
+ const docids = matches?.map(m => m.replace('"documentId":"', '').replace('"', ''));
+ const docs = !docids
+ ? []
+ : docids
+ .map(id => DocServer.GetCachedRefField(id))
+ .filter(f => f)
+ .map(f => f as Doc);
+ const changesMade = this.props.Document.dockingConfig !== json;
+ if (changesMade) {
+ this.props.Document.dockingConfig = json;
+ this.props.Document.data = new List<Doc>(docs);
+ }
+ this._flush?.end();
+ this._flush = undefined;
+ };
+
@action
onPointerUp = (e: MouseEvent): void => {
window.removeEventListener('pointerup', this.onPointerUp);
- const flush = this._flush;
- this._flush = undefined;
- if (flush) {
- DragManager.CompleteWindowDrag = undefined;
- if (!this.stateChanged()) flush.cancel();
- else flush.end();
- }
+ DragManager.CompleteWindowDrag = undefined;
+ setTimeout(this.endUndoBatch, 100);
};
@action
@@ -393,10 +410,8 @@ export class CollectionDockingView extends CollectionSubView() {
window.addEventListener('mouseup', this.onPointerUp);
if (!htmlTarget.closest('*.lm_content') && (htmlTarget.closest('*.lm_tab') || htmlTarget.closest('*.lm_stack'))) {
const className = typeof htmlTarget.className === 'string' ? htmlTarget.className : '';
- if (!className.includes('lm_close') && !className.includes('lm_maximise')) {
- this._flush = UndoManager.StartBatch('golden layout edit');
- DocServer.UPDATE_SERVER_CACHE();
- }
+ if (className.includes('lm_maximise')) this._flush = UndoManager.StartBatch('tab maximize');
+ else if (!className.includes('lm_close')) DocServer.UPDATE_SERVER_CACHE();
}
}
if (!InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE) && !InteractionUtils.IsType(e, InteractionUtils.PENTYPE) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) {
@@ -411,8 +426,8 @@ export class CollectionDockingView extends CollectionSubView() {
const _height = Number(getComputedStyle(content).height.replace('px', ''));
return CollectionFreeFormView.UpdateIcon(this.layoutDoc[Id] + '-icon' + new Date().getTime(), content, _width, _height, _width, _height, 0, 1, true, this.layoutDoc[Id] + '-icon', (iconFile, _nativeWidth, _nativeHeight) => {
const proto = this.dataDoc; // Cast(img.proto, Doc, null)!;
- proto['thumb-nativeWidth'] = _width;
- proto['thumb-nativeHeight'] = _height;
+ proto['thumb_nativeWidth'] = _width;
+ proto['thumb_nativeHeight'] = _height;
proto.thumb = new ImageField(iconFile);
});
}
@@ -434,11 +449,11 @@ export class CollectionDockingView extends CollectionSubView() {
.map(f => f as Doc);
const newtabs = origtabs.map(origtab => {
const origtabdocs = DocListCast(origtab.data);
- const newtab = origtabdocs.length ? Doc.MakeCopy(origtab, true, undefined, true) : Doc.MakeAlias(origtab);
- const newtabdocs = origtabdocs.map(origtabdoc => Doc.MakeAlias(origtabdoc));
+ const newtab = origtabdocs.length ? Doc.MakeCopy(origtab, true, undefined, true) : Doc.MakeEmbedding(origtab);
+ const newtabdocs = origtabdocs.map(origtabdoc => Doc.MakeEmbedding(origtabdoc));
if (newtabdocs.length) {
Doc.GetProto(newtab).data = new List<Doc>(newtabdocs);
- newtabdocs.forEach(ntab => (ntab.context = newtab));
+ newtabdocs.forEach(ntab => (ntab.embedContainer = newtab));
}
json = json.replace(origtab[Id], newtab[Id]);
return newtab;
@@ -452,25 +467,12 @@ export class CollectionDockingView extends CollectionSubView() {
stateChanged = () => {
this._ignoreStateChange = JSON.stringify(this._goldenLayout.toConfig());
const json = JSON.stringify(this._goldenLayout.toConfig());
- const matches = json.match(/\"documentId\":\"[a-z0-9-]+\"/g);
- const docids = matches?.map(m => m.replace('"documentId":"', '').replace('"', ''));
- const docs = !docids
- ? []
- : docids
- .map(id => DocServer.GetCachedRefField(id))
- .filter(f => f)
- .map(f => f as Doc);
const changesMade = this.props.Document.dockingConfig !== json;
- if (changesMade && !this._flush) {
- UndoManager.RunInBatch(() => {
- this.props.Document.dockingConfig = json;
- this.props.Document.data = new List<Doc>(docs);
- }, 'state changed');
- }
return changesMade;
};
tabDestroyed = (tab: any) => {
+ this._flush = this._flush ?? UndoManager.StartBatch('tab movement');
if (tab.DashDoc && ![DocumentType.KVP, DocumentType.PRES].includes(tab.DashDoc?.type)) {
Doc.AddDocToList(Doc.MyHeaderBar, 'data', tab.DashDoc);
Doc.AddDocToList(Doc.MyRecentlyClosed, 'data', tab.DashDoc, undefined, true, true);
@@ -498,8 +500,8 @@ export class CollectionDockingView extends CollectionSubView() {
const docToAdd = Docs.Create.FreeformDocument([], {
_width: this.props.PanelWidth(),
_height: this.props.PanelHeight(),
- _backgroundGridShow: true,
- _fitWidth: true,
+ _freeform_backgroundGrid: true,
+ _layout_fitWidth: true,
title: `Untitled Tab ${NumCast(dashboard['pane-count'])}`,
});
this.props.Document.isShared && inheritParentAcls(this.props.Document, docToAdd);
@@ -541,8 +543,8 @@ export class CollectionDockingView extends CollectionSubView() {
const docToAdd = Docs.Create.FreeformDocument([], {
_width: this.props.PanelWidth(),
_height: this.props.PanelHeight(),
- _fitWidth: true,
- _backgroundGridShow: true,
+ _layout_fitWidth: true,
+ _freeform_backgroundGrid: true,
title: `Untitled Tab ${NumCast(dashboard['pane-count'])}`,
});
this.props.Document.isShared && inheritParentAcls(this.props.Document, docToAdd);
@@ -586,8 +588,12 @@ ScriptingGlobals.add(
case OpenWhere.addRight:
return CollectionDockingView.AddSplit(doc, OpenWhereMod.right);
case OpenWhere.overlay:
- if (doc === 'repl') OverlayView.Instance.addWindow(<ScriptingRepl />, { x: 300, y: 100, width: 200, height: 200, title: 'Scripting REPL' });
- else Doc.AddDocToList(Doc.MyOverlayDocs, undefined, doc);
+ // prettier-ignore
+ switch (doc) {
+ case '<ScriptingRepl />': return OverlayView.Instance.addWindow(<ScriptingRepl />, { x: 300, y: 100, width: 200, height: 200, title: 'Scripting REPL' });
+ case "<UndoStack>": return OverlayView.Instance.addWindow(<UndoStack />, { x: 300, y: 100, width: 200, height: 200, title: 'Scripting REPL' });
+ }
+ Doc.AddToMyOverlay(doc);
}
},
'opens up document in location specified',
diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
index befd89e41..64f9c6a87 100644
--- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
+++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
@@ -2,7 +2,8 @@ import React = require('react');
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
-import { DataSym, Doc, DocListCast } from '../../../fields/Doc';
+import { Doc, DocListCast } from '../../../fields/Doc';
+import { DocData } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
import { PastelSchemaPalette, SchemaHeaderField } from '../../../fields/SchemaHeaderField';
import { ScriptField } from '../../../fields/ScriptField';
@@ -44,7 +45,7 @@ interface CMVFieldRowProps {
@observer
export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowProps> {
@observable private _background = 'inherit';
- @observable private _createAliasSelected: boolean = false;
+ @observable private _createEmbeddingSelected: boolean = false;
@observable private heading: string = '';
@observable private color: string = '#f1efeb';
@observable private collapsed: boolean = false;
@@ -95,7 +96,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
@undoBatch
rowDrop = action((e: Event, de: DragManager.DropEvent) => {
- this._createAliasSelected = false;
+ this._createEmbeddingSelected = false;
if (de.complete.docDragData) {
this.props.parent.Document.dropConverter instanceof ScriptField && this.props.parent.Document.dropConverter.script.run({ dragData: de.complete.docDragData });
const key = this.props.pivotField;
@@ -117,12 +118,12 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
@action
headingChanged = (value: string, shiftDown?: boolean) => {
- this._createAliasSelected = false;
+ this._createEmbeddingSelected = false;
const key = this.props.pivotField;
const castedValue = this.getValue(value);
if (castedValue) {
- if (this.props.parent.columnHeaders) {
- if (this.props.parent.columnHeaders.map(i => i.heading).indexOf(castedValue.toString()) > -1) {
+ if (this.props.parent.colHeaderData) {
+ if (this.props.parent.colHeaderData.map(i => i.heading).indexOf(castedValue.toString()) > -1) {
return false;
}
}
@@ -135,7 +136,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
@action
changeColumnColor = (color: string) => {
- this._createAliasSelected = false;
+ this._createEmbeddingSelected = false;
this._color = color;
};
@@ -143,53 +144,53 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
@action
pointerLeaveRow = () => {
- this._createAliasSelected = false;
+ this._createEmbeddingSelected = false;
this._background = 'inherit';
};
@action
addDocument = (value: string, shiftDown?: boolean, forceEmptyNote?: boolean) => {
if (!value && !forceEmptyNote) return false;
- this._createAliasSelected = false;
+ this._createEmbeddingSelected = false;
const key = this.props.pivotField;
- const newDoc = Docs.Create.TextDocument('', { _autoHeight: true, _width: 200, _fitWidth: true, title: value });
+ const newDoc = Docs.Create.TextDocument('', { _layout_autoHeight: true, _width: 200, _layout_fitWidth: true, title: value });
const onLayoutDoc = this.onLayoutDoc(key);
FormattedTextBox.SelectOnLoad = newDoc[Id];
FormattedTextBox.SelectOnLoadChar = value;
- (onLayoutDoc ? newDoc : newDoc[DataSym])[key] = this.getValue(this.props.heading);
+ (onLayoutDoc ? newDoc : newDoc[DocData])[key] = this.getValue(this.props.heading);
const docs = this.props.parent.childDocList;
return docs ? (docs.splice(0, 0, newDoc) ? true : false) : this.props.parent.props.addDocument?.(newDoc) || false; // should really extend addDocument to specify insertion point (at beginning of list)
};
deleteRow = undoBatch(
action(() => {
- this._createAliasSelected = false;
+ this._createEmbeddingSelected = false;
const key = this.props.pivotField;
this.props.docList.forEach(d => Doc.SetInPlace(d, key, undefined, true));
- if (this.props.parent.columnHeaders && this.props.headingObject) {
- const index = this.props.parent.columnHeaders.indexOf(this.props.headingObject);
- this.props.parent.columnHeaders.splice(index, 1);
+ if (this.props.parent.colHeaderData && this.props.headingObject) {
+ const index = this.props.parent.colHeaderData.indexOf(this.props.headingObject);
+ this.props.parent.colHeaderData.splice(index, 1);
}
})
);
@action
collapseSection = (e: any) => {
- this._createAliasSelected = false;
+ this._createEmbeddingSelected = false;
this.toggleVisibility();
e.stopPropagation();
};
headerMove = (e: PointerEvent) => {
- const alias = Doc.MakeAlias(this.props.Document);
+ const embedding = Doc.MakeEmbedding(this.props.Document);
const key = this.props.pivotField;
let value = this.getValue(this.heading);
value = typeof value === 'string' ? `"${value}"` : value;
const script = `return doc.${key} === ${value}`;
const compiled = CompileScript(script, { params: { doc: Doc.name } });
if (compiled.compiled) {
- alias.viewSpecScript = new ScriptField(compiled);
- DragManager.StartDocumentDrag([this._headerRef.current!], new DragManager.DocumentDragData([alias]), e.clientX, e.clientY);
+ embedding.viewSpecScript = new ScriptField(compiled);
+ DragManager.StartDocumentDrag([this._headerRef.current!], new DragManager.DocumentDragData([embedding]), e.clientX, e.clientY);
}
return true;
};
@@ -198,7 +199,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
headerDown = (e: React.PointerEvent<HTMLDivElement>) => {
if (e.button === 0 && !e.ctrlKey) {
setupMoveUpEvents(this, e, this.headerMove, emptyFunction, e => !this.props.chromeHidden && this.collapseSection(e));
- this._createAliasSelected = false;
+ this._createEmbeddingSelected = false;
}
};
@@ -242,16 +243,16 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
);
};
- toggleAlias = action(() => (this._createAliasSelected = true));
+ toggleEmbedding = action(() => (this._createEmbeddingSelected = true));
toggleVisibility = () => (this._collapsed = !this.collapsed);
renderMenu = () => {
- const selected = this._createAliasSelected;
+ const selected = this._createEmbeddingSelected;
return (
<div className="collectionStackingView-optionPicker">
<div className="optionOptions">
- <div className={'optionPicker' + (selected === true ? ' active' : '')} onClick={this.toggleAlias}>
- Create Alias
+ <div className={'optionPicker' + (selected === true ? ' active' : '')} onClick={this.toggleEmbedding}>
+ Create Embedding
</div>
<div className={'optionPicker' + (selected === true ? ' active' : '')} onClick={this.deleteRow}>
Delete
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 2154016bd..fc3f713ce 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -14,7 +14,7 @@ import { ObjectField } from '../../../fields/ObjectField';
import { RichTextField } from '../../../fields/RichTextField';
import { listSpec } from '../../../fields/Schema';
import { ScriptField } from '../../../fields/ScriptField';
-import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types';
+import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../fields/Types';
import { GestureUtils } from '../../../pen-gestures/GestureUtils';
import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents, Utils } from '../../../Utils';
import { Docs } from '../../documents/Documents';
@@ -108,8 +108,8 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> {
<CollectionLinearView
Document={selDoc}
DataDoc={undefined}
- fieldKey={'data'}
- dropAction={'alias'}
+ fieldKey="data"
+ dropAction="embed"
setHeight={returnFalse}
styleProvider={DefaultStyleProvider}
rootSelected={returnTrue}
@@ -130,8 +130,8 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> {
renderDepth={0}
focus={emptyFunction}
whenChildContentsActiveChanged={emptyFunction}
- docFilters={returnEmptyFilter}
- docRangeFilters={returnEmptyFilter}
+ childFilters={returnEmptyFilter}
+ childFiltersByRanges={returnEmptyFilter}
searchFilterDocs={returnEmptyDoclist}
/>
</div>
@@ -172,7 +172,7 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> {
// [<CollectionViewBaseChrome key="chrome"
// docView={this.SelectedCollection}
// fieldKey={this.SelectedCollection.LayoutFieldKey}
- // type={StrCast(this.SelectedCollection?.props.Document._viewType, CollectionViewType.Invalid) as CollectionViewType} />,
+ // type={StrCast(this.SelectedCollection?.props.Document._type_collection, CollectionViewType.Invalid) as CollectionViewType} />,
// prop,
// /*button*/]);
}
@@ -246,47 +246,47 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
_viewCommand = {
params: ['target'],
title: 'bookmark view',
- script: "self.target._panX = self['target-panX']; self.target._panY = self['target-panY']; self.target._viewScale = self['target-viewScale']; gotoFrame(self.target, self['target-currentFrame']);",
+ script: "self.target._freeform_panX = self['target-freeform_panX']; self.target._freeform_panY = self['target-freeform_panY']; self.target._freeform_scale = self['target_freeform_scale']; gotoFrame(self.target, self['target-currentFrame']);",
immediate: undoBatch((source: Doc[]) => {
- this.target._panX = 0;
- this.target._panY = 0;
- this.target._viewScale = 1;
+ this.target._freeform_panX = 0;
+ this.target._freeform_panY = 0;
+ this.target._freeform_scale = 1;
this.target._currentFrame = this.target._currentFrame === undefined ? undefined : 0;
}),
initialize: (button: Doc) => {
- button['target-panX'] = this.target._panX;
- button['target-panY'] = this.target._panY;
- button['target-viewScale'] = this.target._viewScale;
+ button['target-panX'] = this.target._freeform_panX;
+ button['target-panY'] = this.target._freeform_panY;
+ button['target-_ayout_scale'] = this.target._freeform_scale;
button['target-currentFrame'] = this.target._currentFrame;
},
};
_clusterCommand = {
params: ['target'],
title: 'fit content',
- script: 'self.target._fitContentsToBox = !self.target._fitContentsToBox;',
- immediate: undoBatch((source: Doc[]) => (this.target._fitContentsToBox = !this.target._fitContentsToBox)),
+ script: 'self.target._freeform_fitContentsToBox = !self.target._freeform_fitContentsToBox;',
+ immediate: undoBatch((source: Doc[]) => (this.target._freeform_fitContentsToBox = !this.target._freeform_fitContentsToBox)),
initialize: emptyFunction,
};
_fitContentCommand = {
params: ['target'],
title: 'toggle clusters',
- script: 'self.target._useClusters = !self.target._useClusters;',
- immediate: undoBatch((source: Doc[]) => (this.target._useClusters = !this.target._useClusters)),
+ script: 'self.target._freeform_useClusters = !self.target._freeform_useClusters;',
+ immediate: undoBatch((source: Doc[]) => (this.target._freeform_useClusters = !this.target._freeform_useClusters)),
initialize: emptyFunction,
};
_saveFilterCommand = {
params: ['target'],
title: 'save filter',
- script: `self.target._docFilters = compareLists(self['target-docFilters'],self.target._docFilters) ? undefined : copyField(self['target-docFilters']);
+ script: `self.target._childFilters = compareLists(self['target-childFilters'],self.target._childFilters) ? undefined : copyField(self['target-childFilters']);
self.target._searchFilterDocs = compareLists(self['target-searchFilterDocs'],self.target._searchFilterDocs) ? undefined: copyField(self['target-searchFilterDocs']);`,
immediate: undoBatch((source: Doc[]) => {
- this.target._docFilters = undefined;
+ this.target._childFilters = undefined;
this.target._searchFilterDocs = undefined;
}),
initialize: (button: Doc) => {
const activeDash = Doc.ActiveDashboard;
if (activeDash) {
- button['target-docFilters'] = (Doc.MySearcher._docFilters || activeDash._docFilters) instanceof ObjectField ? ObjectField.MakeCopy((Doc.MySearcher._docFilters || activeDash._docFilters) as any as ObjectField) : undefined;
+ button['target-childFilters'] = (Doc.MySearcher._childFilters || activeDash._childFilters) instanceof ObjectField ? ObjectField.MakeCopy((Doc.MySearcher._childFilters || activeDash._childFilters) as any as ObjectField) : undefined;
button['target-searchFilterDocs'] = activeDash._searchFilterDocs instanceof ObjectField ? ObjectField.MakeCopy(activeDash._searchFilterDocs as any as ObjectField) : undefined;
}
},
@@ -347,9 +347,9 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
@undoBatch
viewChanged = (e: React.ChangeEvent) => {
- const target = this.document !== Doc.MyLeftSidebarPanel ? this.document : (this.document.proto as Doc);
+ const target = this.document !== Doc.MyLeftSidebarPanel ? this.document : DocCast(this.document.proto);
//@ts-ignore
- target._viewType = e.target.selectedOptions[0].value;
+ target._type_collection = e.target.selectedOptions[0].value;
};
commandChanged = (e: React.ChangeEvent) => {
@@ -440,8 +440,8 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
const c = {
params: ['target'],
title: vtype,
- script: `this.target._viewType = '${StrCast(this.props.type)}'`,
- immediate: (source: Doc[]) => (this.document._viewType = Doc.getDocTemplate(source?.[0])),
+ script: `this.target._type_collection = '${StrCast(this.props.type)}'`,
+ immediate: (source: Doc[]) => (this.document._type_collection = Doc.getDocTemplate(source?.[0])),
initialize: emptyFunction,
};
DragManager.StartButtonDrag([this._viewRef.current!], c.script, StrCast(c.title), { target: this.document }, c.params, c.initialize, e.clientX, e.clientY);
@@ -548,8 +548,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
@undoBatch
@action
startRecording = () => {
- const doc = Docs.Create.ScreenshotDocument({ title: 'screen recording', _fitWidth: true, _width: 400, _height: 200, mediaState: 'pendingRecording' });
- //Doc.AddDocToList(Doc.MyOverlayDocs, undefined, doc);
+ const doc = Docs.Create.ScreenshotDocument({ title: 'screen recording', _layout_fitWidth: true, _width: 400, _height: 200, mediaState: 'pendingRecording' });
CollectionDockingView.AddSplit(doc, OpenWhereMod.right);
};
@@ -568,29 +567,29 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
}
@undoBatch
- onAlias = () => {
+ onEmbed = () => {
if (this.selectedDoc && this.selectedDocumentView) {
// const copy = Doc.MakeCopy(this.selectedDocumentView.props.Document, true);
// copy.x = NumCast(this.selectedDoc.x) + NumCast(this.selectedDoc._width);
// copy.y = NumCast(this.selectedDoc.y) + 30;
// this.selectedDocumentView.props.addDocument?.(copy);
- const alias = Doc.MakeAlias(this.selectedDoc);
- alias.x = NumCast(this.selectedDoc.x) + NumCast(this.selectedDoc._width);
- alias.y = NumCast(this.selectedDoc.y) + 30;
- this.selectedDocumentView.props.addDocument?.(alias);
+ const embedding = Doc.MakeEmbedding(this.selectedDoc);
+ embedding.x = NumCast(this.selectedDoc.x) + NumCast(this.selectedDoc._width);
+ embedding.y = NumCast(this.selectedDoc.y) + 30;
+ this.selectedDocumentView.props.addDocument?.(embedding);
}
};
- onAliasButtonDown = (e: React.PointerEvent): void => {
- setupMoveUpEvents(this, e, this.onAliasButtonMoved, emptyFunction, emptyFunction);
+ onEmbedButtonDown = (e: React.PointerEvent): void => {
+ setupMoveUpEvents(this, e, this.onEmbedButtonMoved, emptyFunction, emptyFunction);
};
@undoBatch
- onAliasButtonMoved = (e: PointerEvent) => {
+ onEmbedButtonMoved = (e: PointerEvent) => {
const contentDiv = this.selectedDocumentView?.ContentDiv;
if (contentDiv && this.selectedDoc) {
const dragData = new DragManager.DocumentDragData([this.selectedDoc]);
const offset = [e.clientX - contentDiv.getBoundingClientRect().x, e.clientY - contentDiv.getBoundingClientRect().y];
- dragData.defaultDropAction = 'alias';
+ dragData.defaultDropAction = 'embed';
dragData.canEmbed = true;
DragManager.StartDocumentDrag([contentDiv], dragData, e.clientX, e.clientY, {
offsetX: offset[0],
@@ -603,11 +602,11 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
};
@computed
- get aliasButton() {
+ get embedButton() {
const targetDoc = this.selectedDoc;
return !targetDoc || targetDoc.type === DocumentType.PRES ? null : (
- <Tooltip title={<div className="dash-tooltip">{'Tap or Drag to create an alias'}</div>} placement="top">
- <button className="antimodeMenu-button" onPointerDown={this.onAliasButtonDown} onClick={this.onAlias} style={{ cursor: 'drag' }}>
+ <Tooltip title={<div className="dash-tooltip">{'Tap or Drag to create an embedding'}</div>} placement="top">
+ <button className="antimodeMenu-button" onPointerDown={this.onEmbedButtonDown} onClick={this.onEmbed} style={{ cursor: 'drag' }}>
<FontAwesomeIcon className="colMenu-icon" icon="copy" size="lg" />
</button>
</Tooltip>
@@ -639,8 +638,8 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
key="float"
style={{
backgroundColor: this.props.docView.layoutDoc.z ? '121212' : undefined,
- pointerEvents: this.props.docView.props.docViewPath().lastElement()?.rootDoc?._viewType !== CollectionViewType.Freeform ? 'none' : undefined,
- color: this.props.docView.props.docViewPath().lastElement()?.rootDoc?._viewType !== CollectionViewType.Freeform ? 'dimgrey' : undefined,
+ pointerEvents: this.props.docView.props.docViewPath().lastElement()?.rootDoc?._type_collection !== CollectionViewType.Freeform ? 'none' : undefined,
+ color: this.props.docView.props.docViewPath().lastElement()?.rootDoc?._type_collection !== CollectionViewType.Freeform ? 'dimgrey' : undefined,
}}
onClick={undoBatch(() => this.props.docView.props.CollectionFreeFormDocumentView?.().float())}>
<FontAwesomeIcon icon={['fab', 'buffer']} size={'lg'} />
@@ -657,7 +656,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
<div className="collectionViewBaseChrome">
{this.notACollection || this.props.type === CollectionViewType.Invalid ? null : this.viewModes}
<div className="collectionMenu-divider" key="divider1"></div>
- {this.aliasButton}
+ {this.embedButton}
{/* {this.pinButton} */}
{this.toggleOverlayButton}
<div className="collectionMenu-divider" key="divider2"></div>
@@ -691,7 +690,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionView
return this.props.docView.props.Document;
}
@computed get dataField() {
- return this.document[this.props.docView.LayoutFieldKey + (this.props.isOverlay ? '-annotations' : '')];
+ return this.document[this.props.docView.LayoutFieldKey + (this.props.isOverlay ? '_annotations' : '')];
}
@computed get childDocs() {
return DocListCast(this.dataField);
@@ -798,7 +797,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionView
if (doc.type === DocumentType.INK) {
switch (field) {
case 'width':
- doc.strokeWidth = Number(value);
+ doc.stroke_width = Number(value);
break;
case 'color':
doc.color = String(value);
@@ -807,7 +806,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionView
doc.fillColor = String(value);
break;
case 'dash':
- doc.strokeDash = value;
+ doc.stroke_dash = value;
}
}
})
@@ -1005,16 +1004,13 @@ export class CollectionStackingViewChrome extends React.Component<CollectionView
if (Doc.noviceMode) {
if (docs instanceof Doc) {
- const keys = Object.keys(docs).filter(key => key.indexOf('title') >= 0 || key.indexOf('author') >= 0 || key.indexOf('creationDate') >= 0 || key.indexOf('lastModified') >= 0 || (key[0].toUpperCase() === key[0] && key[0] !== '_'));
+ const keys = Object.keys(docs).filter(key => key.indexOf('title') >= 0 || key.indexOf('author') >= 0 || key.indexOf('author_date') >= 0 || key.indexOf('modificationDate') >= 0 || (key[0].toUpperCase() === key[0] && key[0] !== '_'));
return keys.filter(key => key.toLowerCase().indexOf(val) > -1);
- } else {
- const keys = new Set<string>();
- docs.forEach(doc => Doc.allKeys(doc).forEach(key => keys.add(key)));
- const noviceKeys = Array.from(keys).filter(
- key => key.indexOf('title') >= 0 || key.indexOf('author') >= 0 || key.indexOf('creationDate') >= 0 || key.indexOf('lastModified') >= 0 || (key[0]?.toUpperCase() === key[0] && key[0] !== '_')
- );
- return noviceKeys.filter(key => key.toLowerCase().indexOf(val) > -1);
}
+ const keys = new Set<string>();
+ docs.forEach(doc => Doc.allKeys(doc).forEach(key => keys.add(key)));
+ const noviceKeys = Array.from(keys).filter(key => key.indexOf('title') >= 0 || key.indexOf('author') >= 0 || key.indexOf('author_date') >= 0 || key.indexOf('modificationDate') >= 0 || (key[0]?.toUpperCase() === key[0] && key[0] !== '_'));
+ return noviceKeys.filter(key => key.toLowerCase().indexOf(val) > -1);
}
if (docs instanceof Doc) {
@@ -1125,13 +1121,13 @@ export class CollectionNoteTakingViewChrome extends React.Component<CollectionVi
if (Doc.UserDoc().noviceMode) {
if (docs instanceof Doc) {
- const keys = Object.keys(docs).filter(key => key.indexOf('title') >= 0 || key.indexOf('author') >= 0 || key.indexOf('creationDate') >= 0 || key.indexOf('lastModified') >= 0 || (key[0].toUpperCase() === key[0] && key[0] !== '_'));
+ const keys = Object.keys(docs).filter(key => key.indexOf('title') >= 0 || key.indexOf('author') >= 0 || key.indexOf('author_date') >= 0 || key.indexOf('modificationDate') >= 0 || (key[0].toUpperCase() === key[0] && key[0] !== '_'));
return keys.filter(key => key.toLowerCase().indexOf(val) > -1);
} else {
const keys = new Set<string>();
docs.forEach(doc => Doc.allKeys(doc).forEach(key => keys.add(key)));
const noviceKeys = Array.from(keys).filter(
- key => key.indexOf('title') >= 0 || key.indexOf('author') >= 0 || key.indexOf('creationDate') >= 0 || key.indexOf('lastModified') >= 0 || (key[0]?.toUpperCase() === key[0] && key[0] !== '_')
+ key => key.indexOf('title') >= 0 || key.indexOf('author') >= 0 || key.indexOf('author_date') >= 0 || key.indexOf('modificationDate') >= 0 || (key[0]?.toUpperCase() === key[0] && key[0] !== '_')
);
return noviceKeys.filter(key => key.toLowerCase().indexOf(val) > -1);
}
@@ -1235,9 +1231,9 @@ export class CollectionSchemaViewChrome extends React.Component<CollectionViewMe
const dividerWidth = 4;
const borderWidth = Number(COLLECTION_BORDER_WIDTH);
const panelWidth = this.props.docView.props.PanelWidth();
- const previewWidth = NumCast(this.document.schemaPreviewWidth);
+ const previewWidth = NumCast(this.document.schema_previewWidth);
const tableWidth = panelWidth - 2 * borderWidth - dividerWidth - previewWidth;
- this.document.schemaPreviewWidth = previewWidth === 0 ? Math.min(tableWidth / 3, 200) : 0;
+ this.document.schema_previewWidth = previewWidth === 0 ? Math.min(tableWidth / 3, 200) : 0;
};
@undoBatch
@@ -1254,7 +1250,7 @@ export class CollectionSchemaViewChrome extends React.Component<CollectionViewMe
};
render() {
- const previewWidth = NumCast(this.document.schemaPreviewWidth);
+ const previewWidth = NumCast(this.document.schema_previewWidth);
const textWrapped = Cast(this.document.textwrappedSchemaRows, listSpec('string'), []).length > 0;
return (
diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index 99d4d0bee..675f23970 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -2,7 +2,8 @@ import React = require('react');
import { CursorProperty } from 'csstype';
import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
-import { DataSym, Doc, Field, HeightSym, Opt, WidthSym } from '../../../fields/Doc';
+import { Doc, Field, Opt } from '../../../fields/Doc';
+import { DocData, Height, Width } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
import { List } from '../../../fields/List';
import { listSpec } from '../../../fields/Schema';
@@ -49,12 +50,12 @@ export class CollectionNoteTakingView extends CollectionSubView() {
return BoolCast(this.layoutDoc.chromeHidden);
}
// columnHeaders returns the list of SchemaHeaderFields currently being used by the layout doc to render the columns
- @computed get columnHeaders() {
- const columnHeaders = Cast(this.dataDoc.columnHeaders, listSpec(SchemaHeaderField), null);
- const needsUnsetCategory = this.childDocs.some(d => !d[this.notetakingCategoryField] && !columnHeaders?.find(sh => sh.heading === 'unset'));
- if (needsUnsetCategory || columnHeaders === undefined || columnHeaders.length === 0) {
+ @computed get colHeaderData() {
+ const colHeaderData = Cast(this.dataDoc[this.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null);
+ const needsUnsetCategory = this.childDocs.some(d => !d[this.notetakingCategoryField] && !colHeaderData?.find(sh => sh.heading === 'unset'));
+ if (needsUnsetCategory || colHeaderData === undefined || colHeaderData.length === 0) {
setTimeout(() => {
- const columnHeaders = Array.from(Cast(this.dataDoc.columnHeaders, listSpec(SchemaHeaderField), null) ?? []);
+ const columnHeaders = Array.from(Cast(this.dataDoc[this.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null) ?? []);
const needsUnsetCategory = this.childDocs.some(d => !d[this.notetakingCategoryField] && !columnHeaders?.find(sh => sh.heading === 'unset'));
if (needsUnsetCategory || columnHeaders.length === 0) {
columnHeaders.push(new SchemaHeaderField('unset', undefined, undefined, 1));
@@ -62,7 +63,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
}
});
}
- return columnHeaders ?? ([] as SchemaHeaderField[]);
+ return colHeaderData ?? ([] as SchemaHeaderField[]);
}
@computed get headerMargin() {
return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HeaderMargin);
@@ -78,7 +79,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
}
// numGroupColumns returns the number of columns
@computed get numGroupColumns() {
- return this.columnHeaders.length;
+ return this.colHeaderData.length;
}
// PanelWidth returns the size of the total available space the view occupies
@computed get PanelWidth() {
@@ -117,7 +118,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
// (2) documentView gets unmounted as you remove it from the list
@computed get Sections() {
TraceMobx();
- const columnHeaders = this.columnHeaders;
+ const columnHeaders = this.colHeaderData;
// filter out the currently dragged docs from the child docs, since we will insert them later
const docs = this.childDocs.filter(d => !DragManager.docsBeingDragged.includes(d));
const sections = new Map<SchemaHeaderField, Doc[]>(columnHeaders.map(sh => [sh, []] as [SchemaHeaderField, []]));
@@ -149,9 +150,10 @@ export class CollectionNoteTakingView extends CollectionSubView() {
componentDidMount() {
super.componentDidMount?.();
document.addEventListener('pointerup', this.removeDocDragHighlight, true);
- this._disposers.autoHeight = reaction(
- () => this.layoutDoc._autoHeight,
- autoHeight => autoHeight && this.props.setHeight?.(Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), this.headerMargin + Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace('px', ''))))))
+ this._disposers.layout_autoHeight = reaction(
+ () => this.layoutDoc._layout_autoHeight,
+ layout_autoHeight =>
+ layout_autoHeight && this.props.setHeight?.(Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), this.headerMargin + Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace('px', ''))))))
);
}
@@ -199,13 +201,17 @@ export class CollectionNoteTakingView extends CollectionSubView() {
};
styleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string) => {
- if (property === StyleProp.BoxShadow && doc && DragManager.docsBeingDragged.includes(doc)) {
- return `#9c9396 ${StrCast(doc?.boxShadow, '10px 10px 0.9vw')}`;
- }
- if (property === StyleProp.Opacity && doc) {
- if (this.props.childOpacity) {
- return this.props.childOpacity();
- }
+ switch (property) {
+ case StyleProp.BoxShadow:
+ if (doc && DragManager.docsBeingDragged.includes(doc)) {
+ return `#9c9396 ${StrCast(doc?.layout_boxShadow, '10px 10px 0.9vw')}`;
+ }
+ break;
+ case StyleProp.Opacity:
+ if (doc && this.props.childOpacity) {
+ return this.props.childOpacity();
+ }
+ break;
}
return this.props.styleProvider?.(doc, props, property);
};
@@ -224,13 +230,13 @@ export class CollectionNoteTakingView extends CollectionSubView() {
ref={r => (dref = r || undefined)}
Document={doc}
pointerEvents={this.blockPointerEventsWhenDragging}
- DataDoc={dataDoc || (!Doc.AreProtosEqual(doc[DataSym], doc) && doc[DataSym])}
+ DataDoc={dataDoc ?? (!Doc.AreProtosEqual(doc[DocData], doc) ? doc[DocData] : undefined)}
renderDepth={this.props.renderDepth + 1}
PanelWidth={width}
PanelHeight={height}
styleProvider={this.styleProvider}
docViewPath={this.props.docViewPath}
- fitWidth={this.props.childFitWidth}
+ layout_fitWidth={this.props.childLayoutFitWidth}
isContentActive={emptyFunction}
onKey={this.onKeyDown}
//TODO: change this from a prop to a parameter passed into a function
@@ -238,22 +244,22 @@ export class CollectionNoteTakingView extends CollectionSubView() {
isDocumentActive={this.isContentActive}
LayoutTemplate={this.props.childLayoutTemplate}
LayoutTemplateString={this.props.childLayoutString}
- NativeWidth={this.props.childIgnoreNativeSize ? returnZero : this.props.childFitWidth?.(doc) || (doc._fitWidth && !Doc.NativeWidth(doc)) ? width : undefined} // explicitly ignore nativeWidth/height if childIgnoreNativeSize is set- used by PresBox
- NativeHeight={this.props.childIgnoreNativeSize ? returnZero : this.props.childFitWidth?.(doc) || (doc._fitWidth && !Doc.NativeHeight(doc)) ? height : undefined}
+ NativeWidth={this.props.childIgnoreNativeSize ? returnZero : this.props.childLayoutFitWidth?.(doc) || (doc._layout_fitWidth && !Doc.NativeWidth(doc)) ? width : undefined} // explicitly ignore nativeWidth/height if childIgnoreNativeSize is set- used by PresBox
+ NativeHeight={this.props.childIgnoreNativeSize ? returnZero : this.props.childLayoutFitWidth?.(doc) || (doc._layout_fitWidth && !Doc.NativeHeight(doc)) ? height : undefined}
dontCenter={this.props.childIgnoreNativeSize ? 'xy' : undefined}
dontRegisterView={dataDoc ? true : BoolCast(this.layoutDoc.childDontRegisterViews, this.props.dontRegisterView)}
rootSelected={this.rootSelected}
- showTitle={this.props.childShowTitle}
+ layout_showTitle={this.props.childlayout_showTitle}
dropAction={StrCast(this.layoutDoc.childDropAction) as dropActionType}
onClick={this.onChildClickHandler}
onDoubleClick={this.onChildDoubleClickHandler}
ScreenToLocalTransform={noteTakingDocTransform}
focus={this.focusDocument}
- docFilters={this.childDocFilters}
+ childFilters={this.childDocFilters}
hideDecorationTitle={this.props.childHideDecorationTitle?.()}
hideResizeHandles={this.props.childHideResizeHandles?.()}
hideTitle={this.props.childHideTitle?.()}
- docRangeFilters={this.childDocRangeFilters}
+ childFiltersByRanges={this.childDocRangeFilters}
searchFilterDocs={this.searchFilterDocs}
addDocument={this.props.addDocument}
moveDocument={this.props.moveDocument}
@@ -280,10 +286,10 @@ export class CollectionNoteTakingView extends CollectionSubView() {
// if a note doc. Otherwise, returns the normal width (for graphs, images, etc...)
getDocWidth(d: Doc) {
const heading = !d[this.notetakingCategoryField] ? 'unset' : Field.toString(d[this.notetakingCategoryField] as Field);
- const existingHeader = this.columnHeaders.find(sh => sh.heading === heading);
+ const existingHeader = this.colHeaderData.find(sh => sh.heading === heading);
const existingWidth = existingHeader?.width ? existingHeader.width : 0;
const maxWidth = existingWidth > 0 ? existingWidth * this.availableWidth : this.maxColWidth;
- const width = d.fitWidth ? maxWidth : d[WidthSym]();
+ const width = d.layout_fitWidth ? maxWidth : d[Width]();
return Math.min(maxWidth - CollectionNoteTakingViewColumn.ColumnMargin, width < maxWidth ? width : maxWidth);
}
@@ -293,14 +299,14 @@ export class CollectionNoteTakingView extends CollectionSubView() {
const childLayoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.());
const childDataDoc = !d.isTemplateDoc && !d.isTemplateForField ? undefined : this.props.DataDoc;
const maxHeight = (lim => (lim === 0 ? this.props.PanelWidth() : lim === -1 ? 10000 : lim))(NumCast(this.layoutDoc.childLimitHeight, -1));
- const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._fitWidth || this.props.childFitWidth?.(d)) ? d[WidthSym]() : 0);
- const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._fitWidth || this.props.childFitWidth?.(d)) ? d[HeightSym]() : 0);
+ const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._layout_fitWidth || this.props.childLayoutFitWidth?.(d)) ? d[Width]() : 0);
+ const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._layout_fitWidth || this.props.childLayoutFitWidth?.(d)) ? d[Height]() : 0);
if (nw && nh) {
const docWid = this.getDocWidth(d);
return Math.min(maxHeight, (docWid * nh) / nw);
}
const childHeight = NumCast(childLayoutDoc._height);
- const panelHeight = childLayoutDoc._fitWidth || this.props.childFitWidth?.(d) ? Number.MAX_SAFE_INTEGER : this.props.PanelHeight() - 2 * this.yMargin;
+ const panelHeight = childLayoutDoc._layout_fitWidth || this.props.childLayoutFitWidth?.(d) ? Number.MAX_SAFE_INTEGER : this.props.PanelHeight() - 2 * this.yMargin;
return Math.min(childHeight, maxHeight, panelHeight);
}
@@ -318,7 +324,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
const n = headers.length;
const curWidths = headers.reduce((sum, hdr) => sum + Math.abs(hdr.width), 0);
const scaleFactor = 1 / curWidths;
- this.dataDoc.columnHeaders = new List<SchemaHeaderField>(
+ this.dataDoc[this.fieldKey + '_columnHeaders'] = new List<SchemaHeaderField>(
headers.map(h => {
h.setWidth(Math.abs(h.width) * scaleFactor);
return h;
@@ -352,7 +358,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
});
// we alter the pivot fields of the docs in case they are moved to a new column.
const colIndex = this.getColumnFromXCoord(xCoord);
- const colHeader = colIndex === undefined ? 'unset' : StrCast(this.columnHeaders[colIndex].heading);
+ const colHeader = colIndex === undefined ? 'unset' : StrCast(this.colHeaderData[colIndex].heading);
DragManager.docsBeingDragged.forEach(d => (d[this.notetakingCategoryField] = colHeader));
// used to notify sections to re-render
this.docsDraggedRowCol.length = 0;
@@ -365,12 +371,12 @@ export class CollectionNoteTakingView extends CollectionSubView() {
// This function is used to know which document a column SHOULD be in while it is being dragged.
getColumnFromXCoord = (xCoord: number): number | undefined => {
let colIndex: number | undefined = undefined;
- const numColumns = this.columnHeaders.length;
+ const numColumns = this.colHeaderData.length;
const coords = [];
let colStartXCoord = 0;
for (let i = 0; i < numColumns; i++) {
coords.push(colStartXCoord);
- colStartXCoord += this.columnHeaders[i].width * this.availableWidth + this.DividerWidth;
+ colStartXCoord += this.colHeaderData[i].width * this.availableWidth + this.DividerWidth;
}
coords.push(this.PanelWidth);
for (let i = 0; i < numColumns; i++) {
@@ -386,7 +392,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
getDocsFromXCoord = (xCoord: number): Doc[] => {
const docsMatchingHeader: Doc[] = [];
const colIndex = this.getColumnFromXCoord(xCoord);
- const colHeader = colIndex === undefined ? 'unset' : StrCast(this.columnHeaders[colIndex].heading);
+ const colHeader = colIndex === undefined ? 'unset' : StrCast(this.colHeaderData[colIndex].heading);
this.childDocs?.map(d => {
if (d instanceof Promise) return;
const sectionValue = (d[this.notetakingCategoryField] as object) ?? 'unset';
@@ -401,7 +407,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
@action
onKeyDown = (e: React.KeyboardEvent, fieldProps: FieldViewProps) => {
const docView = fieldProps.DocumentView?.();
- if (docView && (e.ctrlKey || docView.rootDoc._singleLine) && ['Enter'].includes(e.key)) {
+ if (docView && (e.ctrlKey || docView.rootDoc._createDocOnCR) && ['Enter'].includes(e.key)) {
e.stopPropagation?.();
const newDoc = Doc.MakeCopy(docView.rootDoc, true);
Doc.GetProto(newDoc).text = undefined;
@@ -436,10 +442,10 @@ export class CollectionNoteTakingView extends CollectionSubView() {
}
}
}
- } else if (de.complete.linkDragData?.dragDocument.context === this.props.Document && de.complete.linkDragData?.linkDragView?.props.CollectionFreeFormDocumentView?.()) {
- const source = Docs.Create.TextDocument('', { _width: 200, _height: 75, _fitWidth: true, title: 'dropped annotation' });
+ } else if (de.complete.linkDragData?.dragDocument.embedContainer === this.props.Document && de.complete.linkDragData?.linkDragView?.props.CollectionFreeFormDocumentView?.()) {
+ const source = Docs.Create.TextDocument('', { _width: 200, _height: 75, _layout_fitWidth: true, title: 'dropped annotation' });
this.props.addDocument?.(source);
- de.complete.linkDocument = DocUtils.MakeLink(source, de.complete.linkDragData.linkSourceGetAnchor(), { linkRelationship: 'doc annotation' }); // TODODO this is where in text links get passed
+ de.complete.linkDocument = DocUtils.MakeLink(source, de.complete.linkDragData.linkSourceGetAnchor(), { link_relationship: 'doc annotation' }); // TODODO this is where in text links get passed
e.stopPropagation();
} else if (de.complete.annoDragData?.dragDocument && super.onInternalDrop(e, de)) return this.internalAnchorAnnoDrop(e, de.complete.annoDragData);
return false;
@@ -468,7 +474,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
this.onPointerMove(true, e.clientX, e.clientY);
docus?.map((doc: Doc) => this.addDocument(doc));
const newDoc = this.childDocs.lastElement();
- const colHeader = colInd === undefined ? 'unset' : StrCast(this.columnHeaders[colInd].heading);
+ const colHeader = colInd === undefined ? 'unset' : StrCast(this.colHeaderData[colInd].heading);
newDoc[this.notetakingCategoryField] = colHeader;
const docs = this.childDocList;
if (docs && targInd !== -1) {
@@ -502,7 +508,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
this.refList.push(ref);
this.observer = new _global.ResizeObserver(
action((entries: any) => {
- if (this.layoutDoc._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) {
+ if (this.layoutDoc._layout_autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) {
const height = this.headerMargin + Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace('px', '')))));
if (!LightboxView.IsLightboxDocView(this.props.docViewPath())) {
this.props.setHeight?.(height);
@@ -516,7 +522,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
select={this.props.select}
addDocument={this.addDocument}
chromeHidden={this.chromeHidden}
- columnHeaders={this.columnHeaders}
+ colHeaderData={this.colHeaderData}
Document={this.props.Document}
DataDoc={this.props.DataDoc}
resizeColumns={this.resizeColumns}
@@ -524,6 +530,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
numGroupColumns={this.numGroupColumns}
gridGap={this.gridGap}
pivotField={this.notetakingCategoryField}
+ fieldKey={this.fieldKey}
dividerWidth={this.DividerWidth}
maxColWidth={this.maxColWidth}
availableWidth={this.availableWidth}
@@ -546,15 +553,15 @@ export class CollectionNoteTakingView extends CollectionSubView() {
@undoBatch
@action
addGroup = (value: string) => {
- if (this.columnHeaders) {
- for (const header of this.columnHeaders) {
+ if (this.colHeaderData) {
+ for (const header of this.colHeaderData) {
if (header.heading === value) {
alert('You cannot use an existing column name. Please try a new column name');
return value;
}
}
}
- const columnHeaders = Array.from(Cast(this.props.Document.columnHeaders, listSpec(SchemaHeaderField), null));
+ const columnHeaders = Array.from(Cast(this.dataDoc[this.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null));
const newColWidth = 1 / (this.numGroupColumns + 1);
columnHeaders.push(new SchemaHeaderField(value, undefined, undefined, newColWidth));
value && this.resizeColumns(columnHeaders);
@@ -566,7 +573,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
if (!e.isPropagationStopped()) {
const subItems: ContextMenuProps[] = [];
subItems.push({ description: `${this.layoutDoc._columnsFill ? 'Variable Size' : 'Autosize'} Column`, event: () => (this.layoutDoc._columnsFill = !this.layoutDoc._columnsFill), icon: 'plus' });
- subItems.push({ description: `${this.layoutDoc._autoHeight ? 'Variable Height' : 'Auto Height'}`, event: () => (this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight), icon: 'plus' });
+ subItems.push({ description: `${this.layoutDoc._layout_autoHeight ? 'Variable Height' : 'Auto Height'}`, event: () => (this.layoutDoc._layout_autoHeight = !this.layoutDoc._layout_autoHeight), icon: 'plus' });
subItems.push({ description: 'Clear All', event: () => (this.dataDoc.data = new List([])), icon: 'times' });
ContextMenu.Instance.addItem({ description: 'Options...', subitems: subItems, icon: 'eye' });
}
@@ -576,8 +583,8 @@ export class CollectionNoteTakingView extends CollectionSubView() {
@action
setColumnStartXCoords = (movementXScreen: number, colIndex: number) => {
const movementX = this.props.ScreenToLocalTransform().transformDirection(movementXScreen, 0)[0];
- const leftHeader = this.columnHeaders[colIndex];
- const rightHeader = this.columnHeaders[colIndex + 1];
+ const leftHeader = this.colHeaderData[colIndex];
+ const rightHeader = this.colHeaderData[colIndex + 1];
leftHeader.setWidth(leftHeader.width + movementX / this.availableWidth);
rightHeader.setWidth(rightHeader.width - movementX / this.availableWidth);
};
@@ -600,42 +607,6 @@ export class CollectionNoteTakingView extends CollectionSubView() {
return eles;
}
- @computed get buttonMenu() {
- const menuDoc: Doc = Cast(this.rootDoc.buttonMenuDoc, Doc, null);
- if (menuDoc) {
- const width = NumCast(menuDoc._width, 30);
- const height = NumCast(menuDoc._height, 30);
- return (
- <div className="buttonMenu-docBtn" style={{ width, height }}>
- <DocumentView
- Document={menuDoc}
- DataDoc={menuDoc}
- isContentActive={this.props.isContentActive}
- isDocumentActive={returnTrue}
- addDocument={this.props.addDocument}
- moveDocument={this.props.moveDocument}
- addDocTab={this.props.addDocTab}
- pinToPres={emptyFunction}
- rootSelected={this.props.isSelected}
- removeDocument={this.props.removeDocument}
- ScreenToLocalTransform={Transform.Identity}
- PanelWidth={() => 35}
- PanelHeight={() => 35}
- renderDepth={this.props.renderDepth}
- focus={emptyFunction}
- styleProvider={this.props.styleProvider}
- docViewPath={returnEmptyDoclist}
- whenChildContentsActiveChanged={emptyFunction}
- bringToFront={emptyFunction}
- docFilters={this.props.docFilters}
- docRangeFilters={this.props.docRangeFilters}
- searchFilterDocs={this.props.searchFilterDocs}
- />
- </div>
- );
- }
- }
-
@computed get nativeWidth() {
return Doc.NativeWidth(this.layoutDoc);
}
@@ -655,35 +626,25 @@ export class CollectionNoteTakingView extends CollectionSubView() {
render() {
TraceMobx();
- const buttonMenu = this.rootDoc.buttonMenu;
- const noviceExplainer = StrCast(this.rootDoc.explainer);
return (
- <>
- {buttonMenu || noviceExplainer ? (
- <div className="documentButtonMenu" key="buttons">
- {buttonMenu ? this.buttonMenu : null}
- {Doc.UserDoc().noviceMode && noviceExplainer ? <div className="documentExplanation">{noviceExplainer}</div> : null}
- </div>
- ) : null}
- <div
- className="collectionNoteTakingView"
- ref={this.createRef}
- key="notes"
- style={{
- overflowY: this.props.isContentActive() ? 'auto' : 'hidden',
- background: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor),
- pointerEvents: this.backgroundEvents ? 'all' : undefined,
- }}
- onScroll={action(e => (this._scroll = e.currentTarget.scrollTop))}
- onPointerLeave={action(e => (this.docsDraggedRowCol.length = 0))}
- onPointerMove={e => e.buttons && this.onPointerMove(false, e.clientX, e.clientY)}
- onDragOver={e => this.onPointerMove(true, e.clientX, e.clientY)}
- onDrop={this.onExternalDrop.bind(this)}
- onContextMenu={this.onContextMenu}
- onWheel={e => this.props.isContentActive(true) && e.stopPropagation()}>
- {this.renderedSections}
- </div>
- </>
+ <div
+ className="collectionNoteTakingView"
+ ref={this.createRef}
+ key="notes"
+ style={{
+ overflowY: this.props.isContentActive() ? 'auto' : 'hidden',
+ background: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor),
+ pointerEvents: this.backgroundEvents ? 'all' : undefined,
+ }}
+ onScroll={action(e => (this._scroll = e.currentTarget.scrollTop))}
+ onPointerLeave={action(e => (this.docsDraggedRowCol.length = 0))}
+ onPointerMove={e => e.buttons && this.onPointerMove(false, e.clientX, e.clientY)}
+ onDragOver={e => this.onPointerMove(true, e.clientX, e.clientY)}
+ onDrop={this.onExternalDrop.bind(this)}
+ onContextMenu={this.onContextMenu}
+ onWheel={e => this.props.isContentActive(true) && e.stopPropagation()}>
+ {this.renderedSections}
+ </div>
);
}
}
diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
index 28bdd0cb9..2f28ecd00 100644
--- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
@@ -29,8 +29,9 @@ interface CSVFieldColumnProps {
docList: Doc[];
heading: string;
pivotField: string;
+ fieldKey: string | undefined;
chromeHidden?: boolean;
- columnHeaders: SchemaHeaderField[] | undefined;
+ colHeaderData: SchemaHeaderField[] | undefined;
headingObject: SchemaHeaderField | undefined;
yMargin: number;
numGroupColumns: number;
@@ -61,9 +62,9 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
// columnWidth returns the width of a column in absolute pixels
@computed get columnWidth() {
- if (!this.props.columnHeaders || !this.props.headingObject || this.props.columnHeaders.length === 1) return '100%';
- const i = this.props.columnHeaders.indexOf(this.props.headingObject);
- return this.props.columnHeaders[i].width * 100 + '%';
+ if (!this.props.colHeaderData || !this.props.headingObject || this.props.colHeaderData.length === 1) return '100%';
+ const i = this.props.colHeaderData.indexOf(this.props.headingObject);
+ return this.props.colHeaderData[i].width * 100 + '%';
}
private dropDisposer?: DragManager.DragDropDisposer;
@@ -105,7 +106,7 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
headingChanged = (value: string, shiftDown?: boolean) => {
const castedValue = this.getValue(value);
if (castedValue) {
- if (this.props.columnHeaders?.map(i => i.heading).indexOf(castedValue.toString()) !== -1) {
+ if (this.props.colHeaderData?.map(i => i.heading).indexOf(castedValue.toString()) !== -1) {
return false;
}
this.props.docList.forEach(d => (d[this.props.pivotField] = castedValue));
@@ -120,14 +121,15 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
@action pointerEntered = () => SnappingManager.GetIsDragging() && (this._background = '#b4b4b4');
@action pointerLeave = () => (this._background = 'inherit');
- textCallback = (char: string) => this.addNewTextDoc('-typed text-', false, true);
+ @undoBatch
+ addTextNote = (char: string) => this.addNewTextDoc('-typed text-', false, true);
// addNewTextDoc is called when a user starts typing in a column to create a new node
@action
addNewTextDoc = (value: string, shiftDown?: boolean, forceEmptyNote?: boolean) => {
if (!value && !forceEmptyNote) return false;
const key = this.props.pivotField;
- const newDoc = Docs.Create.TextDocument(value, { _height: 18, _width: 200, _fitWidth: true, title: value, _autoHeight: true });
+ const newDoc = Docs.Create.TextDocument(value, { _height: 18, _width: 200, _layout_fitWidth: true, title: value, _layout_autoHeight: true });
const colValue = this.getValue(this.props.heading);
newDoc[key] = colValue;
FormattedTextBox.SelectOnLoad = newDoc[Id];
@@ -141,11 +143,11 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
@undoBatch
@action
deleteColumn = () => {
- const columnHeaders = Array.from(Cast(this.props.Document.columnHeaders, listSpec(SchemaHeaderField), null));
+ const colHdrData = Array.from(Cast(this.props.Document[this.props.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null));
if (this.props.headingObject) {
this.props.docList.forEach(d => (d[this.props.pivotField] = undefined));
- columnHeaders.splice(columnHeaders.indexOf(this.props.headingObject), 1);
- this.props.resizeColumns(columnHeaders);
+ colHdrData.splice(colHdrData.indexOf(this.props.headingObject), 1);
+ this.props.resizeColumns(colHdrData);
}
};
@@ -211,7 +213,7 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
!Doc.UserDoc().noviceMode && ContextMenu.Instance.addItem({ description: 'Containers ...', subitems: layoutItems, icon: 'eye' });
ContextMenu.Instance.setDefaultItem('::', (name: string): void => {
Doc.GetProto(this.props.Document)[name] = '';
- const created = Docs.Create.TextDocument('', { title: name, _width: 250, _autoHeight: true });
+ const created = Docs.Create.TextDocument('', { title: name, _width: 250, _layout_autoHeight: true });
if (created) {
if (this.props.Document.isTemplateDoc) {
Doc.MakeMetadataFieldTemplate(created, this.props.Document);
@@ -243,7 +245,7 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
style={{ background: evContents !== `No Value` ? this._color : 'inherit' }}>
<EditableView GetValue={() => evContents} isEditingCallback={isEditing => isEditing && this.props.select(false)} SetValue={this.headingChanged} contents={evContents} oneLine={true} />
</div>
- {(this.props.columnHeaders?.length ?? 0) > 1 && (
+ {(this.props.colHeaderData?.length ?? 0) > 1 && (
<button className="collectionNoteTakingView-sectionDelete" onClick={this.deleteColumn}>
<FontAwesomeIcon icon="trash" size="lg" />
</button>
@@ -271,7 +273,7 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
{!this.props.chromeHidden ? (
<div className="collectionNoteTakingView-DocumentButtons" style={{ marginBottom: 10 }}>
<div key={`${heading}-add-document`} className="collectionNoteTakingView-addDocumentButton">
- <EditableView GetValue={returnEmptyString} SetValue={this.addNewTextDoc} textCallback={this.textCallback} placeholder={"Type ':' for commands"} contents={'+ New Node'} menuCallback={this.menuCallback} />
+ <EditableView GetValue={returnEmptyString} SetValue={this.addNewTextDoc} textCallback={this.addTextNote} placeholder={"Type ':' for commands"} contents={'+ New Node'} menuCallback={this.menuCallback} />
</div>
<div key={`${this.props.Document[Id]}-addGroup`} className="collectionNoteTakingView-addDocumentButton">
<EditableView {...this.props.editableViewProps()} />
diff --git a/src/client/views/collections/CollectionPileView.tsx b/src/client/views/collections/CollectionPileView.tsx
index 5b96a8682..57d9bbb49 100644
--- a/src/client/views/collections/CollectionPileView.tsx
+++ b/src/client/views/collections/CollectionPileView.tsx
@@ -1,6 +1,7 @@
import { action, computed, IReactionDisposer, reaction } from 'mobx';
import { observer } from 'mobx-react';
-import { Doc, DocListCast, HeightSym, WidthSym } from '../../../fields/Doc';
+import { Doc, DocListCast } from '../../../fields/Doc';
+import { Height, Width } from '../../../fields/DocSymbols';
import { NumCast, StrCast } from '../../../fields/Types';
import { emptyFunction, returnFalse, returnTrue, setupMoveUpEvents } from '../../../Utils';
import { DocUtils } from '../../documents/Documents';
@@ -22,7 +23,7 @@ export class CollectionPileView extends CollectionSubView() {
componentDidMount() {
if (this.layoutEngine() !== computePassLayout.name && this.layoutEngine() !== computeStarburstLayout.name) {
- this.Document._pileLayoutEngine = computePassLayout.name;
+ this.Document._freeform_pileEngine = computePassLayout.name;
}
this._originalChrome = this.layoutDoc._chromeHidden;
this.layoutDoc._chromeHidden = true;
@@ -32,7 +33,7 @@ export class CollectionPileView extends CollectionSubView() {
Object.values(this._disposers).forEach(disposer => disposer?.());
}
- layoutEngine = () => StrCast(this.Document._pileLayoutEngine);
+ layoutEngine = () => StrCast(this.Document._freeform_pileEngine);
@undoBatch
addPileDoc = (doc: Doc | Doc[]) => {
@@ -72,28 +73,29 @@ export class CollectionPileView extends CollectionSubView() {
// toggles the pileup between starburst to compact
toggleStarburst = action(() => {
+ this.layoutDoc._freeform_scale = undefined;
if (this.layoutEngine() === computeStarburstLayout.name) {
- if (this.rootDoc[WidthSym]() !== NumCast(this.rootDoc._starburstDiameter, 500)) {
- this.rootDoc._starburstDiameter = this.rootDoc[WidthSym]();
+ if (this.rootDoc[Width]() !== NumCast(this.rootDoc._starburstDiameter, 500)) {
+ this.rootDoc._starburstDiameter = this.rootDoc[Width]();
}
const defaultSize = 110;
- this.rootDoc.x = NumCast(this.rootDoc.x) + this.layoutDoc[WidthSym]() / 2 - NumCast(this.layoutDoc._starburstPileWidth, defaultSize) / 2;
- this.rootDoc.y = NumCast(this.rootDoc.y) + this.layoutDoc[HeightSym]() / 2 - NumCast(this.layoutDoc._starburstPileHeight, defaultSize) / 2;
- this.layoutDoc._width = NumCast(this.layoutDoc._starburstPileWidth, defaultSize);
- this.layoutDoc._height = NumCast(this.layoutDoc._starburstPileHeight, defaultSize);
+ this.rootDoc.x = NumCast(this.rootDoc.x) + this.layoutDoc[Width]() / 2 - NumCast(this.layoutDoc._freeform_pileWidth, defaultSize) / 2;
+ this.rootDoc.y = NumCast(this.rootDoc.y) + this.layoutDoc[Height]() / 2 - NumCast(this.layoutDoc._freeform_pileHeight, defaultSize) / 2;
+ this.layoutDoc._width = NumCast(this.layoutDoc._freeform_pileWidth, defaultSize);
+ this.layoutDoc._height = NumCast(this.layoutDoc._freeform_pileHeight, defaultSize);
DocUtils.pileup(this.childDocs, undefined, undefined, NumCast(this.layoutDoc._width) / 2, false);
- this.layoutDoc._panX = 0;
- this.layoutDoc._panY = -10;
- this.props.Document._pileLayoutEngine = computePassLayout.name;
+ this.layoutDoc._freeform_panX = 0;
+ this.layoutDoc._freeform_panY = -10;
+ this.props.Document._freeform_pileEngine = computePassLayout.name;
} else {
const defaultSize = NumCast(this.rootDoc._starburstDiameter, 500);
- this.rootDoc.x = NumCast(this.rootDoc.x) + this.layoutDoc[WidthSym]() / 2 - defaultSize / 2;
- this.rootDoc.y = NumCast(this.rootDoc.y) + this.layoutDoc[HeightSym]() / 2 - defaultSize / 2;
- this.layoutDoc._starburstPileWidth = this.layoutDoc[WidthSym]();
- this.layoutDoc._starburstPileHeight = this.layoutDoc[HeightSym]();
- this.layoutDoc._panX = this.layoutDoc._panY = 0;
+ this.rootDoc.x = NumCast(this.rootDoc.x) + this.layoutDoc[Width]() / 2 - defaultSize / 2;
+ this.rootDoc.y = NumCast(this.rootDoc.y) + this.layoutDoc[Height]() / 2 - defaultSize / 2;
+ this.layoutDoc._freeform_pileWidth = this.layoutDoc[Width]();
+ this.layoutDoc._freeform_pileHeight = this.layoutDoc[Height]();
+ this.layoutDoc._freeform_panX = this.layoutDoc._freeform_panY = 0;
this.layoutDoc._width = this.layoutDoc._height = defaultSize;
- this.props.Document._pileLayoutEngine = computeStarburstLayout.name;
+ this.props.Document._freeform_pileEngine = computeStarburstLayout.name;
}
});
diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx
index 22a575989..9d5cb257a 100644
--- a/src/client/views/collections/CollectionStackedTimeline.tsx
+++ b/src/client/views/collections/CollectionStackedTimeline.tsx
@@ -24,7 +24,7 @@ import { undoBatch, UndoManager } from '../../util/UndoManager';
import { AudioWaveform } from '../AudioWaveform';
import { CollectionSubView } from '../collections/CollectionSubView';
import { LightboxView } from '../LightboxView';
-import { DocFocusFunc, DocFocusOptions, DocumentView, DocumentViewProps } from '../nodes/DocumentView';
+import { DocFocusFunc, DocFocusOptions, DocumentView, DocumentViewProps, OpenWhere } from '../nodes/DocumentView';
import { LabelBox } from '../nodes/LabelBox';
import { VideoBox } from '../nodes/VideoBox';
import './CollectionStackedTimeline.scss';
@@ -41,7 +41,9 @@ export type CollectionStackedTimelineProps = {
mediaPath: string;
dictationKey: string;
rawDuration: number;
+ dataFieldKey: string;
fieldKey: string;
+ thumbnails?: () => string[];
};
// trimming state: shows full clip, current trim bounds, or not trimming
@@ -80,6 +82,9 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
get minTrimLength() {
return Math.max(this._timeline?.getBoundingClientRect() ? 0.05 * this.clipDuration : 0, 0.5);
}
+ @computed get thumbnails() {
+ return this.props.thumbnails?.();
+ }
@computed get trimStart() {
return this.IsTrimming !== TrimScope.None ? this._trimStart : this.clipStart;
@@ -102,7 +107,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
}
@computed get currentTime() {
- return NumCast(this.layoutDoc._currentTimecode);
+ return NumCast(this.layoutDoc._layout_currentTimecode);
}
@computed get zoomFactor() {
@@ -114,7 +119,8 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
// onClick play scripts
CollectionStackedTimeline.RangeScript =
CollectionStackedTimeline.RangeScript ||
- ScriptField.MakeFunction(`scriptContext.clickAnchor(this, clientX)`, {
+ ScriptField.MakeFunction(`setTimeout(() => scriptContext.clickAnchor(this, clientX))`, {
+ // setTimeout is a hack to run script in its own properly named undo group (instead of being part of the generic onClick)
self: Doc.name,
scriptContext: 'any',
clientX: 'number',
@@ -219,12 +225,12 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
};
getLinkData(l: Doc) {
- let la1 = l.anchor1 as Doc;
- let la2 = l.anchor2 as Doc;
+ let la1 = l.link_anchor_1 as Doc;
+ let la2 = l.link_anchor_2 as Doc;
const linkTime = NumCast(la2[this.props.startTag], NumCast(la1[this.props.startTag]));
if (Doc.AreProtosEqual(la1, this.dataDoc)) {
- la1 = l.anchor2 as Doc;
- la2 = l.anchor1 as Doc;
+ la1 = l.link_anchor_2 as Doc;
+ la2 = l.link_anchor_1 as Doc;
}
return { la1, la2, linkTime };
}
@@ -292,10 +298,9 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
const clientX = e.clientX;
if (rect) {
this._hoverTime = this.toTimeline(clientX - rect.x, rect.width);
- if (this.dataDoc.thumbnails) {
+ if (this.thumbnails) {
const nearest = Math.floor((this._hoverTime / this.props.rawDuration) * VideoBox.numThumbnails);
- const thumbnails = StrListCast(this.dataDoc.thumbnails);
- const imgField = thumbnails?.length > 0 ? new ImageField(thumbnails[nearest]) : undefined;
+ const imgField = this.thumbnails.length > 0 ? new ImageField(this.thumbnails[nearest]) : undefined;
this._thumbnail = imgField?.url?.href ? imgField.url.href.replace('.png', '_m.png') : undefined;
}
}
@@ -399,17 +404,15 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
docAnchor ??
Docs.Create.LabelDocument({
title: ComputedField.MakeFunction(`self["${endTag}"] ? "#" + formatToTime(self["${startTag}"]) + "-" + formatToTime(self["${endTag}"]) : "#" + formatToTime(self["${startTag}"])`) as any,
- _minFontSize: 12,
- _maxFontSize: 24,
- _singleLine: true,
+ _label_minFontSize: 12,
+ _label_maxFontSize: 24,
_stayInCollection: true,
backgroundColor: 'rgba(128, 128, 128, 0.5)',
- useLinkSmallAnchor: true,
- hideLinkButton: true,
+ layout_hideLinkButton: true,
onClick: FollowLinkScript(),
annotationOn: rootDoc,
- _timelineLabel: true,
- borderRounding: anchorEndTime === undefined ? '100%' : undefined,
+ _isTimelineLabel: true,
+ layout_borderRounding: anchorEndTime === undefined ? '100%' : undefined,
});
Doc.GetProto(anchor)[startTag] = anchorStartTime;
Doc.GetProto(anchor)[endTag] = anchorEndTime;
@@ -434,7 +437,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
this.scrollToTime(seekTimeInSeconds);
}
} else {
- if (seekTimeInSeconds < NumCast(this.layoutDoc._currentTimecode) && endTime > NumCast(this.layoutDoc._currentTimecode)) {
+ if (seekTimeInSeconds < NumCast(this.layoutDoc._layout_currentTimecode) && endTime > NumCast(this.layoutDoc._layout_currentTimecode)) {
if (!this.layoutDoc.autoPlayAnchors && this.props.playing()) {
this.props.Pause();
} else {
@@ -455,7 +458,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
}
const seekTimeInSeconds = this.anchorStart(anchorDoc) - 0.05;
const endTime = this.anchorEnd(anchorDoc);
- if (seekTimeInSeconds < NumCast(this.layoutDoc._currentTimecode) + 1e-4 && endTime > NumCast(this.layoutDoc._currentTimecode) - 1e-4) {
+ if (seekTimeInSeconds < NumCast(this.layoutDoc._layout_currentTimecode) + 1e-4 && endTime > NumCast(this.layoutDoc._layout_currentTimecode) - 1e-4) {
if (this.props.playing()) this.props.Pause();
else if (this.layoutDoc.autoPlayAnchors) this.props.Play();
else if (!this.layoutDoc.autoPlayAnchors) {
@@ -596,6 +599,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
{!this.props.PanelHeight() ? null : (
<AudioWaveform
rawDuration={this.props.rawDuration}
+ fieldKey={this.props.dataFieldKey}
duration={this.clipDuration}
mediaPath={this.props.mediaPath}
layoutDoc={this.layoutDoc}
@@ -661,6 +665,8 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
interface StackedTimelineAnchorProps {
mark: Doc;
+ whenChildContentsActiveChanged: (isActive: boolean) => void;
+ addDocTab: (doc: Doc, where: OpenWhere) => boolean;
rangeClickScript: () => ScriptField;
rangePlayScript: () => ScriptField;
left: number;
@@ -709,7 +715,7 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps>
() => this.props.currentTimecode(),
time => {
const dictationDoc = Cast(this.props.layoutDoc['data-dictation'], Doc, null);
- const isDictation = dictationDoc && LinkManager.Links(this.props.mark).some(link => Cast(link.anchor1, Doc, null)?.annotationOn === dictationDoc);
+ const isDictation = dictationDoc && LinkManager.Links(this.props.mark).some(link => Cast(link.link_anchor_1, Doc, null)?.annotationOn === dictationDoc);
if (
!LightboxView.LightboxDoc &&
// bcz: when should links be followed? we don't want to move away from the video to follow a link but we can open it in a sidebar/etc. But we don't know that upfront.
@@ -746,7 +752,7 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps>
if (timelineOnly) {
if (!left && time !== undefined && time <= NumCast(anchor[this.props.startTag])) time = undefined;
Doc.SetInPlace(anchor, left ? this.props.startTag : this.props.endTag, time, true);
- if (!left) Doc.SetInPlace(anchor, 'borderRounding', time !== undefined ? undefined : '100%', true);
+ if (!left) Doc.SetInPlace(anchor, 'layout_borderRounding', time !== undefined ? undefined : '100%', true);
} else {
anchor[left ? '_timecodeToShow' : '_timecodeToHide'] = time;
}
@@ -808,16 +814,14 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps>
isDocumentActive={this.props.isDocumentActive}
PanelWidth={width}
PanelHeight={height}
- fitWidth={returnTrue}
+ layout_fitWidth={returnTrue}
ScreenToLocalTransform={screenXf}
- addDocTab={returnFalse}
pinToPres={emptyFunction}
- whenChildContentsActiveChanged={emptyFunction}
focus={focusFunc}
isContentActive={returnFalse}
searchFilterDocs={returnEmptyDoclist}
- docFilters={returnEmptyFilter}
- docRangeFilters={returnEmptyFilter}
+ childFilters={returnEmptyFilter}
+ childFiltersByRanges={returnEmptyFilter}
rootSelected={returnFalse}
onClick={script}
onDoubleClick={this.props.layoutDoc.autoPlayAnchors ? undefined : doublescript}
diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss
index f3397e2c4..99a68e94b 100644
--- a/src/client/views/collections/CollectionStackingView.scss
+++ b/src/client/views/collections/CollectionStackingView.scss
@@ -372,7 +372,8 @@
.editableView-container-editing-oneLine,
.editableView-container-editing {
color: grey;
- padding-top: 10px;
+ padding-top: 5px;
+ padding-bottom: 5px;
width: 100%;
}
@@ -387,7 +388,8 @@
letter-spacing: 2px;
color: grey;
border: 0px;
- padding-top: 10px; // 12px 10px 11px 10px;
+ padding-top: 5px; // 12px 10px 11px 10px;
+ padding-bottom: 5px; // 12px 10px 11px 10px;
}
}
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index eedf639aa..3c0d8cbc3 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -3,7 +3,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { CursorProperty } from 'csstype';
import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
-import { DataSym, Doc, HeightSym, Opt, WidthSym } from '../../../fields/Doc';
+import { Doc, Opt } from '../../../fields/Doc';
+import { DocData, Height, Width } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
import { List } from '../../../fields/List';
import { listSpec } from '../../../fields/Schema';
@@ -36,7 +37,7 @@ export type collectionStackingViewProps = {
sortFunc?: (a: Doc, b: Doc) => number;
chromeHidden?: boolean;
// view type is stacking
- viewType?: CollectionViewType;
+ type_collection?: CollectionViewType;
NativeWidth?: () => number;
NativeHeight?: () => number;
};
@@ -49,7 +50,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
// Not sure what a pivot field is. Seems like we cause reaction in MobX get rid of it once we exit this view
_pivotFieldDisposer?: IReactionDisposer;
// Seems like we cause reaction in MobX get rid of our height once we exit this view
- _autoHeightDisposer?: IReactionDisposer;
+ _layout_autoHeightDisposer?: IReactionDisposer;
// keeping track of documents. Updated on internal and external drops. What's the difference?
_docXfs: { height: () => number; width: () => number; stackedDocTransform: () => Transform }[] = [];
// Doesn't look like this field is being used anywhere. Obsolete?
@@ -65,8 +66,8 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
return this.props.chromeHidden || BoolCast(this.layoutDoc.chromeHidden);
}
// it looks like this gets the column headers that Mehek was showing just now
- @computed get columnHeaders() {
- return Cast(this.layoutDoc._columnHeaders, listSpec(SchemaHeaderField), null);
+ @computed get colHeaderData() {
+ return Cast(this.layoutDoc['_' + this.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null);
}
// Still not sure what a pivot is, but it appears that we can actually filter docs somehow?
@computed get pivotField() {
@@ -94,7 +95,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
}
// are we stacking or masonry?
@computed get isStackingView() {
- return (this.props.viewType ?? this.layoutDoc._viewType) === CollectionViewType.Stacking;
+ return (this.props.type_collection ?? this.layoutDoc._type_collection) === CollectionViewType.Stacking;
}
// this is the number of StackingViewFieldColumns that we have
@computed get numGroupColumns() {
@@ -116,10 +117,10 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
constructor(props: any) {
super(props);
- if (this.columnHeaders === undefined) {
+ if (this.colHeaderData === undefined) {
// TODO: what is a layout doc? Is it literally how this document is supposed to be layed out?
// here we're making an empty list of column headers (again, what Mehek showed us)
- this.layoutDoc._columnHeaders = new List<SchemaHeaderField>();
+ this.layoutDoc['_' + this.fieldKey + '_columnHeaders'] = new List<SchemaHeaderField>();
}
}
@@ -154,14 +155,14 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
//TODO: this seems important
get Sections() {
// appears that pivot field IS actually for sorting
- if (!this.pivotField || this.columnHeaders instanceof Promise) return new Map<SchemaHeaderField, Doc[]>();
+ if (!this.pivotField || this.colHeaderData instanceof Promise) return new Map<SchemaHeaderField, Doc[]>();
- if (this.columnHeaders === undefined) {
- setTimeout(() => (this.layoutDoc._columnHeaders = new List<SchemaHeaderField>()), 0);
+ if (this.colHeaderData === undefined) {
+ setTimeout(() => (this.layoutDoc['_' + this.fieldKey + '_columnHeaders'] = new List<SchemaHeaderField>()), 0);
return new Map<SchemaHeaderField, Doc[]>();
}
- const columnHeaders = Array.from(this.columnHeaders);
- const fields = new Map<SchemaHeaderField, Doc[]>(columnHeaders.map(sh => [sh, []] as [SchemaHeaderField, []]));
+ const colHeaderData = Array.from(this.colHeaderData);
+ const fields = new Map<SchemaHeaderField, Doc[]>(colHeaderData.map(sh => [sh, []] as [SchemaHeaderField, []]));
let changed = false;
this.filteredChildren.map(d => {
const sectionValue = (d[this.pivotField] ? d[this.pivotField] : `NO ${this.pivotField.toUpperCase()} VALUE`) as object;
@@ -170,13 +171,13 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
const castedSectionValue = !isNaN(parsed) ? parsed : sectionValue;
// look for if header exists already
- const existingHeader = columnHeaders.find(sh => sh.heading === (castedSectionValue ? castedSectionValue.toString() : `NO ${this.pivotField.toUpperCase()} VALUE`));
+ const existingHeader = colHeaderData.find(sh => sh.heading === (castedSectionValue ? castedSectionValue.toString() : `NO ${this.pivotField.toUpperCase()} VALUE`));
if (existingHeader) {
fields.get(existingHeader)!.push(d);
} else {
const newSchemaHeader = new SchemaHeaderField(castedSectionValue ? castedSectionValue.toString() : `NO ${this.pivotField.toUpperCase()} VALUE`);
fields.set(newSchemaHeader, [d]);
- columnHeaders.push(newSchemaHeader);
+ colHeaderData.push(newSchemaHeader);
changed = true;
}
});
@@ -187,13 +188,13 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
.filter(key => !fields.get(key)!.length)
.map(header => {
fields.delete(header);
- columnHeaders.splice(columnHeaders.indexOf(header), 1);
+ colHeaderData.splice(colHeaderData.indexOf(header), 1);
changed = true;
});
}
changed &&
setTimeout(
- action(() => this.columnHeaders?.splice(0, this.columnHeaders.length, ...columnHeaders)),
+ action(() => this.colHeaderData?.splice(0, this.colHeaderData.length, ...colHeaderData)),
0
);
return fields;
@@ -206,12 +207,12 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
// reset section headers when a new filter is inputted
this._pivotFieldDisposer = reaction(
() => this.pivotField,
- () => (this.layoutDoc._columnHeaders = new List())
+ () => (this.layoutDoc['_' + this.fieldKey + '_columnHeaders'] = new List())
);
- this._autoHeightDisposer = reaction(
- () => this.layoutDoc._autoHeight,
- autoHeight =>
- autoHeight &&
+ this._layout_autoHeightDisposer = reaction(
+ () => this.layoutDoc._layout_autoHeight,
+ layout_autoHeight =>
+ layout_autoHeight &&
this.props.setHeight?.(
Math.min(
NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER),
@@ -224,7 +225,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
componentWillUnmount() {
super.componentWillUnmount();
this._pivotFieldDisposer?.();
- this._autoHeightDisposer?.();
+ this._layout_autoHeightDisposer?.();
}
isAnyChildContentActive = () => this.props.isAnyChildContentActive();
@@ -282,12 +283,12 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
if (docView && ['Enter'].includes(e.key) && e.ctrlKey) {
e.stopPropagation?.();
const below = !e.altKey && e.key !== 'Tab';
- const layoutKey = StrCast(docView.LayoutFieldKey);
+ const layout_fieldKey = StrCast(docView.LayoutFieldKey);
const newDoc = Doc.MakeCopy(docView.rootDoc, true);
const dataField = docView.rootDoc[Doc.LayoutFieldKey(newDoc)];
- newDoc[DataSym][Doc.LayoutFieldKey(newDoc)] = dataField === undefined || Cast(dataField, listSpec(Doc), null)?.length !== undefined ? new List<Doc>([]) : undefined;
- if (layoutKey !== 'layout' && docView.rootDoc[layoutKey] instanceof Doc) {
- newDoc[layoutKey] = docView.rootDoc[layoutKey];
+ newDoc[DocData][Doc.LayoutFieldKey(newDoc)] = dataField === undefined || Cast(dataField, listSpec(Doc), null)?.length !== undefined ? new List<Doc>([]) : undefined;
+ if (layout_fieldKey !== 'layout' && docView.rootDoc[layout_fieldKey] instanceof Doc) {
+ newDoc[layout_fieldKey] = docView.rootDoc[layout_fieldKey];
}
Doc.GetProto(newDoc).text = undefined;
FormattedTextBox.SelectOnLoad = newDoc[Id];
@@ -320,36 +321,36 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
<DocumentView
ref={r => (dref = r || undefined)}
Document={doc}
- DataDoc={dataDoc || (!Doc.AreProtosEqual(doc[DataSym], doc) && doc[DataSym])}
+ DataDoc={dataDoc ?? (!Doc.AreProtosEqual(doc[DocData], doc) ? doc[DocData] : undefined)}
renderDepth={this.props.renderDepth + 1}
PanelWidth={width}
PanelHeight={height}
pointerEvents={this.props.DocumentView?.().props.onClick?.() ? returnNone : undefined} // if the stack has an onClick, then we don't want the contents to be interactive (see CollectionPileView)
styleProvider={this.styleProvider}
docViewPath={this.props.docViewPath}
- fitWidth={this.props.childFitWidth}
+ layout_fitWidth={this.props.childLayoutFitWidth}
isContentActive={doc.onClick ? this.isChildButtonContentActive : this.isChildContentActive}
onKey={this.onKeyDown}
onBrowseClick={this.props.onBrowseClick}
isDocumentActive={this.isContentActive}
LayoutTemplate={this.props.childLayoutTemplate}
LayoutTemplateString={this.props.childLayoutString}
- NativeWidth={this.props.childIgnoreNativeSize ? returnZero : this.props.childFitWidth?.(doc) || (doc._fitWidth && !Doc.NativeWidth(doc)) ? width : undefined} // explicitly ignore nativeWidth/height if childIgnoreNativeSize is set- used by PresBox
- NativeHeight={this.props.childIgnoreNativeSize ? returnZero : this.props.childFitWidth?.(doc) || (doc._fitWidth && !Doc.NativeHeight(doc)) ? height : undefined}
+ NativeWidth={this.props.childIgnoreNativeSize ? returnZero : this.props.childLayoutFitWidth?.(doc) || (doc._layout_fitWidth && !Doc.NativeWidth(doc)) ? width : undefined} // explicitly ignore nativeWidth/height if childIgnoreNativeSize is set- used by PresBox
+ NativeHeight={this.props.childIgnoreNativeSize ? returnZero : this.props.childLayoutFitWidth?.(doc) || (doc._layout_fitWidth && !Doc.NativeHeight(doc)) ? height : undefined}
dontCenter={this.props.childIgnoreNativeSize ? 'xy' : undefined}
- dontRegisterView={BoolCast(this.layoutDoc.childDontRegisterViews, this.props.dontRegisterView)} // used to be true if DataDoc existed, but template textboxes won't autoHeight resize if dontRegisterView is set, but they need to.
+ dontRegisterView={BoolCast(this.layoutDoc.childDontRegisterViews, this.props.dontRegisterView)} // used to be true if DataDoc existed, but template textboxes won't layout_autoHeight resize if dontRegisterView is set, but they need to.
rootSelected={this.rootSelected}
- showTitle={this.props.childShowTitle}
+ layout_showTitle={this.props.childlayout_showTitle}
dropAction={StrCast(this.layoutDoc.childDropAction) as dropActionType}
onClick={this.onChildClickHandler}
onDoubleClick={this.onChildDoubleClickHandler}
ScreenToLocalTransform={stackedDocTransform}
focus={this.focusDocument}
- docFilters={this.childDocFilters}
+ childFilters={this.childDocFilters}
hideDecorationTitle={this.props.childHideDecorationTitle?.()}
hideResizeHandles={this.props.childHideResizeHandles?.()}
hideTitle={this.props.childHideTitle?.()}
- docRangeFilters={this.childDocRangeFilters}
+ childFiltersByRanges={this.childDocRangeFilters}
searchFilterDocs={this.searchFilterDocs}
xPadding={NumCast(this.layoutDoc._childXPadding, this.props.childXPadding)}
yPadding={NumCast(this.layoutDoc._childYPadding, this.props.childYPadding)}
@@ -376,8 +377,8 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
if (!d) return 0;
const childLayoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.());
const maxWidth = this.columnWidth / this.numGroupColumns;
- if (!this.layoutDoc._columnsFill && !(childLayoutDoc._fitWidth || this.props.childFitWidth?.(d))) {
- return Math.min(d[WidthSym](), maxWidth);
+ if (!this.layoutDoc._columnsFill && !(childLayoutDoc._layout_fitWidth || this.props.childLayoutFitWidth?.(d))) {
+ return Math.min(d[Width](), maxWidth);
}
return maxWidth;
}
@@ -386,15 +387,15 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
const childLayoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.());
const childDataDoc = !d.isTemplateDoc && !d.isTemplateForField ? undefined : this.props.DataDoc;
const maxHeight = (lim => (lim === 0 ? this.props.PanelWidth() : lim === -1 ? 10000 : lim))(NumCast(this.layoutDoc.childLimitHeight, -1));
- const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._fitWidth || this.props.childFitWidth?.(d)) ? d[WidthSym]() : 0);
- const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._fitWidth || this.props.childFitWidth?.(d)) ? d[HeightSym]() : 0);
+ const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._layout_fitWidth || this.props.childLayoutFitWidth?.(d)) ? d[Width]() : 0);
+ const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._layout_fitWidth || this.props.childLayoutFitWidth?.(d)) ? d[Height]() : 0);
if (nw && nh) {
const colWid = this.columnWidth / (this.isStackingView ? this.numGroupColumns : 1);
const docWid = this.layoutDoc._columnsFill ? colWid : Math.min(this.getDocWidth(d), colWid);
return Math.min(maxHeight, (docWid * nh) / nw);
}
const childHeight = NumCast(childLayoutDoc._height);
- const panelHeight = childLayoutDoc._fitWidth || this.props.childFitWidth?.(d) ? Number.MAX_SAFE_INTEGER : this.props.PanelHeight() - 2 * this.yMargin;
+ const panelHeight = childLayoutDoc._layout_fitWidth || this.props.childLayoutFitWidth?.(d) ? Number.MAX_SAFE_INTEGER : this.props.PanelHeight() - 2 * this.yMargin;
return Math.min(childHeight, maxHeight, panelHeight);
}
@@ -460,10 +461,10 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
docs.splice(insertInd - offset, 0, ...newDocs);
}
}
- } else if (de.complete.linkDragData?.dragDocument.context === this.props.Document && de.complete.linkDragData?.linkDragView?.props.CollectionFreeFormDocumentView?.()) {
- const source = Docs.Create.TextDocument('', { _width: 200, _height: 75, _fitWidth: true, title: 'dropped annotation' });
+ } else if (de.complete.linkDragData?.dragDocument.embedContainer === this.props.Document && de.complete.linkDragData?.linkDragView?.props.CollectionFreeFormDocumentView?.()) {
+ const source = Docs.Create.TextDocument('', { _width: 200, _height: 75, _layout_fitWidth: true, title: 'dropped annotation' });
this.props.addDocument?.(source);
- de.complete.linkDocument = DocUtils.MakeLink(source, de.complete.linkDragData.linkSourceGetAnchor(), { linkRelationship: 'doc annotation' }); // TODODO this is where in text links get passed
+ de.complete.linkDocument = DocUtils.MakeLink(source, de.complete.linkDragData.linkSourceGetAnchor(), { link_relationship: 'doc annotation' }); // TODODO this is where in text links get passed
e.stopPropagation();
} else if (de.complete.annoDragData?.dragDocument && super.onInternalDrop(e, de)) return this.internalAnchorAnnoDrop(e, de.complete.annoDragData);
return false;
@@ -526,7 +527,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
this.refList.push(ref);
this.observer = new _global.ResizeObserver(
action((entries: any) => {
- if (this.layoutDoc._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) {
+ if (this.layoutDoc._layout_autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) {
const height = this.headerMargin + Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace('px', '')))));
if (!LightboxView.IsLightboxDocView(this.props.docViewPath())) {
this.props.setHeight?.(height);
@@ -539,7 +540,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
}}
addDocument={this.addDocument}
chromeHidden={this.chromeHidden}
- columnHeaders={this.columnHeaders}
+ colHeaderData={this.colHeaderData}
Document={this.props.Document}
DataDoc={this.props.DataDoc}
renderChildren={this.children}
@@ -581,7 +582,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
this.refList.push(ref);
this.observer = new _global.ResizeObserver(
action((entries: any) => {
- if (this.layoutDoc._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) {
+ if (this.layoutDoc._layout_autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) {
const height = this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace('px', '')), 0);
this.props.setHeight?.(this.headerMargin + height);
}
@@ -608,9 +609,9 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
/// add a new group category (column) to the active set of note categories. (e.g., if the pivot field is 'transportation', groups might be 'car', 'plane', 'bike', etc)
@action
addGroup = (value: string) => {
- if (value && this.columnHeaders) {
+ if (value && this.colHeaderData) {
const schemaHdrField = new SchemaHeaderField(value);
- this.columnHeaders.push(schemaHdrField);
+ this.colHeaderData.push(schemaHdrField);
return true;
}
return false;
@@ -630,7 +631,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
const options = cm.findByDescription('Options...');
const optionItems: ContextMenuProps[] = options && 'subitems' in options ? options.subitems : [];
optionItems.push({ description: `${this.layoutDoc._columnsFill ? 'Variable Size' : 'Autosize'} Column`, event: () => (this.layoutDoc._columnsFill = !this.layoutDoc._columnsFill), icon: 'plus' });
- optionItems.push({ description: `${this.layoutDoc._autoHeight ? 'Variable Height' : 'Auto Height'}`, event: () => (this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight), icon: 'plus' });
+ optionItems.push({ description: `${this.layoutDoc._layout_autoHeight ? 'Variable Height' : 'Auto Height'}`, event: () => (this.layoutDoc._layout_autoHeight = !this.layoutDoc._layout_autoHeight), icon: 'plus' });
optionItems.push({ description: 'Clear All', event: () => (this.dataDoc[this.fieldKey ?? 'data'] = new List([])), icon: 'times' });
!options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'compass' });
}
@@ -649,7 +650,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
return35 = () => 35;
@computed get buttonMenu() {
- const menuDoc: Doc = Cast(this.rootDoc.buttonMenuDoc, Doc, null);
+ const menuDoc: Doc = Cast(this.rootDoc.layout_headerButton, Doc, null);
// TODO:glr Allow support for multiple buttons
if (menuDoc) {
const width: number = NumCast(menuDoc._width, 30);
@@ -678,8 +679,8 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
docViewPath={returnEmptyDoclist}
whenChildContentsActiveChanged={emptyFunction}
bringToFront={emptyFunction}
- docFilters={this.props.docFilters}
- docRangeFilters={this.props.docRangeFilters}
+ childFilters={this.props.childFilters}
+ childFiltersByRanges={this.props.childFiltersByRanges}
searchFilterDocs={this.props.searchFilterDocs}
/>
</div>
@@ -710,7 +711,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
contents: '+ ADD A GROUP',
};
const buttonMenu = this.rootDoc.buttonMenu;
- const noviceExplainer = this.rootDoc.explainer;
+ const noviceExplainer = this.rootDoc.layout_explainer;
return (
<>
{buttonMenu || noviceExplainer ? (
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index d62c4dc62..6be9cb72d 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -34,7 +34,7 @@ interface CSVFieldColumnProps {
heading: string;
pivotField: string;
chromeHidden?: boolean;
- columnHeaders: SchemaHeaderField[] | undefined;
+ colHeaderData: SchemaHeaderField[] | undefined;
headingObject: SchemaHeaderField | undefined;
yMargin: number;
columnWidth: number;
@@ -93,7 +93,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
@undoBatch
columnDrop = action((e: Event, de: DragManager.DropEvent) => {
const drop = { docs: de.complete.docDragData?.droppedDocuments, val: this.getValue(this._heading) };
- drop.docs?.forEach(d => Doc.SetInPlace(d, this.props.pivotField, drop.val, false));
+ this.props.pivotField && drop.docs?.forEach(d => Doc.SetInPlace(d, this.props.pivotField, drop.val, false));
});
getValue = (value: string): any => {
const parsed = parseInt(value);
@@ -107,7 +107,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
headingChanged = (value: string, shiftDown?: boolean) => {
const castedValue = this.getValue(value);
if (castedValue) {
- if (this.props.columnHeaders?.map(i => i.heading).indexOf(castedValue.toString()) !== -1) {
+ if (this.props.colHeaderData?.map(i => i.heading).indexOf(castedValue.toString()) !== -1) {
return false;
}
this.props.docList.forEach(d => (d[this.props.pivotField] = castedValue));
@@ -128,13 +128,13 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
@action pointerEntered = () => SnappingManager.GetIsDragging() && (this._background = '#b4b4b4');
@action pointerLeave = () => (this._background = 'inherit');
- textCallback = (char: string) => this.addNewTextDoc('-typed text-', false, true);
+ @undoBatch typedNote = (char: string) => this.addNewTextDoc('-typed text-', false, true);
@action
addNewTextDoc = (value: string, shiftDown?: boolean, forceEmptyNote?: boolean) => {
if (!value && !forceEmptyNote) return false;
const key = this.props.pivotField;
- const newDoc = Docs.Create.TextDocument(value, { _height: 18, _width: 200, _fitWidth: true, title: value, _autoHeight: true });
+ const newDoc = Docs.Create.TextDocument(value, { _height: 18, _width: 200, _layout_fitWidth: true, title: value, _layout_autoHeight: true });
newDoc[key] = this.getValue(this.props.heading);
const maxHeading = this.props.docList.reduce((maxHeading, doc) => (NumCast(doc.heading) > maxHeading ? NumCast(doc.heading) : maxHeading), 0);
const heading = maxHeading === 0 || this.props.docList.length === 0 ? 1 : maxHeading === 1 ? 2 : 3;
@@ -147,9 +147,9 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
@action
deleteColumn = () => {
this.props.docList.forEach(d => (d[this.props.pivotField] = undefined));
- if (this.props.columnHeaders && this.props.headingObject) {
- const index = this.props.columnHeaders.indexOf(this.props.headingObject);
- this.props.columnHeaders.splice(index, 1);
+ if (this.props.colHeaderData && this.props.headingObject) {
+ const index = this.props.colHeaderData.indexOf(this.props.headingObject);
+ this.props.colHeaderData.splice(index, 1);
}
};
@@ -163,15 +163,15 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
//TODO: I think this is where I'm supposed to edit stuff
startDrag = (e: PointerEvent, down: number[], delta: number[]) => {
- // is MakeAlias a way to make a copy of a doc without rendering it?
- const alias = Doc.MakeAlias(this.props.Document);
- alias._width = this.props.columnWidth / (this.props.columnHeaders?.length || 1);
- alias._pivotField = undefined;
+ // is MakeEmbedding a way to make a copy of a doc without rendering it?
+ const embedding = Doc.MakeEmbedding(this.props.Document);
+ embedding._width = this.props.columnWidth / (this.props.colHeaderData?.length || 1);
+ embedding._pivotField = undefined;
let value = this.getValue(this._heading);
value = typeof value === 'string' ? `"${value}"` : value;
- alias.viewSpecScript = ScriptField.MakeFunction(`doc.${this.props.pivotField} === ${value}`, { doc: Doc.name });
- if (alias.viewSpecScript) {
- DragManager.StartDocumentDrag([this._headerRef.current!], new DragManager.DocumentDragData([alias]), e.clientX, e.clientY);
+ embedding.viewSpecScript = ScriptField.MakeFunction(`doc.${this.props.pivotField} === ${value}`, { doc: Doc.name });
+ if (embedding.viewSpecScript) {
+ DragManager.StartDocumentDrag([this._headerRef.current!], new DragManager.DocumentDragData([embedding]), e.clientX, e.clientY);
return true;
}
return false;
@@ -266,7 +266,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
!Doc.noviceMode && ContextMenu.Instance.addItem({ description: 'Containers ...', subitems: layoutItems, icon: 'eye' });
ContextMenu.Instance.setDefaultItem('::', (name: string): void => {
Doc.GetProto(this.props.Document)[name] = '';
- const created = Docs.Create.TextDocument('', { title: name, _width: 250, _autoHeight: true });
+ const created = Docs.Create.TextDocument('', { title: name, _width: 250, _layout_autoHeight: true });
if (created) {
if (this.props.Document.isTemplateDoc) {
Doc.MakeMetadataFieldTemplate(created, this.props.Document);
@@ -363,7 +363,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
<EditableView
GetValue={returnEmptyString}
SetValue={this.addNewTextDoc}
- textCallback={this.textCallback}
+ textCallback={this.typedNote}
placeholder={"Type ':' for commands"}
contents={<FontAwesomeIcon icon={'plus'} />}
menuCallback={this.menuCallback}
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 5b9453666..d1b7f6ff6 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -1,11 +1,11 @@
import { action, computed, observable } from 'mobx';
import * as rp from 'request-promise';
import CursorField from '../../../fields/CursorField';
-import { AclPrivate, Doc, DocListCast, Field, Opt, StrListCast } from '../../../fields/Doc';
+import { Doc, DocListCast, Field, Opt, StrListCast } from '../../../fields/Doc';
+import { AclPrivate } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
import { List } from '../../../fields/List';
import { listSpec } from '../../../fields/Schema';
-import { ScriptField } from '../../../fields/ScriptField';
import { Cast, ScriptCast, StrCast } from '../../../fields/Types';
import { WebField } from '../../../fields/URLField';
import { GestureUtils } from '../../../pen-gestures/GestureUtils';
@@ -28,8 +28,8 @@ export function CollectionSubView<X>(moreProps?: X) {
private gestureDisposer?: GestureUtils.GestureEventDisposer;
protected _multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer;
protected _mainCont?: HTMLDivElement;
- @observable _focusFilters: Opt<string[]>; // docFilters that are overridden when previewing a link to an anchor which has docFilters set on it
- @observable _focusRangeFilters: Opt<string[]>; // docRangeFilters that are overridden when previewing a link to an anchor which has docRangeFilters set on it
+ @observable _focusFilters: Opt<string[]>; // childFilters that are overridden when previewing a link to an anchor which has childFilters set on it
+ @observable _focusRangeFilters: Opt<string[]>; // childFiltersByRanges that are overridden when previewing a link to an anchor which has childFiltersByRanges set on it
protected createDashEventsTarget = (ele: HTMLDivElement | null) => {
//used for stacking and masonry view
this.dropDisposer?.();
@@ -65,11 +65,7 @@ export function CollectionSubView<X>(moreProps?: X) {
// to its children which may be templates.
// If 'annotationField' is specified, then all children exist on that field of the extension document, otherwise, they exist directly on the data document under 'fieldKey'
@computed get dataField() {
- if (this.layoutDoc[this.props.fieldKey]) return this.layoutDoc[this.props.fieldKey];
- // sets the dataDoc's data field to an empty list if the data field is undefined - prevents issues with addonly
- // setTimeout changes it outside of the @computed section
- !this.dataDoc[this.props.fieldKey] && setTimeout(() => !this.dataDoc[this.props.fieldKey] && (this.dataDoc[this.props.fieldKey] = new List<Doc>()));
- return this.dataDoc[this.props.fieldKey];
+ return this.layoutDoc[this.props.fieldKey];
}
get childLayoutPairs(): { layout: Doc; data: Doc }[] {
@@ -85,13 +81,13 @@ export function CollectionSubView<X>(moreProps?: X) {
get childDocList() {
return Cast(this.dataField, listSpec(Doc));
}
- collectionFilters = () => this._focusFilters ?? StrListCast(this.props.Document._docFilters);
- collectionRangeDocFilters = () => this._focusRangeFilters ?? Cast(this.props.Document._docRangeFilters, listSpec('string'), []);
+ collectionFilters = () => this._focusFilters ?? StrListCast(this.props.Document._childFilters);
+ collectionRangeDocFilters = () => this._focusRangeFilters ?? Cast(this.props.Document._childFiltersByRanges, listSpec('string'), []);
// child filters apply to the descendants of the documents in this collection
- childDocFilters = () => [...(this.props.docFilters?.().filter(f => Utils.IsRecursiveFilter(f)) || []), ...this.collectionFilters()];
+ childDocFilters = () => [...(this.props.childFilters?.().filter(f => Utils.IsRecursiveFilter(f)) || []), ...this.collectionFilters()];
// unrecursive filters apply to the documents in the collection, but no their children. See Utils.noRecursionHack
- unrecursiveDocFilters = () => [...(this.props.docFilters?.().filter(f => !Utils.IsRecursiveFilter(f)) || [])];
- childDocRangeFilters = () => [...(this.props.docRangeFilters?.() || []), ...this.collectionRangeDocFilters()];
+ unrecursiveDocFilters = () => [...(this.props.childFilters?.().filter(f => !Utils.IsRecursiveFilter(f)) || [])];
+ childDocRangeFilters = () => [...(this.props.childFiltersByRanges?.() || []), ...this.collectionRangeDocFilters()];
searchFilterDocs = () => this.props.searchFilterDocs?.() ?? DocListCast(this.props.Document._searchFilterDocs);
@computed.struct get childDocs() {
TraceMobx();
@@ -110,38 +106,41 @@ export function CollectionSubView<X>(moreProps?: X) {
rawdocs = rootDoc && !this.props.isAnnotationOverlay ? [Doc.GetProto(rootDoc)] : [];
}
- const childDocs = rawdocs.filter(d => !(d instanceof Promise) && GetEffectiveAcl(Doc.GetProto(d)) !== AclPrivate && (this.props.ignoreUnrendered || !d.unrendered)).map(d => d as Doc);
+ const childDocs = rawdocs.filter(d => !(d instanceof Promise) && GetEffectiveAcl(Doc.GetProto(d)) !== AclPrivate && (this.props.ignoreUnrendered || !d.layout_unrendered)).map(d => d as Doc);
const childDocFilters = this.childDocFilters();
- const docRangeFilters = this.childDocRangeFilters();
+ const childFiltersByRanges = this.childDocRangeFilters();
const searchDocs = this.searchFilterDocs();
- if (this.props.Document.dontRegisterView || (!childDocFilters.length && !this.unrecursiveDocFilters().length && !docRangeFilters.length && !searchDocs.length)) {
+ if (this.props.Document.dontRegisterView || (!childDocFilters.length && !this.unrecursiveDocFilters().length && !childFiltersByRanges.length && !searchDocs.length)) {
return childDocs.filter(cd => !cd.cookies); // remove any documents that require a cookie if there are no filters to provide one
}
const docsforFilter: Doc[] = [];
childDocs.forEach(d => {
// dragging facets
- const dragged = this.props.docFilters?.().some(f => f.includes(Utils.noDragsDocFilter));
+ const dragged = this.props.childFilters?.().some(f => f.includes(Utils.noDragsDocFilter));
if (dragged && DragManager.docsBeingDragged.includes(d)) return false;
- let notFiltered = d.z || Doc.IsSystem(d) || DocUtils.FilterDocs([d], this.unrecursiveDocFilters(), docRangeFilters, this.props.Document).length > 0;
+ let notFiltered = d.z || Doc.IsSystem(d) || DocUtils.FilterDocs([d], this.unrecursiveDocFilters(), childFiltersByRanges, this.props.Document).length > 0;
if (notFiltered) {
- notFiltered = (!searchDocs.length || searchDocs.includes(d)) && DocUtils.FilterDocs([d], childDocFilters, docRangeFilters, this.props.Document).length > 0;
+ notFiltered = (!searchDocs.length || searchDocs.includes(d)) && DocUtils.FilterDocs([d], childDocFilters, childFiltersByRanges, this.props.Document).length > 0;
const fieldKey = Doc.LayoutFieldKey(d);
const annos = !Field.toString(Doc.LayoutField(d) as Field).includes(CollectionView.name);
- const data = d[annos ? fieldKey + '-annotations' : fieldKey];
- if (data !== undefined) {
- let subDocs = DocListCast(data);
+ const data = d[annos ? fieldKey + '_annotations' : fieldKey];
+ const side = annos && d[fieldKey + '_sidebar'];
+ if (data !== undefined || side !== undefined) {
+ let subDocs = [...DocListCast(data), ...DocListCast(side)];
if (subDocs.length > 0) {
let newarray: Doc[] = [];
- notFiltered = notFiltered || (!searchDocs.length && DocUtils.FilterDocs(subDocs, childDocFilters, docRangeFilters, d).length);
+ notFiltered = notFiltered || (!searchDocs.length && DocUtils.FilterDocs(subDocs, childDocFilters, childFiltersByRanges, d).length);
while (subDocs.length > 0 && !notFiltered) {
newarray = [];
subDocs.forEach(t => {
const fieldKey = Doc.LayoutFieldKey(t);
const annos = !Field.toString(Doc.LayoutField(t) as Field).includes(CollectionView.name);
- notFiltered = notFiltered || ((!searchDocs.length || searchDocs.includes(t)) && ((!childDocFilters.length && !docRangeFilters.length) || DocUtils.FilterDocs([t], childDocFilters, docRangeFilters, d).length));
- DocListCast(t[annos ? fieldKey + '-annotations' : fieldKey]).forEach(newdoc => newarray.push(newdoc));
+ notFiltered =
+ notFiltered || ((!searchDocs.length || searchDocs.includes(t)) && ((!childDocFilters.length && !childFiltersByRanges.length) || DocUtils.FilterDocs([t], childDocFilters, childFiltersByRanges, d).length));
+ DocListCast(t[annos ? fieldKey + '_annotations' : fieldKey]).forEach(newdoc => newarray.push(newdoc));
+ annos && DocListCast(t[fieldKey + '_sidebar']).forEach(newdoc => newarray.push(newdoc));
});
subDocs = newarray;
}
@@ -188,9 +187,9 @@ export function CollectionSubView<X>(moreProps?: X) {
protected onInternalPreDrop(e: Event, de: DragManager.DropEvent, targetAction: dropActionType) {
if (de.complete.docDragData) {
- // if targetDropAction is, say 'alias', but we're just dragging within a collection, we want to ignore the targetAction.
+ // if targetDropAction is, say 'embed', but we're just dragging within a collection, we want to ignore the targetAction.
// otherwise, the targetAction should become the actual action (which can still be overridden by the userDropAction -eg, shift/ctrl keys)
- if (targetAction && !de.complete.docDragData.draggedDocuments.some(d => d.context === this.props.Document && this.childDocs.includes(d))) {
+ if (targetAction && !de.complete.docDragData.draggedDocuments.some(d => d.embedContainer === this.props.Document && this.childDocs.includes(d))) {
de.complete.docDragData.dropAction = targetAction;
}
e.stopPropagation();
@@ -213,7 +212,7 @@ export function CollectionSubView<X>(moreProps?: X) {
const movedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] === d);
const addedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] !== d);
if (movedDocs.length) {
- const canAdd = this.props.Document._viewType === CollectionViewType.Pile || de.embedKey || this.props.Document.allowOverlayDrop || Doc.AreProtosEqual(Cast(movedDocs[0].annotationOn, Doc, null), this.props.Document);
+ const canAdd = this.props.Document._type_collection === CollectionViewType.Pile || de.embedKey || this.props.Document.allowOverlayDrop || Doc.AreProtosEqual(Cast(movedDocs[0].annotationOn, Doc, null), this.props.Document);
added = docDragData.moveDocument(movedDocs, this.props.Document, canAdd ? this.addDocument : returnFalse);
} else {
ScriptCast(this.props.Document.dropConverter)?.script.run({ dragData: docDragData });
@@ -282,7 +281,7 @@ export function CollectionSubView<X>(moreProps?: X) {
addDocument(Docs.Create.WebDocument(href, { ...options, title: href }));
}
} else if (text) {
- addDocument(Docs.Create.TextDocument(text, { ...options, _showTitle: StrCast(Doc.UserDoc().showTitle), _width: 100, _height: 25 }));
+ addDocument(Docs.Create.TextDocument(text, { ...options, _layout_showTitle: StrCast(Doc.UserDoc().layout_showTitle), _width: 100, _height: 25 }));
}
return;
}
@@ -375,7 +374,7 @@ export function CollectionSubView<X>(moreProps?: X) {
_width: 400,
_height: 512,
_nativeWidth: 850,
- useCors: true,
+ data_useCors: true,
})
);
return;
@@ -417,7 +416,7 @@ export function CollectionSubView<X>(moreProps?: X) {
proto._height = 20;
return proto;
}),
- { _width: 150, _height: 600, title: 'across', backgroundColor: 'white', _singleLine: true }
+ { _width: 150, _height: 600, title: 'across', backgroundColor: 'white', _createDocOnCR: true }
)
);
});
@@ -448,7 +447,7 @@ export function CollectionSubView<X>(moreProps?: X) {
}
if (generatedDocuments.length) {
// Creating a dash document
- const isFreeformView = this.props.Document._viewType === CollectionViewType.Freeform;
+ const isFreeformView = this.props.Document._type_collection === CollectionViewType.Freeform;
const set = !isFreeformView
? generatedDocuments
: generatedDocuments.length > 1
diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx
index 3cdb460a3..60e6815e5 100644
--- a/src/client/views/collections/CollectionTimeView.tsx
+++ b/src/client/views/collections/CollectionTimeView.tsx
@@ -35,7 +35,7 @@ export class CollectionTimeView extends CollectionSubView() {
async componentDidMount() {
this.props.setContentView?.(this);
//const detailView = (await DocCastAsync(this.props.Document.childClickedOpenTemplateView)) || DocUtils.findTemplate("detailView", StrCast(this.rootDoc.type), "");
- ///const childText = "const alias = getAlias(self); switchView(alias, detailView); alias.dropAction='alias'; useRightSplit(alias, shiftKey); ";
+ ///const childText = "const embedding = getEmbedding(self); switchView(embedding, detailView); embedding.dropAction='embed'; useRightSplit(embedding, shiftKey); ";
runInAction(() => {
this._childClickedScript = ScriptField.MakeScript('openInLightbox(self)', { this: Doc.name });
this._viewDefDivClick = ScriptField.MakeScript('pivotColumnClick(this,payload)', { payload: 'any' });
@@ -47,18 +47,18 @@ export class CollectionTimeView extends CollectionSubView() {
}
getAnchor = (addAsAnnotation: boolean) => {
- const anchor = Docs.Create.HTMLAnchorDocument([], {
+ const anchor = Docs.Create.HTMLMarkerDocument([], {
title: ComputedField.MakeFunction(`"${this.pivotField}"])`) as any,
annotationOn: this.rootDoc,
});
- PresBox.pinDocView(anchor, { pinData: { viewType: true, pivot: true, filters: true } }, this.rootDoc);
+ PresBox.pinDocView(anchor, { pinData: { type_collection: true, pivot: true, filters: true } }, this.rootDoc);
if (addAsAnnotation) {
// when added as an annotation, links to anchors can be found as links to the document even if the anchors are not rendered
- if (Cast(this.dataDoc[this.props.fieldKey + '-annotations'], listSpec(Doc), null) !== undefined) {
- Cast(this.dataDoc[this.props.fieldKey + '-annotations'], listSpec(Doc), []).push(anchor);
+ if (Cast(this.dataDoc[this.props.fieldKey + '_annotations'], listSpec(Doc), null) !== undefined) {
+ Cast(this.dataDoc[this.props.fieldKey + '_annotations'], listSpec(Doc), []).push(anchor);
} else {
- this.dataDoc[this.props.fieldKey + '-annotations'] = new List<Doc>([anchor]);
+ this.dataDoc[this.props.fieldKey + '_annotations'] = new List<Doc>([anchor]);
}
}
return anchor;
@@ -125,8 +125,8 @@ export class CollectionTimeView extends CollectionSubView() {
goTo = (prevFilterIndex: number) => {
this.layoutDoc._pivotField = this.layoutDoc['_prevPivotFields' + prevFilterIndex];
- this.layoutDoc._docFilters = ObjectField.MakeCopy(this.layoutDoc['_prevDocFilter' + prevFilterIndex] as ObjectField);
- this.layoutDoc._docRangeFilters = ObjectField.MakeCopy(this.layoutDoc['_prevDocRangeFilters' + prevFilterIndex] as ObjectField);
+ this.layoutDoc._childFilters = ObjectField.MakeCopy(this.layoutDoc['_prevDocFilter' + prevFilterIndex] as ObjectField);
+ this.layoutDoc._childFiltersByRanges = ObjectField.MakeCopy(this.layoutDoc['_prevDocRangeFilters' + prevFilterIndex] as ObjectField);
this.layoutDoc._prevFilterIndex = prevFilterIndex;
};
@@ -136,7 +136,7 @@ export class CollectionTimeView extends CollectionSubView() {
if (prevFilterIndex > 0) {
this.goTo(prevFilterIndex - 1);
} else {
- this.layoutDoc._docFilters = new List([]);
+ this.layoutDoc._childFilters = new List([]);
}
};
@@ -145,7 +145,7 @@ export class CollectionTimeView extends CollectionSubView() {
<div className="collectionTimeView-innards" key="timeline" style={{ pointerEvents: this.props.isContentActive() ? undefined : 'none' }} onClick={this.contentsDown}>
<CollectionFreeFormView
{...this.props}
- engineProps={{ pivotField: this.pivotField, docFilters: this.childDocFilters, docRangeFilters: this.childDocRangeFilters }}
+ engineProps={{ pivotField: this.pivotField, childFilters: this.childDocFilters, childFiltersByRanges: this.childDocRangeFilters }}
fitContentsToBox={returnTrue}
childClickScript={this._childClickedScript}
viewDefDivClick={this.layoutEngine() === computeTimelineLayout.name ? undefined : this._viewDefDivClick}
@@ -276,12 +276,12 @@ export class CollectionTimeView extends CollectionSubView() {
ScriptingGlobals.add(function pivotColumnClick(pivotDoc: Doc, bounds: ViewDefBounds) {
const pivotField = StrCast(pivotDoc._pivotField, 'author');
let prevFilterIndex = NumCast(pivotDoc._prevFilterIndex);
- const originalFilter = StrListCast(ObjectField.MakeCopy(pivotDoc._docFilters as ObjectField));
- pivotDoc['_prevDocFilter' + prevFilterIndex] = ObjectField.MakeCopy(pivotDoc._docFilters as ObjectField);
- pivotDoc['_prevDocRangeFilters' + prevFilterIndex] = ObjectField.MakeCopy(pivotDoc._docRangeFilters as ObjectField);
+ const originalFilter = StrListCast(ObjectField.MakeCopy(pivotDoc._childFilters as ObjectField));
+ pivotDoc['_prevDocFilter' + prevFilterIndex] = ObjectField.MakeCopy(pivotDoc._childFilters as ObjectField);
+ pivotDoc['_prevDocRangeFilters' + prevFilterIndex] = ObjectField.MakeCopy(pivotDoc._childFiltersByRanges as ObjectField);
pivotDoc['_prevPivotFields' + prevFilterIndex] = pivotField;
pivotDoc._prevFilterIndex = ++prevFilterIndex;
- pivotDoc._docFilters = new List();
+ pivotDoc._childFilters = new List();
setTimeout(
action(() => {
const filterVals = bounds.payload as string[];
@@ -292,7 +292,7 @@ ScriptingGlobals.add(function pivotColumnClick(pivotDoc: Doc, bounds: ViewDefBou
pivotDoc._pivotField = filterVals[0];
}
}
- const newFilters = StrListCast(pivotDoc._docFilters);
+ const newFilters = StrListCast(pivotDoc._childFilters);
if (newFilters.length && originalFilter.length && newFilters.lastElement() === originalFilter.lastElement()) {
pivotDoc._prevFilterIndex = --prevFilterIndex;
pivotDoc['_prevDocFilter' + prevFilterIndex] = undefined;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index f81c17a7b..ed1e0c067 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -1,6 +1,7 @@
import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
-import { DataSym, Doc, DocListCast, HeightSym, Opt, StrListCast, WidthSym } from '../../../fields/Doc';
+import { Doc, DocListCast, Opt, StrListCast } from '../../../fields/Doc';
+import { DocData, Height, Width } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
import { InkTool } from '../../../fields/InkField';
import { listSpec } from '../../../fields/Schema';
@@ -104,7 +105,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
componentDidMount() {
//this.props.setContentView?.(this);
this._disposers.autoheight = reaction(
- () => this.rootDoc.autoHeight,
+ () => this.rootDoc.layout_autoHeight,
auto => auto && this.computeHeight(),
{ fireImmediately: true }
);
@@ -114,25 +115,25 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
if (!this._isDisposing) {
const titleHeight = !this._titleRef ? this.marginTop() : Number(getComputedStyle(this._titleRef).height.replace('px', ''));
const bodyHeight = Array.from(this.refList).reduce((p, r) => p + Number(getComputedStyle(r).height.replace('px', '')), this.marginBot()) + 6;
- this.layoutDoc._autoHeightMargins = bodyHeight;
+ this.layoutDoc._layout_autoHeightMargins = bodyHeight;
!this.props.dontRegisterView && this.props.setHeight?.(bodyHeight + titleHeight);
}
};
unobserveHeight = (ref: any) => {
this.refList.delete(ref);
- this.rootDoc.autoHeight && this.computeHeight();
+ this.rootDoc.layout_autoHeight && this.computeHeight();
};
observeHeight = (ref: any) => {
if (ref) {
this.refList.add(ref);
this.observer = new _global.ResizeObserver(
action((entries: any) => {
- if (this.rootDoc.autoHeight && ref && this.refList.size && !SnappingManager.GetIsDragging()) {
+ if (this.rootDoc.layout_autoHeight && ref && this.refList.size && !SnappingManager.GetIsDragging()) {
this.computeHeight();
}
})
);
- this.rootDoc.autoHeight && this.computeHeight();
+ this.rootDoc.layout_autoHeight && this.computeHeight();
this.observer.observe(ref);
}
};
@@ -144,7 +145,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
protected onInternalPreDrop = (e: Event, de: DragManager.DropEvent, targetAction: dropActionType) => {
const dragData = de.complete.docDragData;
if (dragData) {
- const isInTree = () => Doc.AreProtosEqual(dragData.treeViewDoc, this.props.Document) || dragData.draggedDocuments.some(d => d.context === this.doc && this.childDocs.includes(d));
+ const isInTree = () => Doc.AreProtosEqual(dragData.treeViewDoc, this.props.Document) || dragData.draggedDocuments.some(d => d.embedContainer === this.doc && this.childDocs.includes(d));
dragData.dropAction = targetAction && !isInTree() ? targetAction : this.doc === dragData?.treeViewDoc ? 'same' : dragData.dropAction;
}
};
@@ -154,15 +155,15 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
@action
remove = (doc: Doc | Doc[]): boolean => {
const docs = doc instanceof Doc ? [doc] : doc;
- const targetDataDoc = this.doc[DataSym];
+ const targetDataDoc = this.doc[DocData];
const value = DocListCast(targetDataDoc[this.props.fieldKey]);
const result = value.filter(v => !docs.includes(v));
if ((doc instanceof Doc ? [doc] : doc).some(doc => SelectionManager.Views().some(dv => Doc.AreProtosEqual(dv.rootDoc, doc)))) SelectionManager.DeselectAll();
- if (result.length !== value.length) {
- const ind = targetDataDoc[this.props.fieldKey].indexOf(doc);
- const prev = ind && targetDataDoc[this.props.fieldKey][ind - 1];
+ if (result.length !== value.length && doc instanceof Doc) {
+ const ind = DocListCast(targetDataDoc[this.props.fieldKey]).indexOf(doc);
+ const prev = ind && DocListCast(targetDataDoc[this.props.fieldKey])[ind - 1];
this.props.removeDocument?.(doc);
- if (ind > 0) {
+ if (ind > 0 && prev) {
FormattedTextBox.SelectOnLoad = prev[Id];
DocumentManager.Instance.getDocumentView(prev, this.props.DocumentView?.())?.select(false);
}
@@ -175,8 +176,8 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
addDoc = (docs: Doc | Doc[], relativeTo: Opt<Doc>, before?: boolean): boolean => {
const doAddDoc = (doc: Doc | Doc[]) =>
(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);
+ const res = flg && Doc.AddDocToList(this.doc[DocData], this.props.fieldKey, doc, relativeTo, before);
+ res && (doc.embedContainer = this.props.Document);
return res;
}, true);
if (this.doc.resolvedDataDoc instanceof Promise) return false;
@@ -229,18 +230,18 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
return (
<FormattedTextBox
{...this.props}
- fieldKey={'text'}
+ fieldKey="text"
renderDepth={this.props.renderDepth + 1}
isContentActive={this.isContentActive}
isDocumentActive={this.isContentActive}
rootSelected={returnTrue}
- forceAutoHeight={true} // needed to make the title resize even if the rest of the tree view is not autoHeight
+ forceAutoHeight={true} // needed to make the title resize even if the rest of the tree view is not layout_autoHeight
PanelWidth={this.documentTitleWidth}
PanelHeight={this.documentTitleHeight}
NativeDimScaling={returnOne}
onKey={this.onKey}
- docFilters={returnEmptyFilter}
- docRangeFilters={returnEmptyFilter}
+ childFilters={returnEmptyFilter}
+ childFiltersByRanges={returnEmptyFilter}
searchFilterDocs={returnEmptyDoclist}
addDocument={returnFalse}
moveDocument={returnFalse}
@@ -313,12 +314,12 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
}
@computed get noviceExplainer() {
- return !Doc.noviceMode || !this.rootDoc.explainer ? null : <div className="documentExplanation"> {StrCast(this.rootDoc.explainer)} </div>;
+ return !Doc.noviceMode || !this.rootDoc.layout_explainer ? null : <div className="documentExplanation"> {StrCast(this.rootDoc.layout_explainer)} </div>;
}
return35 = () => 35;
@computed get buttonMenu() {
- const menuDoc = Cast(this.rootDoc.buttonMenuDoc, Doc, null);
+ const menuDoc = Cast(this.rootDoc.layout_headerButton, Doc, null);
// To create a multibutton menu add a CollectionLinearView
return !menuDoc ? null : (
<div className="buttonMenu-docBtn" style={{ width: NumCast(menuDoc._width, 30), height: NumCast(menuDoc._height, 30) }}>
@@ -342,8 +343,8 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
docViewPath={returnEmptyDoclist}
whenChildContentsActiveChanged={emptyFunction}
bringToFront={emptyFunction}
- docFilters={this.props.docFilters}
- docRangeFilters={this.props.docRangeFilters}
+ childFilters={this.props.childFilters}
+ childFiltersByRanges={this.props.childFiltersByRanges}
searchFilterDocs={this.props.searchFilterDocs}
/>
</div>
@@ -368,16 +369,16 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
marginX = () => NumCast(this.doc._xMargin);
marginTop = () => NumCast(this.doc._yMargin);
marginBot = () => NumCast(this.doc._yMargin);
- documentTitleWidth = () => Math.min(this.layoutDoc?.[WidthSym](), this.panelWidth());
- documentTitleHeight = () => (this.layoutDoc?.[HeightSym]() || 0) - NumCast(this.layoutDoc.autoHeightMargins);
+ documentTitleWidth = () => Math.min(this.layoutDoc?.[Width](), this.panelWidth());
+ documentTitleHeight = () => (this.layoutDoc?.[Height]() || 0) - NumCast(this.layoutDoc.layout_autoHeightMargins);
truncateTitleWidth = () => this.treeViewtruncateTitleWidth;
onChildClick = () => this.props.onChildClick?.() || ScriptCast(this.doc.onChildClick);
panelWidth = () => Math.max(0, this.props.PanelWidth() - 2 * this.marginX() * (this.props.NativeDimScaling?.() || 1));
- addAnnotationDocument = (doc: Doc | Doc[]) => this.addDocument(doc, `${this.props.fieldKey}-annotations`) || false;
- remAnnotationDocument = (doc: Doc | Doc[]) => this.removeDocument(doc, `${this.props.fieldKey}-annotations`) || false;
+ addAnnotationDocument = (doc: Doc | Doc[]) => this.addDocument(doc, `${this.props.fieldKey}_annotations`) || false;
+ remAnnotationDocument = (doc: Doc | Doc[]) => this.removeDocument(doc, `${this.props.fieldKey}_annotations`) || false;
moveAnnotationDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[], annotationKey?: string) => boolean) =>
- this.moveDocument(doc, targetCollection, addDocument, `${this.props.fieldKey}-annotations`) || false;
+ this.moveDocument(doc, targetCollection, addDocument, `${this.props.fieldKey}_annotations`) || false;
@observable _headerHeight = 0;
@computed get content() {
@@ -430,7 +431,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
render() {
TraceMobx();
- const scale = (this.props.NativeDimScaling?.() || 1) * NumCast(this.layoutDoc._viewScale, 1) || 1;
+ 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 ? (
@@ -443,7 +444,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
isAnnotationOverlay={true}
isAnnotationOverlayScrollable={true}
childDocumentsActive={this.props.isDocumentActive}
- fieldKey={this.props.fieldKey + '-annotations'}
+ fieldKey={this.props.fieldKey + '_annotations'}
dropAction={'move'}
select={emptyFunction}
addDocument={this.addAnnotationDocument}
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index b76033a0c..7913d3188 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -47,8 +47,8 @@ interface CollectionViewProps_ extends FieldViewProps {
childDocuments?: Doc[]; // used to override the documents shown by the sub collection to an explicit list (see LinkBox)
childDocumentsActive?: () => boolean | undefined; // whether child documents can be dragged if collection can be dragged (eg., in a when a Pile document is in startburst mode)
childContentsActive?: () => boolean | undefined;
- childFitWidth?: (child: Doc) => boolean;
- childShowTitle?: () => string;
+ childLayoutFitWidth?: (child: Doc) => boolean;
+ childlayout_showTitle?: () => string;
childOpacity?: () => number;
childContextMenuItems?: () => { script: ScriptField; label: string }[];
childHideTitle?: () => boolean; // whether to hide the documentdecorations title for children
@@ -87,7 +87,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatab
}
get collectionViewType(): CollectionViewType | undefined {
- const viewField = StrCast(this.layoutDoc._viewType);
+ const viewField = StrCast(this.layoutDoc._type_collection);
if (CollectionView._safeMode) {
switch (viewField) {
case CollectionViewType.Freeform:
@@ -127,15 +127,15 @@ export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatab
}
};
- setupViewTypes(category: string, func: (viewType: CollectionViewType) => Doc) {
- if (!Doc.IsSystem(this.rootDoc) && this.rootDoc._viewType !== CollectionViewType.Docking && !this.rootDoc.isGroup && !this.rootDoc.annotationOn) {
+ setupViewTypes(category: string, func: (type_collection: CollectionViewType) => Doc) {
+ if (!Doc.IsSystem(this.rootDoc) && this.rootDoc._type_collection !== CollectionViewType.Docking && !this.rootDoc.isGroup && !this.rootDoc.annotationOn) {
// prettier-ignore
const subItems: ContextMenuProps[] = [
{ description: 'Freeform', event: () => func(CollectionViewType.Freeform), icon: 'signature' },
{ description: 'Schema', event: () => func(CollectionViewType.Schema), icon: 'th-list' },
{ description: 'Tree', event: () => func(CollectionViewType.Tree), icon: 'tree' },
- { description: 'Stacking', event: () => (func(CollectionViewType.Stacking)._autoHeight = true), icon: 'ellipsis-v' },
- { description: 'Notetaking', event: () => (func(CollectionViewType.NoteTaking)._autoHeight = true), icon: 'ellipsis-v' },
+ { description: 'Stacking', event: () => (func(CollectionViewType.Stacking)._layout_autoHeight = true), icon: 'ellipsis-v' },
+ { description: 'Notetaking', event: () => (func(CollectionViewType.NoteTaking)._layout_autoHeight = true), icon: 'ellipsis-v' },
{ description: 'Multicolumn', event: () => func(CollectionViewType.Multicolumn), icon: 'columns' },
{ description: 'Multirow', event: () => func(CollectionViewType.Multirow), icon: 'columns' },
{ description: 'Masonry', event: () => func(CollectionViewType.Masonry), icon: 'columns' },
@@ -159,8 +159,8 @@ export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatab
// need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
!Doc.noviceMode &&
this.setupViewTypes('UI Controls...', vtype => {
- const newRendition = Doc.MakeAlias(this.rootDoc);
- newRendition._viewType = vtype;
+ const newRendition = Doc.MakeEmbedding(this.rootDoc);
+ newRendition._type_collection = vtype;
this.props.addDocTab(newRendition, OpenWhere.addRight);
return newRendition;
});
@@ -190,9 +190,9 @@ export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatab
description: `Edit ${func.name} script`,
icon: 'edit',
event: (obj: any) => {
- const alias = Doc.MakeAlias(this.rootDoc);
- DocUtils.makeCustomViewClicked(alias, undefined, func.key);
- this.props.addDocTab(alias, OpenWhere.addRight);
+ const embedding = Doc.MakeEmbedding(this.rootDoc);
+ DocUtils.makeCustomViewClicked(embedding, undefined, func.key);
+ this.props.addDocTab(embedding, OpenWhere.addRight);
},
})
);
@@ -244,7 +244,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent<ViewBoxAnnotatab
<div
className="collectionView"
onContextMenu={this.onContextMenu}
- style={{ pointerEvents: this.props.DocumentView?.()?.props.docViewPath().lastElement()?.rootDoc?._viewType === CollectionViewType.Freeform && this.rootDoc._lockedPosition ? 'none' : undefined }}>
+ style={{ pointerEvents: this.props.DocumentView?.()?.props.docViewPath().lastElement()?.rootDoc?._type_collection === CollectionViewType.Freeform && this.rootDoc._lockedPosition ? 'none' : undefined }}>
{this.renderSubView(this.collectionViewType, props)}
</div>
);
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 45604c1bf..75e4e8abf 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -5,22 +5,21 @@ import { clamp } from 'lodash';
import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as ReactDOM from 'react-dom/client';
-import { DataSym, Doc, HeightSym, Opt, WidthSym } from '../../../fields/Doc';
+import { Doc, Opt } from '../../../fields/Doc';
+import { DocData, Height, Width } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
import { List } from '../../../fields/List';
import { FieldId } from '../../../fields/RefField';
-import { listSpec } from '../../../fields/Schema';
import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../fields/Types';
import { emptyFunction, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick, Utils } from '../../../Utils';
import { DocServer } from '../../DocServer';
-import { DocUtils } from '../../documents/Documents';
import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
import { DocumentManager } from '../../util/DocumentManager';
import { DragManager, dropActionType } from '../../util/DragManager';
import { SelectionManager } from '../../util/SelectionManager';
import { SnappingManager } from '../../util/SnappingManager';
import { Transform } from '../../util/Transform';
-import { undoBatch, UndoManager } from '../../util/UndoManager';
+import { undoable, UndoManager } from '../../util/UndoManager';
import { DashboardView } from '../DashboardView';
import { Colors, Shadows } from '../global/globalEnums';
import { LightboxView } from '../LightboxView';
@@ -116,15 +115,13 @@ export class TabDocView extends React.Component<TabDocViewProps> {
titleEle.size = StrCast(doc.title).length + 3;
titleEle.value = doc.title;
- titleEle.onkeydown = (e: KeyboardEvent) => {
- e.stopPropagation();
- };
- titleEle.onchange = undoBatch(
- action((e: any) => {
+ titleEle.onkeydown = (e: KeyboardEvent) => e.stopPropagation();
+ titleEle.onchange = (e: any) => {
+ undoable(() => {
titleEle.size = e.currentTarget.value.length + 3;
Doc.GetProto(doc).title = e.currentTarget.value;
- })
- );
+ }, 'edit tab title')();
+ };
if (tab.element[0].children[1].children.length === 1) {
iconWrap.className = 'lm_iconWrap lm_moreInfo';
@@ -198,7 +195,9 @@ export class TabDocView extends React.Component<TabDocViewProps> {
action(selected => {
if (selected) this._activated = true;
const toggle = tab.element[0].children[2].children[0] as HTMLInputElement;
- selected && tab.contentItem !== tab.header.parent.getActiveContentItem() && UndoManager.RunInBatch(() => tab.header.parent.setActiveContentItem(tab.contentItem), 'tab switch');
+ if (selected && tab.contentItem !== tab.header.parent.getActiveContentItem()) {
+ undoable(() => tab.header.parent.setActiveContentItem(tab.contentItem), 'tab switch')();
+ }
toggle.style.fontWeight = selected ? 'bold' : '';
// toggle.style.textTransform = selected ? "uppercase" : "";
}),
@@ -234,7 +233,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
public static PinDoc(docs: Doc | Doc[], pinProps: PinProps) {
const docList = docs instanceof Doc ? [docs] : docs;
- const batch = UndoManager.StartBatch('pinning doc');
+ const batch = UndoManager.StartBatch('Pin doc to pres trail');
const curPres = Doc.ActivePresentation ?? Doc.MakeCopy(Doc.UserDoc().emptyTrail as Doc, true);
if (!Doc.ActivePresentation) {
@@ -252,11 +251,11 @@ export class TabDocView extends React.Component<TabDocViewProps> {
const pinDoc = Doc.MakeDelegate(anchorDoc && anchorDoc !== doc ? anchorDoc : doc);
pinDoc.presentationTargetDoc = anchorDoc ?? doc;
pinDoc.title = doc.title + ' - Slide';
- pinDoc.data = new List<Doc>(); // the children of the alias' layout are the presentation slide children. the alias' 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.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.context = curPres;
+ pinDoc.embedContainer = 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.
@@ -264,7 +263,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
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
- const duration = NumCast(doc[`${Doc.LayoutFieldKey(pinDoc)}-duration`], null);
+ const duration = NumCast(doc[`${Doc.LayoutFieldKey(pinDoc)}_duration`], null);
if (pinProps.pinViewport) PresBox.pinDocView(pinDoc, pinProps, anchorDoc ?? doc);
if (!pinProps?.audioRange && duration !== undefined) {
@@ -283,7 +282,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
pinDoc.title = doc.title + ' (move)';
pinDoc.presMovement = PresMovement.Pan;
}
- if (pinDoc.isInkMask) {
+ if (pinDoc.stroke_isInkMask) {
pinDoc.presHideAfter = true;
pinDoc.presHideBefore = true;
pinDoc.presMovement = PresMovement.None;
@@ -294,12 +293,12 @@ export class TabDocView extends React.Component<TabDocViewProps> {
pinDoc && PresBox.Instance?.addToSelectedArray(pinDoc); //Update selected array
});
if (
+ // open the presentation trail if it's not already opened
!Array.from(CollectionDockingView.Instance?.tabMap ?? [])
.map(d => d.DashDoc)
.includes(curPres)
) {
- const docs = Cast(Doc.MyOverlayDocs.data, listSpec(Doc), []);
- if (docs.includes(curPres)) docs.splice(docs.indexOf(curPres), 1);
+ if (Doc.IsInMyOverlay(curPres)) Doc.RemFromMyOverlay(curPres);
CollectionDockingView.AddSplit(curPres, OpenWhereMod.right);
setTimeout(() => DocumentManager.Instance.showDocument(docList.lastElement(), { willPan: true }), 100); // keeps the pinned doc in view since the sidebar shifts things
}
@@ -349,7 +348,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
// lightbox - will add the document to any collection along the path from the document to the docking view that has a field isLightbox. if none is found, it adds to the full screen lightbox
addDocTab = (doc: Doc, location: OpenWhere) => {
SelectionManager.DeselectAll();
- const whereFields = doc._viewType === CollectionViewType.Docking ? [OpenWhere.dashboard] : location.split(':');
+ const whereFields = doc._type_collection === CollectionViewType.Docking ? [OpenWhere.dashboard] : location.split(':');
const keyValue = whereFields[1]?.includes('KeyValue');
const whereMods: OpenWhereMod = whereFields.length > 1 ? (whereFields[1].replace('KeyValue', '') as OpenWhereMod) : OpenWhereMod.none;
if (doc.dockingConfig) return DashboardView.openDashboard(doc);
@@ -357,7 +356,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
switch (whereFields[0]) {
case undefined:
case OpenWhere.lightbox: if (this.layoutDoc?._isLightbox) {
- const lightboxView = !doc.annotationOn && DocCast(doc.context) ? DocumentManager.Instance.getFirstDocumentView(DocCast(doc.context)) : undefined;
+ const lightboxView = !doc.annotationOn && DocCast(doc.embedContainer) ? DocumentManager.Instance.getFirstDocumentView(DocCast(doc.embedContainer)) : undefined;
const data = lightboxView?.dataDoc[Doc.LayoutFieldKey(lightboxView.rootDoc)];
if (lightboxView && (!data || data instanceof List)) {
lightboxView.layoutDoc[Doc.LayoutFieldKey(lightboxView.rootDoc)] = new List<Doc>([doc]);
@@ -383,7 +382,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
};
getCurrentFrame = () => {
- return NumCast(Cast(PresBox.Instance.childDocs[PresBox.Instance.itemIndex].presentationTargetDoc, Doc, null)._currentFrame);
+ return NumCast(Cast(PresBox.Instance.activeItem.presentationTargetDoc, Doc, null)._currentFrame);
};
static Activate = (tabDoc: Doc) => {
const tab = Array.from(CollectionDockingView.Instance?.tabMap!).find(tab => tab.DashDoc === tabDoc);
@@ -408,8 +407,8 @@ export class TabDocView extends React.Component<TabDocViewProps> {
PanelHeight = () => this._panelHeight;
miniMapColor = () => this.tabColor;
tabView = () => this._view;
- disableMinimap = () => !this._document || this._document.layout !== CollectionView.LayoutString(Doc.LayoutFieldKey(this._document)) || this._document?._viewType !== CollectionViewType.Freeform;
- hideMinimap = () => this.disableMinimap() || BoolCast(this._document?.hideMinimap);
+ disableMinimap = () => !this._document || this._document.layout !== CollectionView.LayoutString(Doc.LayoutFieldKey(this._document)) || this._document?._type_collection !== CollectionViewType.Freeform;
+ hideMinimap = () => this.disableMinimap() || BoolCast(this._document?.layout_hideMinimap);
@computed get docView() {
return !this._activated || !this._document ? null : (
@@ -425,7 +424,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
LayoutTemplateString={this.props.keyValue ? KeyValueBox.LayoutString() : undefined}
hideTitle={this.props.keyValue}
Document={this._document}
- DataDoc={!Doc.AreProtosEqual(this._document[DataSym], this._document) ? this._document[DataSym] : undefined}
+ DataDoc={!Doc.AreProtosEqual(this._document[DocData], this._document) ? this._document[DocData] : undefined}
onBrowseClick={MainView.Instance.exploreMode}
waitForDoubleClickToClick={MainView.Instance.waitForDoubleClick}
isContentActive={returnTrue}
@@ -433,8 +432,8 @@ export class TabDocView extends React.Component<TabDocViewProps> {
PanelWidth={this.PanelWidth}
PanelHeight={this.PanelHeight}
styleProvider={DefaultStyleProvider}
- docFilters={CollectionDockingView.Instance?.childDocFilters ?? returnEmptyDoclist}
- docRangeFilters={CollectionDockingView.Instance?.childDocRangeFilters ?? returnEmptyDoclist}
+ childFilters={CollectionDockingView.Instance?.childDocFilters ?? returnEmptyDoclist}
+ childFiltersByRanges={CollectionDockingView.Instance?.childDocRangeFilters ?? returnEmptyDoclist}
searchFilterDocs={CollectionDockingView.Instance?.searchFilterDocs ?? returnEmptyDoclist}
addDocument={undefined}
removeDocument={this.remDocTab}
@@ -449,19 +448,19 @@ export class TabDocView extends React.Component<TabDocViewProps> {
pinToPres={TabDocView.PinDoc}
/>
<TabMinimapView key="minimap" hideMinimap={this.hideMinimap} addDocTab={this.addDocTab} PanelHeight={this.PanelHeight} PanelWidth={this.PanelWidth} background={this.miniMapColor} document={this._document} tabView={this.tabView} />
- <Tooltip key="ttip" title={<div className="dash-tooltip">{this._document.hideMinimap ? 'Open minimap' : 'Close minimap'}</div>}>
+ <Tooltip key="ttip" title={<div className="dash-tooltip">{this._document.layout_hideMinimap ? 'Open minimap' : 'Close minimap'}</div>}>
<div
className="miniMap-hidden"
style={{
- display: this.disableMinimap() || this._document._viewType !== 'freeform' ? 'none' : undefined,
- color: this._document.hideMinimap ? Colors.BLACK : Colors.WHITE,
- backgroundColor: this._document.hideMinimap ? Colors.LIGHT_GRAY : Colors.MEDIUM_BLUE,
- boxShadow: this._document.hideMinimap ? Shadows.STANDARD_SHADOW : undefined,
+ display: this.disableMinimap() || this._document._type_collection !== 'freeform' ? 'none' : undefined,
+ color: this._document.layout_hideMinimap ? Colors.BLACK : Colors.WHITE,
+ backgroundColor: this._document.layout_hideMinimap ? Colors.LIGHT_GRAY : Colors.MEDIUM_BLUE,
+ boxShadow: this._document.layout_hideMinimap ? Shadows.STANDARD_SHADOW : undefined,
}}
onPointerDown={e => e.stopPropagation()}
onClick={action(e => {
e.stopPropagation();
- this._document!.hideMinimap = !this._document!.hideMinimap;
+ this._document!.layout_hideMinimap = !this._document!.layout_hideMinimap;
})}>
<FontAwesomeIcon icon={'globe-asia'} size="lg" />
</div>
@@ -535,7 +534,7 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
return 'gray';
}
})(doc.type as DocumentType);
- return !background ? undefined : <div style={{ width: doc[WidthSym](), height: doc[HeightSym](), position: 'absolute', display: 'block', background }} />;
+ return !background ? undefined : <div style={{ width: doc[Width](), height: doc[Height](), position: 'absolute', display: 'block', background }} />;
}
}
};
@@ -559,8 +558,8 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
this,
e,
action((e: PointerEvent, down: number[], delta: number[]) => {
- doc._panX = clamp(NumCast(doc._panX) + (delta[0] / miniSize) * renderBounds.dim, renderBounds.l, renderBounds.l + renderBounds.dim);
- doc._panY = clamp(NumCast(doc._panY) + (delta[1] / miniSize) * renderBounds.dim, renderBounds.t, renderBounds.t + renderBounds.dim);
+ doc._freeform_panX = clamp(NumCast(doc._freeform_panX) + (delta[0] / miniSize) * renderBounds.dim, renderBounds.l, renderBounds.l + renderBounds.dim);
+ doc._freeform_panY = clamp(NumCast(doc._freeform_panY) + (delta[1] / miniSize) * renderBounds.dim, renderBounds.t, renderBounds.t + renderBounds.dim);
return false;
}),
emptyFunction,
@@ -569,10 +568,10 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
};
render() {
if (!this.renderBounds) return null;
- const miniWidth = (this.props.PanelWidth() / NumCast(this.props.document._viewScale, 1) / this.renderBounds.dim) * 100;
- const miniHeight = (this.props.PanelHeight() / NumCast(this.props.document._viewScale, 1) / this.renderBounds.dim) * 100;
- const miniLeft = 50 + ((NumCast(this.props.document._panX) - this.renderBounds.cx) / this.renderBounds.dim) * 100 - miniWidth / 2;
- const miniTop = 50 + ((NumCast(this.props.document._panY) - this.renderBounds.cy) / this.renderBounds.dim) * 100 - miniHeight / 2;
+ const miniWidth = (this.props.PanelWidth() / NumCast(this.props.document._freeform_scale, 1) / this.renderBounds.dim) * 100;
+ const miniHeight = (this.props.PanelHeight() / NumCast(this.props.document._freeform_scale, 1) / this.renderBounds.dim) * 100;
+ const miniLeft = 50 + ((NumCast(this.props.document._freeform_) - this.renderBounds.cx) / this.renderBounds.dim) * 100 - miniWidth / 2;
+ const miniTop = 50 + ((NumCast(this.props.document._freeform_panY) - this.renderBounds.cy) / this.renderBounds.dim) * 100 - miniHeight / 2;
const miniSize = this.returnMiniSize();
return this.props.hideMinimap() ? null : (
<div className="miniMap" style={{ width: miniSize, height: miniSize, background: this.props.background() }}>
@@ -603,8 +602,8 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
styleProvider={TabMinimapView.miniStyleProvider}
addDocTab={this.props.addDocTab}
pinToPres={TabDocView.PinDoc}
- docFilters={CollectionDockingView.Instance?.childDocFilters ?? returnEmptyDoclist}
- docRangeFilters={CollectionDockingView.Instance?.childDocRangeFilters ?? returnEmptyDoclist}
+ childFilters={CollectionDockingView.Instance?.childDocFilters ?? returnEmptyDoclist}
+ childFiltersByRanges={CollectionDockingView.Instance?.childDocRangeFilters ?? returnEmptyDoclist}
searchFilterDocs={CollectionDockingView.Instance?.searchFilterDocs ?? returnEmptyDoclist}
fitContentsToBox={returnTrue}
/>
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 4adf86683..6bc30c451 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -2,7 +2,8 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
-import { DataSym, Doc, DocListCast, Field, HeightSym, Opt, StrListCast, WidthSym } from '../../../fields/Doc';
+import { Doc, DocListCast, Field, Opt, StrListCast } from '../../../fields/Doc';
+import { DocData, Height, Width } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
import { List } from '../../../fields/List';
import { RichTextField } from '../../../fields/RichTextField';
@@ -10,7 +11,7 @@ import { listSpec } from '../../../fields/Schema';
import { ComputedField, ScriptField } from '../../../fields/ScriptField';
import { BoolCast, Cast, DocCast, FieldValue, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
import { TraceMobx } from '../../../fields/util';
-import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, returnZero, simulateMouseClick, Utils } from '../../../Utils';
+import { emptyFunction, return18, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, returnZero, simulateMouseClick, Utils } from '../../../Utils';
import { Docs, DocUtils } from '../../documents/Documents';
import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
import { DocumentManager } from '../../util/DocumentManager';
@@ -102,7 +103,7 @@ export class TreeView extends React.Component<TreeViewProps> {
private _treedropDisposer?: DragManager.DragDropDisposer;
get treeViewOpenIsTransient() {
- return this.props.treeView.doc.treeViewOpenIsTransient || Doc.IsPrototype(this.doc);
+ return this.props.treeView.doc.treeViewOpenIsTransient || Doc.IsDataProto(this.doc);
}
set treeViewOpen(c: boolean) {
if (this.treeViewOpenIsTransient) this._transientOpenState = c;
@@ -118,14 +119,14 @@ export class TreeView extends React.Component<TreeViewProps> {
return 'TreeView(' + this.props.document.title + ')';
} // this makes mobx trace() statements more descriptive
get defaultExpandedView() {
- return this.doc.viewType === CollectionViewType.Docking
+ return this.doc._type_collection === CollectionViewType.Docking
? this.fieldKey
: this.props.treeView.dashboardMode
? this.fieldKey
: this.props.treeView.fileSysMode
? this.doc.isFolder
? this.fieldKey
- : 'aliases' // for displaying
+ : 'embeddings' // for displaying
: this.props.treeView.outlineMode || this.childDocs
? this.fieldKey
: Doc.noviceMode
@@ -146,7 +147,7 @@ export class TreeView extends React.Component<TreeViewProps> {
return NumCast(this.props.treeViewParent.maxEmbedHeight, 200);
}
@computed get dataDoc() {
- return this.props.document.treeViewChildrenOnRoot ? this.doc : this.doc[DataSym];
+ return this.props.document.treeViewChildrenOnRoot ? this.doc : this.doc[DocData];
}
@computed get layoutDoc() {
return Doc.Layout(this.doc);
@@ -160,11 +161,11 @@ export class TreeView extends React.Component<TreeViewProps> {
@computed get childLinks() {
return this.childDocList('links');
}
- @computed get childAliases() {
- return this.childDocList('aliases');
+ @computed get childEmbeddings() {
+ return this.childDocList('proto_embeddings');
}
@computed get childAnnos() {
- return this.childDocList(this.fieldKey + '-annotations');
+ return this.childDocList(this.fieldKey + '_annotations');
}
@computed get selected() {
return SelectionManager.IsSelected(this._docRef);
@@ -191,10 +192,10 @@ export class TreeView extends React.Component<TreeViewProps> {
};
@undoBatch @action remove = (doc: Doc | Doc[], key: string) => {
this.props.treeView.props.select(false);
- const ind = this.dataDoc[key].indexOf(doc);
+ const ind = DocListCast(this.dataDoc[key]).indexOf(doc instanceof Doc ? doc : doc.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(this.dataDoc[key][ind - 1], this.props.treeView.props.DocumentView?.())?.select(false);
+ res && ind > 0 && DocumentManager.Instance.getDocumentView(DocListCast(this.dataDoc[key])[ind - 1], this.props.treeView.props.DocumentView?.())?.select(false);
return res;
};
@@ -219,11 +220,13 @@ export class TreeView extends React.Component<TreeViewProps> {
if (this.props.document.isFolder || Doc.IsSystem(this.props.document)) {
this.treeViewOpen = !this.treeViewOpen;
} else {
- // choose an appropriate alias or make one. --- choose the first alias that (1) user owns, (2) has no context field ... otherwise make a new alias
- const bestAlias =
- docView.props.Document.author === Doc.CurrentUserEmail && !Doc.IsPrototype(docView.props.Document) ? docView.props.Document : DocListCast(this.props.document.aliases).find(doc => !doc.context && doc.author === Doc.CurrentUserEmail);
- const nextBestAlias = DocListCast(this.props.document.aliases).find(doc => doc.author === Doc.CurrentUserEmail);
- this.props.addDocTab(bestAlias ?? nextBestAlias ?? Doc.MakeAlias(this.props.document), OpenWhere.lightbox);
+ // 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.props.Document.author === Doc.CurrentUserEmail && !Doc.IsDataProto(docView.props.Document)
+ ? docView.props.Document
+ : DocListCast(this.props.document.proto_embeddings).find(doc => !doc.embedContainer && doc.author === Doc.CurrentUserEmail);
+ const nextBestEmbedding = DocListCast(this.props.document.proto_embeddings).find(doc => doc.author === Doc.CurrentUserEmail);
+ this.props.addDocTab(bestEmbedding ?? nextBestEmbedding ?? Doc.MakeEmbedding(this.props.document), OpenWhere.lightbox);
}
};
@@ -310,17 +313,17 @@ export class TreeView extends React.Component<TreeViewProps> {
title: '-title-',
treeViewExpandedViewLock: true,
treeViewExpandedView: 'data',
- _viewType: CollectionViewType.Tree,
- hideLinkButton: true,
- _showSidebar: true,
- _fitWidth: true,
+ _type_collection: CollectionViewType.Tree,
+ layout_hideLinkButton: true,
+ _layout_showSidebar: true,
+ _layout_fitWidth: true,
treeViewType: TreeViewType.outline,
x: 0,
y: 0,
_xMargin: 0,
_yMargin: 0,
- _autoHeight: true,
- _singleLine: true,
+ _layout_autoHeight: true,
+ _createDocOnCR: true,
_width: 1000,
_height: 10,
});
@@ -359,7 +362,7 @@ export class TreeView extends React.Component<TreeViewProps> {
if (de.complete.linkDragData) {
const sourceDoc = de.complete.linkDragData.linkSourceGetAnchor();
const destDoc = this.doc;
- DocUtils.MakeLink(sourceDoc, destDoc, { linkRelationship: 'tree link' });
+ DocUtils.MakeLink(sourceDoc, destDoc, { link_relationship: 'tree link' });
e.stopPropagation();
}
const docDragData = de.complete.docDragData;
@@ -378,14 +381,14 @@ export class TreeView extends React.Component<TreeViewProps> {
const innerAdd = (doc: Doc) => {
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.context = this.doc.context);
+ dataIsComputed && (doc.embedContainer = this.doc.embedContainer);
return added;
};
return (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && innerAdd(doc), true as boolean);
};
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)?.freezeChildren).includes('add')) || forceAdd;
+ const canAdd = (!this.props.treeView.outlineMode && !StrCast((inside ? this.props.document : this.props.treeViewParent)?.treeViewFreezeChildren).includes('add')) || forceAdd;
if (canAdd) {
this.props.parentTreeView instanceof TreeView && (this.props.parentTreeView.dropping = true);
const res = UndoManager.RunInTempBatch(() => droppedDocuments.reduce((added, d) => (move ? move(d, undefined, addDoc) || (dropAction === 'proto' ? addDoc(d) : false) : addDoc(d)) || added, false));
@@ -408,16 +411,16 @@ export class TreeView extends React.Component<TreeViewProps> {
embeddedPanelHeight = () => {
const layoutDoc = (temp => temp && Doc.expandTemplateLayout(temp, this.props.document))(this.props.treeView.props.childLayoutTemplate?.()) || this.layoutDoc;
return Math.min(
- layoutDoc[HeightSym](),
+ layoutDoc[Height](),
this.MAX_EMBED_HEIGHT,
(() => {
const aspect = Doc.NativeAspect(layoutDoc);
if (aspect) return this.embeddedPanelWidth() / (aspect || 1);
- return layoutDoc._fitWidth
+ return layoutDoc._layout_fitWidth
? !Doc.NativeHeight(layoutDoc)
? NumCast(layoutDoc._height)
: Math.min((this.embeddedPanelWidth() * NumCast(layoutDoc.scrollHeight, Doc.NativeHeight(layoutDoc))) / (Doc.NativeWidth(layoutDoc) || NumCast(this.props.treeViewParent._height)))
- : (this.embeddedPanelWidth() * layoutDoc[HeightSym]()) / layoutDoc[WidthSym]();
+ : (this.embeddedPanelWidth() * layoutDoc[Height]()) / layoutDoc[Width]();
})()
);
};
@@ -441,7 +444,7 @@ export class TreeView extends React.Component<TreeViewProps> {
const innerAdd = (doc: 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.context = this.doc.context);
+ dataIsComputed && (doc.embedContainer = this.doc.embedContainer);
return added;
};
return (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && innerAdd(doc), true as boolean);
@@ -527,7 +530,7 @@ export class TreeView extends React.Component<TreeViewProps> {
TraceMobx();
const expandKey = this.treeViewExpandedView;
const sortings = (this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewSortings) as { [key: string]: { color: string; label: string } }) ?? {};
- if (['links', 'annotations', 'aliases', this.fieldKey].includes(expandKey)) {
+ if (['links', 'annotations', 'embeddings', this.fieldKey].includes(expandKey)) {
const sorting = StrCast(this.doc.treeViewSortCriterion, TreeSort.None);
const sortKeys = Object.keys(sortings);
const curSortIndex = Math.max(
@@ -549,12 +552,12 @@ export class TreeView extends React.Component<TreeViewProps> {
}
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 && added && (doc.context = this.doc.context);
+ !dataIsComputed && added && (doc.embedContainer = this.doc.embedContainer);
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 docs = expandKey === 'aliases' ? this.childAliases : expandKey === 'links' ? this.childLinks : expandKey === 'annotations' ? this.childAnnos : this.childDocs;
+ const docs = expandKey === 'embeddings' ? this.childEmbeddings : expandKey === 'links' ? this.childLinks : expandKey === 'annotations' ? this.childAnnos : this.childDocs;
let downX = 0,
downY = 0;
if (docs?.length && this._renderCount < docs?.length) {
@@ -670,7 +673,7 @@ export class TreeView extends React.Component<TreeViewProps> {
@computed get renderBullet() {
TraceMobx();
- const iconType = this.props.treeView.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewIcon + (this.treeViewOpen ? ':open' : '')) || 'question';
+ const iconType = this.props.treeView.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewIcon + (this.treeViewOpen ? ':open' : !this.childDocs.length ? ':empty' : '')) || 'question';
const checked = this.onCheckedClick ? this.doc.treeViewChecked ?? 'unchecked' : undefined;
return (
<div
@@ -706,13 +709,13 @@ export class TreeView extends React.Component<TreeViewProps> {
}
@computed get validExpandViewTypes() {
- const annos = () => (DocListCast(this.doc[this.fieldKey + '-annotations']).length && !this.props.treeView.dashboardMode ? 'annotations' : '');
+ const annos = () => (DocListCast(this.doc[this.fieldKey + '_annotations']).length && !this.props.treeView.dashboardMode ? 'annotations' : '');
const links = () => (LinkManager.Links(this.doc).length && !this.props.treeView.dashboardMode ? 'links' : '');
const data = () => (this.childDocs || this.props.treeView.dashboardMode ? this.fieldKey : '');
- const aliases = () => (this.props.treeView.dashboardMode ? '' : 'aliases');
+ const embeddings = () => (this.props.treeView.dashboardMode ? '' : 'embeddings');
const fields = () => (Doc.noviceMode ? '' : 'fields');
- const layout = Doc.noviceMode || this.doc.viewType === CollectionViewType.Docking ? [] : ['layout'];
- return [data(), ...layout, ...(this.props.treeView.fileSysMode ? [aliases(), links(), annos()] : []), fields()].filter(m => m);
+ const layout = Doc.noviceMode || this.doc._type_collection === CollectionViewType.Docking ? [] : ['layout'];
+ return [data(), ...layout, ...(this.props.treeView.fileSysMode ? [embeddings(), links(), annos()] : []), fields()].filter(m => m);
}
@action
expandNextviewType = () => {
@@ -729,7 +732,7 @@ export class TreeView extends React.Component<TreeViewProps> {
return this.props.treeViewHideHeaderFields() || this.doc.treeViewHideHeaderFields ? null : (
<>
{customHeaderButtons} {/* e.g.,. hide button is set by dashboardStyleProvider */}
- {this.doc.hideContextMenu ? null : (
+ {this.doc._layout_hideContextMenu ? null : (
<FontAwesomeIcon
title="context menu"
key="bars"
@@ -759,7 +762,7 @@ export class TreeView extends React.Component<TreeViewProps> {
const makeFolder = { script: ScriptField.MakeFunction(`scriptContext.makeFolder()`, { scriptContext: 'any' })!, icon: 'folder-plus', label: 'New Folder' };
const deleteItem = { script: ScriptField.MakeFunction(`scriptContext.deleteItem()`, { scriptContext: 'any' })!, icon: 'folder-plus', label: 'Delete' };
const folderOp = this.childDocs?.length ? [makeFolder] : [];
- const openAlias = { script: ScriptField.MakeFunction(`openDoc(getAlias(self), ${OpenWhere.addRight})`)!, icon: 'copy', label: 'Open Alias' };
+ const openEmbedding = { script: ScriptField.MakeFunction(`openDoc(getEmbedding(self), "${OpenWhere.addRight}")`)!, icon: 'copy', label: 'Open New Embedding' };
const focusDoc = { script: ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!, icon: 'eye', label: 'Focus or Open' };
return [
...(this.props.contextMenuItems ?? []).filter(mi => (!mi.filter ? true : mi.filter.script.run({ doc: this.doc })?.result)),
@@ -768,10 +771,10 @@ export class TreeView extends React.Component<TreeViewProps> {
: Doc.IsSystem(this.doc)
? []
: this.props.treeView.fileSysMode && this.doc === Doc.GetProto(this.doc)
- ? [openAlias, makeFolder]
- : this.doc.viewType === CollectionViewType.Docking
+ ? [openEmbedding, makeFolder]
+ : this.doc._type_collection === CollectionViewType.Docking
? []
- : [deleteItem, openAlias, focusDoc]),
+ : [deleteItem, openEmbedding, focusDoc]),
];
};
childContextMenuItems = () => {
@@ -854,7 +857,6 @@ export class TreeView extends React.Component<TreeViewProps> {
};
titleWidth = () => Math.max(20, Math.min(this.props.treeView.truncateTitleWidth(), this.props.panelWidth())) / (this.props.treeView.props.NativeDimScaling?.() || 1) - this.headerEleWidth - treeBulletWidth();
- return18 = () => 18;
/**
* Renders the EditableView title element for placement into the tree.
*/
@@ -896,7 +898,7 @@ export class TreeView extends React.Component<TreeViewProps> {
}
})}
Document={this.doc}
- fitWidth={returnTrue}
+ layout_fitWidth={returnTrue}
DataDoc={undefined}
scriptContext={this}
hideDecorationTitle={this.props.treeView.outlineMode}
@@ -916,10 +918,11 @@ export class TreeView extends React.Component<TreeViewProps> {
moveDocument={this.move}
removeDocument={this.props.removeDoc}
ScreenToLocalTransform={this.getTransform}
- NativeHeight={this.return18}
+ NativeHeight={return18}
NativeWidth={returnZero}
+ shouldNotScale={returnTrue}
PanelWidth={this.titleWidth}
- PanelHeight={this.return18}
+ PanelHeight={return18}
contextMenuItems={this.contextMenuItems}
renderDepth={1}
isContentActive={this.props.isContentActive}
@@ -927,13 +930,13 @@ export class TreeView extends React.Component<TreeViewProps> {
focus={this.refocus}
whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged}
bringToFront={emptyFunction}
- disableDocBrushing={this.props.treeView.props.disableDocBrushing}
+ disableBrushing={this.props.treeView.props.disableBrushing}
hideLinkButton={BoolCast(this.props.treeView.props.Document.childHideLinkButton)}
dontRegisterView={BoolCast(this.props.treeView.props.Document.childDontRegisterViews, this.props.dontRegisterView)}
xPadding={NumCast(this.props.treeView.props.Document.childXPadding, this.props.treeView.props.childXPadding)}
yPadding={NumCast(this.props.treeView.props.Document.childYPadding, this.props.treeView.props.childYPadding)}
- docFilters={returnEmptyFilter}
- docRangeFilters={returnEmptyFilter}
+ childFilters={returnEmptyFilter}
+ childFiltersByRanges={returnEmptyFilter}
searchFilterDocs={returnEmptyDoclist}
/>
);
@@ -985,7 +988,7 @@ export class TreeView extends React.Component<TreeViewProps> {
ref={action((r: DocumentView | null) => (this._dref = r))}
Document={this.doc}
DataDoc={undefined}
- fitWidth={this.fitWidthFilter}
+ layout_fitWidth={this.fitWidthFilter}
PanelWidth={this.embeddedPanelWidth}
PanelHeight={this.embeddedPanelHeight}
LayoutTemplateString={asText ? FormattedTextBox.LayoutString('text') : undefined}
@@ -1007,8 +1010,8 @@ export class TreeView extends React.Component<TreeViewProps> {
treeViewDoc={this.props.treeView?.props.Document}
rootSelected={returnTrue}
docViewPath={this.props.treeView.props.docViewPath}
- docFilters={returnEmptyFilter}
- docRangeFilters={returnEmptyFilter}
+ childFilters={returnEmptyFilter}
+ childFiltersByRanges={returnEmptyFilter}
searchFilterDocs={returnEmptyDoclist}
addDocument={this.props.addDocument}
moveDocument={this.move}
@@ -1018,7 +1021,7 @@ export class TreeView extends React.Component<TreeViewProps> {
yPadding={NumCast(this.props.treeView.props.Document.childYPadding, this.props.treeView.props.childYPadding)}
addDocTab={this.props.addDocTab}
pinToPres={this.props.treeView.props.pinToPres}
- disableDocBrushing={this.props.treeView.props.disableDocBrushing}
+ disableBrushing={this.props.treeView.props.disableBrushing}
bringToFront={returnFalse}
scriptContext={this}
/>
@@ -1028,7 +1031,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.unrendered && !this.doc.treeViewFieldKey ? (
+ return this.props.treeView.Document.treeViewHideUnrendered && this.doc.layout_unrendered && !this.doc.treeViewFieldKey ? (
<div></div>
) : (
<>
@@ -1179,7 +1182,7 @@ export class TreeView extends React.Component<TreeViewProps> {
TreeView._editTitleOnLoad = editTitle ? { id: child[Id], parent } : undefined;
Doc.AddDocToList(newParent, fieldKey, child, addAfter, false);
newParent.treeViewOpen = true;
- child.context = treeView.Document;
+ child.embedContainer = treeView.Document;
}
};
const indent = i === 0 ? undefined : (editTitle: boolean) => dentDoc(editTitle, docs[i - 1], undefined, treeViewRefs.get(docs[i - 1]));
@@ -1188,7 +1191,7 @@ export class TreeView extends React.Component<TreeViewProps> {
const childLayout = Doc.Layout(pair.layout);
const rowHeight = () => {
const aspect = Doc.NativeAspect(childLayout);
- return aspect ? Math.min(childLayout[WidthSym](), rowWidth()) / aspect : childLayout[HeightSym]();
+ return aspect ? Math.min(childLayout[Width](), rowWidth()) / aspect : childLayout[Height]();
};
return (
<TreeView
@@ -1208,7 +1211,7 @@ export class TreeView extends React.Component<TreeViewProps> {
onCheckedClick={onCheckedClick}
onChildClick={onChildClick}
renderDepth={renderDepth}
- removeDoc={StrCast(treeViewParent.freezeChildren).includes('remove') ? undefined : remove}
+ removeDoc={StrCast(treeViewParent.treeViewFreezeChildren).includes('remove') ? undefined : remove}
addDocument={addDocument}
styleProvider={styleProvider}
panelWidth={rowWidth}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
index fee4705e6..1e76d373c 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
@@ -1,4 +1,5 @@
-import { Doc, Field, FieldResult, HeightSym, WidthSym } from '../../../../fields/Doc';
+import { Doc, Field, FieldResult } from '../../../../fields/Doc';
+import { Height, Width } from '../../../../fields/DocSymbols';
import { Id, ToString } from '../../../../fields/FieldSymbols';
import { ObjectField } from '../../../../fields/ObjectField';
import { RefField } from '../../../../fields/RefField';
@@ -90,8 +91,8 @@ export function computePassLayout(poolData: Map<string, PoolData>, pivotDoc: Doc
docMap.set(layout[Id], {
x: NumCast(layout.x),
y: NumCast(layout.y),
- width: layout[WidthSym](),
- height: layout[HeightSym](),
+ width: layout[Width](),
+ height: layout[Height](),
pair: { layout, data },
transition: 'all .3s',
replica: '',
@@ -105,8 +106,8 @@ export function computeStarburstLayout(poolData: Map<string, PoolData>, pivotDoc
const burstDiam = [NumCast(pivotDoc._width), NumCast(pivotDoc._height)];
const burstScale = NumCast(pivotDoc._starburstDocScale, 1);
childPairs.forEach(({ layout, data }, i) => {
- const aspect = layout[HeightSym]() / layout[WidthSym]();
- const docSize = Math.min(Math.min(400, layout[WidthSym]()), Math.min(400, layout[WidthSym]()) / aspect) * burstScale;
+ const aspect = layout[Height]() / layout[Width]();
+ const docSize = Math.min(Math.min(400, layout[Width]()), Math.min(400, layout[Width]()) / aspect) * burstScale;
const deg = (i / childPairs.length) * Math.PI * 2;
docMap.set(layout[Id], {
x: Math.min(burstDiam[0] / 2 - docSize, Math.max(-burstDiam[0] / 2, (Math.cos(deg) * burstDiam[0]) / 2 - docSize / 2)),
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
index 0dfd119d7..f1d98d22a 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
@@ -1,6 +1,7 @@
import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
-import { CssSym, Doc, Field } from '../../../../fields/Doc';
+import { Doc, Field } from '../../../../fields/Doc';
+import { DocCss } from '../../../../fields/DocSymbols';
import { Id } from '../../../../fields/FieldSymbols';
import { List } from '../../../../fields/List';
import { Cast, NumCast, StrCast } from '../../../../fields/Types';
@@ -34,11 +35,11 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
this._anchorDisposer = reaction(
() => [
this.props.A.props.ScreenToLocalTransform(),
- Cast(Cast(Cast(this.props.A.rootDoc, Doc, null)?.anchor1, Doc, null)?.annotationOn, Doc, null)?.scrollTop,
- Cast(Cast(Cast(this.props.A.rootDoc, Doc, null)?.anchor1, Doc, null)?.annotationOn, Doc, null)?.[CssSym],
+ Cast(Cast(Cast(this.props.A.rootDoc, Doc, null)?.link_anchor_1, Doc, null)?.annotationOn, Doc, null)?.layout_scrollTop,
+ Cast(Cast(Cast(this.props.A.rootDoc, Doc, null)?.link_anchor_1, Doc, null)?.annotationOn, Doc, null)?.[DocCss],
this.props.B.props.ScreenToLocalTransform(),
- Cast(Cast(Cast(this.props.A.rootDoc, Doc, null)?.anchor2, Doc, null)?.annotationOn, Doc, null)?.scrollTop,
- Cast(Cast(Cast(this.props.A.rootDoc, Doc, null)?.anchor2, Doc, null)?.annotationOn, Doc, null)?.[CssSym],
+ Cast(Cast(Cast(this.props.A.rootDoc, Doc, null)?.link_anchor_2, Doc, null)?.annotationOn, Doc, null)?.layout_scrollTop,
+ Cast(Cast(Cast(this.props.A.rootDoc, Doc, null)?.link_anchor_2, Doc, null)?.annotationOn, Doc, null)?.[DocCss],
],
action(() => {
this._start = Date.now();
@@ -58,7 +59,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.linkDisplay) && (this._opacity = 0.05)),
+ action(() => (!LinkDocs.length || !linkDoc.link_displayLine) && (this._opacity = 0.05)),
750
); // this will unhighlight the link line.
const a = A.ContentDiv.getBoundingClientRect();
@@ -72,36 +73,36 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
// if there's an element in the DOM with a classname containing a link anchor's id,
// then that DOM element is a hyperlink source for the current anchor and we want to place our link box at it's top right
// otherwise, we just use the computed nearest point on the document boundary to the target Document
- const targetAhyperlink = Array.from(window.document.getElementsByClassName((linkDoc.anchor1 as Doc)[Id])).lastElement();
- const targetBhyperlink = Array.from(window.document.getElementsByClassName((linkDoc.anchor2 as Doc)[Id])).lastElement();
+ const targetAhyperlink = Array.from(window.document.getElementsByClassName((linkDoc.link_anchor_1 as Doc)[Id])).lastElement();
+ const targetBhyperlink = Array.from(window.document.getElementsByClassName((linkDoc.link_anchor_2 as Doc)[Id])).lastElement();
if ((!targetAhyperlink && !a.width) || (!targetBhyperlink && !b.width)) return;
if (!targetAhyperlink) {
- if (linkDoc.linkAutoMove) {
- linkDoc.anchor1_x = ((apt.point.x - aleft) / awidth) * 100;
- linkDoc.anchor1_y = ((apt.point.y - atop) / aheight) * 100;
+ if (linkDoc.link_autoMoveAnchors) {
+ linkDoc.link_anchor_1_x = ((apt.point.x - aleft) / awidth) * 100;
+ linkDoc.link_anchor_1_y = ((apt.point.y - atop) / aheight) * 100;
}
} else {
const m = targetAhyperlink.getBoundingClientRect();
const mp = A.props.ScreenToLocalTransform().transformPoint(m.right, m.top + 5);
const mpx = mp[0] / A.props.PanelWidth();
const mpy = mp[1] / A.props.PanelHeight();
- if (mpx >= 0 && mpx <= 1) linkDoc.anchor1_x = mpx * 100;
- if (mpy >= 0 && mpy <= 1) linkDoc.anchor1_y = mpy * 100;
+ if (mpx >= 0 && mpx <= 1) linkDoc.link_anchor_1_x = mpx * 100;
+ if (mpy >= 0 && mpy <= 1) linkDoc.link_anchor_1_y = mpy * 100;
if (getComputedStyle(targetAhyperlink).fontSize === '0px') linkDoc.opacity = 0;
else linkDoc.opacity = 1;
}
if (!targetBhyperlink) {
- if (linkDoc.linkAutoMove) {
- linkDoc.anchor2_x = ((bpt.point.x - bleft) / bwidth) * 100;
- linkDoc.anchor2_y = ((bpt.point.y - btop) / bheight) * 100;
+ if (linkDoc.link_autoMoveAnchors) {
+ linkDoc.link_anchor_2_x = ((bpt.point.x - bleft) / bwidth) * 100;
+ linkDoc.link_anchor_2_y = ((bpt.point.y - btop) / bheight) * 100;
}
} else {
const m = targetBhyperlink.getBoundingClientRect();
const mp = B.props.ScreenToLocalTransform().transformPoint(m.right, m.top + 5);
const mpx = mp[0] / B.props.PanelWidth();
const mpy = mp[1] / B.props.PanelHeight();
- if (mpx >= 0 && mpx <= 1) linkDoc.anchor2_x = mpx * 100;
- if (mpy >= 0 && mpy <= 1) linkDoc.anchor2_y = mpy * 100;
+ if (mpx >= 0 && mpx <= 1) linkDoc.link_anchor_2_x = mpx * 100;
+ if (mpy >= 0 && mpy <= 1) linkDoc.link_anchor_2_y = mpy * 100;
if (getComputedStyle(targetBhyperlink).fontSize === '0px') linkDoc.opacity = 0;
else linkDoc.opacity = 1;
}
@@ -112,8 +113,8 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
this,
e,
(e, down, delta) => {
- this.props.LinkDocs[0].linkOffsetX = NumCast(this.props.LinkDocs[0].linkOffsetX) + delta[0];
- this.props.LinkDocs[0].linkOffsetY = NumCast(this.props.LinkDocs[0].linkOffsetY) + delta[1];
+ this.props.LinkDocs[0].link_relationship_OffsetX = NumCast(this.props.LinkDocs[0].link_relationship_OffsetX) + delta[0];
+ this.props.LinkDocs[0].link_relationship_OffsetY = NumCast(this.props.LinkDocs[0].link_relationship_OffsetY) + delta[1];
return false;
},
emptyFunction,
@@ -205,8 +206,8 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
const bclipped = bleft !== b.left || btop !== b.top;
if (aclipped && bclipped) return undefined;
const clipped = aclipped || bclipped;
- const pt1inside = NumCast(LinkDocs[0].anchor1_x) % 100 !== 0 && NumCast(LinkDocs[0].anchor1_y) % 100 !== 0;
- const pt2inside = NumCast(LinkDocs[0].anchor2_x) % 100 !== 0 && NumCast(LinkDocs[0].anchor2_y) % 100 !== 0;
+ const pt1inside = NumCast(LinkDocs[0].link_anchor_1_x) % 100 !== 0 && NumCast(LinkDocs[0].link_anchor_1_y) % 100 !== 0;
+ const pt2inside = NumCast(LinkDocs[0].link_anchor_2_x) % 100 !== 0 && NumCast(LinkDocs[0].link_anchor_2_y) % 100 !== 0;
const pt1 = [aleft + a.width / 2, atop + a.height / 2];
const pt2 = [bleft + b.width / 2, btop + b.width / 2];
const pt2vec = pt2inside ? [-0.7071, 0.7071] : [(bDocBounds.left + bDocBounds.right) / 2 - pt2[0], (bDocBounds.top + bDocBounds.bottom) / 2 - pt2[1]];
@@ -223,8 +224,8 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
const aActive = A.isSelected() || Doc.IsBrushed(A.rootDoc);
const bActive = B.isSelected() || Doc.IsBrushed(B.rootDoc);
- const textX = (Math.min(pt1[0], pt2[0]) + Math.max(pt1[0], pt2[0])) / 2 + NumCast(LinkDocs[0].linkOffsetX);
- const textY = (pt1[1] + pt2[1]) / 2 + NumCast(LinkDocs[0].linkOffsetY);
+ const textX = (Math.min(pt1[0], pt2[0]) + Math.max(pt1[0], pt2[0])) / 2 + NumCast(LinkDocs[0].link_relationship_OffsetX);
+ const textY = (pt1[1] + pt2[1]) / 2 + NumCast(LinkDocs[0].link_relationship_OffsetY);
return {
a,
b,
@@ -244,12 +245,12 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
const link = this.props.LinkDocs[0];
const { a, b, pt1norm, pt2norm, aActive, bActive, textX, textY, pt1, pt2 } = this.renderData;
- const linkRelationship = Field.toString(link?.linkRelationship as any as Field); //get string representing relationship
- const linkRelationshipList = Doc.UserDoc().linkRelationshipList as List<string>;
- const linkColorList = Doc.UserDoc().linkColorList as List<string>;
- const linkRelationshipSizes = Doc.UserDoc().linkRelationshipSizes as List<number>;
+ const linkRelationship = Field.toString(link?.link_relationship as any as Field); //get string representing relationship
+ const linkRelationshipList = Doc.UserDoc().link_relationshipList as List<string>;
+ const linkColorList = Doc.UserDoc().link_ColorList as List<string>;
+ const linkRelationshipSizes = Doc.UserDoc().link_relationshipSizes as List<number>;
const currRelationshipIndex = linkRelationshipList.indexOf(linkRelationship);
- const linkDescription = Field.toString(link.description as any as Field);
+ const linkDescription = Field.toString(link.link_description as any as Field);
const linkSize = currRelationshipIndex === -1 || currRelationshipIndex >= linkRelationshipSizes.length ? -1 : linkRelationshipSizes[currRelationshipIndex];
@@ -261,11 +262,11 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
//thickness varies linearly from 3px to 12px for increasing link count
const strokeWidth = linkSize === -1 ? '3px' : Math.floor(2 + 10 * (linkSize / Math.max(...linkRelationshipSizes))) + 'px';
- if (link.linkDisplayArrow === undefined) {
- link.linkDisplayArrow = false;
+ if (link.link_displayArrow === undefined) {
+ link.link_displayArrow = false;
}
- return link.opacity === 0 || !a.width || !b.width || (!link.linkDisplay && !aActive && !bActive) ? null : (
+ return link.opacity === 0 || !a.width || !b.width || (!link.link_displayLine && !aActive && !bActive) ? null : (
<>
<defs>
<marker id={`${link[Id] + 'arrowhead'}`} markerWidth="4" markerHeight="3" refX="0" refY="1.5" orient="auto">
@@ -294,7 +295,7 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
style={{ pointerEvents: 'visibleStroke', opacity: this._opacity, stroke, strokeWidth }}
onClick={this.onClickLine}
d={`M ${pt1[0]} ${pt1[1]} C ${pt1[0] + pt1norm[0]} ${pt1[1] + pt1norm[1]}, ${pt2[0] + pt2norm[0]} ${pt2[1] + pt2norm[1]}, ${pt2[0]} ${pt2[1]}`}
- markerEnd={link.linkDisplayArrow ? `url(#${link[Id] + 'arrowhead'})` : ''}
+ markerEnd={link.link_displayArrow ? `url(#${link[Id] + 'arrowhead'})` : ''}
/>
{textX === undefined || !linkDescription ? null : (
<text filter={`url(#${link[Id] + 'background'})`} className="collectionfreeformlinkview-linkText" x={textX} y={textY} onPointerDown={this.pointerDown}>
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 29bdc0e2d..11151e74e 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -4,7 +4,8 @@ import { action, computed, IReactionDisposer, observable, reaction, runInAction,
import { observer } from 'mobx-react';
import { computedFn } from 'mobx-utils';
import { DateField } from '../../../../fields/DateField';
-import { DataSym, Doc, DocListCast, HeightSym, Opt, WidthSym } from '../../../../fields/Doc';
+import { Doc, DocListCast, Opt } from '../../../../fields/Doc';
+import { DocData, Height, Width } from '../../../../fields/DocSymbols';
import { Id } from '../../../../fields/FieldSymbols';
import { InkData, InkField, InkTool, PointData, Segment } from '../../../../fields/InkField';
import { List } from '../../../../fields/List';
@@ -53,7 +54,6 @@ import { MarqueeView } from './MarqueeView';
import React = require('react');
export type collectionFreeformViewProps = {
- noPointerWheel?: () => boolean; // turn off pointerwheel interactions (see PDFViewer)
NativeWidth?: () => number;
NativeHeight?: () => number;
originTopLeft?: boolean;
@@ -101,13 +101,13 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
return this.props.isAnnotationOverlay;
}
public get scaleFieldKey() {
- return this.props.viewField ? this.props.viewField + '-viewScale' : '_viewScale';
+ return (this.props.viewField ?? '') + '_freeform_scale';
}
private get panXFieldKey() {
- return this.props.viewField ? this.props.viewField + '-panX' : '_panX';
+ return (this.props.viewField ?? '') + '_freeform_panX';
}
private get panYFieldKey() {
- return this.props.viewField ? this.props.viewField + '-panY' : '_panY';
+ return (this.props.viewField ?? '') + '_freeform_panY';
}
private get borderWidth() {
return this.isAnnotationOverlay ? 0 : COLLECTION_BORDER_WIDTH;
@@ -147,7 +147,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
};
}
@computed get fitContentsToBox() {
- return (this.props.fitContentsToBox?.() || this.Document._fitContentsToBox) && !this.isAnnotationOverlay;
+ return (this.props.fitContentsToBox?.() || this.Document._freeform_fitContentsToBox) && !this.isAnnotationOverlay;
}
@computed get contentBounds() {
const cb = Cast(this.rootDoc.contentBounds, listSpec('number'));
@@ -174,7 +174,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const dv = this.props.DocumentView?.();
const scaling = this.fitContentsToBox || !this.nativeDimScaling ? 1 : this.nativeDimScaling;
// if freeform has a native aspect, then the panel height needs to be adjusted to match it
- const aspect = dv?.nativeWidth && dv?.nativeHeight && !dv.layoutDoc.fitWidth ? dv.nativeHeight / dv.nativeWidth : this.props.PanelHeight() / this.props.PanelWidth();
+ const aspect = dv?.nativeWidth && dv?.nativeHeight && !dv.layoutDoc.layout_fitWidth ? dv.nativeHeight / dv.nativeWidth : this.props.PanelHeight() / this.props.PanelWidth();
return this.props.isAnnotationOverlay || this.props.originTopLeft ? 0 : (aspect * this.props.PanelWidth()) / 2 / scaling; // shift so pan position is at center of window for non-overlay collections
}
@computed get cachedGetLocalTransform(): Transform {
@@ -240,16 +240,16 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
shrinkWrap = () => {
if (this.props.DocumentView?.().nativeWidth) return;
const vals = this.fitToContentVals;
- this.layoutDoc._panX = vals.bounds.cx;
- this.layoutDoc._panY = vals.bounds.cy;
- this.layoutDoc._viewScale = vals.scale;
+ this.layoutDoc._freeform_panX = vals.bounds.cx;
+ this.layoutDoc._freeform_panY = vals.bounds.cy;
+ this.layoutDoc._freeform_scale = vals.scale;
};
freeformData = (force?: boolean) => (!this._firstRender && (this.fitContentsToBox || force) ? this.fitToContentVals : undefined);
reverseNativeScaling = () => (this.fitContentsToBox ? true : false);
- // panx, pany, zoomscale all attempt to get values first from the layout controller, then from the layout/dataDoc (or template layout doc), and finally from the resolved template data document.
+ // freeform_panx, freeform_pany, freeform_scale all attempt to get values first from the layout controller, then from the layout/dataDoc (or template layout doc), and finally from the resolved template data document.
// this search order, for example, allows icons of cropped images to find the panx/pany/zoom on the cropped image's data doc instead of the usual layout doc because the zoom/panX/panY define the cropped image
- panX = () => this.freeformData()?.bounds.cx ?? NumCast(this.Document[this.panXFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.panX, 1));
- panY = () => this.freeformData()?.bounds.cy ?? NumCast(this.Document[this.panYFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.panY, 1));
+ panX = () => this.freeformData()?.bounds.cx ?? NumCast(this.Document[this.panXFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.freeform_panX, 1));
+ panY = () => this.freeformData()?.bounds.cy ?? NumCast(this.Document[this.panYFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.freeform_panY, 1));
zoomScaling = () => this.freeformData()?.scale ?? NumCast(Doc.Layout(this.Document)[this.scaleFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.[this.scaleFieldKey], 1));
contentTransform = () =>
this.props.isAnnotationOverlay && this.zoomScaling() === 1 ? `` : `translate(${this.cachedCenteringShiftX}px, ${this.cachedCenteringShiftY}px) scale(${this.zoomScaling()}) translate(${-this.panX()}px, ${-this.panY()}px)`;
@@ -298,7 +298,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
isCurrent(doc: Doc) {
const dispTime = NumCast(doc._timecodeToShow, -1);
const endTime = NumCast(doc._timecodeToHide, dispTime + 1.5);
- const curTime = NumCast(this.Document._currentTimecode, -1);
+ const curTime = NumCast(this.Document._layout_currentTimecode, -1);
return dispTime === -1 || curTime === -1 || (curTime - dispTime >= -1e-4 && curTime <= endTime);
}
@@ -349,7 +349,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
.map(pair => pair.layout)
.slice()
.sort((doc1, doc2) => NumCast(doc1.zIndex) - NumCast(doc2.zIndex));
- zsorted.forEach((doc, index) => (doc.zIndex = doc.isInkMask ? 5000 : index + 1));
+ zsorted.forEach((doc, index) => (doc.zIndex = doc.stroke_isInkMask ? 5000 : index + 1));
const dvals = CollectionFreeFormDocumentView.getValues(refDoc, NumCast(refDoc.activeFrame, 1000));
const dropPos = this.Document._currentFrame !== undefined ? [NumCast(dvals.x), NumCast(dvals.y)] : [NumCast(refDoc.x), NumCast(refDoc.y)];
@@ -367,7 +367,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
d.x = x + NumCast(d.x) - dropPos[0];
d.y = y + NumCast(d.y) - dropPos[1];
}
- d._lastModified = new DateField();
+ d._layout_modificationDate = new DateField();
const nd = [Doc.NativeWidth(layoutDoc), Doc.NativeHeight(layoutDoc)];
layoutDoc._width = NumCast(layoutDoc._width, 300);
layoutDoc._height = NumCast(layoutDoc._height, nd[0] && nd[1] ? (nd[1] / nd[0]) * NumCast(layoutDoc._width) : 300);
@@ -419,11 +419,11 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
internalLinkDrop(e: Event, de: DragManager.DropEvent, linkDragData: DragManager.LinkDragData, xp: number, yp: number) {
if (linkDragData.linkDragView.props.docViewPath().includes(this.props.docViewPath().lastElement())) {
// dragged document is a child of this collection
- if (!linkDragData.linkDragView.props.CollectionFreeFormDocumentView?.() || linkDragData.dragDocument.context !== this.props.Document) {
- // if the source doc view's context isn't this same freeformcollectionlinkDragData.dragDocument.context === this.props.Document
+ if (!linkDragData.linkDragView.props.CollectionFreeFormDocumentView?.() || linkDragData.dragDocument.embedContainer !== this.props.Document) {
+ // if the source doc view's embedContainer isn't this same freeformcollectionlinkDragData.dragDocument.embedContainer === this.props.Document
const source = Docs.Create.TextDocument('', { _width: 200, _height: 75, x: xp, y: yp, title: 'dropped annotation' });
this.props.addDocument?.(source);
- de.complete.linkDocument = DocUtils.MakeLink(linkDragData.linkSourceGetAnchor(), source, { linkRelationship: 'annotated by:annotation of' }); // TODODO this is where in text links get passed
+ de.complete.linkDocument = DocUtils.MakeLink(linkDragData.linkSourceGetAnchor(), source, { link_relationship: 'annotated by:annotation of' }); // TODODO this is where in text links get passed
}
e.stopPropagation(); // do nothing if link is dropped into any freeform view parent of dragged document
return true;
@@ -447,7 +447,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
return this.childLayoutPairs
.map(pair => pair.layout)
.reduce((cluster, cd) => {
- const grouping = this.props.Document._useClusters ? NumCast(cd.cluster, -1) : NumCast(cd.group, -1);
+ const grouping = this.props.Document._freeform_useClusters ? NumCast(cd.layout_cluster, -1) : NumCast(cd.group, -1);
if (grouping !== -1) {
const layoutDoc = Doc.Layout(cd);
const cx = NumCast(cd.x) - this._clusterDistance / 2;
@@ -464,10 +464,10 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
if (cluster !== -1) {
const ptsParent = e instanceof PointerEvent ? e : e.targetTouches.item(0);
if (ptsParent) {
- const eles = this.childLayoutPairs.map(pair => pair.layout).filter(cd => (this.props.Document._useClusters ? NumCast(cd.cluster) : NumCast(cd.group, -1)) === cluster);
+ const eles = this.childLayoutPairs.map(pair => pair.layout).filter(cd => (this.props.Document._freeform_useClusters ? NumCast(cd.layout_cluster) : NumCast(cd.group, -1)) === cluster);
const clusterDocs = eles.map(ele => DocumentManager.Instance.getDocumentView(ele, this.props.DocumentView?.())!);
const { left, top } = clusterDocs[0].getBounds() || { left: 0, top: 0 };
- const de = new DragManager.DocumentDragData(eles, e.ctrlKey || e.altKey ? 'alias' : undefined);
+ const de = new DragManager.DocumentDragData(eles, e.ctrlKey || e.altKey ? 'embed' : undefined);
de.moveDocument = this.props.moveDocument;
de.offset = this.getTransform().transformDirection(ptsParent.clientX - left, ptsParent.clientY - top);
DragManager.StartDocumentDrag(
@@ -484,10 +484,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
return false;
}
- @undoBatch
@action
- updateClusters(_useClusters: boolean) {
- this.props.Document._useClusters = _useClusters;
+ updateClusters(_freeform_useClusters: boolean) {
+ this.props.Document._freeform_useClusters = _freeform_useClusters;
this._clusterSets.length = 0;
this.childLayoutPairs.map(pair => pair.layout).map(c => this.updateCluster(c));
}
@@ -495,70 +494,74 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
@action
updateClusterDocs(docs: Doc[]) {
const childLayouts = this.childLayoutPairs.map(pair => pair.layout);
- if (this.props.Document._useClusters) {
+ if (this.props.Document._freeform_useClusters) {
const docFirst = docs[0];
docs.map(doc => this._clusterSets.map(set => Doc.IndexOf(doc, set) !== -1 && set.splice(Doc.IndexOf(doc, set), 1)));
- const preferredInd = NumCast(docFirst.cluster);
- docs.map(doc => (doc.cluster = -1));
+ const preferredInd = NumCast(docFirst.layout_cluster);
+ docs.map(doc => (doc.layout_cluster = -1));
docs.map(doc =>
this._clusterSets.map((set, i) =>
set.map(member => {
- if (docFirst.cluster === -1 && Doc.IndexOf(member, childLayouts) !== -1 && Doc.overlapping(doc, member, this._clusterDistance)) {
- docFirst.cluster = i;
+ if (docFirst.layout_cluster === -1 && Doc.IndexOf(member, childLayouts) !== -1 && Doc.overlapping(doc, member, this._clusterDistance)) {
+ docFirst.layout_cluster = i;
}
})
)
);
- if (docFirst.cluster === -1 && preferredInd !== -1 && this._clusterSets.length > preferredInd && (!this._clusterSets[preferredInd] || !this._clusterSets[preferredInd].filter(member => Doc.IndexOf(member, childLayouts) !== -1).length)) {
- docFirst.cluster = preferredInd;
+ if (
+ docFirst.layout_cluster === -1 &&
+ preferredInd !== -1 &&
+ this._clusterSets.length > preferredInd &&
+ (!this._clusterSets[preferredInd] || !this._clusterSets[preferredInd].filter(member => Doc.IndexOf(member, childLayouts) !== -1).length)
+ ) {
+ docFirst.layout_cluster = preferredInd;
}
this._clusterSets.map((set, i) => {
- if (docFirst.cluster === -1 && !set.filter(member => Doc.IndexOf(member, childLayouts) !== -1).length) {
- docFirst.cluster = i;
+ if (docFirst.layout_cluster === -1 && !set.filter(member => Doc.IndexOf(member, childLayouts) !== -1).length) {
+ docFirst.layout_cluster = i;
}
});
- if (docFirst.cluster === -1) {
+ if (docFirst.layout_cluster === -1) {
docs.map(doc => {
- doc.cluster = this._clusterSets.length;
+ doc.layout_cluster = this._clusterSets.length;
this._clusterSets.push([doc]);
});
} else if (this._clusterSets.length) {
- for (let i = this._clusterSets.length; i <= NumCast(docFirst.cluster); i++) !this._clusterSets[i] && this._clusterSets.push([]);
- docs.map(doc => this._clusterSets[(doc.cluster = NumCast(docFirst.cluster))].push(doc));
+ for (let i = this._clusterSets.length; i <= NumCast(docFirst.layout_cluster); i++) !this._clusterSets[i] && this._clusterSets.push([]);
+ docs.map(doc => this._clusterSets[(doc.layout_cluster = NumCast(docFirst.layout_cluster))].push(doc));
}
- childLayouts.map(child => !this._clusterSets.some((set, i) => Doc.IndexOf(child, set) !== -1 && child.cluster === i) && this.updateCluster(child));
+ childLayouts.map(child => !this._clusterSets.some((set, i) => Doc.IndexOf(child, set) !== -1 && child.layout_cluster === i) && this.updateCluster(child));
}
}
- @undoBatch
@action
updateCluster(doc: Doc) {
const childLayouts = this.childLayoutPairs.map(pair => pair.layout);
- if (this.props.Document._useClusters) {
+ if (this.props.Document._freeform_useClusters) {
this._clusterSets.forEach(set => Doc.IndexOf(doc, set) !== -1 && set.splice(Doc.IndexOf(doc, set), 1));
- const preferredInd = NumCast(doc.cluster);
- doc.cluster = -1;
+ const preferredInd = NumCast(doc.layout_cluster);
+ doc.layout_cluster = -1;
this._clusterSets.forEach((set, i) =>
set.forEach(member => {
- if (doc.cluster === -1 && Doc.IndexOf(member, childLayouts) !== -1 && Doc.overlapping(doc, member, this._clusterDistance)) {
- doc.cluster = i;
+ if (doc.layout_cluster === -1 && Doc.IndexOf(member, childLayouts) !== -1 && Doc.overlapping(doc, member, this._clusterDistance)) {
+ doc.layout_cluster = i;
}
})
);
- if (doc.cluster === -1 && preferredInd !== -1 && this._clusterSets.length > preferredInd && (!this._clusterSets[preferredInd] || !this._clusterSets[preferredInd].filter(member => Doc.IndexOf(member, childLayouts) !== -1).length)) {
- doc.cluster = preferredInd;
+ if (doc.layout_cluster === -1 && preferredInd !== -1 && this._clusterSets.length > preferredInd && (!this._clusterSets[preferredInd] || !this._clusterSets[preferredInd].filter(member => Doc.IndexOf(member, childLayouts) !== -1).length)) {
+ doc.layout_cluster = preferredInd;
}
this._clusterSets.forEach((set, i) => {
- if (doc.cluster === -1 && !set.filter(member => Doc.IndexOf(member, childLayouts) !== -1).length) {
- doc.cluster = i;
+ if (doc.layout_cluster === -1 && !set.filter(member => Doc.IndexOf(member, childLayouts) !== -1).length) {
+ doc.layout_cluster = i;
}
});
- if (doc.cluster === -1) {
- doc.cluster = this._clusterSets.length;
+ if (doc.layout_cluster === -1) {
+ doc.layout_cluster = this._clusterSets.length;
this._clusterSets.push([doc]);
} else if (this._clusterSets.length) {
- for (let i = this._clusterSets.length; i <= doc.cluster; i++) !this._clusterSets[i] && this._clusterSets.push([]);
- this._clusterSets[doc.cluster ?? 0].push(doc);
+ for (let i = this._clusterSets.length; i <= doc.layout_cluster; i++) !this._clusterSets[i] && this._clusterSets.push([]);
+ this._clusterSets[doc.layout_cluster ?? 0].push(doc);
}
}
}
@@ -567,8 +570,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
let styleProp = this.props.styleProvider?.(doc, props, property); // bcz: check 'props' used to be renderDepth + 1
switch (property) {
case StyleProp.BackgroundColor:
- const cluster = NumCast(doc?.cluster);
- if (this.Document._useClusters && doc?.type !== DocumentType.IMG) {
+ const cluster = NumCast(doc?.layout_cluster);
+ if (this.Document._freeform_useClusters && doc?.type !== DocumentType.IMG) {
if (this._clusterSets.length <= cluster) {
setTimeout(() => doc && this.updateCluster(doc));
} else {
@@ -592,7 +595,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
trySelectCluster = (addToSel: boolean) => {
if (this._hitCluster !== -1) {
!addToSel && SelectionManager.DeselectAll();
- const eles = this.childLayoutPairs.map(pair => pair.layout).filter(cd => (this.props.Document._useClusters ? NumCast(cd.cluster) : NumCast(cd.group, -1)) === this._hitCluster);
+ const eles = this.childLayoutPairs.map(pair => pair.layout).filter(cd => (this.props.Document._freeform_useClusters ? NumCast(cd.layout_cluster) : NumCast(cd.group, -1)) === this._hitCluster);
this.selectDocuments(eles);
return true;
}
@@ -633,7 +636,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
case InkTool.None:
if (!(this.props.layoutEngine?.() || StrCast(this.layoutDoc._layoutEngine))) {
this._hitCluster = this.pickCluster(this.getTransform().transformPoint(e.clientX, e.clientY));
- setupMoveUpEvents(this, e, this.onPointerMove, emptyFunction, emptyFunction, this._hitCluster !== -1 ? true : false);
+ setupMoveUpEvents(this, e, this.onPointerMove, emptyFunction, emptyFunction, this._hitCluster !== -1 ? true : false, false);
}
break;
}
@@ -679,7 +682,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const B = this.getTransform().transformBounds(ge.bounds.left, ge.bounds.top, ge.bounds.width, ge.bounds.height);
const inkDoc = Docs.Create.InkDocument(
ActiveInkColor(),
- Doc.ActiveTool,
ActiveInkWidth() * this.props.ScreenToLocalTransform().Scale,
ActiveInkBezierApprox(),
ActiveFillColor(),
@@ -706,7 +708,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
case GestureUtils.Gestures.Rectangle:
if (this._inkToTextStartX && this._inkToTextStartY) {
const end = this.getTransform().transformPoint(Math.max(...ge.points.map(p => p.X)), Math.max(...ge.points.map(p => p.Y)));
- const setDocs = this.getActiveDocuments().filter(s => s.proto?.type === 'rtf' && s.color);
+ const setDocs = this.getActiveDocuments().filter(s => DocCast(s.proto)?.type === DocumentType.RTF && s.color);
const sets = setDocs.map(sd => {
return Cast(sd.text, RichTextField)?.Text as string;
});
@@ -718,9 +720,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const inks = this.getActiveDocuments().filter(doc => {
if (doc.type === 'ink') {
const l = NumCast(doc.x);
- const r = l + doc[WidthSym]();
+ const r = l + doc[Width]();
const t = NumCast(doc.y);
- const b = t + doc[HeightSym]();
+ const b = t + doc[Height]();
const pass = !(this._inkToTextStartX! > r || end[0] < l || this._inkToTextStartY! > b || end[1] < t);
return pass;
}
@@ -835,7 +837,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
this.getEraserIntersections({ X: currPoint.X - delta[0], Y: currPoint.Y - delta[1] }, currPoint).forEach(intersect => {
if (!this._deleteList.includes(intersect.inkView)) {
this._deleteList.push(intersect.inkView);
- SetActiveInkWidth(StrCast(intersect.inkView.rootDoc.strokeWidth?.toString()) || '1');
+ SetActiveInkWidth(StrCast(intersect.inkView.rootDoc.stroke_width?.toString()) || '1');
SetActiveInkColor(StrCast(intersect.inkView.rootDoc.color?.toString()) || 'black');
// create a new curve by appending all curves of the current segment together in order to render a single new stroke.
if (!e.shiftKey) {
@@ -867,9 +869,14 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
Doc.ActiveTool = InkTool.None;
} else {
if (this.tryDragCluster(e, this._hitCluster)) {
+ e.stopPropagation(); // we're moving a cluster, so stop propagation and return true to end panning and let the document drag take over
return true;
}
- this.pan(e);
+ // pan the view if this is a regular collection, or it's an overlay and the overlay is zoomed (otherwise, there's nothing to pan)
+ if (!this.props.isAnnotationOverlay || 1 - NumCast(this.rootDoc._freeform_scale_min, 1) / this.getLocalTransform().inverse().Scale) {
+ this.pan(e);
+ e.stopPropagation(); // if we are actually panning, stop propagation -- this will preven things like the overlayView from dragging the document while we're panning
+ }
}
return false;
};
@@ -1014,7 +1021,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
@action
zoom = (pointX: number, pointY: number, deltaY: number): void => {
- if (this.Document._isGroup) return;
+ if (this.Document._isGroup || this.Document._freeform_noZoom) return;
let deltaScale = deltaY > 0 ? 1 / 1.05 : 1.05;
if (deltaScale < 0) deltaScale = -deltaScale;
const [x, y] = this.getTransform().transformPoint(pointX, pointY);
@@ -1022,50 +1029,42 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
if (deltaScale * invTransform.Scale > 20) {
deltaScale = 20 / invTransform.Scale;
}
- if (deltaScale < 1 && invTransform.Scale <= NumCast(this.rootDoc._viewScaleMin, 1) && this.isAnnotationOverlay) {
+ if (deltaScale < 1 && invTransform.Scale <= NumCast(this.rootDoc._freeform_scale_min, 1) && this.isAnnotationOverlay) {
+ this.setPan(0, 0);
return;
}
- if (deltaScale * invTransform.Scale < NumCast(this.rootDoc._viewScaleMin, 1) && this.isAnnotationOverlay) {
- deltaScale = NumCast(this.rootDoc._viewScaleMin, 1) / invTransform.Scale;
+ if (deltaScale * invTransform.Scale < NumCast(this.rootDoc._freeform_scale_min, 1) && this.isAnnotationOverlay) {
+ deltaScale = NumCast(this.rootDoc._freeform_scale_min, 1) / invTransform.Scale;
}
- const localTransform = this.getLocalTransform().inverse().scaleAbout(deltaScale, x, y);
+ const localTransform = invTransform.scaleAbout(deltaScale, x, y);
if (localTransform.Scale >= 0.05 || localTransform.Scale > this.zoomScaling()) {
const safeScale = Math.min(Math.max(0.05, localTransform.Scale), 20);
this.props.Document[this.scaleFieldKey] = Math.abs(safeScale);
- this.setPan(-localTransform.TranslateX / safeScale, (this.props.originTopLeft ? undefined : NumCast(this.props.Document.scrollTop) * safeScale) || -localTransform.TranslateY / safeScale);
+ this.setPan(-localTransform.TranslateX / safeScale, (this.props.originTopLeft ? undefined : NumCast(this.props.Document.layout_scrollTop) * safeScale) || -localTransform.TranslateY / safeScale);
}
};
@action
onPointerWheel = (e: React.WheelEvent): void => {
- if (this.props.noPointerWheel?.() || this.Document._isGroup || !this.isContentActive()) return; // group style collections neither pan nor zoom
+ if (this.Document._isGroup || !this.isContentActive()) return; // group style collections neither pan nor zoom
PresBox.Instance?.pauseAutoPres();
- if (this.layoutDoc._Transform || DocListCast(Doc.MyOverlayDocs?.data).includes(this.props.Document) || this.props.Document.treeViewOutlineMode === TreeViewType.outline) return;
+ if (this.layoutDoc._Transform || this.props.Document.treeViewOutlineMode === TreeViewType.outline) return;
e.stopPropagation();
- e.preventDefault();
+ 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;
switch (!e.ctrlKey ? Doc.UserDoc().freeformScrollMode : freeformScrollMode.Pan) {
case freeformScrollMode.Pan:
// if ctrl is selected then zoom
- if (e.ctrlKey) {
- if (this.props.isContentActive(true)) {
- this.zoom(e.clientX, e.clientY, e.deltaY); // if (!this.props.isAnnotationOverlay) // bcz: do we want to zoom in on images/videos/etc?
- }
- } // otherwise pan
- else if (this.props.isContentActive(true)) {
- const dx = -e.deltaX;
- const dy = -e.deltaY;
- if (e.shiftKey) {
- !this.props.isAnnotationOverlayScrollable && this.scrollPan({ deltaX: dy, deltaY: 0 });
- } else {
- !this.props.isAnnotationOverlayScrollable && this.scrollPan({ deltaX: dx, deltaY: dy });
- }
+ if (!e.ctrlKey && this.props.isContentActive(true)) {
+ this.scrollPan({ deltaX: -e.deltaX, deltaY: e.shiftKey ? 0 : -Math.max(-1, Math.min(1, e.deltaY)) });
+ break;
}
- break;
default:
case freeformScrollMode.Zoom:
- if (this.props.isContentActive(true)) {
- !this.props.isAnnotationOverlayScrollable && this.zoom(e.clientX, e.clientY, e.deltaY); // if (!this.props.isAnnotationOverlay) // bcz: do we want to zoom in on images/videos/etc?
+ if ((e.ctrlKey || !scrollable) && this.props.isContentActive(true)) {
+ this.zoom(e.clientX, e.clientY, Math.max(-1, Math.min(1, e.deltaY))); // if (!this.props.isAnnotationOverlay) // bcz: do we want to zoom in on images/videos/etc?
+ e.preventDefault();
}
break;
}
@@ -1108,31 +1107,30 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
else if (ranges.yrange.max <= panY - panelHgtMin / 2) panY = ranges.yrange.min - (this.props.originTopLeft ? panelHgtMax / 2 : panelHgtMin / 2);
}
}
- if (!this.layoutDoc._lockedTransform || LightboxView.LightboxDoc || DocListCast(Doc.MyOverlayDocs?.data).includes(this.Document)) {
+ if (!this.layoutDoc._lockedTransform || LightboxView.LightboxDoc) {
this.setPanZoomTransition(panTime);
- const scale = this.getLocalTransform().inverse().Scale;
- const minScale = NumCast(this.rootDoc._viewScaleMin, 1);
- const minPanX = NumCast(this.rootDoc._panXMin, 0);
- const minPanY = NumCast(this.rootDoc._panYMin, 0);
- const newPanX = Math.min(minPanX + (1 - minScale / scale) * NumCast(this.rootDoc._panXMax, this.nativeWidth), Math.max(minPanX, panX));
+ const minScale = NumCast(this.rootDoc._freeform_scale_min, 1);
+ const scale = 1 - minScale / this.getLocalTransform().inverse().Scale;
+ const minPanX = NumCast(this.rootDoc._freeform_panX_min, 0);
+ const minPanY = NumCast(this.rootDoc._freeform_panY_min, 0);
+ const maxPanX = NumCast(this.rootDoc._freeform_panX_max, this.nativeWidth);
+ const newPanX = Math.min(minPanX + scale * maxPanX, Math.max(minPanX, panX));
const fitYscroll = (((this.nativeHeight / this.nativeWidth) * this.props.PanelWidth() - this.props.PanelHeight()) * this.props.ScreenToLocalTransform().Scale) / minScale;
const nativeHeight = (this.props.PanelHeight() / this.props.PanelWidth() / (this.nativeHeight / this.nativeWidth)) * this.nativeHeight;
const maxScrollTop = this.nativeHeight / this.props.ScreenToLocalTransform().Scale - this.props.PanelHeight();
const maxPanY =
- minPanY + // minPanY + scrolling introduced by view scaling + scrolling introduced by fitWidth
- (1 - minScale / scale) * NumCast(this.rootDoc._panYMax, nativeHeight) +
+ minPanY + // minPanY + scrolling introduced by view scaling + scrolling introduced by layout_fitWidth
+ scale * NumCast(this.rootDoc._panY_max, nativeHeight) +
(!this.props.getScrollHeight?.() ? fitYscroll : 0); // when not zoomed, scrolling is handled via a scrollbar, not panning
let newPanY = Math.max(minPanY, Math.min(maxPanY, panY));
- if (NumCast(this.rootDoc.scrollTop) && NumCast(this.rootDoc._viewScale, minScale) !== minScale) {
- const relTop = NumCast(this.rootDoc.scrollTop) / maxScrollTop;
- this.rootDoc.scrollTop = undefined;
+ if (false && NumCast(this.rootDoc.layout_scrollTop) && NumCast(this.rootDoc._freeform_scale, minScale) !== minScale) {
+ const relTop = NumCast(this.rootDoc.layout_scrollTop) / maxScrollTop;
+ this.rootDoc.layout_scrollTop = undefined;
newPanY = minPanY + relTop * (maxPanY - minPanY);
- } else if (fitYscroll && this.rootDoc.scrollTop === undefined && NumCast(this.rootDoc._viewScale, minScale) === minScale) {
+ } else if (fitYscroll > 2 && this.rootDoc.layout_scrollTop === undefined && NumCast(this.rootDoc._freeform_scale, minScale) === minScale) {
const maxPanY = minPanY + fitYscroll;
const relTop = (panY - minPanY) / (maxPanY - minPanY);
- setTimeout(() => {
- this.rootDoc.scrollTop = relTop * maxScrollTop;
- }, 10);
+ setTimeout(() => (this.rootDoc.layout_scrollTop = relTop * maxScrollTop), 10);
newPanY = minPanY;
}
!this.Document._verticalScroll && (this.Document[this.panXFieldKey] = this.isAnnotationOverlay ? newPanX : panX);
@@ -1143,7 +1141,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
@action
nudge = (x: number, y: number, nudgeTime: number = 500) => {
const collectionDoc = this.props.docViewPath().lastElement().rootDoc;
- if (collectionDoc?._viewType !== CollectionViewType.Freeform || collectionDoc._panX !== undefined) {
+ if (collectionDoc?._type_collection !== CollectionViewType.Freeform || collectionDoc._freeform_ !== undefined) {
this.setPan(
NumCast(this.layoutDoc[this.panXFieldKey]) + ((this.props.PanelWidth() / 2) * x) / this.zoomScaling(), // nudge x,y as a function of panel dimension and scale
NumCast(this.layoutDoc[this.panYFieldKey]) + ((this.props.PanelHeight() / 2) * -y) / this.zoomScaling(),
@@ -1162,7 +1160,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
docs.sort((doc1, doc2) => NumCast(doc1.zIndex) - NumCast(doc2.zIndex));
let zfirst = docs.length ? NumCast(docs[0].zIndex) : 0;
doc.zIndex = zfirst - 1;
- } else if (doc.isInkMask) {
+ } else if (doc.stroke_isInkMask) {
doc.zIndex = 5000;
} else {
const docs = this.childLayoutPairs.map(pair => pair.layout).slice();
@@ -1204,7 +1202,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
calculatePanIntoView = (doc: Doc, xf: Transform, scale?: number) => {
const layoutdoc = Doc.Layout(doc);
const pt = xf.transformPoint(NumCast(doc.x), NumCast(doc.y));
- const pt2 = xf.transformPoint(NumCast(doc.x) + layoutdoc[WidthSym](), NumCast(doc.y) + layoutdoc[HeightSym]());
+ const pt2 = xf.transformPoint(NumCast(doc.x) + layoutdoc[Width](), NumCast(doc.y) + layoutdoc[Height]());
const bounds = { left: pt[0], right: pt2[0], top: pt[1], bot: pt2[1], width: pt2[0] - pt[0], height: pt2[1] - pt[1] };
if (scale !== undefined) {
@@ -1222,8 +1220,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const panelWidth = this.props.isAnnotationOverlay ? this.nativeWidth : this.props.PanelWidth();
const panelHeight = this.props.isAnnotationOverlay ? this.nativeHeight : this.props.PanelHeight();
- const pw = panelWidth / NumCast(this.layoutDoc._viewScale, 1);
- const ph = panelHeight / NumCast(this.layoutDoc._viewScale, 1);
+ const pw = panelWidth / NumCast(this.layoutDoc._freeform_scale, 1);
+ const ph = panelHeight / NumCast(this.layoutDoc._freeform_scale, 1);
const cx = NumCast(this.layoutDoc[this.panXFieldKey]) + (this.props.isAnnotationOverlay ? pw / 2 : 0);
const cy = NumCast(this.layoutDoc[this.panYFieldKey]) + (this.props.isAnnotationOverlay ? ph / 2 : 0);
const screen = { left: cx - pw / 2, right: cx + pw / 2, top: cy - ph / 2, bot: cy + ph / 2 };
@@ -1248,17 +1246,17 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
@action
onKeyDown = (e: React.KeyboardEvent, fieldProps: FieldViewProps) => {
const docView = fieldProps.DocumentView?.();
- if (docView && (e.metaKey || e.ctrlKey || e.altKey || docView.rootDoc._singleLine) && ['Tab', 'Enter'].includes(e.key)) {
+ if (docView && (e.metaKey || e.ctrlKey || e.altKey || docView.rootDoc._createDocOnCR) && ['Tab', 'Enter'].includes(e.key)) {
e.stopPropagation?.();
const below = !e.altKey && e.key !== 'Tab';
- const layoutKey = StrCast(docView.LayoutFieldKey);
+ const layout_fieldKey = StrCast(docView.LayoutFieldKey);
const newDoc = Doc.MakeCopy(docView.rootDoc, true);
const dataField = docView.rootDoc[Doc.LayoutFieldKey(newDoc)];
- newDoc[DataSym][Doc.LayoutFieldKey(newDoc)] = dataField === undefined || Cast(dataField, listSpec(Doc), null)?.length !== undefined ? new List<Doc>([]) : undefined;
+ newDoc[DocData][Doc.LayoutFieldKey(newDoc)] = dataField === undefined || Cast(dataField, listSpec(Doc), null)?.length !== undefined ? new List<Doc>([]) : undefined;
if (below) newDoc.y = NumCast(docView.rootDoc.y) + NumCast(docView.rootDoc._height) + 10;
else newDoc.x = NumCast(docView.rootDoc.x) + NumCast(docView.rootDoc._width) + 10;
- if (layoutKey !== 'layout' && docView.rootDoc[layoutKey] instanceof Doc) {
- newDoc[layoutKey] = docView.rootDoc[layoutKey];
+ if (layout_fieldKey !== 'layout' && docView.rootDoc[layout_fieldKey] instanceof Doc) {
+ newDoc[layout_fieldKey] = docView.rootDoc[layout_fieldKey];
}
Doc.GetProto(newDoc).text = undefined;
FormattedTextBox.SelectOnLoad = newDoc[Id];
@@ -1294,10 +1292,10 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
onDoubleClick={this.onChildDoubleClickHandler}
onBrowseClick={this.onBrowseClickHandler}
ScreenToLocalTransform={childLayout.z ? this.getContainerTransform : this.getTransform}
- PanelWidth={childLayout[WidthSym]}
- PanelHeight={childLayout[HeightSym]}
- docFilters={this.childDocFilters}
- docRangeFilters={this.childDocRangeFilters}
+ PanelWidth={childLayout[Width]}
+ PanelHeight={childLayout[Height]}
+ childFilters={this.childDocFilters}
+ childFiltersByRanges={this.childDocRangeFilters}
searchFilterDocs={this.searchFilterDocs}
isDocumentActive={this.props.childDocumentsActive?.() ? this.props.isDocumentActive : this.isContentActive}
isContentActive={this.props.childContentsActive ?? emptyFunction}
@@ -1315,11 +1313,11 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
sizeProvider={this.childSizeProvider}
dropAction={StrCast(this.props.Document.childDropAction) as dropActionType}
bringToFront={this.bringToFront}
- showTitle={this.props.childShowTitle}
+ layout_showTitle={this.props.childlayout_showTitle}
dontRegisterView={this.props.dontRenderDocuments || this.props.dontRegisterView}
pointerEvents={this.pointerEvents}
//rotation={this.props.styleProvider?.(childLayout, this.props, StyleProp.JitterRotation) || 0}
- //fitContentsToBox={this.props.fitContentsToBox || BoolCast(this.props.freezeChildDimensions)} // bcz: check this
+ //fitContentsToBox={this.props.fitContentsToBox || BoolCast(this.props.treeViewFreezeChildDimensions)} // bcz: check this
/>
);
}
@@ -1329,7 +1327,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
case OpenWhere.inParent:
return this.props.addDocument?.(doc) || false;
case OpenWhere.inParentFromScreen:
- const docContext = DocCast((doc instanceof Doc ? doc : doc?.[0])?.context);
+ const docContext = DocCast((doc instanceof Doc ? doc : doc?.[0])?.embedContainer);
return (
(this.addDocument?.(
(doc instanceof Doc ? [doc] : doc).map(doc => {
@@ -1521,7 +1519,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
elements.push({
ele: this.getChildDocView(entry[1]),
bounds: childData.opacity === 0 ? { ...childData, width: 0, height: 0 } : { ...childData, width: childSize.width, height: childSize.height },
- inkMask: BoolCast(entry[1].pair.layout.isInkMask) ? NumCast(entry[1].pair.layout.opacity, 1) : -1,
+ inkMask: BoolCast(entry[1].pair.layout.stroke_isInkMask) ? NumCast(entry[1].pair.layout.opacity, 1) : -1,
});
});
@@ -1531,20 +1529,20 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
else this.props.Document[this.scaleFieldKey] = Math.max(1, this.zoomScaling()); // NumCast(this.props.Document[this.scaleFieldKey]));
}
- this.Document._useClusters && !this._clusterSets.length && this.childDocs.length && this.updateClusters(true);
+ this.Document._freeform_useClusters && !this._clusterSets.length && this.childDocs.length && this.updateClusters(true);
return elements;
}
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.CollectionAnchorDocument({ title: 'ViewSpec - ' + StrCast(this.layoutDoc._viewType), unrendered: true, presTransition: 500, annotationOn: this.rootDoc });
- PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), pannable: !this.Document._isGroup, viewType: true, filters: true } }, this.rootDoc);
+ const anchor = Docs.Create.CollectionConfigDocument({ title: 'ViewSpec - ' + StrCast(this.layoutDoc._type_collection), layout_unrendered: true, presTransition: 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) {
- if (Cast(this.dataDoc[this.props.fieldKey + '-annotations'], listSpec(Doc), null) !== undefined) {
- Cast(this.dataDoc[this.props.fieldKey + '-annotations'], listSpec(Doc), []).push(anchor);
+ if (Cast(this.dataDoc[this.props.fieldKey + '_annotations'], listSpec(Doc), null) !== undefined) {
+ Cast(this.dataDoc[this.props.fieldKey + '_annotations'], listSpec(Doc), []).push(anchor);
} else {
- this.dataDoc[this.props.fieldKey + '-annotations'] = new List<Doc>([anchor]);
+ this.dataDoc[this.props.fieldKey + '_annotations'] = new List<Doc>([anchor]);
}
}
return anchor;
@@ -1561,14 +1559,14 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
this._disposers.groupBounds = reaction(
() => {
if (this.Document._isGroup && this.childDocs.length === this.childDocList?.length) {
- const clist = this.childDocs.map(cd => ({ x: NumCast(cd.x), y: NumCast(cd.y), width: cd[WidthSym](), height: cd[HeightSym]() }));
+ const clist = this.childDocs.map(cd => ({ x: NumCast(cd.x), y: NumCast(cd.y), width: cd[Width](), height: cd[Height]() }));
return aggregateBounds(clist, NumCast(this.layoutDoc._xPadding), NumCast(this.layoutDoc._yPadding));
}
return undefined;
},
cbounds => {
if (cbounds) {
- const c = [NumCast(this.layoutDoc.x) + this.layoutDoc[WidthSym]() / 2, NumCast(this.layoutDoc.y) + this.layoutDoc[HeightSym]() / 2];
+ const c = [NumCast(this.layoutDoc.x) + this.layoutDoc[Width]() / 2, NumCast(this.layoutDoc.y) + this.layoutDoc[Height]() / 2];
const p = [NumCast(this.layoutDoc[this.panXFieldKey]), NumCast(this.layoutDoc[this.panYFieldKey])];
const pbounds = {
x: cbounds.x - p[0] + c[0],
@@ -1634,8 +1632,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
CollectionFreeFormView.UpdateIcon(
this.layoutDoc[Id] + '-icon' + new Date().getTime(),
this.props.docViewPath().lastElement().ContentDiv!,
- this.layoutDoc[WidthSym](),
- this.layoutDoc[HeightSym](),
+ this.layoutDoc[Width](),
+ this.layoutDoc[Height](),
this.props.PanelWidth(),
this.props.PanelHeight(),
0,
@@ -1644,8 +1642,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
'',
(iconFile, nativeWidth, nativeHeight) => {
this.dataDoc.icon = new ImageField(iconFile);
- this.dataDoc['icon-nativeWidth'] = nativeWidth;
- this.dataDoc['icon-nativeHeight'] = nativeHeight;
+ this.dataDoc['icon_nativeWidth'] = nativeWidth;
+ this.dataDoc['icon_nativeHeight'] = nativeHeight;
}
);
@@ -1694,7 +1692,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
if ((e as any).handlePan || this.props.isAnnotationOverlay) return;
(e as any).handlePan = true;
- if (!this.layoutDoc._noAutoscroll && !this.props.renderDepth && this._marqueeRef) {
+ if (!this.layoutDoc._freeform_noAutoPan && !this.props.renderDepth && this._marqueeRef) {
const dragX = e.detail.clientX;
const dragY = e.detail.clientY;
const bounds = this._marqueeRef?.getBoundingClientRect();
@@ -1759,12 +1757,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
return;
}
!Doc.noviceMode && Doc.UserDoc().defaultTextLayout && appearanceItems.push({ description: 'Reset default note style', event: () => (Doc.UserDoc().defaultTextLayout = undefined), icon: 'eye' });
- appearanceItems.push({ description: (Doc.UserDoc().defaultToFlashcards ? 'Disable' : 'Enable') + ' Flashcard Notes', event: () => (Doc.UserDoc().defaultToFlashcards = !Doc.UserDoc().defaultToFlashcards), icon: 'eye' });
- appearanceItems.push({
- description: `${this.fitContentsToBox ? 'Make Zoomable' : 'Scale to Window'}`,
- event: () => (this.Document._fitContentsToBox = !this.fitContentsToBox),
- icon: !this.fitContentsToBox ? 'expand-arrows-alt' : 'compress-arrows-alt',
- });
appearanceItems.push({ description: `Pin View`, event: () => TabDocView.PinDoc(this.rootDoc, { pinViewport: MarqueeView.CurViewBounds(this.rootDoc, this.props.PanelWidth(), this.props.PanelHeight()) }), icon: 'map-pin' });
!Doc.noviceMode && appearanceItems.push({ description: `update icon`, event: this.updateIcon, icon: 'compress-arrows-alt' });
this.props.renderDepth && appearanceItems.push({ description: 'Ungroup collection', event: this.promoteCollection, icon: 'table' });
@@ -1781,7 +1773,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
!Doc.noviceMode
? viewCtrlItems.push({ description: (SnappingManager.GetShowSnapLines() ? 'Hide' : 'Show') + ' Snap Lines', event: () => SnappingManager.SetShowSnapLines(!SnappingManager.GetShowSnapLines()), icon: 'compress-arrows-alt' })
: null;
- !Doc.noviceMode ? viewCtrlItems.push({ description: (this.Document._useClusters ? 'Hide' : 'Show') + ' Clusters', event: () => this.updateClusters(!this.Document._useClusters), icon: 'braille' }) : null;
+ !Doc.noviceMode ? viewCtrlItems.push({ description: (this.Document._freeform_useClusters ? 'Hide' : 'Show') + ' Clusters', event: () => this.updateClusters(!this.Document._freeform_useClusters), icon: 'braille' }) : null;
!viewctrls && ContextMenu.Instance.addItem({ description: 'UI Controls...', subitems: viewCtrlItems, icon: 'eye' });
const options = ContextMenu.Instance.findByDescription('Options...');
@@ -1847,10 +1839,10 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
incrementalRender = action(() => {
if (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(this.props.docViewPath())) {
- const unrendered = this.childDocs.filter(doc => !this._renderCutoffData.get(doc[Id]));
+ const layout_unrendered = this.childDocs.filter(doc => !this._renderCutoffData.get(doc[Id]));
const loadIncrement = 5;
- for (var i = 0; i < Math.min(unrendered.length, loadIncrement); i++) {
- this._renderCutoffData.set(unrendered[i][Id] + '', true);
+ for (var i = 0; i < Math.min(layout_unrendered.length, loadIncrement); i++) {
+ this._renderCutoffData.set(layout_unrendered[i][Id] + '', true);
}
}
this.childDocs.some(doc => !this._renderCutoffData.get(doc[Id])) && setTimeout(this.incrementalRender, 1);
@@ -1897,7 +1889,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
r?.addEventListener('dashDragAutoScroll', this.onDragAutoScroll as any);
}}
style={{ opacity: this.props.dontRenderDocuments ? 0.7 : undefined }}>
- {this.layoutDoc._backgroundGridShow ? (
+ {this.layoutDoc._freeform_backgroundGrid ? (
<div>
<CollectionFreeFormBackgroundGrid // bcz : UGHH don't know why, but if we don't wrap in a div, then PDF's don't render whenn taking snapshot of a dashboard and the background grid is on!!?
PanelWidth={this.props.PanelWidth}
@@ -1937,7 +1929,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const nh = this.nativeHeight;
const hscale = nh ? this.props.PanelHeight() / nh : 1;
const wscale = nw ? this.props.PanelWidth() / nw : 1;
- return wscale < hscale || this.layoutDoc.fitWidth ? wscale : hscale;
+ return wscale < hscale || this.layoutDoc.layout_fitWidth ? wscale : hscale;
}
nativeDim = () => this.nativeDimScaling;
@@ -1969,6 +1961,12 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
lightboxPanelWidth = () => Math.max(0, this.props.PanelWidth() - 30);
lightboxPanelHeight = () => Math.max(0, this.props.PanelHeight() - 30);
lightboxScreenToLocal = () => this.props.ScreenToLocalTransform().translate(-15, -15);
+ onPassiveWheel = (e: WheelEvent) => {
+ 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;
+ this.props.isSelected() && !scrollable && e.preventDefault();
+ };
+ _oldWheel: any;
render() {
TraceMobx();
return (
@@ -1976,8 +1974,10 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
className="collectionfreeformview-container"
ref={r => {
this.createDashEventsTarget(r);
+ this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel);
+ this._oldWheel = r;
// prevent wheel events from passivly propagating up through containers
- !this.props.isAnnotationOverlay && r?.addEventListener('wheel', (e: WheelEvent) => this.props.isSelected() && e.preventDefault(), { passive: false });
+ r?.addEventListener('wheel', this.onPassiveWheel, { passive: false });
}}
onWheel={this.onPointerWheel}
onClick={this.onClick}
@@ -1987,12 +1987,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
onDragOver={e => e.preventDefault()}
onContextMenu={this.onContextMenu}
style={{
- pointerEvents:
- this.props.Document.type === DocumentType.MARKER
- ? 'none' // bcz: ugh.. this is here to prevent markers, which render as freeform views, from grabbing events -- need a better approach.
- : SnappingManager.GetIsDragging() && this.childDocs.includes(DragManager.docsBeingDragged.lastElement())
- ? 'all'
- : (this.props.pointerEvents?.() as any),
+ pointerEvents: SnappingManager.GetIsDragging() && this.childDocs.includes(DragManager.docsBeingDragged.lastElement()) ? 'all' : (this.props.pointerEvents?.() as any),
textAlign: this.isAnnotationOverlay ? 'initial' : undefined,
transform: `scale(${this.nativeDimScaling || 1})`,
width: `${100 / (this.nativeDimScaling || 1)}%`,
@@ -2012,8 +2007,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
onKey={this.onKeyDown}
onDoubleClick={this.onChildDoubleClickHandler}
onBrowseClick={this.onBrowseClickHandler}
- docFilters={this.childDocFilters}
- docRangeFilters={this.childDocRangeFilters}
+ childFilters={this.childDocFilters}
+ childFiltersByRanges={this.childDocRangeFilters}
searchFilterDocs={this.searchFilterDocs}
isDocumentActive={this.props.childDocumentsActive?.() ? this.props.isDocumentActive : this.isContentActive}
isContentActive={this.props.childContentsActive ?? emptyFunction}
@@ -2310,7 +2305,7 @@ ScriptingGlobals.add(function sendToBack(doc: Doc) {
});
ScriptingGlobals.add(function resetView() {
SelectionManager.Docs().forEach(doc => {
- doc._panX = doc._panY = 0;
- doc._viewScale = 1;
+ doc._freeform_panX = doc._freeform_panY = 0;
+ doc._freeform_scale = 1;
});
});
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 11d466b0f..77cb7f88c 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -1,6 +1,7 @@
import { action, computed, observable } from 'mobx';
import { observer } from 'mobx-react';
-import { AclAdmin, AclAugment, AclEdit, DataSym, Doc, Opt } from '../../../../fields/Doc';
+import { Doc, Opt } from '../../../../fields/Doc';
+import { AclAdmin, AclAugment, AclEdit, DocData } from '../../../../fields/DocSymbols';
import { Id } from '../../../../fields/FieldSymbols';
import { InkData, InkField, InkTool } from '../../../../fields/InkField';
import { List } from '../../../../fields/List';
@@ -52,8 +53,8 @@ export interface MarqueeViewBounds {
@observer
export class MarqueeView extends React.Component<SubCollectionViewProps & MarqueeViewProps> {
public static CurViewBounds(pinDoc: Doc, panelWidth: number, panelHeight: number) {
- const ps = NumCast(pinDoc._viewScale, 1);
- return { left: NumCast(pinDoc._panX) - panelWidth / 2 / ps, top: NumCast(pinDoc._panY) - panelHeight / 2 / ps, width: panelWidth / ps, height: panelHeight / ps };
+ const ps = NumCast(pinDoc._freeform_scale, 1);
+ return { left: NumCast(pinDoc._freeform_panX) - panelWidth / 2 / ps, top: NumCast(pinDoc._freeform_panY) - panelHeight / 2 / ps, width: panelWidth / ps, height: panelHeight / ps };
}
private _commandExecuted = false;
@@ -102,7 +103,6 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
this._lassoPts = [];
};
- @undoBatch
@action
onKeyPress = (e: KeyboardEvent) => {
//make textbox and add it to this collection
@@ -110,8 +110,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
const cm = ContextMenu.Instance;
const [x, y] = this.Transform.transformPoint(this._downX, this._downY);
if (e.key === '?') {
- cm.setDefaultItem('?', (str: string) => this.props.addDocTab(Docs.Create.WebDocument(`https://bing.com/search?q=${str}`, { _width: 400, x, y, _height: 512, _nativeWidth: 850, title: 'bing', useCors: true }), OpenWhere.addRight));
-
+ cm.setDefaultItem('?', (str: string) => this.props.addDocTab(Docs.Create.WebDocument(`https://bing.com/search?q=${str}`, { _width: 400, x, y, _height: 512, _nativeWidth: 850, title: 'bing', data_useCors: true }), OpenWhere.addRight));
cm.displayMenu(this._downX, this._downY, undefined, true);
e.stopPropagation();
} else if (e.key === 'u' && this.props.ungroup) {
@@ -173,7 +172,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
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('live text batch');
+ FormattedTextBox.LiveTextUndo = UndoManager.StartBatch('type new note');
this.props.addLiveTextDocument(DocUtils.GetNewTextDoc('-typed text-', x, y, 200, 100, this.props.xPadding === 0));
e.stopPropagation();
}
@@ -196,7 +195,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
const rowProto = new Doc();
rowProto.title = rowProto.Id;
rowProto._width = 200;
- rowProto.isPrototype = true;
+ 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) {
@@ -204,7 +203,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
continue;
}
const docDataProto = Doc.MakeDelegate(rowProto);
- docDataProto.isPrototype = true;
+ 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;
@@ -327,7 +326,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
} else {
this._downX = x;
this._downY = y;
- const effectiveAcl = GetEffectiveAcl(this.props.Document[DataSym]);
+ const effectiveAcl = GetEffectiveAcl(this.props.Document[DocData]);
if ([AclAdmin, AclEdit, AclAugment].includes(effectiveAcl)) {
PreviewCursor.Show(x, y, this.onKeyPress, this.props.addLiveTextDocument, this.props.getTransform, this.props.addDocument, this.props.nudge, this.props.slowLoadDocuments);
}
@@ -338,7 +337,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
@action
onClick = (e: React.MouseEvent): void => {
if (this.props.pointerEvents?.() === 'none') return;
- if (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD) {
+ if (Utils.isClick(e.clientX, e.clientY, this._downX, this._downY, Date.now())) {
if (Doc.ActiveTool === InkTool.None) {
if (!(e.nativeEvent as any).marqueeHit) {
(e.nativeEvent as any).marqueeHit = true;
@@ -379,10 +378,10 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
Doc.GetProto(doc).data = new List<Doc>(selected);
Doc.GetProto(doc).title = makeGroup ? 'grouping' : 'nested freeform';
!this.props.isAnnotationOverlay && Doc.AddFileOrphan(Doc.GetProto(doc));
- doc._panX = doc._panY = 0;
+ doc._freeform_panX = doc._freeform_panY = 0;
return doc;
})(Doc.MakeCopy(Doc.UserDoc().emptyCollection as Doc, true));
- newCollection.system = undefined;
+ newCollection.isSystem = undefined;
newCollection._width = this.Bounds.width;
newCollection._height = this.Bounds.height;
newCollection._isGroup = makeGroup;
@@ -390,12 +389,13 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
newCollection.enableDragWhenActive = makeGroup;
newCollection.x = this.Bounds.left;
newCollection.y = this.Bounds.top;
- newCollection.fitWidth = true;
- selected.forEach(d => (d.context = newCollection));
+ newCollection.layout_fitWidth = true;
+ selected.forEach(d => (d.embedContainer = newCollection));
this.hideMarquee();
return newCollection;
});
+ @undoBatch
@action
pileup = (e: KeyboardEvent | React.PointerEvent | undefined) => {
const selected = this.marqueeSelect(false);
@@ -432,8 +432,8 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
}
const newCollection = this.getCollection(selected, (e as KeyboardEvent)?.key === 't' ? Docs.Create.StackingDocument : undefined, group);
- newCollection._panX = this.Bounds.left + this.Bounds.width / 2;
- newCollection._panY = this.Bounds.top + this.Bounds.height / 2;
+ newCollection._freeform_panX = this.Bounds.left + this.Bounds.width / 2;
+ newCollection._freeform_panY = this.Bounds.top + this.Bounds.height / 2;
newCollection._currentFrame = activeFrame;
this.props.addDocument?.(newCollection);
this.props.selectDocuments([newCollection]);
@@ -508,35 +508,35 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
};
@undoBatch
- @action
- summary = (e: KeyboardEvent | React.PointerEvent | undefined) => {
+ summary = action((e: KeyboardEvent | React.PointerEvent | undefined) => {
const selected = this.marqueeSelect(false).map(d => {
this.props.removeDocument?.(d);
d.x = NumCast(d.x) - this.Bounds.left;
d.y = NumCast(d.y) - this.Bounds.top;
return d;
});
- const summary = Docs.Create.TextDocument('', { backgroundColor: '#e2ad32', x: this.Bounds.left, y: this.Bounds.top, followLinkToggle: true, _width: 200, _height: 200, _fitContentsToBox: true, _showSidebar: true, title: 'overview' });
+ const summary = Docs.Create.TextDocument('', {
+ backgroundColor: '#e2ad32',
+ x: this.Bounds.left,
+ y: this.Bounds.top,
+ followLinkToggle: true,
+ _width: 200,
+ _height: 200,
+ _layout_fitContentsToBox: true,
+ _layout_showSidebar: true,
+ title: 'overview',
+ });
const portal = Docs.Create.FreeformDocument(selected, { x: this.Bounds.left + 200, y: this.Bounds.top, isGroup: true, backgroundColor: 'transparent' });
- DocUtils.MakeLink(summary, portal, { linkRelationship: 'summary of:summarized by' });
+ DocUtils.MakeLink(summary, portal, { link_relationship: 'summary of:summarized by' });
portal.hidden = true;
this.props.addDocument?.(portal);
this.props.addLiveTextDocument(summary);
MarqueeOptionsMenu.Instance.fadeOut(true);
- };
+ });
@action
- background = (e: KeyboardEvent | React.PointerEvent | undefined) => {
- const newCollection = this.getCollection([], undefined, undefined);
- this.props.addDocument?.(newCollection);
- MarqueeOptionsMenu.Instance.fadeOut(true);
- this.hideMarquee();
- setTimeout(() => this.props.selectDocuments([newCollection]));
- };
-
- @undoBatch
- marqueeCommand = action((e: KeyboardEvent) => {
+ marqueeCommand = (e: KeyboardEvent) => {
if (this._commandExecuted || (e as any).propagationIsStopped) {
return;
}
@@ -547,7 +547,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
this.delete(e, e.key === 'h');
e.stopPropagation();
}
- if ('cbtsSpg'.indexOf(e.key) !== -1) {
+ if ('ctsSpg'.indexOf(e.key) !== -1) {
this._commandExecuted = true;
e.stopPropagation();
e.preventDefault();
@@ -555,7 +555,6 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
if (e.key === 'g') this.collection(e, true);
if (e.key === 'c' || e.key === 't') this.collection(e);
if (e.key === 's' || e.key === 'S') this.summary(e);
- if (e.key === 'b') this.background(e);
if (e.key === 'p') this.pileup(e);
this.cleanupInteractions(false);
}
@@ -565,7 +564,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
e.preventDefault();
this._lassoFreehand = !this._lassoFreehand;
}
- });
+ };
touchesLine(r1: { left: number; top: number; width: number; height: number }) {
for (const lassoPt of this._lassoPts) {
diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
index efd73a927..65578f214 100644
--- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
+++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
@@ -3,9 +3,10 @@ import { Tooltip } from '@material-ui/core';
import { action, IReactionDisposer, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { Doc, HeightSym, Opt, WidthSym } from '../../../../fields/Doc';
+import { Doc, Opt } from '../../../../fields/Doc';
+import { Height, Width } from '../../../../fields/DocSymbols';
import { Id } from '../../../../fields/FieldSymbols';
-import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
+import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
import { emptyFunction, returnEmptyDoclist, returnTrue, StopEvent, Utils } from '../../../../Utils';
import { CollectionViewType } from '../../../documents/DocumentTypes';
import { DocumentManager } from '../../../util/DocumentManager';
@@ -15,6 +16,7 @@ import { DocumentLinksButton } from '../../nodes/DocumentLinksButton';
import { DocumentView } from '../../nodes/DocumentView';
import { LinkDescriptionPopup } from '../../nodes/LinkDescriptionPopup';
import { StyleProp } from '../../StyleProvider';
+import { UndoStack } from '../../UndoStack';
import { CollectionStackedTimeline } from '../CollectionStackedTimeline';
import { CollectionSubView } from '../CollectionSubView';
import './CollectionLinearView.scss';
@@ -22,7 +24,7 @@ import './CollectionLinearView.scss';
/**
* CollectionLinearView is the class for rendering the horizontal collection
* of documents, it useful for horizontal menus. It can either be expandable
- * or not using the linearViewExpandable field.
+ * or not using the linearView_Expandable field.
* It is used in the following locations:
* - It is used in the popup menu on the bottom left (see docButtons() in MainView.tsx)
* - It is used for the context sensitive toolbar at the top (see contMenuButtons() in CollectionMenu.tsx)
@@ -39,12 +41,12 @@ export class CollectionLinearView extends CollectionSubView() {
this._dropDisposer?.();
this._widthDisposer?.();
this._selectedDisposer?.();
- this.childLayoutPairs.map((pair, ind) => ScriptCast(pair.layout.proto?.onPointerUp)?.script.run({ this: pair.layout.proto }, console.log));
+ this.childLayoutPairs.map((pair, ind) => ScriptCast(DocCast(pair.layout.proto)?.onPointerUp)?.script.run({ this: pair.layout.proto }, console.log));
}
componentDidMount() {
this._widthDisposer = reaction(
- () => 5 + NumCast(this.rootDoc.linearBtnWidth, this.dimension()) + (this.layoutDoc.linearViewIsExpanded ? this.childDocs.filter(doc => !doc.hidden).reduce((tot, doc) => (doc[WidthSym]() || this.dimension()) + tot + 4, 0) : 0),
+ () => 5 + NumCast(this.rootDoc.linearBtnWidth, this.dimension()) + (this.layoutDoc.linearView_IsExpanded ? this.childDocs.filter(doc => !doc.hidden).reduce((tot, doc) => (doc[Width]() || this.dimension()) + tot + 4, 0) : 0),
width => this.childDocs.length && (this.layoutDoc._width = width),
{ fireImmediately: true }
);
@@ -60,11 +62,11 @@ export class CollectionLinearView extends CollectionSubView() {
if (isSelected) {
selected = pair;
} else {
- ScriptCast(pair.layout.proto?.onPointerUp)?.script.run({ this: pair.layout.proto }, console.log);
+ ScriptCast(DocCast(pair.layout.proto)?.onPointerUp)?.script.run({ this: pair.layout.proto }, console.log);
}
});
if (selected && selected.layout) {
- ScriptCast(selected.layout.proto?.onPointerDown)?.script.run({ this: selected.layout.proto }, console.log);
+ ScriptCast(DocCast(selected.layout.proto)?.onPointerDown)?.script.run({ this: selected.layout.proto }, console.log);
}
}),
{ fireImmediately: true }
@@ -161,11 +163,17 @@ export class CollectionLinearView extends CollectionSubView() {
</span>
);
};
+
getDisplayDoc = (doc: Doc, preview: boolean = false) => {
- if (doc.icon === 'linkui') return this.getLinkUI();
- if (doc.icon === 'currentlyplayingui') return this.getCurrentlyPlayingUI();
+ // hack to avoid overhead of making UndoStack,etc into DocumentView style Boxes. If the UndoStack is ever intended to become part of the persisten state of the dashboard, then this would have to change.
+ // prettier-ignore
+ switch (doc.layout) {
+ case '<LinkingUI>': return this.getLinkUI();
+ case '<CurrentlyPlayingUI>': return this.getCurrentlyPlayingUI();
+ case '<UndoStack>': return <UndoStack key={doc[Id]} width={200} height={40} inline={true} />;
+ }
- const nested = doc._viewType === CollectionViewType.Linear;
+ const nested = doc._type_collection === CollectionViewType.Linear;
const hidden = doc.hidden === true;
let dref: Opt<HTMLDivElement>;
@@ -197,8 +205,8 @@ export class CollectionLinearView extends CollectionSubView() {
rootSelected={this.props.isSelected}
removeDocument={this.props.removeDocument}
ScreenToLocalTransform={docXf}
- PanelWidth={doc[WidthSym]}
- PanelHeight={nested || doc._height ? doc[HeightSym] : this.dimension}
+ PanelWidth={doc[Width]}
+ PanelHeight={nested || doc._height ? doc[Height] : this.dimension}
renderDepth={this.props.renderDepth + 1}
dontRegisterView={BoolCast(this.rootDoc.childDontRegisterViews)}
focus={emptyFunction}
@@ -206,8 +214,8 @@ export class CollectionLinearView extends CollectionSubView() {
docViewPath={returnEmptyDoclist}
whenChildContentsActiveChanged={emptyFunction}
bringToFront={emptyFunction}
- docFilters={this.props.docFilters}
- docRangeFilters={this.props.docRangeFilters}
+ childFilters={this.props.childFilters}
+ childFiltersByRanges={this.props.childFiltersByRanges}
searchFilterDocs={this.props.searchFilterDocs}
hideResizeHandles={true}
/>
@@ -218,7 +226,7 @@ export class CollectionLinearView extends CollectionSubView() {
render() {
const flexDir = StrCast(this.Document.flexDirection); // Specify direction of linear view content
const flexGap = NumCast(this.Document.flexGap); // Specify the gap between linear view content
- const isExpanded = BoolCast(this.layoutDoc.linearViewIsExpanded);
+ const isExpanded = BoolCast(this.layoutDoc.linearView_IsExpanded);
const menuOpener = (
<label
@@ -231,9 +239,9 @@ export class CollectionLinearView extends CollectionSubView() {
);
return (
- <div className={`collectionLinearView-outer ${this.layoutDoc.linearViewSubMenu}`} style={{ backgroundColor: this.layoutDoc.linearViewIsExpanded ? undefined : 'transparent' }}>
+ <div className={`collectionLinearView-outer ${this.layoutDoc.linearView_SubMenu}`} style={{ backgroundColor: this.layoutDoc.linearView_IsExpanded ? undefined : 'transparent' }}>
<div className="collectionLinearView" ref={this.createDashEventsTarget} onContextMenu={this.myContextMenu} style={{ minHeight: this.dimension() }}>
- {!this.props.Document.linearViewExpandable ? null : (
+ {!this.props.Document.linearView_Expandable ? null : (
<Tooltip title={<div className="dash-tooltip">{isExpanded ? 'Close' : 'Open'}</div>} placement="top">
{menuOpener}
</Tooltip>
@@ -251,11 +259,11 @@ export class CollectionLinearView extends CollectionSubView() {
scriptContext: this.props.scriptContext,
documentView: this.props.DocumentView?.(),
});
- this.layoutDoc.linearViewIsExpanded = this.addMenuToggle.current!.checked;
+ this.layoutDoc.linearView_IsExpanded = this.addMenuToggle.current!.checked;
})}
/>
- {!this.layoutDoc.linearViewIsExpanded ? null : (
+ {!this.layoutDoc.linearView_IsExpanded ? null : (
<div
className="collectionLinearView-content"
style={{
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
index 78d3d1b6e..34fa0343d 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
@@ -259,8 +259,8 @@ export class CollectionMulticolumnView extends CollectionSubView() {
hideDecorationTitle={this.props.childHideDecorationTitle?.()}
fitContentsToBox={this.props.fitContentsToBox}
focus={this.props.focus}
- docFilters={this.childDocFilters}
- docRangeFilters={this.childDocRangeFilters}
+ childFilters={this.childDocFilters}
+ childFiltersByRanges={this.childDocRangeFilters}
searchFilterDocs={this.searchFilterDocs}
dontRegisterView={this.props.dontRegisterView}
addDocument={this.props.addDocument}
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
index 4d61dc272..bab77ed48 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
@@ -258,8 +258,8 @@ export class CollectionMultirowView extends CollectionSubView() {
hideDecorationTitle={this.props.childHideDecorationTitle?.()}
fitContentsToBox={this.props.fitContentsToBox}
focus={this.props.focus}
- docFilters={this.childDocFilters}
- docRangeFilters={this.childDocRangeFilters}
+ childFilters={this.childDocFilters}
+ childFiltersByRanges={this.childDocRangeFilters}
searchFilterDocs={this.searchFilterDocs}
dontRegisterView={this.props.dontRegisterView}
addDocument={this.props.addDocument}
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
index a9434fde3..52ebb7763 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
@@ -104,7 +104,7 @@
.schema-header-row {
cursor: grab;
- justify-content: flex-end;
+ //justify-content: flex-end;
.row-menu {
display: flex;
@@ -182,8 +182,10 @@
.schema-table-cell,
.row-menu {
border: 1px solid $medium-gray;
- overflow: hidden;
+ overflow-x: hidden;
+ overflow-y: auto;
padding: 5px;
+ display: inline-block;
}
.schema-row {
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index a59d7e5a3..15424de98 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -8,17 +8,16 @@ import { Id } from '../../../../fields/FieldSymbols';
import { List } from '../../../../fields/List';
import { listSpec } from '../../../../fields/Schema';
import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../../fields/Types';
-import { emptyFunction, returnDefault, returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../Utils';
+import { emptyFunction, returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../Utils';
import { Docs, DocumentOptions, DocUtils, FInfo } from '../../../documents/Documents';
import { DocumentManager } from '../../../util/DocumentManager';
import { DragManager } from '../../../util/DragManager';
import { SelectionManager } from '../../../util/SelectionManager';
-import { undoBatch } from '../../../util/UndoManager';
+import { undoable, undoBatch } from '../../../util/UndoManager';
import { ContextMenu } from '../../ContextMenu';
import { EditableView } from '../../EditableView';
import { Colors } from '../../global/globalEnums';
import { DocFocusOptions, DocumentView } from '../../nodes/DocumentView';
-import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox';
import { KeyValueBox } from '../../nodes/KeyValueBox';
import { DefaultStyleProvider } from '../../StyleProvider';
import { CollectionSubView } from '../CollectionSubView';
@@ -33,6 +32,7 @@ export enum ColumnType {
Date,
Image,
RTF,
+ Enumeration,
Any,
}
@@ -43,9 +43,10 @@ export const FInfotoColType: { [key: string]: ColumnType } = {
date: ColumnType.Date,
image: ColumnType.Image,
rtf: ColumnType.RTF,
+ enumeration: ColumnType.Enumeration,
};
-const defaultColumnKeys: string[] = ['title', 'type', 'author', 'creationDate', 'text'];
+const defaultColumnKeys: string[] = ['title', 'type', 'author', 'author_date', 'text'];
@observer
export class CollectionSchemaView extends CollectionSubView() {
@@ -55,8 +56,10 @@ export class CollectionSchemaView extends CollectionSubView() {
private _makeNewColumn: boolean = false;
private _documentOptions: DocumentOptions = new DocumentOptions();
private _tableContentRef: HTMLDivElement | null = null;
+ private _menuTarget = React.createRef<HTMLDivElement>();
- public static _rowHeight: number = 50;
+ static _rowHeight: number = 50;
+ static _rowSingleLineHeight: number = 32;
public static _minColWidth: number = 25;
public static _rowMenuWidth: number = 60;
public static _previewDividerWidth: number = 4;
@@ -77,8 +80,13 @@ export class CollectionSchemaView extends CollectionSubView() {
@observable _filterSearchValue: string = '';
@observable _selectedCell: [Doc, number] | undefined;
+ // target HTMLelement portal for showing a popup menu to edit cell values.
+ public get MenuTarget() {
+ return this._menuTarget.current;
+ }
+
@computed get _selectedDocs() {
- return SelectionManager.Docs().filter(doc => Doc.AreProtosEqual(DocCast(doc.context), this.rootDoc));
+ return SelectionManager.Docs().filter(doc => Doc.AreProtosEqual(DocCast(doc.embedContainer), this.rootDoc));
}
@computed get documentKeys() {
@@ -86,7 +94,7 @@ export class CollectionSchemaView extends CollectionSubView() {
}
@computed get previewWidth() {
- return NumCast(this.layoutDoc.schemaPreviewWidth);
+ return NumCast(this.layoutDoc.schema_previewWidth);
}
@computed get tableWidth() {
@@ -94,12 +102,12 @@ export class CollectionSchemaView extends CollectionSubView() {
}
@computed get columnKeys() {
- return Cast(this.layoutDoc.columnKeys, listSpec('string'), defaultColumnKeys);
+ return Cast(this.layoutDoc.schema_columnKeys, listSpec('string'), defaultColumnKeys);
}
@computed get storedColumnWidths() {
const widths = NumListCast(
- this.layoutDoc.columnWidths,
+ this.layoutDoc.schema_columnWidths,
this.columnKeys.map(() => (this.tableWidth - CollectionSchemaView._rowMenuWidth) / this.columnKeys.length)
);
@@ -223,7 +231,7 @@ export class CollectionSchemaView extends CollectionSubView() {
@undoBatch
@action
- setSort = (field: string | undefined, desc: boolean = false) => {
+ setColumnSort = (field: string | undefined, desc: boolean = false) => {
this.layoutDoc.sortField = field;
this.layoutDoc.sortDesc = desc;
};
@@ -242,7 +250,7 @@ export class CollectionSchemaView extends CollectionSubView() {
let currKeys = [...this.columnKeys];
currKeys[index] = newKey;
- this.layoutDoc.columnKeys = new List<string>(currKeys);
+ this.layoutDoc.schema_columnKeys = new List<string>(currKeys);
};
@undoBatch
@@ -256,11 +264,11 @@ export class CollectionSchemaView extends CollectionSubView() {
const currWidths = this.storedColumnWidths.slice();
currWidths.splice(0, 0, newColWidth);
const newDesiredTableWidth = currWidths.reduce((w, cw) => w + cw, 0);
- this.layoutDoc.columnWidths = new List<number>(currWidths.map(w => (w / newDesiredTableWidth) * (this.tableWidth - CollectionSchemaView._rowMenuWidth)));
+ this.layoutDoc.schema_columnWidths = new List<number>(currWidths.map(w => (w / newDesiredTableWidth) * (this.tableWidth - CollectionSchemaView._rowMenuWidth)));
let currKeys = this.columnKeys.slice();
currKeys.splice(0, 0, key);
- this.layoutDoc.columnKeys = new List<string>(currKeys);
+ this.layoutDoc.schema_columnKeys = new List<string>(currKeys);
};
@action
@@ -273,11 +281,11 @@ export class CollectionSchemaView extends CollectionSubView() {
const currWidths = this.storedColumnWidths.slice();
currWidths.splice(index, 1);
const newDesiredTableWidth = currWidths.reduce((w, cw) => w + cw, 0);
- this.layoutDoc.columnWidths = new List<number>(currWidths.map(w => (w / newDesiredTableWidth) * (this.tableWidth - CollectionSchemaView._rowMenuWidth)));
+ this.layoutDoc.schema_columnWidths = new List<number>(currWidths.map(w => (w / newDesiredTableWidth) * (this.tableWidth - CollectionSchemaView._rowMenuWidth)));
let currKeys = this.columnKeys.slice();
currKeys.splice(index, 1);
- this.layoutDoc.columnKeys = new List<string>(currKeys);
+ this.layoutDoc.schema_columnKeys = new List<string>(currKeys);
};
@action
@@ -316,7 +324,7 @@ export class CollectionSchemaView extends CollectionSubView() {
@action
finishResize = () => {
- this.layoutDoc.columnWidths = new List<number>(this._displayColumnWidths);
+ this.layoutDoc.schema_columnWidths = new List<number>(this._displayColumnWidths);
this._displayColumnWidths = undefined;
};
@@ -325,20 +333,18 @@ export class CollectionSchemaView extends CollectionSubView() {
moveColumn = (fromIndex: number, toIndex: number) => {
let currKeys = this.columnKeys.slice();
currKeys.splice(toIndex, 0, currKeys.splice(fromIndex, 1)[0]);
- this.layoutDoc.columnKeys = new List<string>(currKeys);
+ this.layoutDoc.schema_columnKeys = new List<string>(currKeys);
let currWidths = this.storedColumnWidths.slice();
currWidths.splice(toIndex, 0, currWidths.splice(fromIndex, 1)[0]);
- this.layoutDoc.columnWidths = new List<number>(currWidths);
+ this.layoutDoc.schema_columnWidths = new List<number>(currWidths);
};
@action
dragColumn = (e: PointerEvent, index: number) => {
const dragData = new DragManager.ColumnDragData(index);
const dragEles = [this._colEles[index]];
- this.childDocs.forEach(doc => {
- dragEles.push(this._rowEles.get(doc).children[1].children[index]);
- });
+ this.childDocs.forEach(doc => dragEles.push(this._rowEles.get(doc).children[1].children[index]));
DragManager.StartColumnDrag(dragEles, dragData, e.x, e.y);
document.removeEventListener('pointermove', this.highlightDropColumn);
@@ -352,24 +358,28 @@ export class CollectionSchemaView extends CollectionSubView() {
return true;
};
- @action
- highlightDropColumn = (e: PointerEvent) => {
- e.stopPropagation();
- const mouseX = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[0];
+ findDropIndex = (mouseX: number) => {
let index: number | undefined;
this.displayColumnWidths.reduce((total, curr, i) => {
if (total <= mouseX && total + curr >= mouseX) {
- if (mouseX <= total + curr / 2) index = i;
+ if (mouseX <= total + curr) index = i;
else index = i + 1;
}
return total + curr;
}, CollectionSchemaView._rowMenuWidth);
+ return index;
+ };
+ @action
+ highlightDropColumn = (e: PointerEvent) => {
+ e.stopPropagation();
+ const mouseX = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[0];
+ const index = this.findDropIndex(mouseX);
this._colEles.forEach((colRef, i) => {
let leftStyle = '';
let rightStyle = '';
- if (i + 1 === index) rightStyle = `solid 2px ${Colors.MEDIUM_BLUE}`;
- if (i === index && i === 0) leftStyle = `solid 2px ${Colors.MEDIUM_BLUE}`;
+ if (i + 1 === index) rightStyle = `solid 12px ${Colors.MEDIUM_BLUE}`;
+ if (i === index && i === 0) leftStyle = `solid 12px ${Colors.MEDIUM_BLUE}`;
colRef.style.borderLeft = leftStyle;
colRef.style.borderRight = rightStyle;
this.childDocs.forEach(doc => {
@@ -426,15 +436,8 @@ export class CollectionSchemaView extends CollectionSubView() {
if (de.complete.columnDragData) {
e.stopPropagation();
const mouseX = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y)[0];
- let index = de.complete.columnDragData.colIndex;
- this.displayColumnWidths.reduce((total, curr, i) => {
- if (total <= mouseX && total + curr >= mouseX) {
- if (mouseX <= total + curr / 2) index = i;
- else index = i + 1;
- }
- return total + curr;
- }, CollectionSchemaView._rowMenuWidth);
- this.moveColumn(de.complete.columnDragData.colIndex, index);
+ const index = this.findDropIndex(mouseX);
+ this.moveColumn(de.complete.columnDragData.colIndex, index ?? de.complete.columnDragData.colIndex);
this._colEles.forEach((colRef, i) => {
colRef.style.borderLeft = '';
@@ -479,28 +482,15 @@ export class CollectionSchemaView extends CollectionSubView() {
const maxWidth = 1000;
const movedWidth = this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0];
const width = movedWidth < minWidth ? minWidth : movedWidth > maxWidth ? maxWidth : movedWidth;
- this.layoutDoc.schemaPreviewWidth = width;
+ this.layoutDoc.schema_previewWidth = width;
return false;
};
- @action
- addNewTextDoc = (value: string, shiftDown?: boolean, forceEmptyNote?: boolean) => {
- if (!value && !forceEmptyNote) return false;
- const newDoc = Docs.Create.TextDocument(value, { title: value, _autoHeight: true });
- FormattedTextBox.SelectOnLoad = newDoc[Id];
- FormattedTextBox.SelectOnLoadChar = forceEmptyNote ? '' : ' ';
- return this.addRow(newDoc) || false;
- };
-
menuCallback = (x: number, y: number) => {
ContextMenu.Instance.clearItems();
- DocUtils.addDocumentCreatorMenuItems(doc => this.addRow(doc), this.addRow, x, y, true);
+ DocUtils.addDocumentCreatorMenuItems(this.addRow, this.addRow, x, y, true);
- ContextMenu.Instance.setDefaultItem('::', (name: string): void => {
- Doc.GetProto(this.props.Document)[name] = '';
- this.addRow(Docs.Create.TextDocument('', { title: name, _autoHeight: true }));
- });
ContextMenu.Instance.displayMenu(x, y, undefined, true);
};
@@ -515,9 +505,9 @@ export class CollectionSchemaView extends CollectionSubView() {
if (found) {
const rect = found.getBoundingClientRect();
const localRect = this.props.ScreenToLocalTransform().transformBounds(rect.left, rect.top, rect.width, rect.height);
- if (localRect.y < CollectionSchemaView._rowHeight || localRect.y + localRect.height > this.props.PanelHeight()) {
+ if (localRect.y < this.rowHeightFunc() || localRect.y + localRect.height > this.props.PanelHeight()) {
let focusSpeed = options.zoomTime ?? 50;
- smoothScroll(focusSpeed, this._tableContentRef!, localRect.y + this._tableContentRef!.scrollTop - CollectionSchemaView._rowHeight, options.easeFunc);
+ smoothScroll(focusSpeed, this._tableContentRef!, localRect.y + this._tableContentRef!.scrollTop - this.rowHeightFunc(), options.easeFunc);
return focusSpeed;
}
}
@@ -620,7 +610,7 @@ export class CollectionSchemaView extends CollectionSubView() {
this._menuKeys = this.documentKeys.filter(value => value.toLowerCase().includes(this._menuValue.toLowerCase()));
};
- getFieldFilters = (field: string) => StrListCast(this.Document._docFilters).filter(filter => filter.split(':')[0] == field);
+ getFieldFilters = (field: string) => StrListCast(this.Document._childFilters).filter(filter => filter.split(':')[0] == field);
removeFieldFilters = (field: string) => {
this.getFieldFilters(field).forEach(filter => Doc.setDocFilter(this.Document, field, filter.split(':')[1], 'remove'));
@@ -696,6 +686,12 @@ export class CollectionSchemaView extends CollectionSubView() {
);
}
+ onPassiveWheel = (e: WheelEvent) => {
+ // if scrollTop is 0, then don't let wheel trigger scroll on any container (which it would since onScroll won't be triggered on this)
+ if (!this._oldWheel.scrollTop && e.deltaY <= 0) e.preventDefault();
+ e.stopPropagation();
+ };
+ _oldWheel: any;
@computed get keysDropdown() {
return (
<div className="schema-key-search">
@@ -709,16 +705,11 @@ export class CollectionSchemaView extends CollectionSubView() {
</div>
<div
className="schema-key-list"
- ref={r =>
- r?.addEventListener(
- 'wheel', // if scrollTop is 0, then don't let wheel trigger scroll on any container (which it would since onScroll won't be triggered on this)
- (e: WheelEvent) => {
- if (!r.scrollTop && e.deltaY <= 0) e.preventDefault();
- e.stopPropagation();
- },
- { passive: false }
- )
- }>
+ ref={r => {
+ this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel);
+ this._oldWheel = r;
+ r?.addEventListener('wheel', this.onPassiveWheel, { passive: false });
+ }}>
{this._menuKeys.map(key => (
<div
className="schema-search-result"
@@ -772,7 +763,7 @@ export class CollectionSchemaView extends CollectionSubView() {
}
});
- const filters = StrListCast(this.Document._docFilters);
+ const filters = StrListCast(this.Document._childFilters);
return keyOptions.map(key => {
let bool = false;
if (filters !== undefined) {
@@ -836,6 +827,7 @@ export class CollectionSchemaView extends CollectionSubView() {
});
return { docs };
}
+ rowHeightFunc = () => (BoolCast(this.layoutDoc._schema_singleLine) ? CollectionSchemaView._rowSingleLineHeight : CollectionSchemaView._rowHeight);
sortedDocsFunc = () => this.sortedDocs;
isContentActive = () => this.props.isSelected() || this.props.isContentActive();
screenToLocal = () => this.props.ScreenToLocalTransform().translate(-this.tableWidth, 0);
@@ -843,6 +835,7 @@ export class CollectionSchemaView extends CollectionSubView() {
render() {
return (
<div className="collectionSchemaView" ref={(ele: HTMLDivElement | null) => this.createDashEventsTarget(ele)} onDrop={this.onExternalDrop.bind(this)}>
+ <div ref={this._menuTarget} style={{ background: 'red', top: 0, left: 0, position: 'absolute', zIndex: 10000 }}></div>
<div
className="schema-table"
onWheel={e => this.props.isContentActive() && e.stopPropagation()}
@@ -850,7 +843,7 @@ export class CollectionSchemaView extends CollectionSubView() {
// prevent wheel events from passively propagating up through containers
r?.addEventListener('wheel', (e: WheelEvent) => {}, { passive: false });
}}>
- <div className="schema-header-row" style={{ height: CollectionSchemaView._rowHeight }}>
+ <div className="schema-header-row" style={{ height: this.rowHeightFunc() }}>
<div className="row-menu" style={{ width: CollectionSchemaView._rowMenuWidth }}>
<div className="schema-header-button" onPointerDown={e => (this._columnMenuIndex === -1 ? this.closeColumnMenu() : this.openColumnMenu(-1, true))}>
<FontAwesomeIcon icon="plus" />
@@ -864,19 +857,28 @@ export class CollectionSchemaView extends CollectionSubView() {
columnWidths={this.displayColumnWidths}
sortField={this.sortField}
sortDesc={this.sortDesc}
- setSort={this.setSort}
+ setSort={this.setColumnSort}
+ rowHeight={this.rowHeightFunc}
removeColumn={this.removeColumn}
resizeColumn={this.startResize}
openContextMenu={this.openContextMenu}
dragColumn={this.dragColumn}
setColRef={this.setColRef}
+ isContentActive={this.props.isContentActive}
/>
))}
</div>
{this._columnMenuIndex !== undefined && this.renderColumnMenu}
{this._filterColumnIndex !== undefined && this.renderFilterMenu}
- <CollectionSchemaViewDocs schema={this} childDocs={this.sortedDocsFunc} setRef={(ref: HTMLDivElement | null) => (this._tableContentRef = ref)} />
- <EditableView GetValue={returnEmptyString} SetValue={this.addNewTextDoc} placeholder={"Type ':' for commands"} contents={'+ New Node'} menuCallback={this.menuCallback} height={CollectionSchemaView._newNodeInputHeight} />
+ <CollectionSchemaViewDocs schema={this} childDocs={this.sortedDocsFunc} rowHeight={this.rowHeightFunc} setRef={(ref: HTMLDivElement | null) => (this._tableContentRef = ref)} />
+ <EditableView
+ GetValue={returnEmptyString}
+ SetValue={undoable(value => (value ? this.addRow(Docs.Create.TextDocument(value, { title: value, _layout_autoHeight: true })) : false), 'add text doc')}
+ placeholder={"Type ':' for commands"}
+ contents={'+ New Node'}
+ menuCallback={this.menuCallback}
+ height={CollectionSchemaView._newNodeInputHeight}
+ />
</div>
{this.previewWidth > 0 && <div className="schema-preview-divider" style={{ width: CollectionSchemaView._previewDividerWidth }} onPointerDown={this.onDividerDown}></div>}
{this.previewWidth > 0 && (
@@ -897,8 +899,8 @@ export class CollectionSchemaView extends CollectionSubView() {
isContentActive={returnTrue}
isDocumentActive={returnFalse}
ScreenToLocalTransform={this.screenToLocal}
- docFilters={this.childDocFilters}
- docRangeFilters={this.childDocRangeFilters}
+ childFilters={this.childDocFilters}
+ childFiltersByRanges={this.childDocRangeFilters}
searchFilterDocs={this.searchFilterDocs}
styleProvider={DefaultStyleProvider}
docViewPath={returnEmptyDoclist}
@@ -922,20 +924,20 @@ interface CollectionSchemaViewDocsProps {
schema: CollectionSchemaView;
setRef: (ref: HTMLDivElement | null) => void;
childDocs: () => { docs: Doc[] };
+ rowHeight: () => number;
}
@observer
class CollectionSchemaViewDocs extends React.Component<CollectionSchemaViewDocsProps> {
tableWidthFunc = () => this.props.schema.tableWidth;
- rowHeightFunc = () => CollectionSchemaView._rowHeight;
- childScreenToLocal = computedFn((index: number) => () => this.props.schema.props.ScreenToLocalTransform().translate(0, -CollectionSchemaView._rowHeight - index * this.rowHeightFunc()));
+ childScreenToLocal = computedFn((index: number) => () => this.props.schema.props.ScreenToLocalTransform().translate(0, -this.props.rowHeight() - index * this.props.rowHeight()));
render() {
return (
- <div className="schema-table-content" ref={this.props.setRef} style={{ height: `calc(100% - ${CollectionSchemaView._newNodeInputHeight + CollectionSchemaView._rowHeight}px)` }}>
+ <div className="schema-table-content" ref={this.props.setRef} style={{ height: `calc(100% - ${CollectionSchemaView._newNodeInputHeight + this.props.rowHeight()}px)` }}>
{this.props.childDocs().docs.map((doc: Doc, index: number) => {
const dataDoc = !doc.isTemplateDoc && !doc.isTemplateForField ? undefined : this.props.schema.props.DataDoc;
return (
- <div className="schema-row-wrapper" style={{ height: CollectionSchemaView._rowHeight }}>
+ <div className="schema-row-wrapper" style={{ height: this.props.rowHeight() }}>
<DocumentView
key={doc[Id]}
{...this.props.schema.props}
@@ -943,17 +945,18 @@ class CollectionSchemaViewDocs extends React.Component<CollectionSchemaViewDocsP
LayoutTemplateString={SchemaRowBox.LayoutString(this.props.schema.props.fieldKey)}
Document={doc}
DataDoc={dataDoc}
+ yPadding={index}
renderDepth={this.props.schema.props.renderDepth + 1}
PanelWidth={this.tableWidthFunc}
- PanelHeight={this.rowHeightFunc}
+ PanelHeight={this.props.rowHeight}
styleProvider={DefaultStyleProvider}
waitForDoubleClickToClick={returnNever}
defaultDoubleClick={returnIgnore}
enableDragWhenActive={true}
onClickScriptDisable="always"
focus={this.props.schema.focusDocument}
- docFilters={this.props.schema.childDocFilters}
- docRangeFilters={this.props.schema.childDocRangeFilters}
+ childFilters={this.props.schema.childDocFilters}
+ childFiltersByRanges={this.props.schema.childDocRangeFilters}
searchFilterDocs={this.props.schema.searchFilterDocs}
rootSelected={this.props.schema.rootSelected}
ScreenToLocalTransform={this.childScreenToLocal(index)}
@@ -965,7 +968,7 @@ class CollectionSchemaViewDocs extends React.Component<CollectionSchemaViewDocsP
hideTitle={true}
hideDocumentButtonBar={true}
hideLinkAnchors={true}
- fitWidth={returnTrue}
+ layout_fitWidth={returnTrue}
scriptContext={this}
canEmbedOnDrag={true}
/>
diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
index 243fe0c61..65e47f441 100644
--- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
@@ -5,8 +5,6 @@ import { observer } from 'mobx-react';
import { emptyFunction, setupMoveUpEvents } from '../../../../Utils';
import { Colors } from '../../global/globalEnums';
import './CollectionSchemaView.scss';
-import { SnappingManager } from '../../../util/SnappingManager';
-import { DragManager } from '../../../util/DragManager';
export interface SchemaColumnHeaderProps {
columnKeys: string[];
@@ -14,8 +12,10 @@ export interface SchemaColumnHeaderProps {
columnIndex: number;
sortField: string;
sortDesc: boolean;
+ isContentActive: (outsideReaction?: boolean | undefined) => boolean | undefined;
setSort: (field: string | undefined, desc?: boolean) => void;
removeColumn: (index: number) => void;
+ rowHeight: () => number;
resizeColumn: (e: any, index: number) => void;
dragColumn: (e: any, index: number) => boolean;
openContextMenu: (x: number, y: number, index: number) => void;
@@ -45,7 +45,7 @@ export class SchemaColumnHeader extends React.Component<SchemaColumnHeaderProps>
@action
onPointerDown = (e: React.PointerEvent) => {
- setupMoveUpEvents(this, e, e => this.props.dragColumn(e, this.props.columnIndex), emptyFunction, emptyFunction, false);
+ this.props.isContentActive(true) && setupMoveUpEvents(this, e, e => this.props.dragColumn(e, this.props.columnIndex), emptyFunction, emptyFunction, false);
};
render() {
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index ca9e0bda0..4f3503751 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -2,9 +2,12 @@ import React = require('react');
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { computed } from 'mobx';
import { observer } from 'mobx-react';
+import { computedFn } from 'mobx-utils';
+import { Doc } from '../../../../fields/Doc';
+import { BoolCast } from '../../../../fields/Types';
import { DragManager } from '../../../util/DragManager';
import { SnappingManager } from '../../../util/SnappingManager';
-import { undoBatch } from '../../../util/UndoManager';
+import { undoable } from '../../../util/UndoManager';
import { ViewBoxBaseComponent } from '../../DocComponent';
import { Colors } from '../../global/globalEnums';
import { OpenWhere } from '../../nodes/DocumentView';
@@ -12,8 +15,7 @@ import { FieldView, FieldViewProps } from '../../nodes/FieldView';
import { CollectionSchemaView } from './CollectionSchemaView';
import './CollectionSchemaView.scss';
import { SchemaTableCell } from './SchemaTableCell';
-import { computedFn } from 'mobx-utils';
-import { Doc } from '../../../../fields/Doc';
+import { Transform } from '../../../util/Transform';
@observer
export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps>() {
@@ -58,7 +60,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps>() {
onPointerMove = (e: any) => {
if (!SnappingManager.GetIsDragging()) return;
- const dragIsRow = DragManager.docsBeingDragged.some(doc => doc.context === this.schemaDoc); // this.schemaView?._selectedDocs.has(doc) ?? false;
+ const dragIsRow = DragManager.docsBeingDragged.some(doc => doc.embedContainer === this.schemaDoc); // this.schemaView?._selectedDocs.has(doc) ?? false;
if (this._ref && dragIsRow) {
const rect = this._ref.getBoundingClientRect();
@@ -95,7 +97,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps>() {
return (
<div
className="schema-row"
- style={{ height: CollectionSchemaView._rowHeight, backgroundColor: this.props.isSelected() ? Colors.LIGHT_BLUE : undefined }}
+ style={{ height: this.props.PanelHeight(), backgroundColor: this.props.isSelected() ? Colors.LIGHT_BLUE : undefined }}
onPointerEnter={this.onPointerEnter}
onPointerLeave={this.onPointerLeave}
ref={(row: HTMLDivElement | null) => {
@@ -110,18 +112,18 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps>() {
}}>
<div
className="schema-row-button"
- onPointerDown={undoBatch(e => {
+ onPointerDown={undoable(e => {
e.stopPropagation();
this.props.removeDocument?.(this.rootDoc);
- })}>
+ }, 'Delete Row')}>
<FontAwesomeIcon icon="times" />
</div>
<div
className="schema-row-button"
- onPointerDown={e => {
+ onPointerDown={undoable(e => {
e.stopPropagation();
this.props.addDocTab(this.rootDoc, OpenWhere.addRight);
- }}>
+ }, 'Open Doc on Right')}>
<FontAwesomeIcon icon="external-link-alt" />
</div>
</div>
@@ -132,13 +134,23 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps>() {
Document={this.rootDoc}
col={index}
fieldKey={key}
+ allowCRs={false} // to enter text with new lines, must use \n
columnWidth={this.columnWidth(index)}
+ rowHeight={this.schemaView.rowHeightFunc}
isRowActive={this.props.isContentActive}
getFinfo={this.getFinfo}
selectCell={this.selectCell}
deselectCell={this.deselectCell}
selectedCell={this.selectedCell}
setColumnValues={this.setColumnValues}
+ oneLine={BoolCast(this.schemaDoc?._singleLine)}
+ menuTarget={this.schemaView.MenuTarget}
+ transform={() => {
+ const ind = index === this.schemaView.columnKeys.length - 1 ? this.schemaView.columnKeys.length - 3 : index;
+ const x = this.schemaView?.displayColumnWidths.reduce((p, c, i) => (i <= ind ? p + c : p), 0);
+ const y = (this.props.yPadding ?? 0) * this.props.PanelHeight();
+ return new Transform(x + CollectionSchemaView._rowMenuWidth, y, 1);
+ }}
/>
))}
</div>
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index 712bd4491..97264508c 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -1,26 +1,28 @@
-import React = require('react');
+import * as React from 'react';
+import Select, { MenuPlacement } from 'react-select';
import { action, computed, observable } from 'mobx';
import { observer } from 'mobx-react';
import { extname } from 'path';
import DatePicker from 'react-datepicker';
import { DateField } from '../../../../fields/DateField';
import { Doc, DocListCast, Field } from '../../../../fields/Doc';
-import { BoolCast, Cast, DateCast, FieldValue } from '../../../../fields/Types';
+import { RichTextField } from '../../../../fields/RichTextField';
+import { BoolCast, Cast, DateCast, DocCast, FieldValue, StrCast } from '../../../../fields/Types';
import { ImageField } from '../../../../fields/URLField';
import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnZero, Utils } from '../../../../Utils';
import { FInfo } from '../../../documents/Documents';
-import { dropActionType } from '../../../util/DragManager';
+import { DocFocusOrOpen } from '../../../util/DocumentManager';
import { Transform } from '../../../util/Transform';
-import { undoBatch } from '../../../util/UndoManager';
+import { undoable, undoBatch } from '../../../util/UndoManager';
import { EditableView } from '../../EditableView';
import { Colors } from '../../global/globalEnums';
+import { OpenWhere } from '../../nodes/DocumentView';
import { FieldView, FieldViewProps } from '../../nodes/FieldView';
+import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox';
import { KeyValueBox } from '../../nodes/KeyValueBox';
import { DefaultStyleProvider } from '../../StyleProvider';
import { CollectionSchemaView, ColumnType, FInfotoColType } from './CollectionSchemaView';
import './CollectionSchemaView.scss';
-import { RichTextField } from '../../../../fields/RichTextField';
-import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox';
export interface SchemaTableCellProps {
Document: Doc;
@@ -29,17 +31,27 @@ export interface SchemaTableCellProps {
selectCell: (doc: Doc, col: number) => void;
selectedCell: () => [Doc, number] | undefined;
fieldKey: string;
+ maxWidth?: () => number;
columnWidth: () => number;
+ rowHeight: () => number;
+ padding?: number; // default is 5 -- see scss
isRowActive: () => boolean | undefined;
getFinfo: (fieldKey: string) => FInfo | undefined;
setColumnValues: (field: string, value: string) => boolean;
+ oneLine?: boolean; // whether all input should fit on one line vs allowing textare multiline inputs
+ allowCRs?: boolean; // allow carriage returns in text input (othewrise CR ends the edit)
+ finishEdit?: () => void; // notify container that edit is over (eg. to hide view in DashFieldView)
+ options?: string[];
+ menuTarget: HTMLDivElement | null;
+ transform: () => Transform;
}
@observer
export class SchemaTableCell extends React.Component<SchemaTableCellProps> {
- public static colRowHeightFunc() {
- return CollectionSchemaView._rowHeight;
- }
+ static addFieldDoc = (doc: Doc, where: OpenWhere) => {
+ DocFocusOrOpen(doc);
+ return true;
+ };
public static renderProps(props: SchemaTableCellProps) {
const { Document, fieldKey, getFinfo, columnWidth, isRowActive } = props;
let protoCount = 0;
@@ -49,14 +61,14 @@ export class SchemaTableCell extends React.Component<SchemaTableCellProps> {
break;
}
protoCount++;
- doc = doc.proto;
+ doc = DocCast(doc.proto);
}
const parenCount = Math.max(0, protoCount - 1);
const color = protoCount === 0 || (fieldKey.startsWith('_') && Document[fieldKey] === undefined) ? 'black' : 'blue';
const textDecoration = color !== 'black' && parenCount ? 'underline' : '';
const fieldProps: FieldViewProps = {
- docFilters: returnEmptyFilter,
- docRangeFilters: returnEmptyFilter,
+ childFilters: returnEmptyFilter,
+ childFiltersByRanges: returnEmptyFilter,
searchFilterDocs: returnEmptyDoclist,
styleProvider: DefaultStyleProvider,
docViewPath: returnEmptyDoclist,
@@ -64,19 +76,19 @@ export class SchemaTableCell extends React.Component<SchemaTableCellProps> {
isSelected: returnFalse,
setHeight: returnFalse,
select: emptyFunction,
- dropAction: 'alias' as dropActionType,
+ dropAction: 'embed',
bringToFront: emptyFunction,
renderDepth: 1,
isContentActive: returnFalse,
whenChildContentsActiveChanged: emptyFunction,
ScreenToLocalTransform: Transform.Identity,
focus: emptyFunction,
- addDocTab: returnFalse,
+ addDocTab: SchemaTableCell.addFieldDoc,
pinToPres: returnZero,
Document,
- fieldKey,
+ fieldKey: fieldKey,
PanelWidth: columnWidth,
- PanelHeight: SchemaTableCell.colRowHeightFunc,
+ PanelHeight: props.rowHeight,
};
const readOnly = getFinfo(fieldKey)?.readOnly ?? false;
const cursor = !readOnly ? 'text' : 'default';
@@ -98,32 +110,37 @@ export class SchemaTableCell extends React.Component<SchemaTableCellProps> {
style={{
color,
textDecoration,
+ width: '100%',
}}>
<EditableView
+ oneLine={this.props.oneLine}
+ allowCRs={this.props.allowCRs}
contents={<FieldView {...fieldProps} />}
editing={this.selected ? undefined : false}
GetValue={() => Field.toKeyValueString(this.props.Document, this.props.fieldKey)}
- SetValue={undoBatch((value: string, shiftDown?: boolean, enterKey?: boolean) => {
+ SetValue={undoable((value: string, shiftDown?: boolean, enterKey?: boolean) => {
if (shiftDown && enterKey) {
this.props.setColumnValues(this.props.fieldKey.replace(/^_/, ''), value);
}
- return KeyValueBox.SetField(this.props.Document, this.props.fieldKey.replace(/^_/, ''), value);
- })}
+ const ret = KeyValueBox.SetField(this.props.Document, this.props.fieldKey.replace(/^_/, ''), value);
+ this.props.finishEdit?.();
+ return ret;
+ }, 'edit schema cell')}
/>
</div>
);
}
get getCellType() {
+ const columnTypeStr = this.props.getFinfo(this.props.fieldKey)?.fieldType;
const cellValue = this.props.Document[this.props.fieldKey];
if (cellValue instanceof ImageField) return ColumnType.Image;
if (cellValue instanceof DateField) return ColumnType.Date;
if (cellValue instanceof RichTextField) return ColumnType.RTF;
if (typeof cellValue === 'number') return ColumnType.Any;
- if (typeof cellValue === 'string') return ColumnType.Any;
- if (typeof cellValue === 'boolean') return ColumnType.Any;
+ if (typeof cellValue === 'string' && columnTypeStr !== 'enumeration') return ColumnType.Any;
+ if (typeof cellValue === 'boolean') return ColumnType.Boolean;
- const columnTypeStr = this.props.getFinfo(this.props.fieldKey)?.fieldType;
if (columnTypeStr && columnTypeStr in FInfotoColType) {
return FInfotoColType[columnTypeStr];
}
@@ -138,6 +155,7 @@ export class SchemaTableCell extends React.Component<SchemaTableCellProps> {
case ColumnType.Image: return <SchemaImageCell {...this.props} />;
case ColumnType.Boolean: return <SchemaBoolCell {...this.props} />;
case ColumnType.RTF: return <SchemaRTFCell {...this.props} />;
+ case ColumnType.Enumeration: return <SchemaEnumerationCell {...this.props} options={this.props.getFinfo(this.props.fieldKey)?.values?.map(val => val.toString())} />;
case ColumnType.Date: // return <SchemaDateCell {...this.props} />;
default: return this.defaultCellContent;
}
@@ -148,7 +166,7 @@ export class SchemaTableCell extends React.Component<SchemaTableCellProps> {
<div
className="schema-table-cell"
onPointerDown={action(e => !this.selected && this.props.selectCell(this.props.Document, this.props.col))}
- style={{ width: this.props.columnWidth(), border: this.selected ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined }}>
+ style={{ padding: this.props.padding, maxWidth: this.props.maxWidth?.(), width: this.props.columnWidth() || undefined, border: this.selected ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined }}>
{this.content}
</div>
);
@@ -211,8 +229,8 @@ export class SchemaImageCell extends React.Component<SchemaTableCellProps> {
const aspect = Doc.NativeAspect(this.props.Document); // aspect ratio
// let width = Math.max(75, this.props.columnWidth); // get a with that is no smaller than 75px
// const height = Math.max(75, width / aspect); // get a height either proportional to that or 75 px
- const height = CollectionSchemaView._rowHeight - 10;
- const width = height * aspect; // increase the width of the image if necessary to maintain proportionality
+ const height = this.props.rowHeight() ? this.props.rowHeight() - (this.props.padding || 6) * 2 : undefined;
+ const width = height ? height * aspect : undefined; // increase the width of the image if necessary to maintain proportionality
return <img src={this.url} width={width} height={height} style={{}} draggable="false" onPointerEnter={this.showHoverPreview} onPointerMove={this.moveHoverPreview} onPointerLeave={this.removeHoverPreview} />;
}
@@ -254,7 +272,7 @@ export class SchemaRTFCell extends React.Component<SchemaTableCellProps> {
fieldProps.isContentActive = this.selectedFunc;
return (
<div className="schemaRTFCell" style={{ display: 'flex', fontStyle: this.selected ? undefined : 'italic', width: '100%', height: '100%', position: 'relative', color, textDecoration, cursor, pointerEvents }}>
- {this.selected ? <FormattedTextBox {...fieldProps} /> : (field => (field ? Field.toString(field) : ''))(FieldValue(fieldProps.Document[fieldProps.fieldKey]))}
+ {this.selected ? <FormattedTextBox allowScroll={true} {...fieldProps} /> : (field => (field ? Field.toString(field) : ''))(FieldValue(fieldProps.Document[fieldProps.fieldKey]))}
</div>
);
}
@@ -288,10 +306,47 @@ export class SchemaBoolCell extends React.Component<SchemaTableCellProps> {
if (shiftDown && enterKey) {
this.props.setColumnValues(this.props.fieldKey.replace(/^_/, ''), value);
}
- return KeyValueBox.SetField(this.props.Document, this.props.fieldKey.replace(/^_/, ''), value);
+ const set = KeyValueBox.SetField(this.props.Document, this.props.fieldKey.replace(/^_/, ''), value);
+ this.props.finishEdit?.();
+ return set;
})}
/>
</div>
);
}
}
+@observer
+export class SchemaEnumerationCell extends React.Component<SchemaTableCellProps> {
+ @computed get selected() {
+ const selected: [Doc, number] | undefined = this.props.selectedCell();
+ return this.props.isRowActive() && selected?.[0] === this.props.Document && selected[1] === this.props.col;
+ }
+ render() {
+ const { color, textDecoration, fieldProps, cursor, pointerEvents } = SchemaTableCell.renderProps(this.props);
+ const options = this.props.options?.map(facet => ({ value: facet, label: facet }));
+ return (
+ <div className="schemaSelectionCell" style={{ display: 'flex', color, textDecoration, cursor, pointerEvents }}>
+ <div style={{ width: '100%' }}>
+ <Select
+ styles={{
+ menuPortal: base => ({
+ ...base,
+ left: 0,
+ top: 0,
+ transform: `translate(${this.props.transform().TranslateX}px, ${this.props.transform().TranslateY}px)`,
+ width: Number(base.width) * this.props.transform().Scale,
+ zIndex: 9999,
+ }),
+ }}
+ menuPortalTarget={this.props.menuTarget}
+ menuPosition={'absolute'}
+ placeholder={StrCast(this.props.Document[this.props.fieldKey], 'select...')}
+ options={options}
+ isMulti={false}
+ onChange={val => KeyValueBox.SetField(this.props.Document, this.props.fieldKey.replace(/^_/, ''), `"${val?.value ?? ''}"`)}
+ />
+ </div>
+ </div>
+ );
+ }
+}