From d0fccd1050f5d6ccc24c1e4d2b7d1c0ed94fb2a7 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sun, 23 Mar 2025 10:27:28 -0400 Subject: updated more [DocData] to .$ things --- src/client/views/nodes/DataVizBox/components/TableBox.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/client/views/nodes/DataVizBox/components') diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx index 7ef4bca6b..b31a0ec1e 100644 --- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx +++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx @@ -160,8 +160,8 @@ export class TableBox extends ObservableReactComponent { DragManager.StartAnchorAnnoDrag(moveEv.target instanceof HTMLElement ? [moveEv.target] : [], new DragManager.AnchorAnnoDragData(this._props.docView()!, sourceAnchorCreator, targetCreator), downX, downY, { dragComplete: completeEv => { if (!completeEv.aborted && completeEv.annoDragData && completeEv.annoDragData.linkSourceDoc && completeEv.annoDragData.dropDocument && completeEv.linkDocument) { - completeEv.linkDocument[DocData].link_matchEmbeddings = true; - completeEv.linkDocument[DocData].stroke_startMarker = true; + completeEv.linkDocument.$link_matchEmbeddings = true; + completeEv.linkDocument.$stroke_startMarker = true; this._props.docView?.()?._props.addDocument?.(completeEv.linkDocument); } }, -- cgit v1.2.3-70-g09d2 From 7db1a5d9bac676a1874c14cb8bba734fbdc7181e Mon Sep 17 00:00:00 2001 From: bobzel Date: Sun, 23 Mar 2025 12:27:13 -0400 Subject: from last --- src/client/views/collections/CollectionStackedTimeline.tsx | 1 - src/client/views/nodes/DataVizBox/components/TableBox.tsx | 1 - src/client/views/nodes/LinkDescriptionPopup.tsx | 6 ++---- 3 files changed, 2 insertions(+), 6 deletions(-) (limited to 'src/client/views/nodes/DataVizBox/components') diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index 0836cce38..fd4bdf364 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -5,7 +5,6 @@ import { computedFn } from 'mobx-utils'; import * as React from 'react'; import { returnEmptyFilter, returnFalse, returnNone, returnTrue, returnZero, setupMoveUpEvents, smoothScrollHorizontal, StopEvent } from '../../../ClientUtils'; import { Doc, Opt, returnEmptyDoclist } from '../../../fields/Doc'; -import { DocData } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; import { listSpec } from '../../../fields/Schema'; diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx index b31a0ec1e..b6183946a 100644 --- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx +++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx @@ -5,7 +5,6 @@ import * as React from 'react'; import { ClientUtils, setupMoveUpEvents } from '../../../../../ClientUtils'; import { emptyFunction } from '../../../../../Utils'; import { Doc, Field, NumListCast } from '../../../../../fields/Doc'; -import { DocData } from '../../../../../fields/DocSymbols'; import { List } from '../../../../../fields/List'; import { listSpec } from '../../../../../fields/Schema'; import { Cast, DocCast } from '../../../../../fields/Types'; diff --git a/src/client/views/nodes/LinkDescriptionPopup.tsx b/src/client/views/nodes/LinkDescriptionPopup.tsx index 9dff55bf1..aeac100f4 100644 --- a/src/client/views/nodes/LinkDescriptionPopup.tsx +++ b/src/client/views/nodes/LinkDescriptionPopup.tsx @@ -45,15 +45,13 @@ export class LinkDescriptionPopup extends React.Component { @action onDismiss = (add: boolean) => { this.display = false; - if (add) { - LinkManager.Instance.currentLink && (LinkManager.Instance.currentLink.$link_description = this.description); - } + add && LinkManager.Instance.currentLink && (LinkManager.Instance.currentLink.$link_description = this.description); this.description = ''; }; @action onClick = (e: PointerEvent) => { - if (this.popupRef && !this.popupRef.current?.contains(e.target as any)) { + if (this.popupRef && !this.popupRef.current?.contains(e.target as Node)) { this.display = false; this.description = ''; TaskCompletionBox.taskCompleted = false; -- cgit v1.2.3-70-g09d2 From 705975eb43e7904c62e7e847478f6d0dac60d443 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sun, 23 Mar 2025 18:14:31 -0400 Subject: more _props.Document to .Document refactoring. type updates to prosemirrortransfer --- src/client/util/SharingManager.tsx | 2 +- src/client/views/DocComponent.tsx | 85 +++++++--- src/client/views/DocumentDecorations.tsx | 2 +- src/client/views/FieldsDropdown.tsx | 4 +- src/client/views/FilterPanel.tsx | 4 +- src/client/views/LightboxView.tsx | 2 +- src/client/views/SidebarAnnos.tsx | 24 +-- src/client/views/TemplateMenu.tsx | 1 - src/client/views/animationtimeline/Timeline.tsx | 56 +++---- .../collections/CollectionMasonryViewFieldRow.tsx | 8 +- .../views/collections/CollectionNoteTakingView.tsx | 15 +- .../collections/CollectionNoteTakingViewColumn.tsx | 18 +-- .../views/collections/CollectionPivotView.tsx | 2 +- .../views/collections/CollectionStackingView.tsx | 19 +-- .../CollectionStackingViewFieldColumn.tsx | 28 ++-- src/client/views/collections/CollectionSubView.tsx | 10 +- .../views/collections/CollectionTimeView.tsx | 2 +- .../views/collections/CollectionTreeView.tsx | 4 +- src/client/views/collections/TabDocView.tsx | 28 ++-- .../CollectionFreeFormInfoUI.tsx | 14 +- .../CollectionFreeFormPannableContents.tsx | 4 +- .../CollectionFreeFormRemoteCursors.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 48 +++--- .../collections/collectionFreeForm/MarqueeView.tsx | 1 + .../collectionSchema/SchemaCellField.tsx | 4 +- .../collections/collectionSchema/SchemaRowBox.tsx | 2 +- .../collectionSchema/SchemaTableCell.tsx | 46 +++--- .../views/nodes/CollectionFreeFormDocumentView.tsx | 2 +- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 30 ++-- .../nodes/DataVizBox/components/Histogram.tsx | 13 +- .../nodes/DataVizBox/components/LineChart.tsx | 8 +- .../views/nodes/DataVizBox/components/PieChart.tsx | 16 +- .../views/nodes/DataVizBox/components/TableBox.tsx | 10 +- src/client/views/nodes/DocumentView.tsx | 4 +- src/client/views/nodes/FieldView.tsx | 4 +- src/client/views/nodes/ImageBox.tsx | 2 +- src/client/views/nodes/KeyValueBox.tsx | 10 +- src/client/views/nodes/MapBox/MapBox.tsx | 2 +- .../views/nodes/MapboxMapBox/MapboxContainer.tsx | 3 +- src/client/views/nodes/PDFBox.tsx | 3 +- src/client/views/nodes/ScreenshotBox.tsx | 2 - src/client/views/nodes/WebBox.tsx | 2 +- .../views/nodes/formattedText/DashFieldView.tsx | 2 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 10 +- .../formattedText/ProsemirrorExampleTransfer.ts | 174 +++++++++++---------- .../views/nodes/formattedText/SummaryView.tsx | 46 +++--- src/client/views/pdf/PDFViewer.tsx | 30 ++-- src/client/views/search/SearchBox.tsx | 16 +- src/client/views/smartdraw/StickerPalette.tsx | 16 +- src/fields/RichTextUtils.ts | 3 +- src/fields/Types.ts | 5 - src/server/DashSession/DashSessionAgent.ts | 4 +- 52 files changed, 438 insertions(+), 414 deletions(-) (limited to 'src/client/views/nodes/DataVizBox/components') diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 3a248400b..962f51cd4 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -633,7 +633,7 @@ export class SharingManager extends React.Component { private focusOn = (contents: string) => { const title = this.targetDoc ? StrCast(this.targetDoc.title) : ''; - const docs = DocumentView.Selected().length > 1 ? DocumentView.Selected().map(docView => docView.props.Document) : [this.targetDoc]; + const docs = DocumentView.Selected().length > 1 ? DocumentView.Selected().map(docView => docView.Document) : [this.targetDoc]; return ( () { } /** - * This is the document being rendered. In the case of a compound template, it - * may not be the actual document rendered and it also may not be the 'real' root document. - * Rather, it specifies the shared properties of all layouts of the document (eg, x,y,) + * This is the doc that is being rendered. It will be either: + * 1) the same as Document if the root of a regular or compound Doc is rendered + * 2) the same as the layoutDoc if a component of a compound Doc is rendered. + * NOTE: it is very unlikely that you really want to use this method. Instead + * consider: Document, layoutDoc, dataDoc */ - get Document() { - return DocCast(this._props.Document.rootDocument, this._props.Document); + get _renderDoc() { + return this._props.Document; } /** - * This is the document being rendered. It may be a template so it may or may no inherit from the data doc. + * This is the "root" Doc being rendered. In the case of a compound template Doc, + * this is the outermost Doc that represents the entire compound Doc. It is not + * necessarily the Doc being rendered in the current React component. + * This Doc inherits from the dataDoc, and may or may not inherit (or be) the layoutDoc. + */ + get Document() { + return DocCast(this._renderDoc.rootDocument, this._renderDoc); + } + /** + * This is the document being rendered by the React component. In the + * case of a compound template, this will be the expanded template Doc + * that represents the component of the compound Doc being rendered. + * This may or may not inherit from the data doc. */ @computed get layoutDoc() { - return this._props.LayoutTemplateString ? this._props.Document : Doc.Layout(this._props.Document, this._props.LayoutTemplate?.()); + return this._props.LayoutTemplateString ? this._renderDoc : Doc.Layout(this._renderDoc, this._props.LayoutTemplate?.()); } /** - * This is the unique data repository for a dcoument that stores the intrinsic document data + * This is the unique data repository for a document that stores the intrinsic document data. */ @computed get dataDoc() { - return this._props.Document[DocData]; + return this._renderDoc[DocData]; } } return Component; @@ -75,25 +89,40 @@ export function ViewBoxBaseComponent

