diff options
| author | bobzel <zzzman@gmail.com> | 2024-05-08 21:03:27 -0400 |
|---|---|---|
| committer | bobzel <zzzman@gmail.com> | 2024-05-08 21:03:27 -0400 |
| commit | fa4d377b53c9ca31d8900d9c11bd25be57025962 (patch) | |
| tree | 3956413649eabdcbaf71a826dc48f2b28e8bf2b6 /src/client/views/collections | |
| parent | 2e7d3ec952ec88a928f22b8d7a708cc807d9ecdd (diff) | |
| parent | b858bd3cad81da41e63b9f8e807e41421ca4aa34 (diff) | |
Merge branch 'restoringEslint' into nathan-starter
Diffstat (limited to 'src/client/views/collections')
12 files changed, 79 insertions, 125 deletions
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 0ee3575f3..8fb2b30f1 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -22,7 +22,6 @@ import { ScriptingGlobals } from '../../util/ScriptingGlobals'; import { SnappingManager } from '../../util/SnappingManager'; import { undoable, undoBatch, UndoManager } from '../../util/UndoManager'; import { DashboardView } from '../DashboardView'; -import { LightboxView } from '../LightboxView'; import { DocumentView } from '../nodes/DocumentView'; import { OpenWhere, OpenWhereMod } from '../nodes/OpenWhere'; import { OverlayView } from '../OverlayView'; @@ -37,11 +36,13 @@ const _global = (window /* browser */ || global) /* node */ as any; export class CollectionDockingView extends CollectionSubView() { static tabClass: JSX.Element | null = null; /** - * Configure golden layout to render its documents using the specified React component + * Initialize by assigning the add split method to DocumentView and by + * configuring golden layout to render its documents using the specified React component * @param ele - typically would be set to TabDocView */ - static setTabJSXComponent(ele: any) { + public static Init(ele: any) { this.tabClass = ele; + DocumentView.addSplit = CollectionDockingView.AddSplit; } // eslint-disable-next-line no-use-before-define @observable public static Instance: CollectionDockingView | undefined = undefined; @@ -336,7 +337,7 @@ export class CollectionDockingView extends CollectionSubView() { SetPropSetterCb('title', this.titleChanged); // this overrides any previously assigned callback for the property if (this._containerRef.current) { this._lightboxReactionDisposer = reaction( - () => LightboxView.LightboxDoc, + () => DocumentView.LightboxDoc(), doc => setTimeout(() => !doc && this.onResize()) ); new _global.ResizeObserver(this.onResize).observe(this._containerRef.current); @@ -391,7 +392,7 @@ export class CollectionDockingView extends CollectionSubView() { onResize = () => { const cur = this._containerRef.current; // bcz: since GoldenLayout isn't a React component itself, we need to notify it to resize when its document container's size has changed - !LightboxView.LightboxDoc && cur && this._goldenLayout?.updateSize(cur.getBoundingClientRect().width, cur.getBoundingClientRect().height); + !DocumentView.LightboxDoc() && cur && this._goldenLayout?.updateSize(cur.getBoundingClientRect().width, cur.getBoundingClientRect().height); }; endUndoBatch = () => { @@ -633,7 +634,7 @@ export class CollectionDockingView extends CollectionSubView() { ScriptingGlobals.add( // eslint-disable-next-line prefer-arrow-callback function openInLightbox(doc: any) { - LightboxView.Instance.AddDocTab(doc, OpenWhere.lightbox); + CollectionDockingView.Instance?._props.addDocTab(doc, OpenWhere.lightbox); }, 'opens up document in a lightbox', '(doc: any)' diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index e53071584..3eb3008c4 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -26,8 +26,8 @@ import { Transform } from '../../util/Transform'; import { undoBatch } from '../../util/UndoManager'; import { AntimodeMenu } from '../AntimodeMenu'; import { EditableView } from '../EditableView'; -import { DefaultStyleProvider } from '../StyleProvider'; -import { DocumentView, DocumentViewInternal, returnEmptyDocViewList } from '../nodes/DocumentView'; +import { DefaultStyleProvider, returnEmptyDocViewList } from '../StyleProvider'; +import { DocumentView, DocumentViewInternal } from '../nodes/DocumentView'; import './CollectionMenu.scss'; import { CollectionLinearView } from './collectionLinear'; diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx index 53211be77..16c474996 100644 --- a/src/client/views/collections/CollectionNoteTakingView.tsx +++ b/src/client/views/collections/CollectionNoteTakingView.tsx @@ -22,7 +22,6 @@ import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; import { FieldsDropdown } from '../FieldsDropdown'; import { Colors } from '../global/globalEnums'; -import { LightboxView } from '../LightboxView'; import { CollectionFreeFormDocumentView } from '../nodes/CollectionFreeFormDocumentView'; import { DocumentView } from '../nodes/DocumentView'; import { FieldViewProps } from '../nodes/FieldView'; @@ -177,7 +176,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { ); this._disposers.refList = reaction( - () => ({ refList: this._refList.slice(), autoHeight: this.layoutDoc._layout_autoHeight && !LightboxView.Contains(this.DocumentView?.()) }), + () => ({ refList: this._refList.slice(), autoHeight: this.layoutDoc._layout_autoHeight && !DocumentView.LightboxContains(this.DocumentView?.()) }), ({ refList, autoHeight }) => { if (autoHeight) { refList.forEach(r => this.observer.observe(r)); diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx index c098c033b..44ab1968d 100644 --- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx +++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx @@ -4,14 +4,11 @@ import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { lightOrDark, returnEmptyString } from '../../../ClientUtils'; -import { Doc, DocListCast, Opt } from '../../../fields/Doc'; -import { RichTextField } from '../../../fields/RichTextField'; +import { Doc, Opt } from '../../../fields/Doc'; import { listSpec } from '../../../fields/Schema'; import { SchemaHeaderField } from '../../../fields/SchemaHeaderField'; import { Cast, NumCast } from '../../../fields/Types'; -import { ImageField } from '../../../fields/URLField'; import { TraceMobx } from '../../../fields/util'; -import { DocumentFromField } from '../../documents/DocFromField'; import { DocUtils } from '../../documents/DocUtils'; import { Docs } from '../../documents/Documents'; import { DragManager } from '../../util/DragManager'; @@ -19,11 +16,10 @@ import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from '../../util/Transform'; import { undoBatch, undoable } from '../../util/UndoManager'; import { ContextMenu } from '../ContextMenu'; -import { ContextMenuProps } from '../ContextMenuItem'; import { EditableView } from '../EditableView'; import { ObservableReactComponent } from '../ObservableReactComponent'; -import './CollectionNoteTakingView.scss'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; +import './CollectionNoteTakingView.scss'; interface CSVFieldColumnProps { Document: Doc; @@ -171,9 +167,7 @@ export class CollectionNoteTakingViewColumn extends ObservableReactComponent<CSV menuCallback = (x: number, y: number) => { ContextMenu.Instance.clearItems(); - const layoutItems: ContextMenuProps[] = []; - const docItems: ContextMenuProps[] = []; - const dataDoc = this._props.TemplateDataDocument || this._props.Document; + const { pivotField } = this._props; const pivotValue = this.getValue(this._props.heading); DocUtils.addDocumentCreatorMenuItems( @@ -187,50 +181,10 @@ export class CollectionNoteTakingViewColumn extends ObservableReactComponent<CSV x, y, true, - this._props.pivotField, + pivotField, // when created, the new doc's pivotField will be set to pivotValue pivotValue ); - Array.from(Object.keys(Doc.GetProto(dataDoc))) - .filter(fieldKey => dataDoc[fieldKey] instanceof RichTextField || dataDoc[fieldKey] instanceof ImageField || typeof dataDoc[fieldKey] === 'string') - .map(fieldKey => - docItems.push({ - description: ':' + fieldKey, - event: () => { - const created = DocumentFromField(dataDoc, fieldKey, Doc.GetProto(this._props.Document)); - if (created) { - if (this._props.Document.isTemplateDoc) { - Doc.MakeMetadataFieldTemplate(created, this._props.Document); - } - return this._props.addDocument?.(created); - } - return undefined; - }, - icon: 'compress-arrows-alt', - }) - ); - Array.from(Object.keys(Doc.GetProto(dataDoc))) - .filter(fieldKey => DocListCast(dataDoc[fieldKey]).length) - .map(fieldKey => - docItems.push({ - description: ':' + fieldKey, - event: () => { - const created = Docs.Create.CarouselDocument([], { _width: 400, _height: 200, title: fieldKey }); - if (created) { - const container = this._props.Document.resolvedDataDoc ? Doc.GetProto(this._props.Document) : this._props.Document; - if (container.isTemplateDoc) { - Doc.MakeMetadataFieldTemplate(created, container); - return Doc.AddDocToList(container, Doc.LayoutFieldKey(container), created); - } - return this._props.addDocument?.(created) || false; - } - return undefined; - }, - icon: 'compress-arrows-alt', - }) - ); - !Doc.UserDoc().noviceMode && ContextMenu.Instance.addItem({ description: 'Doc Fields ...', subitems: docItems, icon: 'eye' }); - !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, _layout_autoHeight: true }); diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index 1604920f6..fac885300 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -26,7 +26,6 @@ import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from '../../util/Transform'; import { undoBatch, UndoManager } from '../../util/UndoManager'; import { VideoThumbnails } from '../global/globalEnums'; -import { LightboxView } from '../LightboxView'; import { AudioWaveform } from '../nodes/audio/AudioWaveform'; import { DocumentView } from '../nodes/DocumentView'; import { FocusFuncType, StyleProviderFuncType } from '../nodes/FieldView'; @@ -752,10 +751,10 @@ class StackedTimelineAnchor extends ObservableReactComponent<StackedTimelineAnch // const dictationDoc = Cast(this._props.layoutDoc.data_dictation, Doc, null); // const isDictation = dictationDoc && LinkManager.Links(this._props.mark).some(link => Cast(link.link_anchor_1, Doc, null)?.annotationOn === dictationDoc); if ( - !LightboxView.LightboxDoc && + !DocumentView.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. // for now, we won't follow any links when the lightbox is oepn to avoid "losing" the video. - /* (isDictation || !Doc.AreProtosEqual(LightboxView.LightboxDoc, this._props.layoutDoc)) */ + /* (isDictation || !Doc.AreProtosEqual(DocumentView.LightboxDoc(), this._props.layoutDoc)) */ !this._props.layoutDoc.dontAutoFollowLinks && Doc.Links(this._props.mark).length && time > NumCast(this._props.mark[this._props.startTag]) && diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 07aa0f4f0..56d2a6c9c 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -26,7 +26,6 @@ import { undoBatch, UndoManager } from '../../util/UndoManager'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; import { EditableView } from '../EditableView'; -import { LightboxView } from '../LightboxView'; import { CollectionFreeFormDocumentView } from '../nodes/CollectionFreeFormDocumentView'; import { DocumentView } from '../nodes/DocumentView'; import { FieldViewProps } from '../nodes/FieldView'; @@ -229,7 +228,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection layoutAutoHeight => layoutAutoHeight && this._props.setHeight?.(this.headerMargin + (this.isStackingView ? Math.max(...this._refList.map(DivHeight)) : this._refList.reduce((p, r) => p + DivHeight(r), 0))) ); this._disposers.refList = reaction( - () => ({ refList: this._refList.slice(), autoHeight: this.layoutDoc._layout_autoHeight && !LightboxView.Contains(this.DocumentView?.()) }), + () => ({ refList: this._refList.slice(), autoHeight: this.layoutDoc._layout_autoHeight && !DocumentView.LightboxContains(this.DocumentView?.()) }), ({ refList, autoHeight }) => { this.observer.disconnect(); if (autoHeight) refList.forEach(r => this.observer.observe(r)); diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index c1247f5b0..beb8c0666 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -209,7 +209,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree onContextMenu = (): void => { // need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout const layoutItems: ContextMenuProps[] = []; - const menuDoc = ScriptCast(Cast(this.layoutDoc.layout_headerButton, Doc, null)?.onClick).script.originalScript === CollectionTreeView.AddTreeFunc; + const menuDoc = ScriptCast(Cast(this.layoutDoc.layout_headerButton, Doc, null)?.onClick)?.script.originalScript === CollectionTreeView.AddTreeFunc; menuDoc && layoutItems.push({ description: 'Create new folder', event: () => CollectionTreeView.addTreeFolder(this.Document), icon: 'paint-brush' }); if (!Doc.noviceMode) { layoutItems.push({ diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 7cadd072b..b52c7c54c 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -13,7 +13,7 @@ import { Docs } from '../../documents/Documents'; import { ImageUtils } from '../../util/Import & Export/ImageUtils'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; -import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent'; +import { ViewBoxAnnotatableComponent } from '../DocComponent'; import { FieldView } from '../nodes/FieldView'; import { OpenWhere } from '../nodes/OpenWhere'; import { CollectionCalendarView } from './CollectionCalendarView'; @@ -35,7 +35,7 @@ import { CollectionMultirowView } from './collectionMulticolumn/CollectionMultir import { CollectionSchemaView } from './collectionSchema/CollectionSchemaView'; @observer -export class CollectionView extends ViewBoxAnnotatableComponent<CollectionViewProps>() implements ViewBoxInterface { +export class CollectionView extends ViewBoxAnnotatableComponent<CollectionViewProps>() { public static LayoutString(fieldStr: string) { return FieldView.LayoutString(CollectionView, fieldStr); } diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 008ef6ab4..afd584154 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -9,7 +9,7 @@ import * as ReactDOM from 'react-dom/client'; import { ClientUtils, DashColor, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick } from '../../../ClientUtils'; import { emptyFunction } from '../../../Utils'; import { Doc, Opt } from '../../../fields/Doc'; -import { DocData, DocViews } from '../../../fields/DocSymbols'; +import { DocData } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; import { FieldId } from '../../../fields/RefField'; @@ -28,13 +28,14 @@ import { LightboxView } from '../LightboxView'; import { ObservableReactComponent } from '../ObservableReactComponent'; import { PinDocView, PinProps } from '../PinFuncs'; import { StyleProp } from '../StyleProp'; -import { DefaultStyleProvider } from '../StyleProvider'; +import { DefaultStyleProvider, returnEmptyDocViewList } from '../StyleProvider'; import { Colors } from '../global/globalEnums'; -import { DocumentView, returnEmptyDocViewList } from '../nodes/DocumentView'; +import { DocumentView } from '../nodes/DocumentView'; import { FieldViewProps } from '../nodes/FieldView'; import { KeyValueBox } from '../nodes/KeyValueBox'; import { OpenWhere, OpenWhereMod } from '../nodes/OpenWhere'; -import { PresBox, PresMovement } from '../nodes/trails'; +import { PresBox } from '../nodes/trails'; +import { PresMovement } from '../nodes/trails/PresEnums'; import { CollectionDockingView } from './CollectionDockingView'; import { CollectionView } from './CollectionView'; import './TabDocView.scss'; @@ -187,6 +188,11 @@ interface TabDocViewProps { @observer export class TabDocView extends ObservableReactComponent<TabDocViewProps> { static _allTabs = new ObservableSet<TabDocView>(); + public static AllTabDocs() { + return Array.from(TabDocView._allTabs) + .filter(tv => tv._document) + .map(tv => tv._document!); + } _mainCont: HTMLDivElement | null = null; _tabReaction: IReactionDisposer | undefined; @@ -294,7 +300,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> { @observable _isActive: boolean = false; @observable _isAnyChildContentActive = false; public static IsSelected = (doc?: Doc) => { - if (Array.from(doc?.[DocViews] ?? []).some(dv => dv?.IsSelected)) { + if (DocumentView.getViews(doc).some(dv => dv?.IsSelected)) { return true; } return false; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx index 65a2fe0aa..e543b4008 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx @@ -20,6 +20,11 @@ export interface CollectionFreeFormPannableContentsProps { @observer export class CollectionFreeFormPannableContents extends ObservableReactComponent<CollectionFreeFormPannableContentsProps> { static _overlayPlugin: ((fform: Doc) => React.JSX.Element) | null = null; + /** + * Setup a plugin function that returns components to display on a layer above the collection + * See PresBox which renders presenstation paths over the collection + * @param plugin a function that receives the collection Doc and returns JSX Elements + */ public static SetOverlayPlugin(plugin: ((fform: Doc) => React.JSX.Element) | null) { CollectionFreeFormPannableContents._overlayPlugin = plugin; } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 74de6524b..dbd9fb11f 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -28,7 +28,6 @@ import { CollectionViewType, DocumentType } from '../../../documents/DocumentTyp import { DocUtils } from '../../../documents/DocUtils'; import { DragManager } from '../../../util/DragManager'; import { dropActionType } from '../../../util/DropActionTypes'; -import { ReplayMovements } from '../../../util/ReplayMovements'; import { CompileScript } from '../../../util/Scripting'; import { ScriptingGlobals } from '../../../util/ScriptingGlobals'; import { freeformScrollMode, SnappingManager } from '../../../util/SnappingManager'; @@ -36,9 +35,7 @@ import { Transform } from '../../../util/Transform'; import { undoable, undoBatch, UndoManager } from '../../../util/UndoManager'; import { Timeline } from '../../animationtimeline/Timeline'; import { ContextMenu } from '../../ContextMenu'; -import { GestureOverlay } from '../../GestureOverlay'; import { InkingStroke } from '../../InkingStroke'; -import { LightboxView } from '../../LightboxView'; import { CollectionFreeFormDocumentView } from '../../nodes/CollectionFreeFormDocumentView'; import { SchemaCSVPopUp } from '../../nodes/DataVizBox/SchemaCSVPopUp'; import { DocumentView } from '../../nodes/DocumentView'; @@ -367,7 +364,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection } const xfToCollection = options?.docTransform ?? Transform.Identity(); const savedState = { panX: NumCast(this.Document[this.panXFieldKey]), panY: NumCast(this.Document[this.panYFieldKey]), scale: options?.willZoomCentered ? this.Document[this.scaleFieldKey] : undefined }; - const cantTransform = this.fitContentsToBox || ((this.Document.isGroup || this.layoutDoc._lockedTransform) && !LightboxView.LightboxDoc); + const cantTransform = this.fitContentsToBox || ((this.Document.isGroup || this.layoutDoc._lockedTransform) && !DocumentView.LightboxDoc()); const { panX, panY, scale } = cantTransform || (!options.willPan && !options.willZoomCentered) ? savedState : this.calculatePanIntoView(anchor, xfToCollection, options?.willZoomCentered ? options?.zoomScale ?? 0.75 : undefined); // focus on the document in the collection @@ -620,7 +617,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection return false; }; forceStrokeGesture = (e: PointerEvent, gesture: Gestures, points: InkData, text?: any) => { - this.onGesture(e, new GestureUtils.GestureEvent(gesture, points, GestureOverlay.getBounds(points), text)); + this.onGesture(e, new GestureUtils.GestureEvent(gesture, points, InkField.getBounds(points), text)); }; onPointerMove = (e: PointerEvent) => { @@ -838,8 +835,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection @action setPan(panXIn: number, panYIn: number, panTime: number = 0, allowScroll = false) { let [panX, panY] = [panXIn, panYIn]; - // this is the easiest way to do this -> will talk with Bob about using mobx to do this to remove this line of code. - if (Doc.UserDoc()?.presentationMode === 'watching') ReplayMovements.Instance.pauseFromInteraction(); if (!this.isAnnotationOverlay && this.childDocs.length) { // this section wraps the pan position, horizontally and/or vertically whenever the content is panned out of the viewing bounds @@ -849,7 +844,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection panX = clamp(panX, xrangeMin - widScaling / 2, xrangeMax + widScaling / 2); panY = clamp(panY, yrangeMin - hgtScaling / 2, yrangeMax + hgtScaling / 2); } - if (!this.layoutDoc._lockedTransform || LightboxView.LightboxDoc) { + if (!this.layoutDoc._lockedTransform || DocumentView.LightboxDoc()) { this.setPanZoomTransition(panTime); const minScale = NumCast(this.dataDoc._freeform_scale_min, 1); const scale = 1 - minScale / this.zoomScaling(); @@ -882,6 +877,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection nudge = (x: number, y: number, nudgeTime: number = 500) => { const collectionDoc = this.Document; if (collectionDoc?._type_collection !== CollectionViewType.Freeform) { + SnappingManager.TriggerUserPanned(); 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(), @@ -1008,6 +1004,15 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection } return undefined; }; + + removeDocument = (docs: Doc | Doc[], annotationKey?: string | undefined) => { + const ret = !!this._props.removeDocument?.(docs, annotationKey); + // if this is a group and we have fewer than 2 Docs, then just promote what's left to our parent and get rid of the group. + if (ret && DocListCast(this.dataDoc[annotationKey ?? this.fieldKey]).length < 2 && this.Document.isGroup) { + this.promoteCollection(); + } + return ret; + }; childPointerEventsFunc = () => this._childPointerEvents; childContentsActive = () => (this._props.childContentsActive ?? this.isContentActive() === false ? returnFalse : emptyFunction)(); getChildDocView(entry: PoolData) { @@ -1050,7 +1055,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection focus={this.Document.isGroup ? this.groupFocus : this.isAnnotationOverlay ? this._props.focus : this.focus} addDocTab={this.addDocTab} addDocument={this._props.addDocument} - removeDocument={this._props.removeDocument} + removeDocument={this.removeDocument} moveDocument={this._props.moveDocument} pinToPres={this._props.pinToPres} whenChildContentsActiveChanged={this._props.whenChildContentsActiveChanged} @@ -1525,7 +1530,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection incrementalRendering = () => this.childDocs.filter(doc => !this._renderCutoffData.get(doc[Id])).length !== 0; incrementalRender = action(() => { - if (!LightboxView.LightboxDoc || LightboxView.Contains(this.DocumentView?.())) { + if (!DocumentView.LightboxDoc() || DocumentView.LightboxContains(this.DocumentView?.())) { const layoutUnrendered = this.childDocs.filter(doc => !this._renderCutoffData.get(doc[Id])); const loadIncrement = this.Document.isTemplateDoc ? Number.MAX_VALUE : 5; for (let i = 0; i < Math.min(layoutUnrendered.length, loadIncrement); i++) { diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index b017eb62b..5874364e0 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -25,9 +25,9 @@ import { Transform } from '../../../util/Transform'; import { undoBatch, undoable } from '../../../util/UndoManager'; import { EditableView } from '../../EditableView'; import { ObservableReactComponent } from '../../ObservableReactComponent'; -import { DefaultStyleProvider } from '../../StyleProvider'; +import { DefaultStyleProvider, returnEmptyDocViewList } from '../../StyleProvider'; import { Colors } from '../../global/globalEnums'; -import { DocFocusOrOpen, returnEmptyDocViewList } from '../../nodes/DocumentView'; +import { DocumentView } from '../../nodes/DocumentView'; import { FieldViewProps } from '../../nodes/FieldView'; import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; import { FInfotoColType } from './CollectionSchemaView'; @@ -59,6 +59,14 @@ export interface SchemaTableCellProps { rootSelected?: () => boolean; } +function selectedCell(props: SchemaTableCellProps) { + return ( + props.isRowActive() && + props.selectedCol() === props.col && // + props.selectedCells()?.filter(d => d === props.Document)?.length + ); +} + @observer export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellProps> { constructor(props: SchemaTableCellProps) { @@ -67,7 +75,7 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro } static addFieldDoc = (docs: Doc | Doc[] /* , where: OpenWhere */) => { - DocFocusOrOpen(toList(docs)[0]); + DocumentView.FocusOrOpen(toList(docs)[0]); return true; }; public static renderProps(props: SchemaTableCellProps) { @@ -114,11 +122,6 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro return { color, textDecoration, fieldProps, cursor, pointerEvents }; } - @computed get selected() { - const selectedDocs: Doc[] | undefined = this._props.selectedCells(); - return this._props.isRowActive() && selectedDocs?.filter(doc => doc === this._props.Document).length !== 0 && this._props.selectedCol() === this._props.col; - } - @computed get defaultCellContent() { const { color, textDecoration, fieldProps, pointerEvents } = SchemaTableCell.renderProps(this._props); @@ -132,12 +135,12 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro pointerEvents, }}> <EditableView - ref={r => this.selected && this._props.autoFocus && r?.setIsFocused(true)} + ref={r => selectedCell(this._props) && this._props.autoFocus && r?.setIsFocused(true)} oneLine={this._props.oneLine} allowCRs={this._props.allowCRs} contents={undefined} fieldContents={fieldProps} - editing={this.selected ? undefined : false} + editing={selectedCell(this._props) ? undefined : false} GetValue={() => Field.toKeyValueString(fieldProps.Document, this._props.fieldKey, SnappingManager.MetaKey)} SetValue={undoable((value: string, shiftDown?: boolean, enterKey?: boolean) => { if (shiftDown && enterKey) { @@ -157,30 +160,27 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro 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' && columnTypeStr !== FInfoFieldType.enumeration) return ColumnType.Any; if (typeof cellValue === 'boolean') return ColumnType.Boolean; - - if (columnTypeStr && columnTypeStr in FInfotoColType) { - return FInfotoColType[columnTypeStr]; - } + if (columnTypeStr && columnTypeStr in FInfotoColType) return FInfotoColType[columnTypeStr]; return ColumnType.Any; } get content() { - const cellType: ColumnType = this.getCellType; // prettier-ignore - switch (cellType) { - case ColumnType.Image: return <SchemaImageCell {...this._props} />; - case ColumnType.Boolean: return <SchemaBoolCell {...this._props} />; - case ColumnType.RTF: return <SchemaRTFCell {...this._props} />; + switch (this.getCellType) { + 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 => Field.toString(val))} />; - case ColumnType.Date: return <SchemaDateCell {...this._props} />; - default: return this.defaultCellContent; + case ColumnType.Date: return <SchemaDateCell {...this._props} />; + default: return this.defaultCellContent; } } @@ -193,13 +193,13 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro const shift: boolean = e.shiftKey; const ctrl: boolean = e.ctrlKey; if (this._props.isRowActive?.() !== false) { - if (this.selected && ctrl) { + if (selectedCell(this._props) && ctrl) { this._props.selectCell(this._props.Document, this._props.col, shift, ctrl); e.stopPropagation(); - } else !this.selected && this._props.selectCell(this._props.Document, this._props.col, shift, ctrl); + } else !selectedCell(this._props) && this._props.selectCell(this._props.Document, this._props.col, shift, ctrl); } })} - style={{ padding: this._props.padding, maxWidth: this._props.maxWidth?.(), width: this._props.columnWidth() || undefined, border: this.selected ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined }}> + style={{ padding: this._props.padding, maxWidth: this._props.maxWidth?.(), width: this._props.columnWidth() || undefined, border: selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined }}> {this.content} </div> ); @@ -329,20 +329,14 @@ export class SchemaRTFCell extends ObservableReactComponent<SchemaTableCellProps makeObservable(this); } - @computed get selected() { - const selected = this._props.selectedCells(); - return this._props.isRowActive() && selected && selected?.filter(doc => doc === this._props.Document).length !== 0 && this._props.selectedCol() === this._props.col; - // return this._props.isRowActive() && selected?.[0] === this._props.Document && selected[1] === this._props.col; - } - // if the text box blurs and none of its contents are focused(), then the edit finishes - selectedFunc = () => this.selected; + selectedFunc = () => !!selectedCell(this._props); render() { const { color, textDecoration, fieldProps, cursor, pointerEvents } = SchemaTableCell.renderProps(this._props); fieldProps.isContentActive = this.selectedFunc; return ( - <div className="schemaRTFCell" style={{ fontStyle: this.selected ? undefined : 'italic', color, textDecoration, cursor, pointerEvents }}> - {this.selected ? <FormattedTextBox {...fieldProps} autoFocus onBlur={() => this._props.finishEdit?.()} /> : (field => (field ? Field.toString(field) : ''))(FieldValue(fieldProps.Document[fieldProps.fieldKey]))} + <div className="schemaRTFCell" style={{ fontStyle: selectedCell(this._props) ? undefined : 'italic', color, textDecoration, cursor, pointerEvents }}> + {selectedCell(this._props) ? <FormattedTextBox {...fieldProps} autoFocus onBlur={() => this._props.finishEdit?.()} /> : (field => (field ? Field.toString(field) : ''))(FieldValue(fieldProps.Document[fieldProps.fieldKey]))} </div> ); } @@ -354,10 +348,6 @@ export class SchemaBoolCell extends ObservableReactComponent<SchemaTableCellProp makeObservable(this); } - @computed get selected() { - const selected = this._props.selectedCells(); - return this._props.isRowActive() && selected && selected?.filter(doc => doc === this._props.Document).length !== 0 && this._props.selectedCol() === this._props.col; - } render() { const { color, textDecoration, fieldProps, cursor, pointerEvents } = SchemaTableCell.renderProps(this._props); return ( @@ -375,7 +365,7 @@ export class SchemaBoolCell extends ObservableReactComponent<SchemaTableCellProp <EditableView contents={undefined} fieldContents={fieldProps} - editing={this.selected ? undefined : false} + editing={selectedCell(this._props) ? undefined : false} GetValue={() => Field.toKeyValueString(this._props.Document, this._props.fieldKey)} SetValue={undoBatch((value: string, shiftDown?: boolean, enterKey?: boolean) => { if (shiftDown && enterKey) { @@ -399,10 +389,6 @@ export class SchemaEnumerationCell extends ObservableReactComponent<SchemaTableC makeObservable(this); } - @computed get selected() { - const selected = this._props.selectedCells(); - return this._props.isRowActive() && selected && selected?.filter(doc => doc === this._props.Document).length !== 0 && this._props.selectedCol() === this._props.col; - } render() { const { color, textDecoration, cursor, pointerEvents } = SchemaTableCell.renderProps(this._props); const options = this._props.options?.map(facet => ({ value: facet, label: facet })); |