() { } /** - * This is the document being rendered. In the case of a compound template, it - * may not be the actual document rendered and it also may not be the 'real' root document. - * Rather, it specifies the shared properties of all layouts of the document (eg, x,y,) + * This is the doc that is being rendered. It will be either: + * 1) the same as Document if the root of a regular or compound Doc is rendered + * 2) the same as the layoutDoc if a component of a compound Doc is rendered. + * NOTE: it is very unlikely that you really want to use this method. Instead + * consider: Document, layoutDoc, dataDoc + */ + get _renderDoc() { + return this._props.Document; + } + + /** + * This is the "root" Doc being rendered. In the case of a compound template Doc, + * this is the outermost Doc that represents the entire compound Doc. It is not + * necessarily the Doc being rendered in the current React component. + * This Doc inherits from the dataDoc, and may or may not inherit (or be) the layoutDoc. */ get Document() { - return DocCast(this._props.Document.rootDocument, this._props.Document); + return DocCast(this._renderDoc.rootDocument, this._renderDoc); } /** - * This is the document being rendered. It may be a template so it may or may no inherit from the data doc. + * This is the document being rendered by the React component. In the + * case of a compound template, this will be the expanded template Doc + * that represents the component of the compound Doc being rendered. + * This may or may not inherit from the data doc. */ @computed get layoutDoc() { - return Doc.Layout(this._props.Document); + return Doc.Layout(this._renderDoc); } /** * This is the unique data repository for a dcoument that stores the intrinsic document data */ @computed get dataDoc() { - return this._props.Document.isTemplateForField || this._props.Document.isTemplateDoc ? (this._props.TemplateDataDocument ?? this._props.Document[DocData]) : this._props.Document[DocData]; + return this._renderDoc.isTemplateForField || this._renderDoc.isTemplateDoc ? (this._props.TemplateDataDocument ?? this._renderDoc[DocData]) : this._renderDoc[DocData]; } /** @@ -133,25 +162,37 @@ export function ViewBoxAnnotatableComponent

() { } /** - * This is the document being rendered. In the case of a compound template, it - * may not be the actual document rendered and it also may not be the 'real' root document. - * Rather, it specifies the shared properties of all layouts of the document (eg, x,y,) + * This is the doc that is being rendered. It will be either: + * 1) the same as Document if the root of a regular or compound Doc is rendered + * 2) the same as the layoutDoc if a component of a compound Doc is rendered. + * NOTE: it would unlikely that you really want to use this instead of the + * other Doc options (Document, layoutDoc, dataDoc) + */ + get _renderDoc() { + return this._props.Document; + } + + /** + * This is the "root" Doc being rendered. In the case of a compound template Doc, + * this is the outermost Doc that represents the entire compound Doc. It is not + * necessarily the Doc being rendered in the current React component. + * This Doc inherits from the dataDoc, and may or may not inherit (or be) the layoutDoc. */ @computed get Document() { - return DocCast(this._props.Document.rootDocument, this._props.Document); + return DocCast(this._renderDoc.rootDocument, this._renderDoc); } /** * This is the document being rendered. It may be a template so it may or may no inherit from the data doc. */ @computed get layoutDoc() { - return Doc.Layout(this._props.Document); + return Doc.Layout(this._renderDoc); } /** * This is the unique data repository for a dcoument that stores the intrinsic document data */ @computed get dataDoc() { - return this._props.Document.isTemplateForField || this._props.Document.isTemplateDoc ? (this._props.TemplateDataDocument ?? this._props.Document[DocData]) : this._props.Document[DocData]; + return this._renderDoc.isTemplateForField || this._renderDoc.isTemplateDoc ? (this._props.TemplateDataDocument ?? this._renderDoc[DocData]) : this._props.Document[DocData]; } /** diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 92b4d6fbf..19b987cb5 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -635,7 +635,7 @@ export class DocumentDecorations extends ObservableReactComponent void; menuClose?: () => void; placeholder?: string | (() => string); @@ -36,7 +36,7 @@ export class FieldsDropdown extends ObservableReactComponent(); - SearchUtil.foreachRecursiveDoc([this._props.Document], (depth, doc) => allDocs.add(doc)); + SearchUtil.foreachRecursiveDoc([this._props.Doc], (depth, doc) => allDocs.add(doc)); return Array.from(allDocs); } diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 4fc8d7a68..c3b3f9d0c 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -379,7 +379,7 @@ export class FilterPanel extends ObservableReactComponent {

- +
{/* THE FOLLOWING CODE SHOULD BE DEVELOPER FOR BOOLEAN EXPRESSION (AND / OR) */} {/*
@@ -443,7 +443,7 @@ export class FilterPanel extends ObservableReactComponent {
- +
diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx index 5698da785..de2c7cd09 100644 --- a/src/client/views/LightboxView.tsx +++ b/src/client/views/LightboxView.tsx @@ -317,7 +317,7 @@ export class LightboxView extends ObservableReactComponent {
- {this._showPalette && (this._annoPaletteView = r)} Document={DocCast(Doc.UserDoc().myLightboxDrawings)} />} + {this._showPalette && (this._annoPaletteView = r)} Doc={DocCast(Doc.UserDoc().myLightboxDrawings)} />} {this.renderNavBtn(0, undefined, this._props.PanelHeight / 2 - 12.5, 'chevron-left', this._doc && this._history.length ? true : false, this.previous)} {this.renderNavBtn( this._props.PanelWidth - Math.min(this._props.PanelWidth / 4, this._props.maxBorder[0]), diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx index b3f3a4478..3c0611f03 100644 --- a/src/client/views/SidebarAnnos.tsx +++ b/src/client/views/SidebarAnnos.tsx @@ -22,7 +22,7 @@ import { FieldViewProps } from './nodes/FieldView'; interface ExtraProps { fieldKey: string; - Document: Doc; + Doc: Doc; layoutDoc: Doc; dataDoc: Doc; // usePanelWidth: boolean; @@ -45,7 +45,7 @@ export class SidebarAnnos extends ObservableReactComponent(); @computed get allMetadata() { const keys = new Map>(); - DocListCast(this._props.Document[this.sidebarKey]).forEach(doc => + DocListCast(this._props.Doc[this.sidebarKey]).forEach(doc => SearchUtil.documentKeys(doc) .filter(key => key[0] && key[0] !== '_' && key[0] === key[0].toUpperCase()) .map(key => keys.set(key, doc[key])) @@ -54,7 +54,7 @@ export class SidebarAnnos extends ObservableReactComponent(); - DocListCast(this._props.Document[this.sidebarKey]).forEach(doc => StrListCast(doc.tags).forEach(tag => keys.add(tag))); + DocListCast(this._props.Doc[this.sidebarKey]).forEach(doc => StrListCast(doc.tags).forEach(tag => keys.add(tag))); return Array.from(keys.keys()) .filter(key => key[0]) .filter(key => !key.startsWith('_') && (key[0] === '#' || key[0] === key[0].toUpperCase())) @@ -62,7 +62,7 @@ export class SidebarAnnos extends ObservableReactComponent(); - DocListCast(this._props.Document[this.sidebarKey]).forEach(doc => keys.add(StrCast(doc.author))); + DocListCast(this._props.Doc[this.sidebarKey]).forEach(doc => keys.add(StrCast(doc.author))); return Array.from(keys.keys()).sort(); } @@ -72,7 +72,7 @@ export class SidebarAnnos extends ObservableReactComponent data.split(':')[0]) .filter(data => !filterExlusions?.includes(data.split(':')[0])) .map(data => { - const key = '$'+data.split(':')[0]; + const key = '$' + data.split(':')[0]; const val = Field.Copy(this.allMetadata.get(key)); target[key] = val; return { @@ -148,7 +148,7 @@ export class SidebarAnnos extends ObservableReactComponent { - if (DocListCast(this._props.Document[this.sidebarKey]).find(anno => Doc.AreProtosEqual(doc.layout_unrendered ? DocCast(doc.annotationOn) : doc, anno))) { + if (DocListCast(this._props.Doc[this.sidebarKey]).find(anno => Doc.AreProtosEqual(doc.layout_unrendered ? DocCast(doc.annotationOn) : doc, anno))) { if (this.childFilters()) { // if any child filters exist, get rid of them this._props.layoutDoc._childFilters = new List(); @@ -189,7 +189,7 @@ export class SidebarAnnos extends ObservableReactComponent { const active = this.childFilters().includes(`tags${Doc.FilterSep}${tag}${Doc.FilterSep}check`); return ( -
Doc.setDocFilter(this._props.Document, 'tags', tag, 'check', true, undefined, e.shiftKey)}> +
Doc.setDocFilter(this._props.Doc, 'tags', tag, 'check', true, undefined, e.shiftKey)}> {tag}
); @@ -197,7 +197,7 @@ export class SidebarAnnos extends ObservableReactComponent { const active = this.childFilters().includes(`${tag}${Doc.FilterSep}${Doc.FilterAny}${Doc.FilterSep}exists`); return ( -
Doc.setDocFilter(this._props.Document, tag, Doc.FilterAny, 'exists', true, undefined, e.shiftKey)}> +
Doc.setDocFilter(this._props.Doc, tag, Doc.FilterAny, 'exists', true, undefined, e.shiftKey)}> {tag}
); @@ -205,7 +205,7 @@ export class SidebarAnnos extends ObservableReactComponent { const active = this.childFilters().includes(`author:${user}:check`); return ( -
Doc.setDocFilter(this._props.Document, 'author', user, 'check', true, undefined, e.shiftKey)}> +
Doc.setDocFilter(this._props.Doc, 'author', user, 'check', true, undefined, e.shiftKey)}> {user}
); @@ -216,9 +216,9 @@ export class SidebarAnnos extends ObservableReactComponent diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index 680c8ed0e..1266a11c1 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -80,7 +80,6 @@ export class TemplateMenu extends React.Component { const addedTypes = DocListCast(Cast(Doc.UserDoc().template_clickFuncs, Doc, null)?.data); const templateMenu: Array = []; templateMenu.push(); - // eslint-disable-next-line no-return-assign addedTypes.concat(noteTypes).map(template => (template.treeView_Checked = this.templateIsUsed(firstDoc, template))); this._addedKeys && Array.from(this._addedKeys) diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx index 15683ebf2..cd2c7df1b 100644 --- a/src/client/views/animationtimeline/Timeline.tsx +++ b/src/client/views/animationtimeline/Timeline.tsx @@ -46,7 +46,7 @@ import { Id } from '../../../fields/FieldSymbols'; */ @observer -export class Timeline extends ObservableReactComponent { +export class Timeline extends ObservableReactComponent { // readonly constants private readonly DEFAULT_TICK_SPACING: number = 50; private readonly MAX_TITLE_HEIGHT = 75; @@ -57,7 +57,7 @@ export class Timeline extends ObservableReactComponent { private DEFAULT_CONTAINER_HEIGHT: number = 330; private MIN_CONTAINER_HEIGHT: number = 205; - constructor(props: FieldViewProps) { + constructor(props: FieldViewProps & { Doc: Doc }) { super(props); makeObservable(this); } @@ -90,11 +90,11 @@ export class Timeline extends ObservableReactComponent { */ @computed private get children(): Doc[] { - const annotatedDoc = [DocumentType.IMG, DocumentType.VID, DocumentType.PDF, DocumentType.MAP].includes(StrCast(this._props.Document.type) as unknown as DocumentType); + const annotatedDoc = [DocumentType.IMG, DocumentType.VID, DocumentType.PDF, DocumentType.MAP].includes(StrCast(this._props.Doc.type) as unknown as DocumentType); if (annotatedDoc) { - return DocListCast(this._props.Document[Doc.LayoutFieldKey(this._props.Document) + '_annotations']); + return DocListCast(this._props.Doc[Doc.LayoutFieldKey(this._props.Doc) + '_annotations']); } - return DocListCast(this._props.Document[this._props.fieldKey]); + return DocListCast(this._props.Doc[this._props.fieldKey]); } /// //////lifecycle functions//////////// @@ -104,21 +104,21 @@ export class Timeline extends ObservableReactComponent { this._titleHeight = relativeHeight < this.MAX_TITLE_HEIGHT ? relativeHeight : this.MAX_TITLE_HEIGHT; // check if relHeight is less than Maxheight. Else, just set relheight to max this.MIN_CONTAINER_HEIGHT = this._titleHeight + 130; // offset this.DEFAULT_CONTAINER_HEIGHT = this._titleHeight * 2 + 130; // twice the titleheight + offset - if (!this._props.Document.AnimationLength) { + if (!this._props.Doc.AnimationLength) { // if animation length did not exist - this._props.Document.AnimationLength = this._time; // set it to default time + this._props.Doc.AnimationLength = this._time; // set it to default time } else { - this._time = NumCast(this._props.Document.AnimationLength); // else, set time to animationlength stored from before + this._time = NumCast(this._props.Doc.AnimationLength); // else, set time to animationlength stored from before } this._totalLength = this._tickSpacing * (this._time / this._tickIncrement); // the entire length of the timeline div (actual div part itself) this._visibleLength = this._infoContainer.current!.getBoundingClientRect().width; // the visible length of the timeline (the length that you current see) this._visibleStart = this._infoContainer.current!.scrollLeft; // where the div starts - this._props.Document.isATOn = !this._props.Document.isATOn; // turns the boolean on, saying AT (animation timeline) is on + this._props.Doc.isATOn = !this._props.Doc.isATOn; // turns the boolean on, saying AT (animation timeline) is on this.toggleHandle(); } componentWillUnmount() { - this._props.Document.AnimationLength = this._time; // save animation length + this._props.Doc.AnimationLength = this._time; // save animation length } /// ////////////////////////////////////////////// @@ -224,7 +224,7 @@ export class Timeline extends ObservableReactComponent { */ @action onPanDown = (e: React.PointerEvent) => { - setupMoveUpEvents(this, e, this.onPanMove, emptyFunction, e => this.changeCurrentBarX(this._trackbox.current!.scrollLeft + e.clientX - this._trackbox.current!.getBoundingClientRect().left)); + setupMoveUpEvents(this, e, this.onPanMove, emptyFunction, movEv => this.changeCurrentBarX(this._trackbox.current!.scrollLeft + movEv.clientX - this._trackbox.current!.getBoundingClientRect().left)); }; /** @@ -241,7 +241,7 @@ export class Timeline extends ObservableReactComponent { this._visibleStart -= e.movementX; this._totalLength -= e.movementX; this._time -= RegionHelpers.convertPixelTime(e.movementX, 'mili', 'time', this._tickSpacing, this._tickIncrement); - this._props.Document.AnimationLength = this._time; + this._props.Doc.AnimationLength = this._time; } return false; }; @@ -259,8 +259,8 @@ export class Timeline extends ObservableReactComponent { setupMoveUpEvents( this, e, - action(e => { - const offset = e.clientY - this._timelineContainer.current!.getBoundingClientRect().bottom; + action(movEv => { + const offset = movEv.clientY - this._timelineContainer.current!.getBoundingClientRect().bottom; this._containerHeight = clamp(this.MIN_CONTAINER_HEIGHT, this._containerHeight + offset, this.MAX_CONTAINER_HEIGHT); return false; }), @@ -358,7 +358,7 @@ export class Timeline extends ObservableReactComponent { const size = 40 * scale; // 50 is default const iconSize = 25; const width: number = this._props.PanelWidth(); - const modeType = this._props.Document.isATOn ? 'Author' : 'Play'; + const modeType = this._props.Doc.isATOn ? 'Author' : 'Play'; // decides if information should be omitted because the timeline is very small // if its less than 950 pixels then it's going to be overlapping @@ -397,7 +397,7 @@ export class Timeline extends ObservableReactComponent { tickIncrement={this._tickIncrement} time={this._time} parent={this} - isAuthoring={BoolCast(this._props.Document.isATOn)} + isAuthoring={BoolCast(this._props.Doc.isATOn)} currentBarX={this._currentBarX} totalLength={this._totalLength} visibleLength={this._visibleLength} @@ -418,10 +418,10 @@ export class Timeline extends ObservableReactComponent {
{this.timeIndicator(lengthString, totalTime)} -
this.resetView(this._props.Document)}> +
this.resetView(this._props.Doc)}>
-
this.setView(this._props.Document)}> +
this.setView(this._props.Doc)}>
@@ -431,17 +431,17 @@ export class Timeline extends ObservableReactComponent { }; timeIndicator(lengthString: string, totalTime: number) { - if (this._props.Document.isATOn) { - return
{`Total: ${this.toReadTime(totalTime)}`}
; + if (this._props.Doc.isATOn) { + return
{`Total: ${this.toReadTime(totalTime)}`}
; } else { const ctime = `Current: ${this.getCurrentTime()}`; const ttime = `Total: ${this.toReadTime(this._time)}`; return (
-
+
{ctime}
-
+
{ttime}
@@ -467,8 +467,8 @@ export class Timeline extends ObservableReactComponent { const roundToggleContainer = this._roundToggleContainerRef.current!; const timelineContainer = this._timelineContainer.current!; - this._props.Document.isATOn = !this._props.Document.isATOn; - if (!BoolCast(this._props.Document.isATOn)) { + this._props.Doc.isATOn = !this._props.Doc.isATOn; + if (!BoolCast(this._props.Doc.isATOn)) { // turning on playmode... roundToggle.style.transform = 'translate(0px, 0px)'; roundToggle.style.animationName = 'turnoff'; @@ -543,7 +543,7 @@ export class Timeline extends ObservableReactComponent { // change visible and total width return (
-
+
{this.drawTicks()} @@ -551,7 +551,7 @@ export class Timeline extends ObservableReactComponent {
- {[...this.children, this._props.Document].map(doc => ( + {[...this.children, this._props.Doc].map(doc => ( this.mapOfTracks.push(ref)} @@ -563,7 +563,7 @@ export class Timeline extends ObservableReactComponent { time={this._time} tickSpacing={this._tickSpacing} tickIncrement={this._tickIncrement} - collection={this._props.Document} + collection={this._props.Doc} timelineVisible={true} /> ))} @@ -571,7 +571,7 @@ export class Timeline extends ObservableReactComponent {
Current: {this.getCurrentTime()}
- {[...this.children, this._props.Document].map(doc => ( + {[...this.children, this._props.Doc].map(doc => (
Doc.BrushDoc(doc)} onPointerOut={() => Doc.UnBrushDoc(doc)}>

{StrCast(doc.title)}

diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx index 4fe73895e..89ccf5a0f 100644 --- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx +++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx @@ -22,7 +22,7 @@ import './CollectionStackingView.scss'; interface CMVFieldRowProps { rows: () => number; headings: () => object[]; - Document: Doc; + Doc: Doc; chromeHidden?: boolean; heading: string; headingObject: SchemaHeaderField | undefined; @@ -73,7 +73,7 @@ export class CollectionMasonryViewFieldRow extends ObservableReactComponent { this._dropDisposer?.(); - if (ele) this._dropDisposer = DragManager.MakeDropTarget(ele, this.rowDrop.bind(this), this._props.Document); + if (ele) this._dropDisposer = DragManager.MakeDropTarget(ele, this.rowDrop.bind(this), this._props.Doc); else if (this._ele) this.props.refList.splice(this.props.refList.indexOf(this._ele), 1); this._ele = ele; }; @@ -189,7 +189,7 @@ export class CollectionMasonryViewFieldRow extends ObservableReactComponent { - const embedding = Doc.MakeEmbedding(this._props.Document); + const embedding = Doc.MakeEmbedding(this._props.Doc); const key = this._props.pivotField; let value = this.getValue(this.heading); value = typeof value === 'string' ? `"${value}"` : value; @@ -289,7 +289,7 @@ export class CollectionMasonryViewFieldRow extends ObservableReactComponent evContents} SetValue={this.headingChanged} contents={evContents} oneLine />; - return this._props.Document.miniHeaders ? ( + return this._props.Doc.miniHeaders ? (
{editableHeaderView}
) : !this._props.headingObject ? null : (
diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx index 4650727eb..2dabd3269 100644 --- a/src/client/views/collections/CollectionNoteTakingView.tsx +++ b/src/client/views/collections/CollectionNoteTakingView.tsx @@ -32,6 +32,7 @@ import { CollectionNoteTakingViewColumn } from './CollectionNoteTakingViewColumn import { CollectionNoteTakingViewDivider } from './CollectionNoteTakingViewDivider'; import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView'; import { Property } from 'csstype'; +import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; /** * CollectionNoteTakingView is a column-based view for displaying documents. In this view, the user can (1) @@ -437,10 +438,10 @@ export class CollectionNoteTakingView extends CollectionSubView() { }; @undoBatch - onKeyDown = (e: React.KeyboardEvent, fieldProps: FieldViewProps) => { - if ((e.ctrlKey || fieldProps.Document._createDocOnCR) && ['Enter'].includes(e.key)) { + onKeyDown = (e: React.KeyboardEvent, textBox: FormattedTextBox) => { + if ((e.ctrlKey || textBox.Document._createDocOnCR) && ['Enter'].includes(e.key)) { e.stopPropagation?.(); - const newDoc = Doc.MakeCopy(fieldProps.Document, true); + const newDoc = Doc.MakeCopy(textBox.Document, true); newDoc.$text = undefined; DocumentView.SetSelectOnLoad(newDoc); return this.addDocument?.(newDoc); @@ -543,8 +544,8 @@ export class CollectionNoteTakingView extends CollectionSubView() { addDocument={this.addDocument} chromeHidden={this.chromeHidden} colHeaderData={this.colHeaderData} - Document={this.Document} - TemplateDataDocument={this._props.TemplateDataDocument} + Doc={this.Document} + TemplateDataDoc={this._props.TemplateDataDocument} resizeColumns={this.resizeColumns} renderChildren={this.children} numGroupColumns={this.numGroupColumns} @@ -567,7 +568,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { @undoBatch remColumn = (value: SchemaHeaderField) => { - const colHdrData = Array.from(Cast(this._props.Document[this._props.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null)); + const colHdrData = Array.from(Cast(this.Document[this._props.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null)); if (value) { const index = colHdrData.indexOf(value); index !== -1 && colHdrData.splice(index, 1); @@ -701,7 +702,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { {this.renderedSections}
{ this.layoutDoc._pivotField = fieldKey; this.removeEmptyColumns(); diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx index df9b5a1eb..f283b0abe 100644 --- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx +++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx @@ -21,8 +21,8 @@ import './CollectionNoteTakingView.scss'; import { DocumentView } from '../nodes/DocumentView'; interface CSVFieldColumnProps { - Document: Doc; - TemplateDataDocument: Opt; + Doc: Doc; + TemplateDataDoc: Opt; backgroundColor?: () => string | undefined; docList: Doc[]; heading: string; @@ -65,7 +65,7 @@ export class CollectionNoteTakingViewColumn extends ObservableReactComponent hd.heading === this._props.headingObject?.heading && hd.color === this._props.headingObject.color); return ((this._props.colHeaderData[i].width * this._props.availableWidth) / this._props.PanelWidth()) * 100 + '%'; @@ -81,7 +81,7 @@ export class CollectionNoteTakingViewColumn extends ObservableReactComponent { this.dropDisposer?.(); - if (ele) this.dropDisposer = DragManager.MakeDropTarget(ele, this.columnDrop.bind(this), this._props.Document); + if (ele) this.dropDisposer = DragManager.MakeDropTarget(ele, this.columnDrop.bind(this), this._props.Doc); else if (this._ele) this.props.refList.slice(this.props.refList.indexOf(this._ele), 1); this._ele = ele; }; @@ -155,7 +155,7 @@ export class CollectionNoteTakingViewColumn extends ObservableReactComponent { - const colHdrData = Array.from(Cast(this._props.Document[this._props.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null)); + const colHdrData = Array.from(Cast(this._props.Doc[this._props.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null)); if (this._props.headingObject) { // this._props.docList.forEach(d => (d['$'+this._props.pivotField] = undefined)); colHdrData.splice(colHdrData.indexOf(this._props.headingObject), 1); @@ -184,11 +184,11 @@ export class CollectionNoteTakingViewColumn extends ObservableReactComponent { - Doc.GetProto(this._props.Document)[name] = ''; + Doc.GetProto(this._props.Doc)[name] = ''; 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); + if (this._props.Doc.isTemplateDoc) { + Doc.MakeMetadataFieldTemplate(created, this._props.Doc); } this._props.addDocument?.(created); } @@ -267,7 +267,7 @@ export class CollectionNoteTakingViewColumn extends ObservableReactComponent h[0] === this._props.headingObject) === 0 ? NumCast(this._props.Document.xMargin) : 0, + marginLeft: this._props.headings().findIndex(h => h[0] === this._props.headingObject) === 0 ? NumCast(this._props.Doc.xMargin) : 0, }}>
{this.innards} diff --git a/src/client/views/collections/CollectionPivotView.tsx b/src/client/views/collections/CollectionPivotView.tsx index 2600c0f57..4736070c3 100644 --- a/src/client/views/collections/CollectionPivotView.tsx +++ b/src/client/views/collections/CollectionPivotView.tsx @@ -103,7 +103,7 @@ export class CollectionPivotView extends CollectionSubView() { {this.contents}
{ this.layoutDoc._pivotField = fieldKey; }} diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 9972fe03d..883b0bbe3 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -34,6 +34,7 @@ import './CollectionStackingView.scss'; import { CollectionStackingViewFieldColumn } from './CollectionStackingViewFieldColumn'; import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView'; import { computedFn } from 'mobx-utils'; +import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; export type collectionStackingViewProps = { sortFunc?: (a: Doc, b: Doc) => number; @@ -309,15 +310,15 @@ export class CollectionStackingView extends CollectionSubView { + onKeyDown = (e: React.KeyboardEvent, textBox: FormattedTextBox) => { if (['Enter'].includes(e.key) && e.ctrlKey) { e.stopPropagation?.(); - const layoutFieldKey = StrCast(fieldProps.fieldKey); - const newDoc = Doc.MakeCopy(fieldProps.Document, true); - const dataField = fieldProps.Document[Doc.LayoutFieldKey(newDoc)]; + const layoutFieldKey = StrCast(textBox.fieldKey); + const newDoc = Doc.MakeCopy(textBox.Document, true); + const dataField = textBox.Document[Doc.LayoutFieldKey(newDoc)]; newDoc['$' + Doc.LayoutFieldKey(newDoc)] = dataField === undefined || Cast(dataField, listSpec(Doc), null)?.length !== undefined ? new List([]) : undefined; - if (layoutFieldKey !== 'layout' && fieldProps.Document[layoutFieldKey] instanceof Doc) { - newDoc[layoutFieldKey] = fieldProps.Document[layoutFieldKey]; + if (layoutFieldKey !== 'layout' && textBox.Document[layoutFieldKey] instanceof Doc) { + newDoc[layoutFieldKey] = textBox.Document[layoutFieldKey]; } newDoc.$text = undefined; DocumentView.SetSelectOnLoad(newDoc); @@ -574,8 +575,8 @@ export class CollectionStackingView extends CollectionSubView ; + Doc: Doc; + TemplateDataDoc: Opt; docList: Doc[]; heading: string; pivotField: string; @@ -90,7 +90,7 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent< // is that the only way to have drop targets? createColumnDropRef = (ele: HTMLDivElement | null) => { this.dropDisposer?.(); - if (ele) this.dropDisposer = DragManager.MakeDropTarget(ele, this.columnDrop.bind(this), this._props.Document, this.onInternalPreDrop.bind(this)); + if (ele) this.dropDisposer = DragManager.MakeDropTarget(ele, this.columnDrop.bind(this), this._props.Doc, this.onInternalPreDrop.bind(this)); else if (this._ele) this.props.refList.splice(this.props.refList.indexOf(this._ele), 1); this._ele = ele; }; @@ -183,7 +183,7 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent< // TODO: I think this is where I'm supposed to edit stuff startDrag = (e: PointerEvent) => { // is MakeEmbedding a way to make a copy of a doc without rendering it? - const embedding = Doc.MakeEmbedding(this._props.Document); + const embedding = Doc.MakeEmbedding(this._props.Doc); embedding._width = this._props.columnWidth / (this._props.colHeaderData?.length || 1); embedding._pivotField = undefined; let value = this.getValue(this._heading); @@ -230,7 +230,7 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent< ContextMenu.Instance.clearItems(); const layoutItems: ContextMenuProps[] = []; const docItems: ContextMenuProps[] = []; - const dataDoc = this._props.TemplateDataDocument || this._props.Document; + const dataDoc = this._props.TemplateDataDoc || this._props.Doc; const width = this._ele ? DivWidth(this._ele) : 0; const height = this._ele ? DivHeight(this._ele) : 0; DocUtils.addDocumentCreatorMenuItems( @@ -250,10 +250,10 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent< docItems.push({ description: ':' + fieldKey, event: () => { - const created = DocumentFromField(dataDoc, fieldKey, Doc.GetProto(this._props.Document)); + const created = DocumentFromField(dataDoc, fieldKey, Doc.GetProto(this._props.Doc)); if (created) { - if (this._props.Document.isTemplateDoc) { - Doc.MakeMetadataFieldTemplate(created, this._props.Document); + if (this._props.Doc.isTemplateDoc) { + Doc.MakeMetadataFieldTemplate(created, this._props.Doc); } return this._props.addDocument?.(created); } @@ -270,7 +270,7 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent< 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; + const container = this._props.Doc.resolvedDataDoc ? Doc.GetProto(this._props.Doc) : this._props.Doc; if (container.isTemplateDoc) { Doc.MakeMetadataFieldTemplate(created, container); return Doc.AddDocToList(container, Doc.LayoutFieldKey(container), created); @@ -285,11 +285,11 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent< !Doc.noviceMode && ContextMenu.Instance.addItem({ description: 'Doc Fields ...', subitems: docItems, icon: 'eye' }); !Doc.noviceMode && ContextMenu.Instance.addItem({ description: 'Containers ...', subitems: layoutItems, icon: 'eye' }); ContextMenu.Instance.setDefaultItem('::', (name: string): void => { - Doc.GetProto(this._props.Document)[name] = ''; + Doc.GetProto(this._props.Doc)[name] = ''; 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); + if (this._props.Doc.isTemplateDoc) { + Doc.MakeMetadataFieldTemplate(created, this._props.Doc); } this._props.addDocument?.(created); } @@ -350,10 +350,10 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent<
) : null; const templatecols = `${this._props.columnWidth / this._props.numGroupColumns}px `; - const { type } = this._props.Document; + const { type } = this._props.Doc; return ( <> - {this._props.Document._columnsHideIfEmpty ? null : headingView} + {this._props.Doc._columnsHideIfEmpty ? null : headingView} {this.collapsed ? null : (
() { constructor(props: X & SubCollectionViewProps) { super(props); makeObservable(this); - console.log(`propsTitle: ${this._props.Document.title} DocTitle: ${this.Document.title} LayoutTitle:${this.layoutDoc.title} DataTitle:${this.dataDoc.title}`); - console.log(`tempTitle: ${this._props.TemplateDataDocument?.title} LayouTResolve: ${DocCast(this.layoutDoc.resolvedDataDoc)?.title} propDocResolve: ${DocCast(this._props.Document.resolvedDataDoc)?.title}`); - console.log('Children:', this.childDocs, this.childLayoutPairs); } @observable _focusFilters: Opt = undefined; // childFilters that are overridden when previewing a link to an anchor which has childFilters set on it @@ -111,7 +108,6 @@ export function CollectionSubView() { } get dataDoc() { - console.log(this._props.Document.title + ' isTemplate: ' + this.layoutDoc.isTemplateForField); return this._props.TemplateDataDocument instanceof Doc && this.layoutDoc.isTemplateForField // ? this._props.TemplateDataDocument[DocData] : this.layoutDoc.resolvedDataDoc @@ -135,7 +131,7 @@ export function CollectionSubView() { hasChildDocs = () => this.childLayoutPairs.map(pair => pair.layout); @computed get childLayoutPairs(): { layout: Doc; data: Doc }[] { - const { Document, TemplateDataDocument } = this._props; + const { Document: Document, TemplateDataDocument } = this._props; const validPairs = this.childDocs .map(doc => Doc.GetLayoutDataDocPair(Document, !this._props.isAnnotationOverlay ? TemplateDataDocument : undefined, doc)) .filter( @@ -303,7 +299,7 @@ export function CollectionSubView() { const dragData = de.complete.docDragData; if (dragData) { const sourceDragAction = dragData.dropAction; - const sameCollection = !dragData.draggedDocuments.some(d => d.embedContainer !== this._props.Document); + const sameCollection = !dragData.draggedDocuments.some(d => d.embedContainer !== this._renderDoc); dragData.dropAction = !sameCollection // if doc from another tree ? sourceDragAction || targetDropAction // then use the source's dragAction otherwise the target's : sourceDragAction === dropActionType.inPlace // if source drag is inPlace diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx index 98bd06221..fd562e64f 100644 --- a/src/client/views/collections/CollectionTimeView.tsx +++ b/src/client/views/collections/CollectionTimeView.tsx @@ -121,7 +121,7 @@ export class CollectionTimeView extends CollectionSubView() { {this.contents}
{ this.layoutDoc._pivotField = fieldKey; }} diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index e93724dd4..b7f49ac20 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -241,7 +241,7 @@ export class CollectionTreeView extends CollectionSubView { + onKey = (e: React.KeyboardEvent /* , textBox: FormattedTextBox */) => { if (this.outlineMode && e.key === 'Enter') { e.stopPropagation(); this.makeTextCollection(this.treeChildren); @@ -252,7 +252,6 @@ export class CollectionTreeView extends CollectionSubView {!(this.Document instanceof Doc) || !this.treeChildren ? null : this.Document.treeView_HasOverlay ? ( DocumentView | undefined; addDocTab: (doc: Doc | Doc[], where: OpenWhere) => boolean; PanelWidth: () => number; @@ -100,15 +100,15 @@ export class TabMinimapView extends ObservableReactComponent Cast(this._props.document.childLayoutTemplate, Doc, null); - returnMiniSize = () => NumCast(this._props.document._miniMapSize, 150); + childLayoutTemplate = () => Cast(this._props.doc.childLayoutTemplate, Doc, null); + returnMiniSize = () => NumCast(this._props.doc._miniMapSize, 150); miniDown = (e: React.PointerEvent) => { - const doc = this._props.document; + const doc = this._props.doc; const miniSize = this.returnMiniSize(); doc && setupMoveUpEvents( @@ -127,15 +127,15 @@ export class TabMinimapView extends ObservableReactComponent { const { renderBounds } = this; if (!renderBounds) return
; - const miniWidth = () => (this._props.PanelWidth() / NumCast(this._props.document._freeform_scale, 1) / renderBounds.dim) * 100; - const miniHeight = () => (this._props.PanelHeight() / NumCast(this._props.document._freeform_scale, 1) / renderBounds.dim) * 100; - const miniLeft = () => 50 + ((NumCast(this._props.document._freeform_panX) - renderBounds.cx) / renderBounds.dim) * 100 - miniWidth() / 2; - const miniTop = () => 50 + ((NumCast(this._props.document._freeform_panY) - renderBounds.cy) / renderBounds.dim) * 100 - miniHeight() / 2; + const miniWidth = () => (this._props.PanelWidth() / NumCast(this._props.doc._freeform_scale, 1) / renderBounds.dim) * 100; + const miniHeight = () => (this._props.PanelHeight() / NumCast(this._props.doc._freeform_scale, 1) / renderBounds.dim) * 100; + const miniLeft = () => 50 + ((NumCast(this._props.doc._freeform_panX) - renderBounds.cx) / renderBounds.dim) * 100 - miniWidth() / 2; + const miniTop = () => 50 + ((NumCast(this._props.doc._freeform_panY) - renderBounds.cy) / renderBounds.dim) * 100 - miniHeight() / 2; const miniSize = this.returnMiniSize(); return (
} color={SnappingManager.userVariantColor} type={Type.TERT} onPointerDown={e => e.stopPropagation()} placement="top-end" popup={this.popup} />
@@ -631,7 +631,7 @@ export class TabDocView extends ObservableReactComponent { }}> {!this._activated || !this._document ? null : this.renderDocView(this._document)} {this.disableMinimap() || !this._document ? null : ( - + )}
); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx index 35c6d30fe..89d2bf2c3 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx @@ -12,8 +12,8 @@ import { CollectionFreeFormView } from './CollectionFreeFormView'; import './CollectionFreeFormView.scss'; export interface CollectionFreeFormInfoUIProps { - Document: Doc; - LayoutDoc: Doc; + Doc: Doc; + layoutDoc: Doc; childDocs: () => Doc[]; close: () => void; } @@ -23,7 +23,7 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent Doc[], close: () => void) => ( // - + )); } _firstDocPos = { x: 0, y: 0 }; @@ -40,7 +40,7 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent {this._currState = val;}); } // prettier-ignore componentWillUnmount(): void { - this._props.Document.$backgroundColor = this._originalbackground; + this._props.Doc.$backgroundColor = this._originalbackground; } setCurrState = (state: infoState) => { @@ -51,10 +51,10 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent { - this._originalbackground = StrCast(this._props.Document.$backgroundColor); + this._originalbackground = StrCast(this._props.Doc.$backgroundColor); // state entry functions - // const setBackground = (colour: string) => () => {this._props.Document.$backgroundColor = colour;} // prettier-ignore - // const setOpacity = (opacity: number) => () => {this._props.LayoutDoc.opacity = opacity;} // prettier-ignore + // const setBackground = (colour: string) => () => {this._props.Doc.$backgroundColor = colour;} // prettier-ignore + // const setOpacity = (opacity: number) => () => {this._props.layoutDoc.opacity = opacity;} // prettier-ignore // arc transition trigger conditions const firstDoc = () => (this._props.childDocs().length ? this._props.childDocs()[0] : undefined); const numDocs = () => this._props.childDocs().length; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx index bc9dd022c..2683d9439 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx @@ -7,7 +7,7 @@ import { ObservableReactComponent } from '../../ObservableReactComponent'; import './CollectionFreeFormView.scss'; export interface CollectionFreeFormPannableContentsProps { - Document: Doc; + Doc: Doc; viewDefDivClick?: ScriptField; children?: React.ReactNode | undefined; transition: () => string; @@ -33,7 +33,7 @@ export class CollectionFreeFormPannableContents extends ObservableReactComponent makeObservable(this); } @computed get presPaths() { - return this._props.showPresPaths() ? CollectionFreeFormPannableContents._overlayPlugin?.(this._props.Document) : null; + return this._props.showPresPaths() ? CollectionFreeFormPannableContents._overlayPlugin?.(this._props.Doc) : null; } // rectangle highlight used when following trail/link to a region of a collection that isn't a document showViewport = (viewport: { panX: number; panY: number; width: number; height: number } | undefined) => diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx index f64c6715b..86310dca3 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx @@ -13,7 +13,7 @@ import './CollectionFreeFormView.scss'; @observer export class CollectionFreeFormRemoteCursors extends React.Component { @computed protected get cursors(): CursorField[] { - const { Document } = this.props; + const { Document: Document } = this.props; const cursors = Cast(Document.cursors, listSpec(CursorField)); if (!cursors) { return []; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 6030e146c..25cec9c0d 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1,10 +1,13 @@ -import { Bezier } from 'bezier-js'; import { Button, Colors, Type } from '@dash/components'; +import { Slider } from '@mui/material'; +import { Bezier } from 'bezier-js'; import { Property } from 'csstype'; import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; import * as React from 'react'; +import { AiOutlineSend } from 'react-icons/ai'; +import ReactLoading from 'react-loading'; import { ClientUtils, DashColor, lightOrDark, OmitKeys, returnFalse, returnZero, setupMoveUpEvents, UpdateIcon } from '../../../../ClientUtils'; import { DateField } from '../../../../fields/DateField'; import { Doc, DocListCast, Field, FieldType, Opt, StrListCast } from '../../../../fields/Doc'; @@ -28,6 +31,7 @@ import { DragManager } from '../../../util/DragManager'; import { dropActionType } from '../../../util/DropActionTypes'; import { CompileScript } from '../../../util/Scripting'; import { ScriptingGlobals } from '../../../util/ScriptingGlobals'; +import { SettingsManager } from '../../../util/SettingsManager'; import { freeformScrollMode, SnappingManager } from '../../../util/SnappingManager'; import { Transform } from '../../../util/Transform'; import { undoable, UndoManager } from '../../../util/UndoManager'; @@ -37,26 +41,26 @@ import { InkingStroke } from '../../InkingStroke'; import { CollectionFreeFormDocumentView } from '../../nodes/CollectionFreeFormDocumentView'; import { SchemaCSVPopUp } from '../../nodes/DataVizBox/SchemaCSVPopUp'; import { + ActiveEraserWidth, ActiveInkArrowEnd, ActiveInkArrowStart, - ActiveInkDash, - ActiveEraserWidth, - ActiveInkFillColor, ActiveInkBezierApprox, ActiveInkColor, + ActiveInkDash, + ActiveInkFillColor, ActiveInkWidth, ActiveIsInkMask, DocumentView, SetActiveInkColor, SetActiveInkWidth, } from '../../nodes/DocumentView'; -import { FieldViewProps } from '../../nodes/FieldView'; import { FocusViewOptions } from '../../nodes/FocusViewOptions'; import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; import { OpenWhere } from '../../nodes/OpenWhere'; import { PinDocView, PinProps } from '../../PinFuncs'; -import { StickerPalette } from '../../smartdraw/StickerPalette'; +import { DrawingFillHandler } from '../../smartdraw/DrawingFillHandler'; import { DrawingOptions, SmartDrawHandler } from '../../smartdraw/SmartDrawHandler'; +import { StickerPalette } from '../../smartdraw/StickerPalette'; import { StyleProp } from '../../StyleProp'; import { CollectionSubView, SubCollectionViewProps } from '../CollectionSubView'; import { TreeViewType } from '../CollectionTreeViewType'; @@ -67,11 +71,6 @@ import { CollectionFreeFormPannableContents } from './CollectionFreeFormPannable import { CollectionFreeFormRemoteCursors } from './CollectionFreeFormRemoteCursors'; import './CollectionFreeFormView.scss'; import { MarqueeView } from './MarqueeView'; -import ReactLoading from 'react-loading'; -import { SettingsManager } from '../../../util/SettingsManager'; -import { Slider } from '@mui/material'; -import { AiOutlineSend } from 'react-icons/ai'; -import { DrawingFillHandler } from '../../smartdraw/DrawingFillHandler'; @observer class CollectionFreeFormOverlayView extends React.Component<{ elements: () => ViewDefResult[] }> { @@ -180,10 +179,10 @@ export class CollectionFreeFormView extends CollectionSubView this.fitContentBounds?.cx ?? NumCast(this.Document[this.panXFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.freeform_panX, 1)); - panY = () => this.fitContentBounds?.cy ?? NumCast(this.Document[this.panYFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.freeform_panY, 1)); + panX = () => this.fitContentBounds?.cx ?? NumCast(this.Document[this.panXFieldKey], NumCast(this.Document.freeform_panX, 1)); + panY = () => this.fitContentBounds?.cy ?? NumCast(this.Document[this.panYFieldKey], NumCast(this.Document.freeform_panY, 1)); zoomScaling = () => this.fitContentBounds?.scale ?? NumCast(Doc.Layout(this.Document)[this.scaleFieldKey], 1); // , NumCast(DocCast(this.Document.resolvedDataDoc)?.[this.scaleFieldKey], 1)); PanZoomCenterXf = () => (this._props.isAnnotationOverlay && this.zoomScaling() === 1 ? `` : `translate(${this.centeringShiftX}px, ${this.centeringShiftY}px) scale(${this.zoomScaling()}) translate(${-this.panX()}px, ${-this.panY()}px)`); ScreenToContentsXf = () => this.screenToFreeformContentsXf.copy(); @@ -1489,20 +1488,20 @@ export class CollectionFreeFormView extends CollectionSubView { - const textDoc = DocCast(fieldProps.Document.rootDocument, fieldProps.Document); + createTextDocCopy = undoable((textBox: FormattedTextBox, below: boolean) => { + const textDoc = DocCast(textBox.Document.rootDocument, textBox.Document); const newDoc = Doc.MakeCopy(textDoc, true); - newDoc['$' + Doc.LayoutFieldKey(newDoc, fieldProps.LayoutTemplateString)] = undefined; // the copy should not copy the text contents of it source, just the render style + newDoc['$' + Doc.LayoutFieldKey(newDoc, textBox._props.LayoutTemplateString)] = undefined; // the copy should not copy the text contents of it source, just the render style newDoc.x = NumCast(textDoc.x) + (below ? 0 : NumCast(textDoc._width) + 10); newDoc.y = NumCast(textDoc.y) + (below ? NumCast(textDoc._height) + 10 : 0); DocumentView.SetSelectOnLoad(newDoc); return this.addDocument?.(newDoc); }, 'copied text note'); - onKeyDown = (e: React.KeyboardEvent, fieldProps: FieldViewProps) => { - if ((e.metaKey || e.ctrlKey || e.altKey || fieldProps.Document._createDocOnCR) && ['Tab', 'Enter'].includes(e.key)) { + onKeyDown = (e: React.KeyboardEvent, textBox: FormattedTextBox) => { + if ((e.metaKey || e.ctrlKey || e.altKey || textBox.Document._createDocOnCR) && ['Tab', 'Enter'].includes(e.key)) { e.stopPropagation?.(); - return this.createTextDocCopy(fieldProps, !e.altKey && e.key !== 'Tab'); + return this.createTextDocCopy(textBox, !e.altKey && e.key !== 'Tab'); } return undefined; }; @@ -1685,7 +1684,7 @@ export class CollectionFreeFormView extends CollectionSubView (this._props.Document.isTemplateDoc || this._props.Document.isTemplateForField ? false : !this._renderCutoffData.get(doc[Id] + ''))); + renderCutoffProvider = computedFn((doc: Doc) => (this.Document.isTemplateDoc || this.Document.isTemplateForField ? false : !this._renderCutoffData.get(doc[Id] + ''))); doEngineLayout( poolData: Map, @@ -2115,7 +2114,7 @@ export class CollectionFreeFormView extends CollectionSubView 0 ? undefined : this.nudge} addDocTab={this.addDocTab} @@ -2149,7 +2149,7 @@ export class CollectionFreeFormView extends CollectionSubView {this.layoutDoc._freeform_backgroundGrid ? this.backgroundGrid : null} {this.pannableContents} - {this._showAnimTimeline ? : null} + {this._showAnimTimeline ? : null} ); } diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index e3f4c6605..eaa8826ed 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -32,6 +32,7 @@ import { MarqueeOptionsMenu } from './MarqueeOptionsMenu'; import './MarqueeView.scss'; interface MarqueeViewProps { + Doc: Doc; getContainerTransform: () => Transform; getTransform: () => Transform; activeDocuments: () => Doc[]; diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx index e89822b4c..daffdf1f5 100644 --- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx +++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx @@ -21,11 +21,11 @@ import DOMPurify from 'dompurify'; */ export interface SchemaCellFieldProps { + Doc: Doc; contents: FieldType | undefined; fieldContents?: FieldViewProps; editing?: boolean; oneLine?: boolean; - Document: Doc; fieldKey: string; // eslint-disable-next-line no-use-before-define refSelectModeInfo: { enabled: boolean; currEditing: SchemaCellField | undefined }; @@ -55,7 +55,7 @@ export class SchemaCellField extends ObservableReactComponent() { isolatedSelection={this.isolatedSelection} key={key} rowSelected={this._props.isSelected} - Document={this.Document} + Doc={this.Document} col={index} fieldKey={key} allowCRs={false} // to enter text with new lines, must use \n diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 1b4f200a3..e6fe46638 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -40,7 +40,7 @@ import { SchemaCellField } from './SchemaCellField'; */ export interface SchemaTableCellProps { - Document: Doc; + Doc: Doc; col: number; deselectCell: () => void; selectCell: (doc: Doc, col: number, shift: boolean, ctrl: boolean) => void; @@ -71,7 +71,7 @@ export interface SchemaTableCellProps { } function selectedCell(props: SchemaTableCellProps) { - return props.isRowActive() && props.selectedCol() === props.col && props.selectedCells()?.filter(d => d === props.Document)?.length; + return props.isRowActive() && props.selectedCol() === props.col && props.selectedCells()?.filter(d => d === props.Doc)?.length; } @observer @@ -84,11 +84,11 @@ export class SchemaTableCell extends ObservableReactComponent this._props.highlightCells(this.adjustSelfReference(text))} getCells={(text: string) => this._props.eqHighlightFunc(this.adjustSelfReference(text))} ref={r => selectedCell(this._props) && this._props.autoFocus && r?.setIsFocused(true)} @@ -224,7 +224,7 @@ export class SchemaTableCell extends ObservableReactComponent = []; sides[0] = selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // left sides[1] = selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // right - sides[2] = !this._props.isolatedSelection(this._props.Document)[0] && selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // top - sides[3] = !this._props.isolatedSelection(this._props.Document)[1] && selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // bottom + sides[2] = !this._props.isolatedSelection(this._props.Doc)[0] && selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // top + sides[3] = !this._props.isolatedSelection(this._props.Doc)[1] && selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // bottom return sides; } @@ -272,7 +272,7 @@ export class SchemaTableCell extends ObservableReactComponent Cast(doc[Doc.LayoutFieldKey(doc)], ImageField, null)?.url) .filter(url => url) @@ -359,7 +359,7 @@ export class SchemaImageCell extends ObservableReactComponent { @@ -388,7 +388,7 @@ export class SchemaDateCell extends ObservableReactComponent e.stopPropagation()} style={{ marginRight: 4 }} type="checkbox" - checked={BoolCast(this._props.Document[this._props.fieldKey])} + checked={BoolCast(this._props.Doc[this._props.fieldKey])} onChange={undoable((value: React.ChangeEvent | undefined) => { if ((value?.nativeEvent as MouseEvent | PointerEvent).shiftKey) { this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), (color === 'black' ? '=' : '') + (value?.target?.checked.toString() ?? '')); - } else Doc.SetField(this._props.Document, this._props.fieldKey.replace(/^_/, ''), (color === 'black' ? '=' : '') + (value?.target?.checked.toString() ?? '')); + } else Doc.SetField(this._props.Doc, this._props.fieldKey.replace(/^_/, ''), (color === 'black' ? '=' : '') + (value?.target?.checked.toString() ?? '')); }, 'set bool cell')} /> @@ -463,14 +463,14 @@ export class SchemaBoolCell extends ObservableReactComponent Field.toKeyValueString(this._props.Document, this._props.fieldKey)} + GetValue={() => Field.toKeyValueString(this._props.Doc, this._props.fieldKey)} SetValue={undoable((value: string, shiftDown?: boolean, enterKey?: boolean) => { if (shiftDown && enterKey) { this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), value); this._props.finishEdit?.(); return true; } - const set = Doc.SetField(this._props.Document, this._props.fieldKey.replace(/^_/, ''), value, Doc.IsDataProto(this._props.Document) ? true : undefined); + const set = Doc.SetField(this._props.Doc, this._props.fieldKey.replace(/^_/, ''), value, Doc.IsDataProto(this._props.Doc) ? true : undefined); this._props.finishEdit?.(); return set; }, 'set bool cell')} @@ -538,10 +538,10 @@ export class SchemaEnumerationCell extends ObservableReactComponent Doc.SetField(this._props.Document, this._props.fieldKey.replace(/^_/, ''), `"${val?.value ?? ''}"`)} + onChange={val => Doc.SetField(this._props.Doc, this._props.fieldKey.replace(/^_/, ''), `"${val?.value ?? ''}"`)} />
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index ce1e9280a..6f86383c2 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -304,7 +304,7 @@ export class CollectionFreeFormDocumentView extends DocComponent val.lower)).omit} // prettier-ignore - Document={this._props.Document} + Document={this._renderDoc} renderDepth={this._props.renderDepth} isContentActive={this._props.isContentActive} childFilters={this._props.childFilters} diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index d5e37b3b5..117eb05f8 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -1,43 +1,39 @@ +import { Colors, Toggle, ToggleType, Type } from '@dash/components'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Checkbox } from '@mui/material'; -import { Colors, Toggle, ToggleType, Type } from '@dash/components'; import { IReactionDisposer, ObservableMap, action, computed, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { ClientUtils, returnEmptyString, returnFalse, returnOne, setupMoveUpEvents } from '../../../../ClientUtils'; +import { returnEmptyString, returnFalse, returnOne, setupMoveUpEvents } from '../../../../ClientUtils'; import { emptyFunction } from '../../../../Utils'; -import { Doc, DocListCast, Field, FieldType, NumListCast, Opt, StrListCast } from '../../../../fields/Doc'; -import { AclAdmin, AclAugment, AclEdit } from '../../../../fields/DocSymbols'; +import { Doc, DocListCast, Field, Opt, StrListCast } from '../../../../fields/Doc'; import { InkTool } from '../../../../fields/InkField'; import { List } from '../../../../fields/List'; -import { PrefetchProxy } from '../../../../fields/Proxy'; import { Cast, CsvCast, DocCast, NumCast, StrCast } from '../../../../fields/Types'; import { CsvField } from '../../../../fields/URLField'; -import { GetEffectiveAcl, TraceMobx } from '../../../../fields/util'; +import { TraceMobx } from '../../../../fields/util'; import { GPTCallType, gptAPICall } from '../../../apis/gpt/GPT'; import { DocUtils } from '../../../documents/DocUtils'; import { DocumentType } from '../../../documents/DocumentTypes'; import { Docs } from '../../../documents/Documents'; -import { LinkManager } from '../../../util/LinkManager'; import { UndoManager, undoable } from '../../../util/UndoManager'; import { ContextMenu } from '../../ContextMenu'; import { ViewBoxAnnotatableComponent } from '../../DocComponent'; import { MarqueeAnnotator } from '../../MarqueeAnnotator'; import { PinProps } from '../../PinFuncs'; import { SidebarAnnos } from '../../SidebarAnnos'; -import { CollectionFreeFormView } from '../../collections/collectionFreeForm'; import { AnchorMenu } from '../../pdf/AnchorMenu'; import { GPTPopup, GPTPopupMode } from '../../pdf/GPTPopup/GPTPopup'; import { DocumentView } from '../DocumentView'; import { FieldView, FieldViewProps } from '../FieldView'; import { FocusViewOptions } from '../FocusViewOptions'; import './DataVizBox.scss'; -import { Col, DataVizTemplateInfo, DocCreatorMenu, LayoutType} from './DocCreatorMenu/DocCreatorMenu'; +import { Col, DocCreatorMenu } from './DocCreatorMenu/DocCreatorMenu'; +import { TemplateFieldSize, TemplateFieldType } from './DocCreatorMenu/TemplateBackend'; import { Histogram } from './components/Histogram'; import { LineChart } from './components/LineChart'; import { PieChart } from './components/PieChart'; import { TableBox } from './components/TableBox'; -import { TemplateFieldSize, TemplateFieldType } from './DocCreatorMenu/TemplateBackend'; export enum DataVizView { TABLE = 'table', @@ -440,10 +436,10 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { }; if (!this.records.length) return 'no data/visualization'; switch (this.dataVizView) { - case DataVizView.TABLE: return ; - case DataVizView.LINECHART: return {this._vizRenderer = r ?? undefined;}} vizBox={this} />; - case DataVizView.HISTOGRAM: return {this._vizRenderer = r ?? undefined;}} />; - case DataVizView.PIECHART: return {this._vizRenderer = r ?? undefined;}} + case DataVizView.TABLE: return ; + case DataVizView.LINECHART: return {this._vizRenderer = r ?? undefined;}} vizBox={this} />; + case DataVizView.HISTOGRAM: return {this._vizRenderer = r ?? undefined;}} />; + case DataVizView.PIECHART: return {this._vizRenderer = r ?? undefined;}} margin={{ top: 10, right: 15, bottom: 15, left: 15 }} />; default: } // prettier-ignore @@ -574,9 +570,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { const cols = Array.from(Object.keys(this.records[0])).filter(header => header !== '' && header !== undefined); - cols.forEach(col => { - this.setColumnDefault(col, `${this.records[rowToCheck][col]}`); - }); + cols.forEach(col => this.setColumnDefault(col, `${this.records[rowToCheck][col]}`)); }; updateGPTSummary = async () => { @@ -706,7 +700,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { ref={this._sidebarRef} {...this._props} fieldKey={this.fieldKey} - Document={this.Document} + Doc={this.Document} layoutDoc={this.layoutDoc} dataDoc={this.dataDoc} usePanelWidth diff --git a/src/client/views/nodes/DataVizBox/components/Histogram.tsx b/src/client/views/nodes/DataVizBox/components/Histogram.tsx index 5a9442d2f..776d65211 100644 --- a/src/client/views/nodes/DataVizBox/components/Histogram.tsx +++ b/src/client/views/nodes/DataVizBox/components/Histogram.tsx @@ -17,7 +17,7 @@ import { scaleCreatorNumerical, yAxisCreator } from '../utils/D3Utils'; import './Chart.scss'; export interface HistogramProps { - Document: Doc; + Doc: Doc; layoutDoc: Doc; axes: string[]; titleCol: string; @@ -88,7 +88,7 @@ export class Histogram extends ObservableReactComponent { } @computed get parentViz() { - return DocCast(this._props.Document.dataViz_parentViz); + return DocCast(this._props.Doc.dataViz_parentViz); } @computed get rangeVals(): { xMin?: number; xMax?: number; yMin?: number; yMax?: number } { @@ -126,7 +126,7 @@ export class Histogram extends ObservableReactComponent { const anchor = Docs.Create.ConfigDocument({ title: 'histogram doc selection' + this._currSelected, }); - PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this._props.Document); + PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this._props.Doc); return anchor; }; @@ -416,11 +416,9 @@ export class Histogram extends ObservableReactComponent { let barColor; const barColors = StrListCast(this._props.layoutDoc.dataViz_histogram_barColors).map(each => each.split('::')); barColors.forEach(each => { - // eslint-disable-next-line prefer-destructuring if (d[0] && d[0].toString() && each[0] == d[0].toString()) barColor = each[1]; else { const range = StrCast(each[0]).split(' to '); - // eslint-disable-next-line prefer-destructuring if (Number(range[0]) <= d[0] && d[0] <= Number(range[1])) barColor = each[1]; } }); @@ -454,11 +452,9 @@ export class Histogram extends ObservableReactComponent { let barColor; const barColors = StrListCast(this._props.layoutDoc.dataViz_histogram_barColors).map(each => each.split('::')); barColors.forEach(each => { - // eslint-disable-next-line prefer-destructuring if (d[0] && d[0].toString() && each[0] == d[0].toString()) barColor = each[1]; else { const range = StrCast(each[0]).split(' to '); - // eslint-disable-next-line prefer-destructuring if (Number(range[0]) <= d[0] && d[0] <= Number(range[1])) barColor = each[1]; } }); @@ -471,7 +467,7 @@ export class Histogram extends ObservableReactComponent { this.updateSavedUI(); this._histogramData; let curSelectedBarName = ''; - let titleAccessor: any = 'dataViz_histogram_title'; + let titleAccessor = 'dataViz_histogram_title'; if (this._props.axes.length === 2) titleAccessor = titleAccessor + this._props.axes[0] + '-' + this._props.axes[1]; else if (this._props.axes.length > 0) titleAccessor += this._props.axes[0]; if (!this._props.layoutDoc[titleAccessor]) this._props.layoutDoc[titleAccessor] = this.defaultGraphTitle; @@ -503,7 +499,6 @@ export class Histogram extends ObservableReactComponent { let selectedBarColor; const barColors = StrListCast(this._props.layoutDoc.histogramBarColors).map(each => each.split('::')); barColors.forEach(each => { - // eslint-disable-next-line prefer-destructuring each[0] === curSelectedBarName && (selectedBarColor = each[1]); }); diff --git a/src/client/views/nodes/DataVizBox/components/LineChart.tsx b/src/client/views/nodes/DataVizBox/components/LineChart.tsx index b55d509ff..6b047546c 100644 --- a/src/client/views/nodes/DataVizBox/components/LineChart.tsx +++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx @@ -22,7 +22,7 @@ export interface SelectedDataPoint extends DataPoint { } export interface LineChartProps { vizBox: DataVizBox; - Document: Doc; + Doc: Doc; layoutDoc: Doc; axes: string[]; titleCol: string; @@ -53,7 +53,7 @@ export class LineChart extends ObservableReactComponent { } @computed get titleAccessor() { - let titleAccessor: any = 'dataViz_lineChart_title'; + let titleAccessor = 'dataViz_lineChart_title'; if (this._props.axes.length === 2) titleAccessor = titleAccessor + this._props.axes[0] + '-' + this._props.axes[1]; else if (this._props.axes.length > 0) titleAccessor += this._props.axes[0]; return titleAccessor; @@ -74,7 +74,7 @@ export class LineChart extends ObservableReactComponent { return this._props.axes[1] + ' vs. ' + this._props.axes[0] + ' Line Chart'; } @computed get parentViz() { - return DocCast(this._props.Document.dataViz_parentViz); + return DocCast(this._props.Doc.dataViz_parentViz); } @computed get incomingHighlited() { // return selected x and y axes @@ -113,7 +113,7 @@ export class LineChart extends ObservableReactComponent { // title: 'line doc selection' + (this._currSelected?.x ?? ''), }); - PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this._props.Document); + PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this._props.Doc); anchor.config_dataVizSelection = this._currSelected ? new List([this._currSelected.x, this._currSelected.y]) : undefined; return anchor; }; diff --git a/src/client/views/nodes/DataVizBox/components/PieChart.tsx b/src/client/views/nodes/DataVizBox/components/PieChart.tsx index 86e6ad8e4..0ae70786f 100644 --- a/src/client/views/nodes/DataVizBox/components/PieChart.tsx +++ b/src/client/views/nodes/DataVizBox/components/PieChart.tsx @@ -16,7 +16,7 @@ import { PinProps, PinDocView } from '../../../PinFuncs'; import './Chart.scss'; export interface PieChartProps { - Document: Doc; + Doc: Doc; layoutDoc: Doc; axes: string[]; titleCol: string; @@ -83,7 +83,7 @@ export class PieChart extends ObservableReactComponent { } @computed get parentViz() { - return DocCast(this._props.Document.dataViz_parentViz); + return DocCast(this._props.Doc.dataViz_parentViz); } componentWillUnmount() { @@ -114,7 +114,7 @@ export class PieChart extends ObservableReactComponent { // title: 'piechart doc selection' + this._currSelected, }); - PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this._props.Document); + PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this._props.Doc); return anchor; }; @@ -169,7 +169,6 @@ export class PieChart extends ObservableReactComponent { // inside the slice of it crosses an odd number of edges const showSelected = this.byCategory ? pieDataSet[index] : this._pieChartData[index]; let key = 'data'; // key that represents slice - // eslint-disable-next-line prefer-destructuring if (Object.keys(showSelected)[0] === 'frequency') key = Object.keys(showSelected)[1]; if (changeSelectedVariables) { let sameAsAny = false; @@ -296,7 +295,7 @@ export class PieChart extends ObservableReactComponent { if (descriptionField) dataPointVal[descriptionField] = each[descriptionField]; try { dataPointVal[percentField] = Number(dataPointVal[percentField].replace(/\$/g, '').replace(/%/g, '').replace(/#/g, '').replace(/ { // to make sure all important slice information is on 'd' object let addKey: any = false; if (pieDataSet.length && Object.keys(pieDataSet[0])[0] === 'frequency') { - // eslint-disable-next-line prefer-destructuring addKey = Object.keys(pieDataSet[0])[1]; } arcs.append('path') @@ -324,7 +322,6 @@ export class PieChart extends ObservableReactComponent { const sliceTitle = dataPoint[this._props.axes[0]]; const accessByName = StrCast(sliceTitle) ? StrCast(sliceTitle).replace(/\$/g, '').replace(/%/g, '').replace(/#/g, '').replace(/ { - // eslint-disable-next-line prefer-destructuring each[0] === accessByName && (sliceColor = each[1]); }); } @@ -337,7 +334,7 @@ export class PieChart extends ObservableReactComponent { }); return selectThisData ? 'slice hover' : 'slice'; }) - // @ts-ignore + // @ts-expect-error types don't match .attr('d', arc) .on('click', onPointClick) .on('mouseover', onHover) @@ -388,7 +385,7 @@ export class PieChart extends ObservableReactComponent { }; render() { - let titleAccessor: any = 'dataViz_pie_title'; + let titleAccessor = 'dataViz_pie_title'; if (this._props.axes.length === 2) titleAccessor = titleAccessor + this._props.axes[0] + '-' + this._props.axes[1]; else if (this._props.axes.length > 0) titleAccessor += this._props.axes[0]; if (!this._props.layoutDoc[titleAccessor]) this._props.layoutDoc[titleAccessor] = this.defaultGraphTitle; @@ -420,7 +417,6 @@ export class PieChart extends ObservableReactComponent { let selectedSliceColor; const sliceColors = StrListCast(this._props.layoutDoc.dataViz_pie_sliceColors).map(each => each.split('::')); sliceColors.forEach(each => { - // eslint-disable-next-line prefer-destructuring if (each[0] === curSelectedSliceName!) selectedSliceColor = each[1]; }); diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx index b6183946a..b73123691 100644 --- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx +++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx @@ -19,7 +19,7 @@ import './Chart.scss'; const { DATA_VIZ_TABLE_ROW_HEIGHT } = require('../../../global/globalCssVariables.module.scss'); // prettier-ignore interface TableBoxProps { - Document: Doc; + Doc: Doc; layoutDoc: Doc; records: { [key: string]: unknown }[]; selectAxes: (axes: string[]) => void; @@ -81,7 +81,7 @@ export class TableBox extends ObservableReactComponent { } @computed get parentViz() { - return DocCast(this._props.Document.dataViz_parentViz); + return DocCast(this._props.Doc.dataViz_parentViz); } @computed get columns() { @@ -139,21 +139,21 @@ export class TableBox extends ObservableReactComponent { e, moveEv => { // dragging off a column to create a brushed DataVizBox - const sourceAnchorCreator = () => this._props.docView?.()?.Document || this._props.Document; + const sourceAnchorCreator = () => this._props.docView?.()?.Document || this._props.Doc; const targetCreator = (annotationOn: Doc | undefined) => { const doc = this._props.docView?.()?.Document; if (doc) { const embedding = Doc.MakeEmbedding(doc); embedding._dataViz = DataVizView.TABLE; embedding._dataViz_axes = new List([col]); - embedding._dataViz_parentViz = this._props.Document; + embedding._dataViz_parentViz = this._props.Doc; embedding.annotationOn = annotationOn; embedding.histogramBarColors = Field.Copy(this._props.layoutDoc.histogramBarColors); embedding.defaultHistogramColor = this._props.layoutDoc.defaultHistogramColor; embedding.pieSliceColors = Field.Copy(this._props.layoutDoc.pieSliceColors); return embedding; } - return this._props.Document; + return this._props.Doc; }; if (this._props.docView?.() && !ClientUtils.isClick(moveEv.clientX, moveEv.clientY, downX, downY, Date.now())) { DragManager.StartAnchorAnnoDrag(moveEv.target instanceof HTMLElement ? [moveEv.target] : [], new DragManager.AnchorAnnoDragData(this._props.docView()!, sourceAnchorCreator, targetCreator), downX, downY, { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index e9353b001..c355e57d4 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -758,7 +758,7 @@ export class DocumentViewInternal extends DocComponent { this._changingTitleField = true; })} // prettier-ignore style={{ width: 'max-content', background: SnappingManager.userBackgroundColor, color: SnappingManager.userColor, transformOrigin: 'left', transform: `scale(${this.titleHeight / 30 /* height of Dropdown */})` }}> { if (this.layoutDoc.layout_showTitle) { diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 2e40f39ed..abba99c3d 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -15,6 +15,7 @@ import { FocusViewOptions } from './FocusViewOptions'; import { OpenWhere } from './OpenWhere'; import { WebField } from '../../../fields/URLField'; import { ContextMenuProps } from '../ContextMenuItem'; +import { FormattedTextBox } from './formattedText/FormattedTextBox'; export type FocusFuncType = (doc: Doc, options: FocusViewOptions) => Opt; export type StyleProviderFuncType = ( @@ -83,8 +84,7 @@ export interface FieldViewSharedProps { onDoubleClickScript?: () => ScriptField; onPointerDownScript?: () => ScriptField; onPointerUpScript?: () => ScriptField; - // eslint-disable-next-line no-use-before-define - onKey?: (e: React.KeyboardEvent, fieldProps: FieldViewProps) => boolean | undefined; + onKey?: (e: React.KeyboardEvent, textBox: FormattedTextBox) => boolean | undefined; fitWidth?: (doc: Doc) => boolean | undefined; dontCenter?: 'x' | 'y' | 'xy' | undefined; searchFilterDocs: () => Doc[]; diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 5d9718760..d121b492f 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -648,7 +648,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent() { onClick={action(async () => { this._regenerateLoading = true; if (this._fireflyRefStrength) { - DrawingFillHandler.drawingToImage(this.props.Document, this._fireflyRefStrength, this._regenInput || StrCast(this.Document.title), this.Document)?.then(action(() => (this._regenerateLoading = false))); + DrawingFillHandler.drawingToImage(this.Document, this._fireflyRefStrength, this._regenInput || StrCast(this.Document.title), this.Document)?.then(action(() => (this._regenerateLoading = false))); } else { SmartDrawHandler.Instance.regenerate([this.Document], undefined, undefined, this._regenInput || StrCast(this.Document.title), true).then( action(newImgs => { diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 32c9efbd9..8911fac6d 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -58,8 +58,8 @@ export class KeyValueBox extends ViewBoxBaseComponent() { onEnterKey = (e: React.KeyboardEvent): void => { if (e.key === 'Enter') { e.stopPropagation(); - if (this._keyInput.current?.value && this._valInput.current?.value && this._props.Document) { - if (KeyValueBox.SetField(this._props.Document, this._keyInput.current.value, this._valInput.current.value)) { + if (this._keyInput.current?.value && this._valInput.current?.value && this.Document) { + if (KeyValueBox.SetField(this.Document, this._keyInput.current.value, this._valInput.current.value)) { this._keyInput.current.value = ''; this._valInput.current.value = ''; document.body.focus(); @@ -137,7 +137,7 @@ export class KeyValueBox extends ViewBoxBaseComponent() { rowHeight = () => 30; @computed get createTable() { - const doc = this._props.Document; + const doc = this.Document; if (!doc) { return ( @@ -305,8 +305,8 @@ export class KeyValueBox extends ViewBoxBaseComponent() { openItems.push({ description: 'Default Perspective', event: () => { - this._props.addDocTab(this._props.Document, OpenWhere.close); - this._props.addDocTab(this._props.Document, OpenWhere.addRight); + this._props.addDocTab(this.Document, OpenWhere.close); + this._props.addDocTab(this.Document, OpenWhere.addRight); }, icon: 'image', }); diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index 65d78f754..a563b7c1b 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -1300,7 +1300,7 @@ export class MapBox extends ViewBoxAnnotatableComponent() { ref={this._sidebarRef} {...this._props} fieldKey={this.fieldKey} - Document={this.Document} + Doc={this.Document} layoutDoc={this.layoutDoc} dataDoc={this.dataDoc} usePanelWidth diff --git a/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx b/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx index ddeaf4d0d..e0efab576 100644 --- a/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx +++ b/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx @@ -798,7 +798,6 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent PanelHeight={returnOne} NativeWidth={returnOne} NativeHeight={returnOne} - onKey={undefined} onDoubleClickScript={undefined} childFilters={returnEmptyFilter} childFiltersByRanges={returnEmptyFilter} @@ -830,7 +829,7 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent ref={this._sidebarRef} {...this._props} fieldKey={this.fieldKey} - Document={this.Document} + Doc={this.Document} layoutDoc={this.layoutDoc} dataDoc={this.dataDoc} usePanelWidth diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 5484179be..78ddafa88 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -535,7 +535,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent() { () { pdfBox={this} sidebarAddDoc={this.sidebarAddDocument} addDocTab={this.sidebarAddDocTab} + Doc={this.Document} layoutDoc={this.layoutDoc} dataDoc={this.dataDoc} pdf={this._pdf} diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx index 6289470b6..999f9c1cd 100644 --- a/src/client/views/nodes/ScreenshotBox.tsx +++ b/src/client/views/nodes/ScreenshotBox.tsx @@ -301,7 +301,6 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent()
()
{!(this.dataDoc[this.fieldKey + '_dictation'] instanceof Doc) ? null : ( () { {...this._props} whenChildContentsActiveChanged={this.whenChildContentsActiveChanged} fieldKey={this.fieldKey + '_' + this._urlHash} - Document={this.Document} + Doc={this.Document} layoutDoc={this.layoutDoc} dataDoc={this.dataDoc} setHeight={emptyFunction} diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx index aa2829aaf..bb0efa917 100644 --- a/src/client/views/nodes/formattedText/DashFieldView.tsx +++ b/src/client/views/nodes/formattedText/DashFieldView.tsx @@ -162,7 +162,7 @@ export class DashFieldViewInternal extends ObservableReactComponent (this._expanded ? true : undefined)} diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 9078648e9..925109bfb 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -78,14 +78,14 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent new FormattedTextBoxComment() }), @@ -153,7 +153,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { let mapStyle = assignedMapStyle; - tx2.doc.descendants((node: any, offset: any /* , index: any */) => { + tx2.doc.descendants((node: Node, offset: number /* , index: any */) => { if ((from === undefined || to === undefined || (from <= offset + node.nodeSize && to >= offset)) && (node.type === schema.nodes.ordered_list || node.type === schema.nodes.list_item)) { - const { path } = tx2.doc.resolve(offset) as any; - let depth = Array.from(path).reduce((p: number, c: any) => p + (c.type === schema.nodes.ordered_list ? 1 : 0), 0); + const { path } = tx2.doc.resolve(offset) as unknown as { path: (number | Node)[] }; // bcz: can't access path .. need to FIX + let depth = Array.from(path).reduce((p: number, c: number | Node) => p + ((c as Node).type === schema.nodes.ordered_list ? 1 : 0), 0); if (node.type === schema.nodes.ordered_list) { if (depth === 0 && !assignedMapStyle) mapStyle = node.attrs.mapStyle; depth++; @@ -34,25 +35,25 @@ export const updateBullets = (tx2: Transaction, schema: Schema, assignedMapStyle return tx2; }; -export function buildKeymap>(schema: S, props: any): KeyMap { - const keys: { [key: string]: any } = {}; +export function buildKeymap>(schema: S, tbox?: FormattedTextBox): KeyMap { + const keys: { [key: string]: Command } = {}; - function bind(key: string, cmd: any) { + function bind(key: string, cmd: Command) { keys[key] = cmd; } function onKey(): boolean | undefined { // bcz: this is pretty hacky -- prosemirror doesn't send us the keyboard event, but the 'event' variable is in scope.. so we access it anyway - // eslint-disable-next-line no-restricted-globals - return props.onKey?.(event, props); + return tbox?._props.onKey?.(event, tbox); } - const canEdit = (state: any) => { - const permissions = GetEffectiveAcl(props.TemplateDataDocument ?? props.Document[DocData]); + const canEdit = (state: EditorState) => { + if (!tbox) return true; + const permissions = GetEffectiveAcl(tbox._props.TemplateDataDocument ?? tbox.Document[DocData]); switch (permissions) { case AclAugment: { - const prevNode = state.selection.$cursor.nodeBefore; + const prevNode = (state.selection as any).$cursor.nodeBefore; const prevUser = !prevNode ? ClientUtils.CurrentUserEmail() : prevNode.marks.lastElement()?.attrs.userid; if (prevUser !== ClientUtils.CurrentUserEmail()) { return false; @@ -64,7 +65,7 @@ export function buildKeymap>(schema: S, props: any): KeyMa return true; }; - const toggleEditableMark = (mark: any) => (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state) && toggleMark(mark)(state, dispatch); + const toggleEditableMark = (mark: MarkType) => (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => canEdit(state) && toggleMark(mark)(state, dispatch); // History commands bind('Mod-z', undo); @@ -84,13 +85,13 @@ export function buildKeymap>(schema: S, props: any): KeyMa bind('Mod-U', toggleEditableMark(schema.marks.underline)); // Commands for lists - bind('Ctrl-i', (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state) && wrapInList(schema.nodes.ordered_list)(state as any, dispatch as any)); + bind('Ctrl-i', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => canEdit(state) && wrapInList(schema.nodes.ordered_list)(state, dispatch)); bind('Ctrl-Tab', () => onKey() || true); bind('Alt-Tab', () => onKey() || true); bind('Meta-Tab', () => onKey() || true); bind('Meta-Enter', () => onKey() || true); - bind('Tab', (state: EditorState, dispatch: (tx: Transaction) => void) => { + bind('Tab', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => { if (onKey()) return true; if (!canEdit(state)) return true; const ref = state.selection; @@ -101,13 +102,13 @@ export function buildKeymap>(schema: S, props: any): KeyMa const tx3 = updateBullets(tx2, schema); marks && tx3.ensureMarks([...marks]); marks && tx3.setStoredMarks([...marks]); - dispatch(tx3); + dispatch?.(tx3); }) ) { // couldn't sink into an existing list, so wrap in a new one const newstate = state.applyTransaction(state.tr.setSelection(TextSelection.create(state.doc, range!.start, range!.end))); if ( - !wrapInList(schema.nodes.ordered_list)(newstate.state as any, (tx2: Transaction) => { + !wrapInList(schema.nodes.ordered_list)(newstate.state, (tx2: Transaction) => { const tx25 = updateBullets(tx2, schema); const olNode = tx25.doc.nodeAt(range!.start)!; const tx3 = tx25.setNodeMarkup(range!.start, olNode.type, olNode.attrs, marks); @@ -115,16 +116,16 @@ export function buildKeymap>(schema: S, props: any): KeyMa marks && tx3.ensureMarks([...marks]); marks && tx3.setStoredMarks([...marks]); const tx4 = tx3.setSelection(TextSelection.near(tx3.doc.resolve(state.selection.to + 2))); - dispatch(tx4); + dispatch?.(tx4); }) ) { console.log('bullet promote fail'); } } - return undefined; + return false; }); - bind('Shift-Tab', (state: EditorState, dispatch: (tx: Transaction) => void) => { + bind('Shift-Tab', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => { if (onKey()) return true; if (!canEdit(state)) return true; const marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks()); @@ -134,72 +135,83 @@ export function buildKeymap>(schema: S, props: any): KeyMa const tx3 = updateBullets(tx2, schema); marks && tx3.ensureMarks([...marks]); marks && tx3.setStoredMarks([...marks]); - dispatch(tx3); + dispatch?.(tx3); }) ) { console.log('bullet demote fail'); } - return undefined; + return false; }); // Command to create a new Tab with a PDF of all the command shortcuts - bind('Mod-/', () => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + bind('Mod-/', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => { const newDoc = Docs.Create.PdfDocument(ClientUtils.prepend('/assets/cheat-sheet.pdf'), { _width: 300, _height: 300 }); - props.addDocTab(newDoc, OpenWhere.addRight); + tbox?._props.addDocTab(newDoc, OpenWhere.addRight); + return false; }); // Commands to modify BlockType - bind('Ctrl->', (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state && wrapIn(schema.nodes.blockquote)(state as any, dispatch as any))); - bind('Alt-\\', (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state) && setBlockType(schema.nodes.paragraph)(state as any, dispatch as any)); - bind('Shift-Ctrl-\\', (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state) && setBlockType(schema.nodes.code_block)(state as any, dispatch as any)); + bind('Ctrl->', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => canEdit(state) && wrapIn(schema.nodes.blockquote)(state, dispatch)); + bind('Alt-\\', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => canEdit(state) && setBlockType(schema.nodes.paragraph)(state, dispatch)); + bind('Shift-Ctrl-\\', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => canEdit(state) && setBlockType(schema.nodes.code_block)(state, dispatch)); - bind('Ctrl-m', (state: EditorState, dispatch: (tx: Transaction) => void) => { + bind('Ctrl-m', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => { if (canEdit(state)) { const tr = state.tr.replaceSelectionWith(schema.nodes.equation.create({ fieldKey: 'math' + Utils.GenerateGuid() })); - dispatch(tr.setSelection(new NodeSelection(tr.doc.resolve(tr.selection.$from.pos - 1)))); + dispatch?.(tr.setSelection(new NodeSelection(tr.doc.resolve(tr.selection.$from.pos - 1)))); + return true; } + return false; }); for (let i = 1; i <= 6; i++) { - bind('Shift-Ctrl-' + i, (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state) && setBlockType(schema.nodes.heading, { level: i })(state as any, dispatch as any)); + bind('Shift-Ctrl-' + i, (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => canEdit(state) && setBlockType(schema.nodes.heading, { level: i })(state, dispatch)); } // Command to create a horizontal break line const hr = schema.nodes.horizontal_rule; - bind('Mod-_', (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state) && dispatch(state.tr.replaceSelectionWith(hr.create()).scrollIntoView())); + bind('Mod-_', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => { + if (canEdit(state)) { + dispatch?.(state.tr.replaceSelectionWith(hr.create()).scrollIntoView()); + return true; + } + return false; + }); // Command to unselect all - bind('Escape', (state: EditorState, dispatch: (tx: Transaction) => void) => { - dispatch(state.tr.setSelection(TextSelection.create(state.doc, state.selection.from, state.selection.from))); - (document.activeElement as any).blur?.(); + bind('Escape', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => { + dispatch?.(state.tr.setSelection(TextSelection.create(state.doc, state.selection.from, state.selection.from))); + (document.activeElement as HTMLElement)?.blur?.(); DocumentView.DeselectAll(); + return true; }); bind('Alt-Enter', () => onKey() || true); bind('Ctrl-Enter', () => onKey() || true); - bind('Cmd-a', (state: EditorState, dispatch: (tx: Transaction) => void) => { - dispatch(state.tr.setSelection(new TextSelection(state.doc.resolve(1), state.doc.resolve(state.doc.content.size - 1)))); + bind('Cmd-a', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => { + dispatch?.(state.tr.setSelection(new TextSelection(state.doc.resolve(1), state.doc.resolve(state.doc.content.size - 1)))); return true; }); bind('Cmd-?', () => { RTFMarkup.Instance.setOpen(true); return true; }); - bind('Cmd-e', (state: EditorState, dispatch: (tx: Transaction) => void) => { + bind('Cmd-e', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => { if (!state.selection.empty) { const mark = state.schema.marks.summarizeInclusive.create(); const tr = state.tr.addMark(state.selection.$from.pos, state.selection.$to.pos, mark); const content = tr.selection.content(); - tr.selection.replaceWith(tr, schema.nodes.summary.create({ visibility: false, text: content, textslice: content.toJSON() })); - dispatch(tr); + tr.selection.replaceWith(tr, schema.nodes.summary.create({ visibility: false, text: content, textslice: content.toJSON() }, undefined, state.selection.$anchor.marks() ?? [])); + dispatch?.(tr); } return true; }); - bind('Cmd-]', (state: EditorState, dispatch: (tx: Transaction) => void) => { - const resolved = state.doc.resolve(state.selection.from) as any; + bind('Cmd-]', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => { + const resolved = state.doc.resolve(state.selection.from) as ResolvedPos & { path: (Node | number)[] }; // bcz: this is bad. path is not publically visible const { tr } = state; if (resolved?.parent.type.name === 'paragraph') { - tr.setNodeMarkup(resolved.path[resolved.path.length - 4], schema.nodes.paragraph, { ...resolved.parent.attrs, align: 'right' }, resolved.parent.marks); + tr.setNodeMarkup(resolved.path[resolved.path.length - 4] as number, schema.nodes.paragraph, { ...resolved.parent.attrs, align: 'right' }, resolved.parent.marks); } else { const node = resolved.nodeAfter; const sm = state.storedMarks || undefined; @@ -207,14 +219,14 @@ export function buildKeymap>(schema: S, props: any): KeyMa tr.replaceRangeWith(state.selection.from, state.selection.from, schema.nodes.paragraph.create({ align: 'right' })).setStoredMarks([...node.marks, ...(sm || [])]); } } - dispatch(tr); + dispatch?.(tr); return true; }); - bind('Cmd-\\', (state: EditorState, dispatch: (tx: Transaction) => void) => { - const resolved = state.doc.resolve(state.selection.from) as any; + bind('Cmd-\\', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => { + const resolved = state.doc.resolve(state.selection.from) as ResolvedPos & { path: (Node | number)[] }; // bcz: this is bad. path is not publically visible const { tr } = state; if (resolved?.parent.type.name === 'paragraph') { - tr.setNodeMarkup(resolved.path[resolved.path.length - 4], schema.nodes.paragraph, { ...resolved.parent.attrs, align: 'center' }, resolved.parent.marks); + tr.setNodeMarkup(resolved.path[resolved.path.length - 4] as number, schema.nodes.paragraph, { ...resolved.parent.attrs, align: 'center' }, resolved.parent.marks); } else { const node = resolved.nodeAfter; const sm = state.storedMarks || undefined; @@ -222,14 +234,14 @@ export function buildKeymap>(schema: S, props: any): KeyMa tr.replaceRangeWith(state.selection.from, state.selection.from, schema.nodes.paragraph.create({ align: 'center' })).setStoredMarks([...node.marks, ...(sm || [])]); } } - dispatch(tr); + dispatch?.(tr); return true; }); - bind('Cmd-[', (state: EditorState, dispatch: (tx: Transaction) => void) => { - const resolved = state.doc.resolve(state.selection.from) as any; + bind('Cmd-[', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => { + const resolved = state.doc.resolve(state.selection.from) as ResolvedPos & { path: (Node | number)[] }; // bcz: this is bad. path is not publically visible const { tr } = state; if (resolved?.parent.type.name === 'paragraph') { - tr.setNodeMarkup(resolved.path[resolved.path.length - 4], schema.nodes.paragraph, { ...resolved.parent.attrs, align: 'left' }, resolved.parent.marks); + tr.setNodeMarkup(resolved.path[resolved.path.length - 4] as number, schema.nodes.paragraph, { ...resolved.parent.attrs, align: 'left' }, resolved.parent.marks); } else { const node = resolved.nodeAfter; const sm = state.storedMarks || undefined; @@ -237,16 +249,16 @@ export function buildKeymap>(schema: S, props: any): KeyMa tr.replaceRangeWith(state.selection.from, state.selection.from, schema.nodes.paragraph.create({ align: 'left' })).setStoredMarks([...node.marks, ...(sm || [])]); } } - dispatch(tr); + dispatch?.(tr); return true; }); - bind('Cmd-f', (state: EditorState, dispatch: (tx: Transaction) => void) => { + bind('Cmd-f', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => { const content = state.tr.selection.empty ? undefined : state.tr.selection.content().content.textBetween(0, state.tr.selection.content().size + 1); const newNode = schema.nodes.footnote.create({}, content ? state.schema.text(content) : undefined); const { tr } = state; tr.replaceSelectionWith(newNode); // replace insertion with a footnote. - dispatch( + dispatch?.( tr.setSelection( new NodeSelection( // select the footnote node to open its display tr.doc.resolve( @@ -259,25 +271,25 @@ export function buildKeymap>(schema: S, props: any): KeyMa return true; }); - bind('Ctrl-a', (state: EditorState, dispatch: (tx: Transaction) => void) => { - dispatch(state.tr.setSelection(new TextSelection(state.doc.resolve(1), state.doc.resolve(state.doc.content.size - 1)))); + bind('Ctrl-a', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => { + dispatch?.(state.tr.setSelection(new TextSelection(state.doc.resolve(1), state.doc.resolve(state.doc.content.size - 1)))); return true; }); // backspace = chainCommands(deleteSelection, joinBackward, selectNodeBackward); - const backspace = (state: EditorState, dispatch: (tx: Transaction) => void, view: EditorView) => { + const backspace = (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined, view?: EditorView) => { if (onKey()) return true; if (!canEdit(state)) return true; if ( !deleteSelection(state, (tx: Transaction) => { - dispatch(updateBullets(tx, schema)); + dispatch?.(updateBullets(tx, schema)); }) ) { if ( !joinBackward(state, (tx: Transaction) => { - dispatch(updateBullets(tx, schema)); - if (view.state.selection.$anchor.node(-1)?.type === schema.nodes.list_item) { + dispatch?.(updateBullets(tx, schema)); + if (view?.state.selection.$anchor.node(-1)?.type === schema.nodes.list_item) { // gets rid of an extra paragraph when joining two list items together. joinBackward(view.state, (tx2: Transaction) => view.dispatch(tx2)); } @@ -285,7 +297,7 @@ export function buildKeymap>(schema: S, props: any): KeyMa ) { if ( !selectNodeBackward(state, (tx: Transaction) => { - dispatch(updateBullets(tx, schema)); + dispatch?.(updateBullets(tx, schema)); }) ) { return false; @@ -299,7 +311,7 @@ export function buildKeymap>(schema: S, props: any): KeyMa // newlineInCode, createParagraphNear, liftEmptyBlock, splitBlock // command to break line - const enter = (state: EditorState, dispatch: (tx: Transaction) => void, view: EditorView, once = true) => { + const enter = (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined, view?: EditorView, once = true) => { if (onKey()) return true; if (!canEdit(state)) return true; @@ -311,31 +323,31 @@ export function buildKeymap>(schema: S, props: any): KeyMa !state.selection.$from.node().content.size && trange ) { - dispatch(state.tr.lift(trange, depth) as any); + dispatch?.(state.tr.lift(trange, depth)); return true; } const marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks()); - if (!newlineInCode(state, dispatch as any)) { - const olNode = view.state.selection.$anchor.node(-2); - const liNode = view.state.selection.$anchor.node(-1); + if (!newlineInCode(state, dispatch)) { + const olNode = view?.state.selection.$anchor.node(-2); + const liNode = view?.state.selection.$anchor.node(-1); // prettier-ignore if (liNode?.type === schema.nodes.list_item && !liNode.textContent && - olNode?.type === schema.nodes.ordered_list && once && view.state.selection.$from.depth === 3) + olNode?.type === schema.nodes.ordered_list && once && view?.state.selection.$from.depth === 3) { // handles case of hitting enter at then end of a top-level empty list item - the result is to create a paragraph - for (let i = 0; i < 10 && view.state.selection.$from.depth > 1 && liftListItem(schema.nodes.list_item)(view.state, view.dispatch); i++); + for (let i = 0; i < 10 && view?.state.selection.$from.depth > 1 && liftListItem(schema.nodes.list_item)(view.state, view.dispatch); i++); } else if ( - !splitListItem(schema.nodes.list_item)(state as any, (tx2: Transaction) => { + !splitListItem(schema.nodes.list_item)(state, (tx2: Transaction) => { const tx3 = updateBullets(tx2, schema); marks && tx3.ensureMarks([...marks]); marks && tx3.setStoredMarks([...marks]); - dispatch(tx3); + dispatch?.(tx3); // removes an extra paragraph created when selecting text across two list items or splitting an empty list item - !once && view.dispatch(view.state.tr.deleteRange(view.state.selection.from - 5, view.state.selection.from - 2)); + !once && view?.dispatch(view?.state.tr.deleteRange(view.state.selection.from - 5, view.state.selection.from - 2)); }) ) { - if (once && view.state.selection.$from.node(-2)?.type === schema.nodes.ordered_list && view.state.selection.$from.node(-1)?.type === schema.nodes.list_item && view.state.selection.$from.node(-1)?.textContent === '') { + if (once && view?.state.selection.$from.node(-2)?.type === schema.nodes.ordered_list && view?.state.selection.$from.node(-1)?.type === schema.nodes.list_item && view.state.selection.$from.node(-1)?.textContent === '') { // handles case of hitting enter on an empty list item which needs to create a second empty paragraph, then split it by calling enter() again view.dispatch(view.state.tr.insert(view.state.selection.from, schema.nodes.paragraph.create({}))); enter(view.state, view.dispatch, view, false); @@ -346,12 +358,12 @@ export function buildKeymap>(schema: S, props: any): KeyMa const tonode = tx3.selection.$to.node(); if (tx3.selection.to && tx3.doc.nodeAt(tx3.selection.to - 1)) { const tx4 = tx3.setNodeMarkup(tx3.selection.to - 1, tonode.type, fromattrs, tonode.marks).setStoredMarks(marks || []); - dispatch(tx4); + dispatch?.(tx4); } - if (view.state.selection.$anchor.depth > 0 && - view.state.selection.$anchor.node(view.state.selection.$anchor.depth-1).type === schema.nodes.list_item && - view.state.selection.$anchor.nodeAfter?.type === schema.nodes.text && once) { + if ((view?.state.selection.$anchor.depth ??0) > 0 && + view?.state.selection.$anchor.node(view.state.selection.$anchor.depth-1).type === schema.nodes.list_item && + view?.state.selection.$anchor.nodeAfter?.type === schema.nodes.text && once) { // if text is selected across list items, then we need to forcibly insert a new line since the splitBlock code joins the two list items. enter(view.state, dispatch, view, false); } @@ -368,14 +380,14 @@ export function buildKeymap>(schema: S, props: any): KeyMa // Command to create a blank space bind('Space', () => { - const editDoc = props.TemplateDataDocument ?? props.Document[DocData]; + const editDoc = tbox?._props.TemplateDataDocument ?? tbox?.Document[DocData]; if (editDoc && ![AclAdmin, AclAugment, AclEdit].includes(GetEffectiveAcl(editDoc))) return true; return false; }); - bind('Alt-ArrowUp', (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state) && joinUp(state, dispatch as any)); - bind('Alt-ArrowDown', (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state) && joinDown(state, dispatch as any)); - bind('Mod-BracketLeft', (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state) && lift(state, dispatch as any)); + bind('Alt-ArrowUp', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => canEdit(state) && joinUp(state, dispatch)); + bind('Alt-ArrowDown', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => canEdit(state) && joinDown(state, dispatch)); + bind('Mod-BracketLeft', (state: EditorState, dispatch: ((tx: Transaction) => void) | undefined) => canEdit(state) && lift(state, dispatch)); const cmd = chainCommands(exitCode, (state, dispatch) => { if (dispatch) { diff --git a/src/client/views/nodes/formattedText/SummaryView.tsx b/src/client/views/nodes/formattedText/SummaryView.tsx index 238267f6e..6dea891a0 100644 --- a/src/client/views/nodes/formattedText/SummaryView.tsx +++ b/src/client/views/nodes/formattedText/SummaryView.tsx @@ -1,12 +1,11 @@ import { TextSelection } from 'prosemirror-state'; -import { Fragment, Node, Slice } from 'prosemirror-model'; +import { Attrs, Fragment, Node, Slice } from 'prosemirror-model'; import * as ReactDOM from 'react-dom/client'; import * as React from 'react'; +import { EditorView } from 'prosemirror-view'; -interface ISummaryView {} // currently nothing needs to be rendered for the internal view of a summary. -// eslint-disable-next-line react/prefer-stateless-function -export class SummaryViewInternal extends React.Component { +export class SummaryViewInternal extends React.Component { render() { return null; } @@ -18,30 +17,30 @@ export class SummaryViewInternal extends React.Component { // method instead of changing prosemirror's text when the expand/elide buttons are clicked. export class SummaryView { dom: HTMLSpanElement; // container for label and value - root: any; + root: ReactDOM.Root; - constructor(node: any, view: any, getPos: any) { + constructor(node: Node, view: EditorView, getPos: () => number | undefined) { this.dom = document.createElement('span'); this.dom.className = this.className(node.attrs.visibility); - this.dom.onpointerdown = (e: any) => { + this.dom.onpointerdown = (e: PointerEvent) => { this.onPointerDown(e, node, view, getPos); }; - this.dom.onkeypress = function (e: any) { + this.dom.onkeypress = function (e: KeyboardEvent) { e.stopPropagation(); }; - this.dom.onkeydown = function (e: any) { + this.dom.onkeydown = function (e: KeyboardEvent) { e.stopPropagation(); }; - this.dom.onkeyup = function (e: any) { + this.dom.onkeyup = function (e: KeyboardEvent) { e.stopPropagation(); }; - this.dom.onmousedown = function (e: any) { + this.dom.onmousedown = function (e: MouseEvent) { e.stopPropagation(); }; const js = node.toJSON; - node.toJSON = function (...args: any[]) { - return js.apply(this, args); + node.toJSON = function (...args: unknown[]) { + return js.apply(this, args as []); }; this.root = ReactDOM.createRoot(this.dom); @@ -54,7 +53,7 @@ export class SummaryView { } selectNode() {} - updateSummarizedText(start: any, view: any) { + updateSummarizedText(start: number, view: EditorView) { const mtype = view.state.schema.marks.summarize; const mtypeInc = view.state.schema.marks.summarizeInclusive; let endPos = start; @@ -65,7 +64,7 @@ export class SummaryView { // eslint-disable-next-line no-loop-func view.state.doc.nodesBetween(start, i, (node: Node /* , pos: number, parent: Node, index: number */) => { if (node.isLeaf && !visited.has(node) && !skip) { - if (node.marks.find((m: any) => m.type === mtype || m.type === mtypeInc)) { + if (node.marks.find(m => m.type === mtype || m.type === mtypeInc)) { visited.add(node); endPos = i + node.nodeSize - 1; } else skip = true; @@ -75,21 +74,18 @@ export class SummaryView { return TextSelection.create(view.state.doc, start, endPos); } - onPointerDown = (e: any, node: any, view: any, getPos: any) => { + onPointerDown = (e: PointerEvent, node: Node, view: EditorView, getPos: () => number | undefined) => { const visible = !node.attrs.visibility; - const attrs = { ...node.attrs, visibility: visible }; - let textSelection = TextSelection.create(view.state.doc, getPos() + 1); - if (!visible) { - // update summarized text and save in attrs - textSelection = this.updateSummarizedText(getPos() + 1, view); - attrs.text = textSelection.content(); - attrs.textslice = attrs.text.toJSON(); - } + const textSelection = visible // + ? TextSelection.create(view.state.doc, (getPos() ?? 0) + 1) + : this.updateSummarizedText((getPos() ?? 0) + 1, view); // update summarized text and save in attrs + const text = textSelection.content(); + const attrs = { ...node.attrs, visibility: visible, ...(!visible ? { text, textslice: text.toJSON() } : {}) } as Attrs; view.dispatch( view.state.tr .setSelection(textSelection) // select the current summarized text (or where it will be if its collapsed) .replaceSelection(!visible ? new Slice(Fragment.fromArray([]), 0, 0) : node.attrs.text) // collapse/expand it - .setNodeMarkup(getPos(), undefined, attrs) + .setNodeMarkup(getPos() ?? 0, undefined, attrs) ); // update the attrs e.preventDefault(); e.stopPropagation(); diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 2142adac8..73c2f5eb8 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -35,7 +35,7 @@ export * from 'pdfjs-dist/build/pdf.mjs'; interface IViewerProps extends FieldViewProps { pdfBox: PDFBox; - Document: Doc; + Doc: Doc; dataDoc: Doc; layoutDoc: Doc; fieldKey: string; @@ -113,8 +113,8 @@ export class PDFViewer extends ObservableReactComponent { () => this._props.layoutDoc._layout_autoHeight, layoutAutoHeight => { if (layoutAutoHeight) { - this._props.layoutDoc._nativeHeight = NumCast(this._props.Document[this._props.fieldKey + '_nativeHeight']); - this._props.setHeight?.(NumCast(this._props.Document[this._props.fieldKey + '_nativeHeight']) * (this._props.NativeDimScaling?.() || 1)); + this._props.layoutDoc._nativeHeight = NumCast(this._props.Doc[this._props.fieldKey + '_nativeHeight']); + this._props.setHeight?.(NumCast(this._props.Doc[this._props.fieldKey + '_nativeHeight']) * (this._props.NativeDimScaling?.() || 1)); } } ); @@ -125,7 +125,7 @@ export class PDFViewer extends ObservableReactComponent { { fireImmediately: true } ); this._disposers.curPage = reaction( - () => Cast(this._props.Document._layout_curPage, 'number', null), + () => Cast(this._props.Doc._layout_curPage, 'number', null), page => page !== undefined && page !== this._pdfViewer?.currentPageNumber && this.gotoPage(page), { fireImmediately: true } ); @@ -181,7 +181,7 @@ export class PDFViewer extends ObservableReactComponent { scrollFocus = (doc: Doc, scrollTop: number, options: FocusViewOptions) => { const mainCont = this._mainCont.current; let focusSpeed: Opt; - if (doc !== this._props.Document && mainCont) { + if (doc !== this._props.Doc && mainCont) { const windowHeight = this._props.PanelHeight() / (this._props.NativeDimScaling?.() || 1); const scrollTo = ClientUtils.scrollIntoView(scrollTop, doc[Height](), NumCast(this._props.layoutDoc._layout_scrollTop), windowHeight, windowHeight * 0.1, this._scrollHeight); if (scrollTo !== undefined && scrollTo !== this._props.layoutDoc._layout_scrollTop) { @@ -216,11 +216,11 @@ export class PDFViewer extends ObservableReactComponent { { fireImmediately: true } ); this._disposers.scroll = reaction( - () => Math.abs(NumCast(this._props.Document._layout_scrollTop)), + () => Math.abs(NumCast(this._props.Doc._layout_scrollTop)), pos => { if (!this._ignoreScroll) { this._showWaiting && this.setupPdfJsViewer(); - const viewTrans = quickScroll?.loc ?? StrCast(this._props.Document._viewTransition); + const viewTrans = quickScroll?.loc ?? StrCast(this._props.Doc._viewTransition); const durationMiliStr = viewTrans.match(/([0-9]*)ms/); const durationSecStr = viewTrans.match(/([0-9.]*)s/); const duration = durationMiliStr ? Number(durationMiliStr[1]) : durationSecStr ? Number(durationSecStr[1]) * 1000 : 0; @@ -371,9 +371,9 @@ export class PDFViewer extends ObservableReactComponent { // if alt+left click, drag and annotate this._downX = e.clientX; this._downY = e.clientY; - if ((this._props.Document._freeform_scale || 1) !== 1) return; + if ((this._props.Doc._freeform_scale || 1) !== 1) return; if ((e.button !== 0 || e.altKey) && this._props.isContentActive()) { - this._setPreviewCursor?.(e.clientX, e.clientY, true, false, this._props.Document); + this._setPreviewCursor?.(e.clientX, e.clientY, true, false, this._props.Doc); } if (!e.altKey && e.button === 0 && this._props.isContentActive() && Doc.ActiveTool !== InkTool.Ink) { this._props.select(false); @@ -433,7 +433,7 @@ export class PDFViewer extends ObservableReactComponent { addDrawingAnnotation = (drawing: Doc) => { // drawing.x = this._props.pdfBox.ScreenToLocalBoxXf().TranslateX // const scaleX = this._mainCont.current.offsetWidth / boundingRect.width; - drawing.y = NumCast(drawing.y) + NumCast(this._props.Document.layout_scrollTop); + drawing.y = NumCast(drawing.y) + NumCast(this._props.Doc.layout_scrollTop); this._props.addDocument?.(drawing); }; @@ -478,7 +478,7 @@ export class PDFViewer extends ObservableReactComponent { onClick = (e: React.MouseEvent) => { this._scrollStopper?.(); if (this._setPreviewCursor && e.button === 0 && Math.abs(e.clientX - this._downX) < ClientUtils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < ClientUtils.DRAG_THRESHOLD) { - this._setPreviewCursor(e.clientX, e.clientY, false, false, this._props.Document); + this._setPreviewCursor(e.clientX, e.clientY, false, false, this._props.Doc); } // e.stopPropagation(); // bcz: not sure why this was here. We need to allow the DocumentView to get clicks to process doubleClicks }; @@ -506,7 +506,7 @@ export class PDFViewer extends ObservableReactComponent { @computed get annotationLayer() { const inlineAnnos = this.inlineTextAnnotations.sort((a, b) => NumCast(a.y) - NumCast(b.y)).filter(anno => !anno.hidden); return ( -
+
{inlineAnnos.map(anno => ( ))} @@ -597,7 +597,7 @@ export class PDFViewer extends ObservableReactComponent { onClick={this.onClick} style={{ overflowX: NumCast(this._props.layoutDoc._freeform_scale, 1) !== 1 ? 'scroll' : undefined, - height: !this._props.Document._layout_fitWidth && window.screen.width > 600 ? Doc.NativeHeight(this._props.Document) : `100%`, + height: !this._props.Doc._layout_fitWidth && window.screen.width > 600 ? Doc.NativeHeight(this._props.Doc) : `100%`, }}> {this.pdfViewerDiv} {this.annotationLayer} @@ -606,12 +606,12 @@ export class PDFViewer extends ObservableReactComponent { {!this._mainCont.current || !this._annotationLayer.current || !this.props.pdfBox.DocumentView ? null : ( Pdfjs.PixelsPerInch.PDF_TO_CSS_UNITS} - annotationLayerScrollTop={NumCast(this._props.Document._layout_scrollTop)} + annotationLayerScrollTop={NumCast(this._props.Doc._layout_scrollTop)} addDocument={this.addDocumentWrapper} docView={this.props.pdfBox.DocumentView} screenTransform={this.screenToMarqueeXf} diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 8b7e77fba..1f6e80bd1 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -27,7 +27,7 @@ const MAX_ITERATIONS = 25; const ERROR = 0.03; export interface SearchBoxItemProps { - Document: Doc; + Doc: Doc; searchString: string; isLinkSearch: boolean; matchedKeys: string[]; @@ -64,7 +64,7 @@ export class SearchBoxItem extends ObservableReactComponent }); componentWillUnmount(): void { - const doc = this._props.Document; + const doc = this._props.Doc; DocumentView.getFirstDocumentView(doc)?.ComponentView?.search?.('', undefined, true); } @@ -79,23 +79,23 @@ export class SearchBoxItem extends ObservableReactComponent render() { // eslint-disable-next-line no-use-before-define - const formattedType = SearchBox.formatType(StrCast(this._props.Document.type), StrCast(this._props.Document.type_collection)); - const { title } = this._props.Document; + const formattedType = SearchBox.formatType(StrCast(this._props.Doc.type), StrCast(this._props.Doc.type_collection)); + const { title } = this._props.Doc; return ( {title as string}
}>
this.makeLink(this._props.Document) + ? () => this.makeLink(this._props.Doc) : e => { - this.onResultClick(this._props.Document); + this.onResultClick(this._props.Doc); e.stopPropagation(); } } style={{ fontWeight: Doc.Links(this._props.linkFrom).find( - link => Doc.AreProtosEqual(Doc.getOppositeAnchor(link, this._props.linkFrom!), this._props.Document) || Doc.AreProtosEqual(DocCast(Doc.getOppositeAnchor(link, this._props.linkFrom!)?.annotationOn), this._props.Document) + link => Doc.AreProtosEqual(Doc.getOppositeAnchor(link, this._props.linkFrom!), this._props.Doc) || Doc.AreProtosEqual(DocCast(Doc.getOppositeAnchor(link, this._props.linkFrom!)?.annotationOn), this._props.Doc) ) ? 'bold' : '', @@ -449,7 +449,7 @@ export class SearchBox extends ViewBoxBaseComponent() { resultsJSX.push( { this._selectedResult = doc; })} diff --git a/src/client/views/smartdraw/StickerPalette.tsx b/src/client/views/smartdraw/StickerPalette.tsx index 080a05d42..2260d1f73 100644 --- a/src/client/views/smartdraw/StickerPalette.tsx +++ b/src/client/views/smartdraw/StickerPalette.tsx @@ -25,7 +25,7 @@ import { DrawingOptions, SmartDrawHandler } from './SmartDrawHandler'; import './StickerPalette.scss'; interface StickerPaletteProps { - Document: Doc; + Doc: Doc; } enum StickerPaletteMode { @@ -132,7 +132,7 @@ export class StickerPalette extends ObservableReactComponent { this._isLoading = true; - const prevDrawings = DocListCast(this._props.Document.$data); - this._props.Document.$data = undefined; + const prevDrawings = DocListCast(this._props.Doc.$data); + this._props.Doc.$data = undefined; SmartDrawHandler.Instance.AddDrawing = this.addDrawing; this._canInteract = false; Promise.all( @@ -164,7 +164,7 @@ export class StickerPalette extends ObservableReactComponent { this._gptRes.push(gptRes); drawing.$freeform_fitContentsToBox = true; - Doc.AddDocToList(this._props.Document, 'data', drawing); + Doc.AddDocToList(this._props.Doc, 'data', drawing); }; /** @@ -173,8 +173,8 @@ export class StickerPalette extends ObservableReactComponent { - const cIndex = NumCast(this._props.Document.carousel_index); - const focusedDrawing = DocListCast(this._props.Document.data)[cIndex]; + const cIndex = NumCast(this._props.Doc.carousel_index); + const focusedDrawing = DocListCast(this._props.Doc.data)[cIndex]; focusedDrawing.$title = this._opts.text?.match(/^(.*?)~~~.*$/)?.[1] || this._opts.text; focusedDrawing.$ai_drawing_input = this._opts.text; focusedDrawing.$ai_drawing_complexity = this._opts.complexity; @@ -313,7 +313,7 @@ export class StickerPalette extends ObservableReactComponent {this.renderCreateInput()} {this.renderCreateOptions()} - {this.renderDoc(this._props.Document, (r: DocumentView) => { + {this.renderDoc(this._props.Doc, (r: DocumentView) => { this._docCarouselView = r; })}
diff --git a/src/fields/RichTextUtils.ts b/src/fields/RichTextUtils.ts index 42dd0d432..e16073ff4 100644 --- a/src/fields/RichTextUtils.ts +++ b/src/fields/RichTextUtils.ts @@ -20,6 +20,7 @@ import { Doc, Opt } from './Doc'; import { Id } from './FieldSymbols'; import { RichTextField } from './RichTextField'; import { Cast, StrCast } from './Types'; +import { Upload } from '../server/SharedMediaTypes'; export namespace RichTextUtils { const delimiter = '\n'; @@ -127,7 +128,7 @@ export namespace RichTextUtils { return { baseUrl: embeddedObject.imageProperties!.contentUri! }; }); - const uploads = await Networking.PostToServer('/googlePhotosMediaGet', { mediaItems }); + const uploads = (await Networking.PostToServer('/googlePhotosMediaGet', { mediaItems })) as Upload.FileInformation[]; if (uploads.length !== mediaItems.length) { throw new AssertionError({ expected: mediaItems.length, actual: uploads.length, message: 'Error with internally uploading inlineObjects!' }); diff --git a/src/fields/Types.ts b/src/fields/Types.ts index 474882959..af9cb1180 100644 --- a/src/fields/Types.ts +++ b/src/fields/Types.ts @@ -60,16 +60,13 @@ export type CastCtor = ToConstructor | ListSpec; type WithoutList = T extends List ? (R extends RefField ? (R | Promise)[] : R[]) : T; export function Cast(field: FieldResult, ctor: T): FieldResult>; -// eslint-disable-next-line no-redeclare export function Cast(field: FieldResult, ctor: T, defaultVal: WithoutList>> | null): WithoutList>; -// eslint-disable-next-line no-redeclare export function Cast(field: FieldResult, ctor: T, defaultVal?: ToType | null): FieldResult> | undefined { if (field instanceof Promise) { return defaultVal === undefined ? (field.then(f => Cast(f, ctor) as any) as any) : defaultVal === null ? undefined : defaultVal; } if (field !== undefined && !(field instanceof Promise)) { if (typeof ctor === 'string') { - // eslint-disable-next-line valid-typeof if (typeof field === ctor) { return field as ToType; } @@ -140,9 +137,7 @@ export function ImageCastWithSuffix(field: FieldResult, suffix: string, defaultV } export function FieldValue>(field: FieldResult, defaultValue: U): WithoutList; -// eslint-disable-next-line no-redeclare export function FieldValue(field: FieldResult): Opt; -// eslint-disable-next-line no-redeclare export function FieldValue(field: FieldResult, defaultValue?: T): Opt { return field instanceof Promise || field === undefined ? defaultValue : field; } diff --git a/src/server/DashSession/DashSessionAgent.ts b/src/server/DashSession/DashSessionAgent.ts index 891316b80..8688ec049 100644 --- a/src/server/DashSession/DashSessionAgent.ts +++ b/src/server/DashSession/DashSessionAgent.ts @@ -213,9 +213,9 @@ export class DashSessionAgent extends AppliedSessionAgent { // indicate success or failure mainLog(`${error === null ? green('successfully dispatched') : red('failed to dispatch')} ${zipName} to ${cyan(to)}`); error && mainLog(red(error.message)); - } catch (error: any) { + } catch (error: unknown) { mainLog(red('unable to dispatch zipped backup...')); - mainLog(red(error.message)); + mainLog(red((error as { message: string }).message)); } } } -- cgit v1.2.3-70-g09d2 From 30d4432d159df87fd30382f04c66b958846652da Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 24 Mar 2025 00:52:32 -0400 Subject: major cleanup to histogram. fixing hover and types. --- .../nodes/DataVizBox/components/Histogram.tsx | 221 +++++++++++---------- src/client/views/nodes/ImageBox.tsx | 6 +- 2 files changed, 123 insertions(+), 104 deletions(-) (limited to 'src/client/views/nodes/DataVizBox/components') diff --git a/src/client/views/nodes/DataVizBox/components/Histogram.tsx b/src/client/views/nodes/DataVizBox/components/Histogram.tsx index 776d65211..55c8f37b7 100644 --- a/src/client/views/nodes/DataVizBox/components/Histogram.tsx +++ b/src/client/views/nodes/DataVizBox/components/Histogram.tsx @@ -1,5 +1,5 @@ -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { ColorPicker, EditableText, IconButton, Size, Type } from '@dash/components'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import * as d3 from 'd3'; import { IReactionDisposer, action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; @@ -12,7 +12,7 @@ import { Cast, DocCast, StrCast } from '../../../../../fields/Types'; import { Docs } from '../../../../documents/Documents'; import { undoable } from '../../../../util/UndoManager'; import { ObservableReactComponent } from '../../../ObservableReactComponent'; -import { PinProps, PinDocView } from '../../../PinFuncs'; +import { PinDocView, PinProps } from '../../../PinFuncs'; import { scaleCreatorNumerical, yAxisCreator } from '../utils/D3Utils'; import './Chart.scss'; @@ -21,7 +21,7 @@ export interface HistogramProps { layoutDoc: Doc; axes: string[]; titleCol: string; - records: { [key: string]: any }[]; + records: { [key: string]: string | number }[]; width: number; height: number; dataDoc: Doc; @@ -34,6 +34,16 @@ export interface HistogramProps { }; } +export interface HistogramData { + [key: string]: string | number; +} + +export interface RangeValues { + xMin?: number; + xMax?: number; + yMin?: number; + yMax?: number; +} @observer export class Histogram extends ObservableReactComponent { private _disposers: { [key: string]: IReactionDisposer } = {}; @@ -42,12 +52,12 @@ export class Histogram extends ObservableReactComponent { private numericalXData: boolean = false; // whether the data is organized by numbers rather than categoreis private numericalYData: boolean = false; // whether the y axis is controlled by provided data rather than frequency private maxBins = 15; // maximum number of bins that is readable on a normal sized doc - @observable _currSelected: any | undefined = undefined; // Object of selected bar - private curBarSelected: any = undefined; // histogram bin of selected bar for when just one bar is selected - private selectedData: any[] = []; // array of selected bars - private hoverOverData: any = undefined; // Selection of bar being hovered over + private curBarSelected: d3.Selection | undefined = undefined; + private selectedData: HistogramData[] = []; + private hoverOverData: HistogramData | undefined = undefined; + @observable private _currSelected: HistogramData | undefined = undefined; - constructor(props: any) { + constructor(props: HistogramProps) { super(props); makeObservable(this); } @@ -56,32 +66,38 @@ export class Histogram extends ObservableReactComponent { return !this.parentViz ? this._props.records.map((rec, i) => i) : NumListCast(this.parentViz.dataViz_selectedRows); } // returns all the data records that will be rendered by only returning those records that have been selected by the parent visualization (or all records if there is no parent) - @computed get _tableData() { + + @computed + get _tableData(): Record[] { return !this.parentViz ? this._props.records : this._tableDataIds.map(rowId => this._props.records[rowId]); } - // filters all data to just display selected data if brushed (created from an incoming link) - @computed get _histogramData() { + + @computed + get _histogramData(): HistogramData[] { if (this._props.axes.length < 1) return []; if (this._props.axes.length < 2) { const ax0 = this._props.axes[0]; - if (!/[A-Za-z-:]/.test(this._props.records[0][ax0])) { + if (!/[A-Za-z-:]/.test(this._props.records[0][ax0] as string)) { this.numericalXData = true; } - return this._tableData.map(record => ({ [ax0]: record[this._props.axes[0]] })); + return this._tableData.map(record => ({ [ax0]: record[ax0] })); } const [ax0, ax1] = this._props.axes; - if (!/[A-Za-z-:]/.test(this._props.records[0][ax0])) { + if (!/[A-Za-z-:]/.test(this._props.records[0][ax0] as string)) { this.numericalXData = true; } - if (!/[A-Za-z-:]/.test(this._props.records[0][ax1])) { + if (!/[A-Za-z-:]/.test(this._props.records[0][ax1] as string)) { this.numericalYData = true; } - return this._tableData.map(record => ({ [ax0]: record[this._props.axes[0]], [ax1]: record[this._props.axes[1]] })); + return this._tableData.map(record => ({ + [ax0]: record[ax0], + [ax1]: record[ax1], + })); } - @computed get defaultGraphTitle() { + @computed get defaultGraphTitle(): string { const [ax0, ax1] = this._props.axes; - if (this._props.axes.length < 2 || !ax1 || !/\d/.test(this._props.records[0][ax1]) || !this.numericalYData) { + if (this._props.axes.length < 2 || !ax1 || !/\d/.test(this._props.records[0][ax1] as string) || !this.numericalYData) { return ax0 + ' Histogram'; } return ax0 + ' by ' + ax1 + ' Histogram'; @@ -107,7 +123,8 @@ export class Histogram extends ObservableReactComponent { const svg = this._histogramSvg; if (svg) { const selectedDataBars = StrListCast(this._props.layoutDoc.dataViz_histogram_selectedData); - svg.selectAll('rect').attr('class', (d: any) => { + svg.selectAll('rect').attr('class', dIn => { + const d = dIn as HistogramData; let selected = false; selectedDataBars.forEach(eachSelectedData => { if (d[0] === eachSelectedData) selected = true; @@ -139,70 +156,68 @@ export class Histogram extends ObservableReactComponent { } // cleans data by converting numerical data to numbers and taking out empty cells - data = (dataSet: any) => { - const validData = dataSet.filter((d: { [x: string]: unknown }) => !Object.keys(dataSet[0]).some(key => !d[key] || isNaN(d[key] as any))); + data = (dataSet: HistogramData[]): number[] => { + const validData = dataSet.filter((d: { [x: string]: unknown }) => !Object.keys(dataSet[0]).some(key => !d[key] || isNaN(d[key] as number))); const field = dataSet[0] ? Object.keys(dataSet[0])[0] : undefined; return !field ? [] - : validData.map((d: { [x: string]: any }) => + : validData.map(d => !this.numericalXData // - ? d[field] - : +d[field!].replace(/\$/g, '').replace(/%/g, '').replace(/ { + highlightSelectedBar = (changeSelectedVariables: boolean, svg: d3.Selection, eachRectWidth: number, pointerX: number, xAxisTitle: string, yAxisTitle: string, histDataSet: HistogramData[]) => { let barCounter = -1; - const selected = svg.selectAll('.histogram-bar').filter((d: any) => { + const selected = svg.selectAll('.histogram-bar').filter(dIn => { + const d = dIn as HistogramData; barCounter++; // uses the order of bars and width of each bar to find which one the pointer is over - if (d.length && barCounter * eachRectWidth <= pointerX && pointerX <= (barCounter + 1) * eachRectWidth) { - let showSelected = this.numericalYData - ? this._histogramData.filter((data: { [x: string]: any }) => StrCast(data[xAxisTitle]).replace(/\$/g, '').replace(/%/g, '').replace(/ data[xAxisTitle].replace(/\$/g, '').replace(/%/g, '').replace(/ { - if (!sameAsAny) { - let match = true; - Object.keys(d).forEach(key => { - if (d[key] !== eachData[key]) match = false; - }); - if (match) { - sameAsAny = true; - const index = this.selectedData.indexOf(eachData); - this.selectedData.splice(index, 1); - selectedDataBars.splice(index, 1); - this._currSelected = undefined; - } - } - }); - if (!sameAsAny) { + const alreadySelected = this.selectedData.findIndex(eachData => !Object.keys(d).some(key => d[key as string] !== eachData[key])); + if (alreadySelected !== -1) { + this.selectedData.splice(alreadySelected, 1); + selectedDataBars.splice(alreadySelected, 1); + } else { this.selectedData.push(d); - selectedDataBars.push(d[0]); - this._currSelected = this.selectedData.length > 1 ? undefined : showSelected; + selectedDataBars.push(d[0] as number); } + const showSelectedLabel = (dataset: HistogramData[]) => { + const datum = dataset.lastElement(); + const datumNum = datum as unknown as number[]; + const showSelectedStart = this.numericalYData + ? this._histogramData.filter(data => StrCast(data[xAxisTitle]).replace(/\$/g, '').replace(/%/g, '').replace(/ StrCast(data[xAxisTitle]).replace(/\$/g, '').replace(/%/g, '').replace(/ + dataset.length > 1 + ? '--multiple--' + : !this.numericalXData + ? '' + datum[0] + : datum[0] !== undefined && datum[1] && datum[0] !== datum[1] + ? d3.min(datumNum) + ' to ' + d3.max(datumNum) + : !this.numericalYData + ? showSelectedStart?.[xAxisTitle] + : '' + datum[0]; + return { [xAxisTitle]: getLabel(), frequency: dataset.length > 1 ? Number.NaN : datum.length }; + }; + this._currSelected = this.selectedData.length ? showSelectedLabel(this.selectedData) : undefined; // for filtering child dataviz docs if (this._props.layoutDoc.dataViz_filterSelection) { const selectedRows = Cast(this._props.layoutDoc.dataViz_selectedRows, listSpec('number'), null); this._tableDataIds.forEach(rowID => { let match = false; - for (let i = 0; i < d.length; i++) { - console.log('Compare: ' + this._props.records[rowID][xAxisTitle].replace(/\$/g, '').replace(/%/g, '').replace(/ { }; // draws the histogram - drawChart = (dataSet: any, width: number, height: number) => { + drawChart = (dataSet: HistogramData[], width: number, height: number) => { if (dataSet?.length <= 0) return; d3.select(this._histogramRef).select('svg').remove(); d3.select(this._histogramRef).select('.tooltip').remove(); @@ -233,16 +248,16 @@ export class Histogram extends ObservableReactComponent { const endingPoint = this.numericalXData ? this.rangeVals.xMax! : numBins; // converts data into Objects - let histDataSet = dataSet.filter((d: { [x: string]: unknown }) => !Object.keys(dataSet[0]).some(key => !d[key] || isNaN(d[key] as any))); + let histDataSet = dataSet.filter((d: { [x: string]: unknown }) => !Object.keys(dataSet[0]).some(key => !d[key] || isNaN(d[key] as number))); if (!this.numericalXData) { - const histStringDataSet: { [x: string]: unknown }[] = []; + const histStringDataSet: { [x: string]: number }[] = []; if (this.numericalYData) { for (let i = 0; i < dataSet.length; i++) { - histStringDataSet.push({ [yAxisTitle]: dataSet[i][yAxisTitle], [xAxisTitle]: dataSet[i][xAxisTitle] }); + histStringDataSet.push({ [yAxisTitle]: dataSet[i][yAxisTitle] as number, [xAxisTitle]: dataSet[i][xAxisTitle] as number }); } } else { for (let i = 0; i < uniqueArr.length; i++) { - histStringDataSet.push({ [yAxisTitle]: 0, [xAxisTitle]: uniqueArr[i] }); + histStringDataSet.push({ [yAxisTitle]: 0, [xAxisTitle]: uniqueArr[i] as number }); } for (let i = 0; i < data.length; i++) { const barData = histStringDataSet.filter(each => each[xAxisTitle] == data[i]); @@ -266,9 +281,9 @@ export class Histogram extends ObservableReactComponent { .domain(this.numericalXData ? [startingPoint!, endingPoint!] : [0, numBins]) .range([0, width]); const histogram = d3 - .histogram() + .bin() .value(d => d) - .domain([startingPoint!, endingPoint!]) + .domain([startingPoint, endingPoint]) .thresholds(x.ticks(numBins)); const bins = histogram(data); let eachRectWidth = width / bins.length; @@ -294,9 +309,6 @@ export class Histogram extends ObservableReactComponent { } bins.pop(); eachRectWidth = width / bins.length; - bins.forEach(d => { - d.x0 = d.x0!; - }); xAxis = d3 .axisBottom(x) .ticks(bins.length > 1 ? bins.length - 1 : 1) @@ -330,7 +342,7 @@ export class Histogram extends ObservableReactComponent { } // y-axis const maxFrequency = this.numericalYData ? - d3.max(histDataSet, (d: any) => (d[yAxisTitle] ? Number(d[yAxisTitle]!.replace(/\$/g, '') + d3.max(histDataSet, d => (d[yAxisTitle] ? Number((d[yAxisTitle] as string).replace(/\$/g, '') .replace(/%/g, '').replace(/ d.length); // prettier-ignore const y = d3.scaleLinear().range([height, 0]); @@ -347,20 +359,11 @@ export class Histogram extends ObservableReactComponent { .call(xAxis); // click/hover - const onPointClick = action((e: any) => this.highlightSelectedBar(true, svg, eachRectWidth, d3.pointer(e)[0], xAxisTitle, yAxisTitle, histDataSet)); - const onHover = action((e: any) => { - this.highlightSelectedBar(false, svg, eachRectWidth, d3.pointer(e)[0], xAxisTitle, yAxisTitle, histDataSet); - // eslint-disable-next-line no-use-before-define - updateHighlights(); - }); - const mouseOut = action(() => { - this.hoverOverData = undefined; - // eslint-disable-next-line no-use-before-define - updateHighlights(); - }); + const updateHighlights = () => { const hoverOverBar = this.hoverOverData; const { selectedData } = this; + // eslint-disable-next-line @typescript-eslint/no-explicit-any svg.selectAll('rect').attr('class', (d: any) => { let selected = false; selectedData.forEach(eachSelectedData => { @@ -369,7 +372,18 @@ export class Histogram extends ObservableReactComponent { return (hoverOverBar && hoverOverBar[0] == d[0]) || selected ? 'histogram-bar hover' : 'histogram-bar'; }); }; - svg.on('click', onPointClick).on('mouseover', onHover).on('mouseout', mouseOut); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const onPointClick = action((e: any) => this.highlightSelectedBar(true, svg, eachRectWidth, d3.pointer(e)[0], xAxisTitle, yAxisTitle, histDataSet)); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const mouseEnter = (e: any) => { + this.highlightSelectedBar(false, svg, eachRectWidth, d3.pointer(e)[0], xAxisTitle, yAxisTitle, histDataSet); + updateHighlights(); + }; + const mouseOut = () => { + this.hoverOverData = undefined; + updateHighlights(); + }; + svg.on('click', onPointClick).on('pointerenter', mouseEnter).on('pointerleave', mouseOut); // axis titles svg.append('text') @@ -394,7 +408,7 @@ export class Histogram extends ObservableReactComponent { 'transform', this.numericalYData ? d => { - const eachData = histDataSet.filter((hData: { [x: string]: number }) => hData[xAxisTitle] == d[0]); + const eachData = histDataSet.filter((hData: HistogramData) => hData[xAxisTitle] == d[0]); const length = eachData.length ? StrCast(eachData[0][yAxisTitle]).replace(/\$/g, '').replace(/%/g, '').replace(/ { 'height', this.numericalYData ? d => { - const eachData = histDataSet.filter((hData: { [x: string]: number }) => hData[xAxisTitle] == d[0]); + const eachData = histDataSet.filter((hData: HistogramData) => hData[xAxisTitle] == d[0]); const length = eachData.length ? StrCast(eachData[0][yAxisTitle]).replace(/\$/g, '').replace(/%/g, '').replace(/ height - y(d.length) ) .attr('width', eachRectWidth) - .attr('class', selected ? d => (selected && selected[0] == d[0] ? 'histogram-bar hover' : 'histogram-bar') : () => 'histogram-bar') + .attr('class', selected ? d => (selected?.[0]?.x0 == d.x0 ? 'histogram-bar hover' : 'histogram-bar') : () => 'histogram-bar') .attr('fill', d => { let barColor; const barColors = StrListCast(this._props.layoutDoc.dataViz_histogram_barColors).map(each => each.split('::')); @@ -427,20 +441,24 @@ export class Histogram extends ObservableReactComponent { }; @action changeSelectedColor = (color: string) => { - this.curBarSelected.attr('fill', color); - const barName = StrCast(this._currSelected[this._props.axes[0]].replace(/\$/g, '').replace(/%/g, '').replace(/ each.split('::')[0] === barName && barColors.splice(barColors.indexOf(each), 1)); - barColors.push(StrCast(barName + '::' + color)); + const barColors = Cast(this._props.layoutDoc.dataViz_histogram_barColors, listSpec('string'), null); + barColors.forEach(each => each.split('::')[0] === barName && barColors.splice(barColors.indexOf(each), 1)); + barColors.push(StrCast(barName + '::' + color)); + } }; @action eraseSelectedColor = () => { - this.curBarSelected.attr('fill', this._props.layoutDoc.dataViz_histogram_defaultColor); - const barName = StrCast(this._currSelected[this._props.axes[0]].replace(/\$/g, '').replace(/%/g, '').replace(/ each.split('::')[0] === barName && barColors.splice(barColors.indexOf(each), 1)); + const barColors = Cast(this._props.layoutDoc.dataViz_histogram_barColors, listSpec('string'), null); + barColors.forEach(each => each.split('::')[0] === barName && barColors.splice(barColors.indexOf(each), 1)); + } }; // reloads the bar colors and selected bars @@ -448,14 +466,15 @@ export class Histogram extends ObservableReactComponent { const svg = this._histogramSvg; if (svg) { // bar color - svg.selectAll('rect').attr('fill', (d: any) => { + svg.selectAll('rect').attr('fill', dIn => { + const d = dIn as HistogramData; let barColor; const barColors = StrListCast(this._props.layoutDoc.dataViz_histogram_barColors).map(each => each.split('::')); barColors.forEach(each => { if (d[0] && d[0].toString() && each[0] == d[0].toString()) barColor = each[1]; else { const range = StrCast(each[0]).split(' to '); - if (Number(range[0]) <= d[0] && d[0] <= Number(range[1])) barColor = each[1]; + if (Number(range[0]) <= (d[0] as number) && (d[0] as number) <= Number(range[1])) barColor = each[1]; } }); return barColor ? StrCast(barColor) : StrCast(this._props.layoutDoc.dataViz_histogram_defaultColor); @@ -476,18 +495,18 @@ export class Histogram extends ObservableReactComponent { if (!this._props.layoutDoc.dataViz_histogram_selectedData) this._props.layoutDoc.dataViz_histogram_selectedData = new List(); let selected = 'none'; if (this._currSelected) { - curSelectedBarName = StrCast(this._currSelected![this._props.axes[0]].replace(/\$/g, '').replace(/%/g, '').replace(/ { key // - ? (selected += key + ': ' + this._currSelected[key] + ', ') + ? (selected += key + ': ' + this._currSelected?.[key] + ', ') : ''; }); selected = selected.substring(0, selected.length - 2) + ' }'; - if (this._props.titleCol !== '' && (!this._currSelected.frequency || this._currSelected.frequency < 10)) { + if (this._props.titleCol !== '' && (!this._currSelected.frequency || (this._currSelected.frequency as number) < 10)) { selected += '\n' + this._props.titleCol + ': '; this._tableData.forEach(each => { - if (this._currSelected[this._props.axes[0]] === each[this._props.axes[0]]) { + if (this._currSelected?.[this._props.axes[0]] === each[this._props.axes[0]]) { if (this._props.axes[1]) { if (this._currSelected[this._props.axes[1]] === each[this._props.axes[1]]) selected += each[this._props.titleCol] + ', '; } else selected += each[this._props.titleCol] + ', '; @@ -547,7 +566,7 @@ export class Histogram extends ObservableReactComponent { tooltip="Change Bar Color" type={Type.SEC} icon={} - selectedColor={selectedBarColor || this.curBarSelected.attr('fill')} + selectedColor={selectedBarColor || this.curBarSelected?.attr('fill')} setFinalColor={undoable(color => this.changeSelectedColor(color), 'Change Selected Bar Color')} setSelectedColor={undoable(color => this.changeSelectedColor(color), 'Change Selected Bar Color')} size={Size.XSMALL} diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index d121b492f..3b3bc808a 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -399,15 +399,15 @@ export class ImageBox extends ViewBoxAnnotatableComponent() { }; // updateIcon = () => new Promise(res => res()); - updateIcon = (usePanelDimensions?: boolean) => { + updateIcon = (/* usePanelDimensions?: boolean */) => { const contentDiv = this._mainCont; return !contentDiv ? new Promise(res => res()) : UpdateIcon( this.layoutDoc[Id] + '_icon_' + new Date().getTime(), contentDiv, - usePanelDimensions || true ? this._props.PanelWidth() : NumCast(this.layoutDoc._width), - usePanelDimensions || true ? this._props.PanelHeight() : NumCast(this.layoutDoc._height), + this._props.PanelWidth(), // usePanelDimensions ? this._props.PanelWidth() : NumCast(this.layoutDoc._width), + this._props.PanelHeight(), // usePanelDimensions ? this._props.PanelHeight() : NumCast(this.layoutDoc._height), this._props.PanelWidth(), this._props.PanelHeight(), 0, -- cgit v1.2.3-70-g09d2 From b6cf21b5a52184f89909898d292a79c57c043d7e Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 24 Mar 2025 15:16:36 -0400 Subject: further major cleanup to histograms --- .../nodes/DataVizBox/components/Histogram.tsx | 403 ++++++++------------- 1 file changed, 149 insertions(+), 254 deletions(-) (limited to 'src/client/views/nodes/DataVizBox/components') diff --git a/src/client/views/nodes/DataVizBox/components/Histogram.tsx b/src/client/views/nodes/DataVizBox/components/Histogram.tsx index 55c8f37b7..5450d03b1 100644 --- a/src/client/views/nodes/DataVizBox/components/Histogram.tsx +++ b/src/client/views/nodes/DataVizBox/components/Histogram.tsx @@ -1,11 +1,11 @@ import { ColorPicker, EditableText, IconButton, Size, Type } from '@dash/components'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import * as d3 from 'd3'; -import { IReactionDisposer, action, computed, makeObservable, observable } from 'mobx'; +import { IReactionDisposer, action, computed, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { FaFillDrip } from 'react-icons/fa'; -import { Doc, NumListCast, StrListCast } from '../../../../../fields/Doc'; +import { Doc, NumListCast } from '../../../../../fields/Doc'; import { List } from '../../../../../fields/List'; import { listSpec } from '../../../../../fields/Schema'; import { Cast, DocCast, StrCast } from '../../../../../fields/Types'; @@ -16,12 +16,14 @@ import { PinDocView, PinProps } from '../../../PinFuncs'; import { scaleCreatorNumerical, yAxisCreator } from '../utils/D3Utils'; import './Chart.scss'; +export interface HistogramData { + [key: string]: string | number; +} export interface HistogramProps { Doc: Doc; layoutDoc: Doc; axes: string[]; - titleCol: string; - records: { [key: string]: string | number }[]; + records: HistogramData[]; width: number; height: number; dataDoc: Doc; @@ -34,85 +36,90 @@ export interface HistogramProps { }; } -export interface HistogramData { - [key: string]: string | number; -} - -export interface RangeValues { - xMin?: number; - xMax?: number; - yMin?: number; - yMax?: number; -} @observer export class Histogram extends ObservableReactComponent { private _disposers: { [key: string]: IReactionDisposer } = {}; private _histogramRef: HTMLDivElement | null = null; private _histogramSvg: d3.Selection | undefined; - private numericalXData: boolean = false; // whether the data is organized by numbers rather than categoreis - private numericalYData: boolean = false; // whether the y axis is controlled by provided data rather than frequency - private maxBins = 15; // maximum number of bins that is readable on a normal sized doc - private curBarSelected: d3.Selection | undefined = undefined; - private selectedData: HistogramData[] = []; - private hoverOverData: HistogramData | undefined = undefined; - @observable private _currSelected: HistogramData | undefined = undefined; + private _numericalXData: boolean = false; // whether the data is organized by numbers rather than categoreis + private _numericalYData: boolean = false; // whether the y axis is controlled by provided data rather than frequency + private _maxBins = 15; // maximum number of bins that is readable on a normal sized doc + private _selectedBars: HistogramData[] = []; + @observable private _currSelected: { [key: string]: string | number; frequency: number } | undefined = undefined; constructor(props: HistogramProps) { super(props); makeObservable(this); } + @computed get xAxis() { + return this._props.axes[0]; + } + + @computed get yAxis() { + return this._props.axes[1]; + } + + @computed get Doc() { + return this._props.Doc; + } + @computed get layoutDoc() { + return this._props.layoutDoc; + } + @computed get _tableDataIds() { return !this.parentViz ? this._props.records.map((rec, i) => i) : NumListCast(this.parentViz.dataViz_selectedRows); } // returns all the data records that will be rendered by only returning those records that have been selected by the parent visualization (or all records if there is no parent) - @computed - get _tableData(): Record[] { + @computed get _tableData(): Record[] { return !this.parentViz ? this._props.records : this._tableDataIds.map(rowId => this._props.records[rowId]); } - @computed - get _histogramData(): HistogramData[] { + @computed get _histogramData(): HistogramData[] { if (this._props.axes.length < 1) return []; if (this._props.axes.length < 2) { - const ax0 = this._props.axes[0]; - if (!/[A-Za-z-:]/.test(this._props.records[0][ax0] as string)) { - this.numericalXData = true; + if (!/[A-Za-z-:]/.test(this._props.records[0][this.xAxis] as string)) { + this._numericalXData = true; } - return this._tableData.map(record => ({ [ax0]: record[ax0] })); + return this._tableData.map(record => ({ [this.xAxis]: record[this.xAxis] })); } - const [ax0, ax1] = this._props.axes; - if (!/[A-Za-z-:]/.test(this._props.records[0][ax0] as string)) { - this.numericalXData = true; + if (!/[A-Za-z-:]/.test(this._props.records[0][this.xAxis] as string)) { + this._numericalXData = true; } - if (!/[A-Za-z-:]/.test(this._props.records[0][ax1] as string)) { - this.numericalYData = true; + if (!/[A-Za-z-:]/.test(this._props.records[0][this.yAxis] as string)) { + this._numericalYData = true; } return this._tableData.map(record => ({ - [ax0]: record[ax0], - [ax1]: record[ax1], + [this.xAxis]: record[this.xAxis], + [this.yAxis]: record[this.yAxis], })); } @computed get defaultGraphTitle(): string { - const [ax0, ax1] = this._props.axes; - if (this._props.axes.length < 2 || !ax1 || !/\d/.test(this._props.records[0][ax1] as string) || !this.numericalYData) { - return ax0 + ' Histogram'; + if (!this.yAxis || !/\d/.test(this._props.records[0][this.yAxis] as string) || !this._numericalYData) { + return this.xAxis + ' Histogram'; } - return ax0 + ' by ' + ax1 + ' Histogram'; + return this.xAxis + ' by ' + this.yAxis + ' Histogram'; } @computed get parentViz() { return DocCast(this._props.Doc.dataViz_parentViz); } + @computed get defaultBarColor() { + return Cast(this.layoutDoc.dataViz_histogram_defaultColor, 'string', '#69b3a2'); + } + @computed get barColors() { + return Cast(this.layoutDoc.dataViz_histogram_barColors, listSpec('string'), null); + } + @computed get selectedBins() { + return Cast(this.layoutDoc.dataViz_histogram_selectedBins, listSpec('number'), null); + } + @computed get rangeVals(): { xMin?: number; xMax?: number; yMin?: number; yMax?: number } { - if (this.numericalXData) { - const data = this.data(this._histogramData); - return { xMin: Math.min.apply(null, data), xMax: Math.max.apply(null, data), yMin: 0, yMax: 0 }; - } - return { xMin: 0, xMax: 0, yMin: 0, yMax: 0 }; + const data = this._numericalXData ? this.data(this._histogramData) : [0]; + return { xMin: Math.min(...data), xMax: Math.max(...data), yMin: 0, yMax: 0 }; } componentWillUnmount() { @@ -120,22 +127,31 @@ export class Histogram extends ObservableReactComponent { } componentDidMount() { // restore selected bars - const svg = this._histogramSvg; - if (svg) { - const selectedDataBars = StrListCast(this._props.layoutDoc.dataViz_histogram_selectedData); - svg.selectAll('rect').attr('class', dIn => { - const d = dIn as HistogramData; - let selected = false; - selectedDataBars.forEach(eachSelectedData => { - if (d[0] === eachSelectedData) selected = true; - }); - if (selected) { - this.selectedData.push(d); - return 'histogram-bar hover'; - } - return 'histogram-bar'; - }); - } + this._histogramSvg?.selectAll('rect').attr('class', dIn => { + const d = dIn as HistogramData; + if (this.selectedBins.some(selBin => d[0] === selBin)) { + this._selectedBars.push(d); + return 'histogram-bar hover'; + } + return 'histogram-bar'; + }); + // setup filters to watch selections and filter toggle + this._disposers.selection = reaction( + () => ({ filter: this.layoutDoc.dataViz_filterSelection, hists: this._selectedBars.slice(), cur: this._currSelected }), + ({ filter, hists }) => { + this.layoutDoc.dataViz_selectedRows = !filter + ? undefined + : new List( + this._tableDataIds.filter(rowID => + hists.some(h => { + const val = this._props.records[rowID][this.xAxis]; + return val == h.x0 || (+val >= +h.x0 && +val <= +h.x1); + }) + ) + ); + }, + { fireImmediately: true } + ); } // create a document anchor that stores whatever is needed to reconstruct the viewing state (selection,zoom,etc) @@ -162,73 +178,57 @@ export class Histogram extends ObservableReactComponent { return !field ? [] : validData.map(d => - !this.numericalXData // + !this._numericalXData // ? (d[field] as number) : +d[field].toString().replace(/\$/g, '').replace(/%/g, '').replace(/ | HistogramData) => '' + (Array.isArray(d) ? d[0] : d[0]); + // outlines the bar selected / hovered over highlightSelectedBar = (changeSelectedVariables: boolean, svg: d3.Selection, eachRectWidth: number, pointerX: number, xAxisTitle: string, yAxisTitle: string, histDataSet: HistogramData[]) => { let barCounter = -1; - const selected = svg.selectAll('.histogram-bar').filter(dIn => { + let hoverOverBar: HistogramData | undefined; + svg.selectAll('.histogram-bar').filter(dIn => { const d = dIn as HistogramData; barCounter++; // uses the order of bars and width of each bar to find which one the pointer is over if (d.length && (barCounter * eachRectWidth <= pointerX + 1 || (!barCounter && pointerX <= 0)) && pointerX - 1 <= (barCounter + 1) * eachRectWidth) { if (changeSelectedVariables) { // for when a bar is selected - not just hovered over - const selectedDataBars = Cast(this._props.layoutDoc.dataViz_histogram_selectedData, listSpec('number'), null); - const alreadySelected = this.selectedData.findIndex(eachData => !Object.keys(d).some(key => d[key as string] !== eachData[key])); + const alreadySelected = this._selectedBars.findIndex(eachData => !Object.keys(d).some(key => d[key] !== eachData[key])); if (alreadySelected !== -1) { - this.selectedData.splice(alreadySelected, 1); - selectedDataBars.splice(alreadySelected, 1); + this._selectedBars.splice(alreadySelected, 1); + this.selectedBins.splice(alreadySelected, 1); } else { - this.selectedData.push(d); - selectedDataBars.push(d[0] as number); + this._selectedBars.push(d); + this.selectedBins.push(d[0] as number); } const showSelectedLabel = (dataset: HistogramData[]) => { const datum = dataset.lastElement(); const datumNum = datum as unknown as number[]; - const showSelectedStart = this.numericalYData + const showSelectedStart = this._numericalYData ? this._histogramData.filter(data => StrCast(data[xAxisTitle]).replace(/\$/g, '').replace(/%/g, '').replace(/ StrCast(data[xAxisTitle]).replace(/\$/g, '').replace(/%/g, '').replace(/ - dataset.length > 1 - ? '--multiple--' - : !this.numericalXData - ? '' + datum[0] - : datum[0] !== undefined && datum[1] && datum[0] !== datum[1] + const selectionLabel = dataset.length > 1 + ? dataset.map(dd => this.barLabel(dd)).join('::') + : !this._numericalXData + ? this.barLabel(d) + : datum[0] !== undefined && datum[1] && datum[0] !== datum[1] ? d3.min(datumNum) + ' to ' + d3.max(datumNum) - : !this.numericalYData - ? showSelectedStart?.[xAxisTitle] - : '' + datum[0]; - return { [xAxisTitle]: getLabel(), frequency: dataset.length > 1 ? Number.NaN : datum.length }; + : !this._numericalYData + ? showSelectedStart?.[xAxisTitle] + : this.barLabel(d); // prettier-ignore + return { [xAxisTitle]: selectionLabel, frequency: dataset.length > 1 ? Number.NaN : datum.length } as { [key: string]: string | number; frequency: number }; }; - this._currSelected = this.selectedData.length ? showSelectedLabel(this.selectedData) : undefined; - - // for filtering child dataviz docs - if (this._props.layoutDoc.dataViz_filterSelection) { - const selectedRows = Cast(this._props.layoutDoc.dataViz_selectedRows, listSpec('number'), null); - this._tableDataIds.forEach(rowID => { - let match = false; - for (let i = 0; i < Object.keys(d).length; i++) { - if ((this._props.records[rowID][xAxisTitle] as string).replace(/\$/g, '').replace(/%/g, '').replace(/ { const data = this.data(dataSet); const xAxisTitle = Object.keys(dataSet[0])[0]; - const yAxisTitle = this.numericalYData ? Object.keys(dataSet[0])[1] : 'frequency'; + const yAxisTitle = this._numericalYData ? Object.keys(dataSet[0])[1] : 'frequency'; const uniqueArr: unknown[] = [...new Set(data)]; - let numBins = this.numericalXData && Number.isInteger(data[0]) ? this.rangeVals.xMax! - this.rangeVals.xMin! : uniqueArr.length; - let translateXAxis = !this.numericalXData || numBins < this.maxBins ? width / (numBins + 1) / 2 : 0; - if (numBins > this.maxBins) numBins = this.maxBins; - const startingPoint = this.numericalXData ? this.rangeVals.xMin! : 0; - const endingPoint = this.numericalXData ? this.rangeVals.xMax! : numBins; + let numBins = this._numericalXData && Number.isInteger(data[0]) ? this.rangeVals.xMax! - this.rangeVals.xMin! : uniqueArr.length; + let translateXAxis = !this._numericalXData || numBins < this._maxBins ? width / (numBins + 1) / 2 : 0; + if (numBins > this._maxBins) numBins = this._maxBins; + const startingPoint = this._numericalXData ? this.rangeVals.xMin! : 0; + const endingPoint = this._numericalXData ? this.rangeVals.xMax! : numBins; // converts data into Objects let histDataSet = dataSet.filter((d: { [x: string]: unknown }) => !Object.keys(dataSet[0]).some(key => !d[key] || isNaN(d[key] as number))); - if (!this.numericalXData) { + if (!this._numericalXData) { const histStringDataSet: { [x: string]: number }[] = []; - if (this.numericalYData) { + if (this._numericalYData) { for (let i = 0; i < dataSet.length; i++) { histStringDataSet.push({ [yAxisTitle]: dataSet[i][yAxisTitle] as number, [xAxisTitle]: dataSet[i][xAxisTitle] as number }); } @@ -278,7 +278,7 @@ export class Histogram extends ObservableReactComponent { .attr('transform', 'translate(' + this._props.margin.left + ',' + this._props.margin.top + ')')); let x = d3 .scaleLinear() - .domain(this.numericalXData ? [startingPoint!, endingPoint!] : [0, numBins]) + .domain(this._numericalXData ? [startingPoint!, endingPoint!] : [0, numBins]) .range([0, width]); const histogram = d3 .bin() @@ -294,7 +294,7 @@ export class Histogram extends ObservableReactComponent { // more calculations based on bins // x-axis - if (!this.numericalXData) { + if (!this._numericalXData) { // reorganize to match data if the data is strings rather than numbers // uniqueArr.sort() histDataSet.sort(); @@ -341,15 +341,15 @@ export class Histogram extends ObservableReactComponent { x.range([0, width - eachRectWidth]); } // y-axis - const maxFrequency = this.numericalYData ? - d3.max(histDataSet, d => (d[yAxisTitle] ? Number((d[yAxisTitle] as string).replace(/\$/g, '') - .replace(/%/g, '').replace(/ (d[yAxisTitle] ? + Number(StrCast(d[yAxisTitle]).replace(/\$/g, '').replace(/%/g, '').replace(/ d.length); // prettier-ignore const y = d3.scaleLinear().range([height, 0]); - y.domain([0, +maxFrequency!]); + y.domain([0, maxFrequency ?? 0]); const yAxis = d3.axisLeft(y).ticks(maxFrequency!); - if (this.numericalYData) { - const yScale = scaleCreatorNumerical(0, Number(maxFrequency), height, 0); + if (this._numericalYData) { + const yScale = scaleCreatorNumerical(0, maxFrequency ?? 0, height, 0); yAxisCreator(svg.append('g'), width, yScale); } else { svg.append('g').call(yAxis); @@ -360,30 +360,13 @@ export class Histogram extends ObservableReactComponent { // click/hover - const updateHighlights = () => { - const hoverOverBar = this.hoverOverData; - const { selectedData } = this; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - svg.selectAll('rect').attr('class', (d: any) => { - let selected = false; - selectedData.forEach(eachSelectedData => { - if (d[0] === eachSelectedData[0]) selected = true; - }); - return (hoverOverBar && hoverOverBar[0] == d[0]) || selected ? 'histogram-bar hover' : 'histogram-bar'; - }); - }; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const updateHighlights = (hoverOverBar?: HistogramData) => svg.selectAll('rect').attr('class', (d: any) => 'histogram-bar' + (hoverOverBar?.[0] == d[0] || this._selectedBars.some(hist => d[0] === hist[0]) ? ' hover' : '')); // eslint-disable-next-line @typescript-eslint/no-explicit-any const onPointClick = action((e: any) => this.highlightSelectedBar(true, svg, eachRectWidth, d3.pointer(e)[0], xAxisTitle, yAxisTitle, histDataSet)); // eslint-disable-next-line @typescript-eslint/no-explicit-any - const mouseEnter = (e: any) => { - this.highlightSelectedBar(false, svg, eachRectWidth, d3.pointer(e)[0], xAxisTitle, yAxisTitle, histDataSet); - updateHighlights(); - }; - const mouseOut = () => { - this.hoverOverData = undefined; - updateHighlights(); - }; - svg.on('click', onPointClick).on('pointerenter', mouseEnter).on('pointerleave', mouseOut); + const mouseEnter = (e: any) => updateHighlights(this.highlightSelectedBar(false, svg, eachRectWidth, d3.pointer(e)[0], xAxisTitle, yAxisTitle, histDataSet)); + svg.on('click', onPointClick).on('pointerenter', mouseEnter).on('pointerleave', updateHighlights); // axis titles svg.append('text') @@ -399,138 +382,54 @@ export class Histogram extends ObservableReactComponent { d3.format('.0f'); // draw bars - const selected = this.selectedData; + const selected = this._selectedBars; svg.selectAll('rect') .data(bins) .enter() .append('rect') - .attr( - 'transform', - this.numericalYData + .attr('transform', this._numericalYData ? d => { const eachData = histDataSet.filter((hData: HistogramData) => hData[xAxisTitle] == d[0]); const length = eachData.length ? StrCast(eachData[0][yAxisTitle]).replace(/\$/g, '').replace(/%/g, '').replace(/ 'translate(' + x(d.x0!) + ',' + y(d.length) + ')' - ) - .attr( - 'height', - this.numericalYData + : d => 'translate(' + x(d.x0!) + ',' + y(d.length) + ')') + .attr('height', this._numericalYData ? d => { - const eachData = histDataSet.filter((hData: HistogramData) => hData[xAxisTitle] == d[0]); + const eachData = histDataSet.filter(hData => hData[xAxisTitle] == d[0]); const length = eachData.length ? StrCast(eachData[0][yAxisTitle]).replace(/\$/g, '').replace(/%/g, '').replace(/ height - y(d.length) - ) + : d => height - y(d.length)) .attr('width', eachRectWidth) .attr('class', selected ? d => (selected?.[0]?.x0 == d.x0 ? 'histogram-bar hover' : 'histogram-bar') : () => 'histogram-bar') - .attr('fill', d => { - let barColor; - const barColors = StrListCast(this._props.layoutDoc.dataViz_histogram_barColors).map(each => each.split('::')); - barColors.forEach(each => { - if (d[0] && d[0].toString() && each[0] == d[0].toString()) barColor = each[1]; - else { - const range = StrCast(each[0]).split(' to '); - if (Number(range[0]) <= d[0] && d[0] <= Number(range[1])) barColor = each[1]; - } - }); - return barColor ? StrCast(barColor) : StrCast(this._props.layoutDoc.dataViz_histogram_defaultColor); - }); - }; - - @action changeSelectedColor = (color: string) => { - if (this.curBarSelected) { - this.curBarSelected.attr('fill', color); - const barName = StrCast((this._currSelected![this._props.axes[0]] as string).replace(/\$/g, '').replace(/%/g, '').replace(/ each.split('::')[0] === barName && barColors.splice(barColors.indexOf(each), 1)); - barColors.push(StrCast(barName + '::' + color)); - } + .attr('fill', d => this.barColors?.map(bar => bar.split('::')).find(([barLabel]) => barLabel === this.barLabel(d))?.[1] ?? this.defaultBarColor); // prettier-ignore }; - @action eraseSelectedColor = () => { - if (this.curBarSelected) { - this.curBarSelected.attr('fill', this._props.layoutDoc.dataViz_histogram_defaultColor as string | number); - const barName = StrCast((this._currSelected![this._props.axes[0]] as string).replace(/\$/g, '').replace(/%/g, '').replace(/ each.split('::')[0] === barName && barColors.splice(barColors.indexOf(each), 1)); - } - }; - - // reloads the bar colors and selected bars - updateSavedUI = () => { - const svg = this._histogramSvg; - if (svg) { - // bar color - svg.selectAll('rect').attr('fill', dIn => { - const d = dIn as HistogramData; - let barColor; - const barColors = StrListCast(this._props.layoutDoc.dataViz_histogram_barColors).map(each => each.split('::')); - barColors.forEach(each => { - if (d[0] && d[0].toString() && each[0] == d[0].toString()) barColor = each[1]; - else { - const range = StrCast(each[0]).split(' to '); - if (Number(range[0]) <= (d[0] as number) && (d[0] as number) <= Number(range[1])) barColor = each[1]; - } - }); - return barColor ? StrCast(barColor) : StrCast(this._props.layoutDoc.dataViz_histogram_defaultColor); - }); - } + @action changeSelectedColor = (color: string, erase?: boolean) => { + if (!this.barColors) this.layoutDoc.dataViz_histogram_barColors = new List(); + this._selectedBars.map(this.barLabel).forEach(barName => { + this.barColors.forEach(bar => bar.split('::')[0] === barName && this.barColors.splice(this.barColors.indexOf(bar), 1)); + !erase && this.barColors.push(barName + '::' + color); + }); }; render() { - this.updateSavedUI(); - this._histogramData; - let curSelectedBarName = ''; - let titleAccessor = 'dataViz_histogram_title'; - if (this._props.axes.length === 2) titleAccessor = titleAccessor + this._props.axes[0] + '-' + this._props.axes[1]; - else if (this._props.axes.length > 0) titleAccessor += this._props.axes[0]; - if (!this._props.layoutDoc[titleAccessor]) this._props.layoutDoc[titleAccessor] = this.defaultGraphTitle; - if (!this._props.layoutDoc.dataViz_histogram_defaultColor) this._props.layoutDoc.dataViz_histogram_defaultColor = '#69b3a2'; - if (!this._props.layoutDoc.dataViz_histogram_barColors) this._props.layoutDoc.dataViz_histogram_barColors = new List(); - if (!this._props.layoutDoc.dataViz_histogram_selectedData) this._props.layoutDoc.dataViz_histogram_selectedData = new List(); - let selected = 'none'; - if (this._currSelected) { - curSelectedBarName = StrCast((this._currSelected![this._props.axes[0]] as string).replace(/\$/g, '').replace(/%/g, '').replace(/ { - key // - ? (selected += key + ': ' + this._currSelected?.[key] + ', ') - : ''; - }); - selected = selected.substring(0, selected.length - 2) + ' }'; - if (this._props.titleCol !== '' && (!this._currSelected.frequency || (this._currSelected.frequency as number) < 10)) { - selected += '\n' + this._props.titleCol + ': '; - this._tableData.forEach(each => { - if (this._currSelected?.[this._props.axes[0]] === each[this._props.axes[0]]) { - if (this._props.axes[1]) { - if (this._currSelected[this._props.axes[1]] === each[this._props.axes[1]]) selected += each[this._props.titleCol] + ', '; - } else selected += each[this._props.titleCol] + ', '; - } - }); - selected = selected.slice(0, -1).slice(0, -1); - } - } - let selectedBarColor; - const barColors = StrListCast(this._props.layoutDoc.histogramBarColors).map(each => each.split('::')); - barColors.forEach(each => { - each[0] === curSelectedBarName && (selectedBarColor = each[1]); - }); + if (!this.selectedBins) this.layoutDoc.dataViz_histogram_selectedBins = new List(); + + const titleAccessor = 'dataViz_histogram_title ' + this.xAxis + (this.yAxis ? '-' + this._props.axes[1] : ''); + const selected = !this._currSelected ? 'none' : '{ ' + Object.keys(this._currSelected).map(key => key ? key + ': ' + this._currSelected?.[key]:'').join(", ") + ' }'; // prettier-ignore + const curSelectedBarName = this._selectedBars.length && this.barLabel(this._selectedBars.lastElement()); //.[this.xAxis]).replace(/\$/g, '').replace(/%/g, '').replace(/ bar.split('::'))?.find(([barLabel]) => barLabel === curSelectedBarName)?.[1]; if (this._histogramData.length > 0 || !this.parentViz) { return this._props.axes.length >= 1 ? (
{ - this._props.layoutDoc[titleAccessor] = val as string; - }), + action(val => (this.layoutDoc[titleAccessor] = val)), 'Change Graph Title' )} color="black" @@ -542,13 +441,9 @@ export class Histogram extends ObservableReactComponent { tooltip="Change Default Bar Color" type={Type.SEC} icon={} - selectedColor={StrCast(this._props.layoutDoc.dataViz_histogram_defaultColor)} - setFinalColor={undoable(color => { - this._props.layoutDoc.dataViz_histogram_defaultColor = color; - }, 'Change Default Bar Color')} - setSelectedColor={undoable(color => { - this._props.layoutDoc.dataViz_histogram_defaultColor = color; - }, 'Change Default Bar Color')} + selectedColor={this.defaultBarColor} + setFinalColor={undoable(color => (this.layoutDoc.dataViz_histogram_defaultColor = color), 'Change Default Bar Color')} + setSelectedColor={undoable(color => (this.layoutDoc.dataViz_histogram_defaultColor = color), 'Change Default Bar Color')} size={Size.XSMALL} />
@@ -566,9 +461,9 @@ export class Histogram extends ObservableReactComponent { tooltip="Change Bar Color" type={Type.SEC} icon={} - selectedColor={selectedBarColor || this.curBarSelected?.attr('fill')} - setFinalColor={undoable(color => this.changeSelectedColor(color), 'Change Selected Bar Color')} - setSelectedColor={undoable(color => this.changeSelectedColor(color), 'Change Selected Bar Color')} + selectedColor={selectedBarColor} + setFinalColor={undoable(this.changeSelectedColor, 'Change Selected Bar Color')} + setSelectedColor={undoable(this.changeSelectedColor, 'Change Selected Bar Color')} size={Size.XSMALL} />   @@ -578,7 +473,7 @@ export class Histogram extends ObservableReactComponent { color="black" type={Type.SEC} tooltip="Revert to the default bar color" // - onClick={undoable(this.eraseSelectedColor, 'Change Selected Bar Color')} + onClick={undoable(() => this.changeSelectedColor(this.defaultBarColor, true), 'Change Selected Bar Color')} />
) : null} -- cgit v1.2.3-70-g09d2 From 78ac87b8acf63079071e5e8805692ed8c30042ce Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 23 Apr 2025 22:02:36 -0400 Subject: lots of typechecking fixes. --- .../apis/google_docs/GooglePhotosClientUtils.ts | 2 +- src/client/util/CalendarManager.tsx | 2 +- src/client/util/DocumentManager.ts | 8 +++--- src/client/util/LinkManager.ts | 3 +- src/client/util/ReplayMovements.ts | 6 ++-- src/client/util/ScriptManager.ts | 9 ++---- src/client/util/SearchUtil.ts | 5 ++-- .../util/reportManager/ReportManagerComponents.tsx | 4 +-- src/client/views/DashboardView.tsx | 28 +++++++++---------- src/client/views/InkStrokeProperties.ts | 8 +++--- src/client/views/InkingStroke.tsx | 12 ++++---- src/client/views/PropertiesButtons.tsx | 23 ++++++++-------- .../views/PropertiesDocBacklinksSelector.tsx | 8 ++---- src/client/views/PropertiesDocContextSelector.tsx | 4 +-- src/client/views/UndoStack.tsx | 5 +--- src/client/views/animationtimeline/Region.tsx | 32 ++++++++++------------ src/client/views/animationtimeline/Track.tsx | 24 ++++++++-------- src/client/views/collections/CollectionMenu.tsx | 4 +-- .../collections/CollectionNoteTakingViewColumn.tsx | 2 +- .../views/collections/CollectionPileView.tsx | 1 - .../collections/CollectionStackedTimeline.tsx | 2 +- .../views/collections/CollectionTreeView.tsx | 8 +++--- .../views/collections/FlashcardPracticeUI.tsx | 2 +- src/client/views/collections/TreeView.tsx | 4 +-- .../CollectionFreeFormLayoutEngines.tsx | 2 +- .../collectionFreeForm/FaceCollectionBox.tsx | 13 +++++---- .../collectionSchema/SchemaColumnHeader.tsx | 2 +- .../collectionSchema/SchemaTableCell.tsx | 18 ++++++------ src/client/views/linking/LinkMenuGroup.tsx | 5 ++-- src/client/views/linking/LinkMenuItem.tsx | 4 +-- .../views/newlightbox/ExploreView/ExploreView.tsx | 4 +-- src/client/views/newlightbox/NewLightboxView.tsx | 7 ++--- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 16 +++++------ .../views/nodes/DataVizBox/SchemaCSVPopUp.tsx | 6 ++-- .../nodes/DataVizBox/components/Histogram.tsx | 17 ++++++------ .../nodes/DataVizBox/components/LineChart.tsx | 25 +++++++++++------ .../views/nodes/DataVizBox/components/TableBox.tsx | 2 +- src/client/views/nodes/EquationBox.tsx | 1 - src/client/views/nodes/FieldView.tsx | 7 +++-- src/client/views/nodes/FunctionPlotBox.tsx | 11 ++++---- src/client/views/nodes/ImageBox.tsx | 2 +- .../views/nodes/MapBox/DirectionsAnchorMenu.tsx | 2 +- src/client/views/nodes/calendarBox/CalendarBox.tsx | 3 +- .../nodes/chatbot/chatboxcomponents/ChatBox.tsx | 20 ++++++++------ .../views/nodes/chatbot/tools/GetDocsTool.ts | 5 +++- .../views/nodes/chatbot/vectorstore/Vectorstore.ts | 15 +++++----- .../views/nodes/formattedText/DailyJournal.tsx | 2 +- src/client/views/nodes/scrapbook/ScrapbookBox.tsx | 2 +- src/client/views/pdf/Annotation.tsx | 7 +++-- src/client/views/search/FaceRecognitionHandler.tsx | 6 ++-- src/fields/Doc.ts | 2 +- src/fields/Types.ts | 2 ++ 52 files changed, 207 insertions(+), 207 deletions(-) (limited to 'src/client/views/nodes/DataVizBox/components') diff --git a/src/client/apis/google_docs/GooglePhotosClientUtils.ts b/src/client/apis/google_docs/GooglePhotosClientUtils.ts index 4b86a8341..15fd6313a 100644 --- a/src/client/apis/google_docs/GooglePhotosClientUtils.ts +++ b/src/client/apis/google_docs/GooglePhotosClientUtils.ts @@ -311,7 +311,7 @@ export namespace GooglePhotos { sources .filter(source => ImageCast(Doc.GetProto(source).data)) .forEach(async source => { - const data = ImageCast(Doc.GetProto(source).data); + const data = ImageCast(Doc.GetProto(source).data)!; const url = data.url.href; const target = Doc.MakeEmbedding(source); const description = parseDescription(target, descriptionKey); diff --git a/src/client/util/CalendarManager.tsx b/src/client/util/CalendarManager.tsx index 4e321a893..b50e39c02 100644 --- a/src/client/util/CalendarManager.tsx +++ b/src/client/util/CalendarManager.tsx @@ -162,7 +162,7 @@ export class CalendarManager extends ObservableReactComponent { console.log('my calendars: ', Doc.MyCalendars); if (this.creationType === 'new-calendar') { - Doc.AddDocToList(Doc.MyCalendars, 'data', calendar); // add to new calendar to dashboard calendars + Doc.MyCalendars && Doc.AddDocToList(Doc.MyCalendars, 'data', calendar); // add to new calendar to dashboard calendars } } }; diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index ad57c2a62..3bae2881e 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -173,10 +173,10 @@ export class DocumentManager { while ( containerDocContext.length && DocCast(containerDocContext[0]?.embedContainer) && - DocCast(containerDocContext[0].embedContainer)?._type_collection !== CollectionViewType.Docking && + DocCast(containerDocContext[0].embedContainer)!._type_collection !== CollectionViewType.Docking && (includeExistingViews || !DocumentManager.Instance.getDocumentView(containerDocContext[0])) ) { - containerDocContext = [Cast(containerDocContext[0].embedContainer, Doc, null), ...containerDocContext]; + containerDocContext = [DocCast(containerDocContext[0].embedContainer)!, ...containerDocContext]; } return containerDocContext; } @@ -248,7 +248,7 @@ export class DocumentManager { finished?: (changed: boolean) => void // func called after focusing on target with flag indicating whether anything needed to be done. ) => { const options = optionsIn; - Doc.RemoveDocFromList(Doc.MyRecentlyClosed, undefined, targetDoc); + Doc.MyRecentlyClosed && Doc.RemoveDocFromList(Doc.MyRecentlyClosed, undefined, targetDoc); const docContextPath = DocumentManager.GetContextPath(targetDoc, true); if (docContextPath.some(doc => doc.hidden)) options.toggleTarget = false; let activatedTab = false; @@ -272,7 +272,7 @@ export class DocumentManager { })); if (options.openLocation?.includes(OpenWhere.lightbox)) { // even if we found the document view, if the target is a lightbox, we try to open it in the lightbox to preserve lightbox semantics (eg, there's only one active doc in the lightbox) - const target = DocCast(targetDoc.annotationOn, targetDoc); + const target = DocCast(targetDoc.annotationOn, targetDoc)!; const compView = this.getDocumentView(DocCast(target.embedContainer))?.ComponentView; if ((compView?.addDocTab ?? compView?._props.addDocTab)?.(target, options.openLocation)) { await new Promise(waitres => { diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 344e2e4c0..d8e0c4cbe 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -217,7 +217,8 @@ export class LinkManager { } // finds the opposite anchor of a given anchor in a link - public static getOppositeAnchor(linkDoc: Doc, anchor: Doc): Doc | undefined { + public static getOppositeAnchor(linkDoc: Doc | undefined, anchor: Doc | undefined): Doc | undefined { + if (!linkDoc || !anchor) return undefined; const id = LinkManager.anchorIndex(linkDoc, anchor); const a1 = DocCast(linkDoc.link_anchor_1); const a2 = DocCast(linkDoc.link_anchor_2); diff --git a/src/client/util/ReplayMovements.ts b/src/client/util/ReplayMovements.ts index 62a09a8bc..4f0423342 100644 --- a/src/client/util/ReplayMovements.ts +++ b/src/client/util/ReplayMovements.ts @@ -108,9 +108,11 @@ export class ReplayMovements { movements.forEach((movement, i) => { if (typeof movement.doc === 'string') { - movements[i].doc = IdToDoc(movement.doc); - if (!movements[i].doc) { + const doc = IdToDoc(movement.doc); + if (!doc) { console.log('ERROR: tracked doc not found'); + } else { + movements[i].doc = doc; } } }); diff --git a/src/client/util/ScriptManager.ts b/src/client/util/ScriptManager.ts index 9158f6c0b..8c7f88bf6 100644 --- a/src/client/util/ScriptManager.ts +++ b/src/client/util/ScriptManager.ts @@ -1,7 +1,6 @@ -import { Doc, DocListCast } from '../../fields/Doc'; +import { Doc, DocListCast, StrListCast } from '../../fields/Doc'; import { List } from '../../fields/List'; -import { listSpec } from '../../fields/Schema'; -import { Cast, StrCast } from '../../fields/Types'; +import { StrCast } from '../../fields/Types'; import { Docs } from '../documents/Documents'; import { ScriptingGlobals } from './ScriptingGlobals'; @@ -10,7 +9,6 @@ export class ScriptManager { // eslint-disable-next-line no-use-before-define private static _instance: ScriptManager; public static get Instance(): ScriptManager { - // eslint-disable-next-line no-return-assign return this._instance || (this._instance = new this()); } private constructor() { @@ -58,7 +56,7 @@ export class ScriptManager { public static addScriptToGlobals(scriptDoc: Doc): void { ScriptingGlobals.removeGlobal(StrCast(scriptDoc.name)); - const params = Cast(scriptDoc['data-params'], listSpec('string'), []); + const params = StrListCast(scriptDoc['data-params']); const paramNames = params.reduce((o: string, p: string) => { let out = o; if (params.indexOf(p) === params.length - 1) { @@ -69,7 +67,6 @@ export class ScriptManager { return out; }, '' as string); - // eslint-disable-next-line no-new-func const f = new Function(paramNames, StrCast(scriptDoc.script)); Object.defineProperty(f, 'name', { value: StrCast(scriptDoc.name), writable: false }); diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts index e4adcaa7e..fc3bb99ab 100644 --- a/src/client/util/SearchUtil.ts +++ b/src/client/util/SearchUtil.ts @@ -13,7 +13,7 @@ export namespace SearchUtil { const blockedKeys = matchKeyNames ? [] : Object.entries(DocOptions) - .filter(([, info]: [string, FInfo]) => !info?.searchable()) + .filter(([, info]: [string, FieldType | FInfo | undefined]) => (info instanceof FInfo ? !info.searchable() : true)) .map(([key]) => key); const exact = queryIn.startsWith('='); @@ -22,8 +22,7 @@ export namespace SearchUtil { const results = new ObservableMap(); if (collectionDoc) { const docs = DocListCast(collectionDoc[Doc.LayoutDataKey(collectionDoc)]); - // eslint-disable-next-line @typescript-eslint/ban-types - const docIDs: String[] = []; + const docIDs: string[] = []; SearchUtil.foreachRecursiveDoc(docs, (depth: number, doc: Doc) => { const dtype = StrCast(doc.type) as DocumentType; if (dtype && !blockedTypes.includes(dtype) && !docIDs.includes(doc[Id]) && depth >= 0) { diff --git a/src/client/util/reportManager/ReportManagerComponents.tsx b/src/client/util/reportManager/ReportManagerComponents.tsx index 92f877859..80653779e 100644 --- a/src/client/util/reportManager/ReportManagerComponents.tsx +++ b/src/client/util/reportManager/ReportManagerComponents.tsx @@ -1,5 +1,3 @@ -/* eslint-disable react/require-default-props */ -/* eslint-disable prefer-destructuring */ /* eslint-disable no-use-before-define */ import * as React from 'react'; import ReactMarkdown from 'react-markdown'; @@ -299,7 +297,7 @@ export function IssueView({ issue }: IssueViewProps) { )} - + {issueBody} diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx index f61f6db18..3ceb23ffd 100644 --- a/src/client/views/DashboardView.tsx +++ b/src/client/views/DashboardView.tsx @@ -113,12 +113,12 @@ export class DashboardView extends ObservableReactComponent { getDashboards = (whichGroup: DashboardGroup) => { if (whichGroup === DashboardGroup.MyDashboards) { - return DocListCast(Doc.MyDashboards.data).filter(dashboard => dashboard.$author === ClientUtils.CurrentUserEmail()); + return DocListCast(Doc.MyDashboards?.data).filter(dashboard => dashboard.$author === ClientUtils.CurrentUserEmail()); } - return DocListCast(Doc.MySharedDocs.data_dashboards).filter(doc => doc.dockingConfig); + return DocListCast(Doc.MySharedDocs?.data_dashboards).filter(doc => doc.dockingConfig); }; - isUnviewedSharedDashboard = (dashboard: Doc) => !DocListCast(Doc.MySharedDocs.viewed).includes(dashboard); + isUnviewedSharedDashboard = (dashboard: Doc) => !DocListCast(Doc.MySharedDocs?.viewed).includes(dashboard); @undoBatch createNewDashboard = (name: string, background?: string) => { @@ -155,7 +155,7 @@ export class DashboardView extends ObservableReactComponent { @action openNewDashboardModal = () => { this.openModal = true; - this.setNewDashboardName(`Dashboard ${DocListCast(Doc.MyDashboards.data).length + 1}`); + this.setNewDashboardName(`Dashboard ${DocListCast(Doc.MyDashboards?.data).length + 1}`); }; _downX: number = 0; @@ -191,7 +191,7 @@ export class DashboardView extends ObservableReactComponent {