diff options
Diffstat (limited to 'src/client/views/nodes')
| -rw-r--r-- | src/client/views/nodes/DataVizBox/DataVizBox.scss | 4 | ||||
| -rw-r--r-- | src/client/views/nodes/DataVizBox/DataVizBox.tsx | 79 | ||||
| -rw-r--r-- | src/client/views/nodes/DataVizBox/components/Chart.scss | 50 | ||||
| -rw-r--r-- | src/client/views/nodes/DataVizBox/components/TableBox.scss | 22 | ||||
| -rw-r--r-- | src/client/views/nodes/DataVizBox/components/TableBox.tsx | 215 | ||||
| -rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 48 | ||||
| -rw-r--r-- | src/client/views/nodes/ImageBox.tsx | 1 | ||||
| -rw-r--r-- | src/client/views/nodes/LinkAnchorBox.tsx | 4 | ||||
| -rw-r--r-- | src/client/views/nodes/MapBox/MapBox.tsx | 10 | ||||
| -rw-r--r-- | src/client/views/nodes/PDFBox.tsx | 2 | ||||
| -rw-r--r-- | src/client/views/nodes/WebBox.tsx | 20 | ||||
| -rw-r--r-- | src/client/views/nodes/formattedText/FormattedTextBox.tsx | 1 |
12 files changed, 206 insertions, 250 deletions
diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.scss b/src/client/views/nodes/DataVizBox/DataVizBox.scss index 385ef5a1b..430446c06 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.scss +++ b/src/client/views/nodes/DataVizBox/DataVizBox.scss @@ -1,9 +1,9 @@ .dataviz { - overflow: scroll; + overflow: auto; height: 100%; width: 100%; - .datatype-button{ + .datatype-button { display: flex; flex-direction: row; } diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index 8f32e2ba4..299494c83 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -36,7 +36,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { // all CSV records in the dataset (that aren't an empty row) @computed.struct get records() { var records = DataVizBox.dataset.get(CsvCast(this.rootDoc[this.fieldKey]).url.href); - return records?.filter(record => Object.keys(record).some(key => record[key])); + return records?.filter(record => Object.keys(record).some(key => record[key])) ?? []; } // currently chosen visualization type: line, pie, histogram, table @@ -110,72 +110,37 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { // toggles for user to decide which chart type to view the data in renderVizView = () => { - const width = this.props.PanelWidth() * 0.9; - const height = (this.props.PanelHeight() - 32) /* height of 'change view' button */ * 0.9; - const margin = { top: 10, right: 25, bottom: 75, left: 45 }; - if (this.records) { - switch (this.dataVizView) { - case DataVizView.TABLE: - return <TableBox layoutDoc={this.layoutDoc} records={this.records} axes={this.axes} height={height} width={width} margin={margin} rootDoc={this.rootDoc} docView={this.props.DocumentView} selectAxes={this.selectAxes} />; - case DataVizView.LINECHART: - return ( - <LineChart - layoutDoc={this.layoutDoc} - ref={r => (this._vizRenderer = r ?? undefined)} - height={height} - width={width} - fieldKey={this.fieldKey} - margin={margin} - rootDoc={this.rootDoc} - axes={this.axes} - records={this.records} - dataDoc={this.dataDoc} - /> - ); - case DataVizView.HISTOGRAM: - return ( - <Histogram - layoutDoc={this.layoutDoc} - ref={r => (this._vizRenderer = r ?? undefined)} - height={height} - width={width} - fieldKey={this.fieldKey} - margin={margin} - rootDoc={this.rootDoc} - axes={this.axes} - records={this.records} - dataDoc={this.dataDoc} - /> - ); - case DataVizView.PIECHART: - return ( - <PieChart - layoutDoc={this.layoutDoc} - ref={r => (this._vizRenderer = r ?? undefined)} - height={height} - width={width} - fieldKey={this.fieldKey} - margin={margin} - rootDoc={this.rootDoc} - axes={this.axes} - records={this.records} - dataDoc={this.dataDoc} - /> - ); - } + const sharedProps = { + rootDoc: this.rootDoc, + layoutDoc: this.layoutDoc, + records: this.records, + axes: this.axes, + height: (this.props.PanelHeight() - 32) /* height of 'change view' button */ * 0.9, + width: this.props.PanelWidth() * 0.9, + margin: { top: 10, right: 25, bottom: 75, left: 45 }, + }; + if (!this.records.length) return 'no data/visualization'; + switch (this.dataVizView) { + case DataVizView.TABLE: + return <TableBox {...sharedProps} docView={this.props.DocumentView} selectAxes={this.selectAxes} />; + case DataVizView.LINECHART: + return <LineChart {...sharedProps} dataDoc={this.dataDoc} fieldKey={this.fieldKey} ref={r => (this._vizRenderer = r ?? undefined)} />; + case DataVizView.HISTOGRAM: + return <Histogram {...sharedProps} dataDoc={this.dataDoc} fieldKey={this.fieldKey} ref={r => (this._vizRenderer = r ?? undefined)} />; + case DataVizView.PIECHART: + return <PieChart {...sharedProps} dataDoc={this.dataDoc} fieldKey={this.fieldKey} ref={r => (this._vizRenderer = r ?? undefined)} />; } - return 'no data/visualization'; }; render() { - return !this.records?.length ? ( + return !this.records.length ? ( // displays how to get data into the DataVizBox if its empty <div className="start-message">To create a DataViz box, either import / drag a CSV file into your canvas or copy a data table and use the command 'ctrl + p' to bring the data table to your canvas.</div> ) : ( <div className="dataViz" style={{ - pointerEvents: this.props.isContentActive() === true ? "all" : "none" + pointerEvents: this.props.isContentActive() === true ? 'all' : 'none', }} onWheel={e => e.stopPropagation()} ref={r => diff --git a/src/client/views/nodes/DataVizBox/components/Chart.scss b/src/client/views/nodes/DataVizBox/components/Chart.scss index 50dfe7f05..c788a64c2 100644 --- a/src/client/views/nodes/DataVizBox/components/Chart.scss +++ b/src/client/views/nodes/DataVizBox/components/Chart.scss @@ -1,3 +1,4 @@ +@import '../../../global/globalCssVariables'; .chart-container { display: flex; flex-direction: column; @@ -6,10 +7,10 @@ margin-top: 10px; overflow-y: visible; - .graph{ + .graph { overflow: visible; } - .graph-title{ + .graph-title { align-items: center; font-size: larger; display: flex; @@ -29,7 +30,7 @@ position: relative; margin-bottom: -35px; } - .selected-data{ + .selected-data { align-items: center; text-align: center; display: flex; @@ -44,10 +45,10 @@ stroke-width: 2px; } } - - .histogram-bar{ + + .histogram-bar { outline: thin solid black; - &.hover{ + &.hover { outline: 3px solid black; outline-offset: -3px; } @@ -91,13 +92,34 @@ .tableBox { display: flex; flex-direction: column; -} -.table-container{ - overflow: scroll; - margin: 5px; - margin-left: 25px; - margin-right: 10px; - margin-bottom: 0; + cursor: default; + height: calc(100% - 40px); // bcz: hack 40px is the size of the button rows + .tableBox-container { + overflow: scroll; + margin: 5px; + margin-left: 25px; + margin-right: 10px; + margin-bottom: 0; + .tableBox-table { + height: 100%; + width: 100%; + .tableBox-row { + cursor: pointer; + .tableBox-cell { + text-overflow: ellipsis; + width: 100%; + white-space: pre; + max-width: 150; + overflow: hidden; + } + } + } + tr td { + height: $DATA_VIZ_TABLE_ROW_HEIGHT !important; // bcz: hack. you can't set a <tr> height directly, but you can set the height of all of it's <td>s. So this is the height of a tableBox row. + padding: 0 !important; + vertical-align: middle !important; + } + } } .selectAll-buttons { display: flex; @@ -106,4 +128,4 @@ margin-top: 5px; margin-right: 10px; float: right; -}
\ No newline at end of file +} diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.scss b/src/client/views/nodes/DataVizBox/components/TableBox.scss deleted file mode 100644 index 1264d6a46..000000000 --- a/src/client/views/nodes/DataVizBox/components/TableBox.scss +++ /dev/null @@ -1,22 +0,0 @@ -.table { - margin-top: 10px; - margin-bottom: 10px; - margin-left: 10px; - margin-right: 10px; -} - -.table-row { - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; - padding: 5px; - border-bottom: 1px solid #ccc; -} - -.table-container { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; -}
\ No newline at end of file diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx index 4d6027ca4..b88389de6 100644 --- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx +++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx @@ -1,5 +1,5 @@ import { Button, Type } from 'browndash-components'; -import { action, computed, IReactionDisposer, reaction } from 'mobx'; +import { action, computed, IReactionDisposer, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, Field, NumListCast } from '../../../../../fields/Doc'; @@ -10,6 +10,7 @@ import { emptyFunction, setupMoveUpEvents, Utils } from '../../../../../Utils'; import { DragManager } from '../../../../util/DragManager'; import { DocumentView } from '../../DocumentView'; import { DataVizView } from '../DataVizBox'; +import { DATA_VIZ_TABLE_ROW_HEIGHT } from '../../../global/globalCssVariables.scss'; import './Chart.scss'; interface TableBoxProps { @@ -32,10 +33,17 @@ interface TableBoxProps { @observer export class TableBox extends React.Component<TableBoxProps> { _inputChangedDisposer?: IReactionDisposer; + _containerRef: HTMLDivElement | null = null; + + @observable _scrollTop = -1; + @observable _tableHeight = 0; + @observable _tableContainerHeight = 0; + componentDidMount() { // if the tableData changes (ie., when records are selected by the parent (input) visulization), // then we need to remove any selected rows that are no longer part of the visualized dataset. this._inputChangedDisposer = reaction(() => this._tableData.slice(), this.filterSelectedRowsDown, { fireImmediately: true }); + this.handleScroll(); } componentWillUnmount() { this._inputChangedDisposer?.(); @@ -67,6 +75,89 @@ export class TableBox extends React.Component<TableBoxProps> { this.props.layoutDoc.dataViz_highlitedRows = new List<number>(highlighted.filter(rowId => this._tableDataIds.includes(rowId))); // filters through highlighted to remove guids that were removed in the incoming data }; + @computed get viewScale() { + return this.props.docView?.()?.props.ScreenToLocalTransform().Scale || 1; + } + @computed get rowHeight() { + return (this.viewScale * this._tableHeight) / this._tableDataIds.length; + } + @computed get startID() { + return this.rowHeight ? Math.floor(this._scrollTop / this.rowHeight) : 0; + } + @computed get endID() { + return Math.ceil(this.startID + (this._tableContainerHeight * this.viewScale) / (this.rowHeight || 1)); + } + @action handleScroll = () => { + if (!this.props.docView?.()?.ContentDiv?.hidden) { + this._scrollTop = this._containerRef?.scrollTop ?? 0; + } + }; + @action + tableRowClick = (e: React.MouseEvent, rowId: number) => { + const highlited = Cast(this.props.layoutDoc.dataViz_highlitedRows, listSpec('number'), null); + const selected = Cast(this.props.layoutDoc.dataViz_selectedRows, listSpec('number'), null); + if (e.metaKey) { + // highlighting a row + if (highlited?.includes(rowId)) highlited.splice(highlited.indexOf(rowId), 1); + else highlited?.push(rowId); + if (!selected?.includes(rowId)) selected?.push(rowId); + } else { + // selecting a row + if (selected?.includes(rowId)) { + if (highlited?.includes(rowId)) highlited.splice(highlited.indexOf(rowId), 1); + selected.splice(selected.indexOf(rowId), 1); + } else selected?.push(rowId); + } + e.stopPropagation(); + }; + + columnPointerDown = (e: React.PointerEvent, col: string) => { + const downX = e.clientX; + const downY = e.clientY; + setupMoveUpEvents( + {}, + e, + e => { + // dragging off a column to create a brushed DataVizBox + const sourceAnchorCreator = () => this.props.docView?.()!.rootDoc!; + const targetCreator = (annotationOn: Doc | undefined) => { + const embedding = Doc.MakeEmbedding(this.props.docView?.()!.rootDoc!); + embedding._dataViz = DataVizView.TABLE; + embedding._dataViz_axes = new List<string>([col, col]); + embedding._dataViz_parentViz = this.props.rootDoc; + 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; + }; + if (this.props.docView?.() && !Utils.isClick(e.clientX, e.clientY, downX, downY, Date.now())) { + DragManager.StartAnchorAnnoDrag(e.target instanceof HTMLElement ? [e.target] : [], new DragManager.AnchorAnnoDragData(this.props.docView()!, sourceAnchorCreator, targetCreator), downX, downY, { + dragComplete: e => { + if (!e.aborted && e.annoDragData && e.annoDragData.linkSourceDoc && e.annoDragData.dropDocument && e.linkDocument) { + e.linkDocument.link_displayLine = true; + e.linkDocument.link_matchEmbeddings = true; + e.linkDocument.link_displayArrow = true; + // e.annoDragData.linkSourceDoc.followLinkToggle = e.annoDragData.dropDocument.annotationOn === this.props.rootDoc; + // e.annoDragData.linkSourceDoc.followLinkZoom = false; + } + }, + }); + return true; + } + return false; + }, + emptyFunction, + action(e => { + const newAxes = this.props.axes; + if (newAxes.includes(col)) newAxes.splice(newAxes.indexOf(col), 1); + else if (newAxes.length > 1) newAxes[1] = col; + else newAxes.push(col); + this.props.selectAxes(newAxes); + }) + ); + }; + render() { if (this._tableData.length > 0) { return ( @@ -84,21 +175,33 @@ export class TableBox extends React.Component<TableBoxProps> { <Button onClick={action(() => (this.props.layoutDoc.dataViz_selectedRows = new List<number>()))} text="Deselect All" type={Type.SEC} color={'black'} /> </div> <div - className="table-container" - style={{ height: this.props.height }} - ref={r => - r?.addEventListener( - 'wheel', // if scrollTop is 0, then don't let wheel trigger scroll on any container (which it would since onScroll won't be triggered on this) - (e: WheelEvent) => { - if (!r.scrollTop && e.deltaY <= 0) e.preventDefault(); - e.stopPropagation(); - }, - { passive: false } - ) - }> - <table className="table"> + className={`tableBox-container ${this.columns[0]}`} + style={{ height: '100%', overflow: 'auto' }} + onScroll={this.handleScroll} + ref={action((r: HTMLDivElement | null) => { + this._containerRef = r; + if (!this.props.docView?.()?.ContentDiv?.hidden && r) { + this._tableContainerHeight = r.getBoundingClientRect().height ?? 0; + r.addEventListener( + 'wheel', // if scrollTop is 0, then don't let wheel trigger scroll on any container (which it would since onScroll won't be triggered on this) + (e: WheelEvent) => { + if (!r.scrollTop && e.deltaY <= 0) e.preventDefault(); + e.stopPropagation(); + }, + { passive: false } + ); + } + })}> + <table + className="tableBox-table" + ref={action((r: HTMLTableElement | null) => { + if (!this.props.docView?.()?.ContentDiv?.hidden && r) { + this._tableHeight = r?.getBoundingClientRect().height ?? 0; + } + })}> + <div style={{ height: this.startID * Number(DATA_VIZ_TABLE_ROW_HEIGHT) }} /> <thead> - <tr className="table-row"> + <tr> {this.columns.map(col => ( <th key={this.columns.indexOf(col)} @@ -108,58 +211,7 @@ export class TableBox extends React.Component<TableBoxProps> { fontWeight: 'bolder', border: '3px solid black', }} - onPointerDown={e => { - const downX = e.clientX; - const downY = e.clientY; - setupMoveUpEvents( - {}, - e, - e => { - // dragging off a column to create a brushed DataVizBox - const sourceAnchorCreator = () => this.props.docView?.()!.rootDoc!; - const targetCreator = (annotationOn: Doc | undefined) => { - const embedding = Doc.MakeEmbedding(this.props.docView?.()!.rootDoc!); - embedding._dataViz = DataVizView.TABLE; - embedding._dataViz_axes = new List<string>([col, col]); - embedding._dataViz_parentViz = this.props.rootDoc; - embedding.annotationOn = annotationOn; //this.props.docView?.()!.rootDoc!; - embedding.histogramBarColors = Field.Copy(this.props.layoutDoc.histogramBarColors); - embedding.defaultHistogramColor = this.props.layoutDoc.defaultHistogramColor; - embedding.pieSliceColors = Field.Copy(this.props.layoutDoc.pieSliceColors); - return embedding; - }; - if (this.props.docView?.() && !Utils.isClick(e.clientX, e.clientY, downX, downY, Date.now())) { - DragManager.StartAnchorAnnoDrag( - e.target instanceof HTMLElement ? [e.target] : [], - new DragManager.AnchorAnnoDragData(this.props.docView()!, sourceAnchorCreator, targetCreator), - downX, - downY, - { - dragComplete: e => { - if (!e.aborted && e.annoDragData && e.annoDragData.linkSourceDoc && e.annoDragData.dropDocument && e.linkDocument) { - e.linkDocument.link_displayLine = true; - e.linkDocument.link_matchEmbeddings = true; - e.linkDocument.link_displayArrow = true; - // e.annoDragData.linkSourceDoc.followLinkToggle = e.annoDragData.dropDocument.annotationOn === this.props.rootDoc; - // e.annoDragData.linkSourceDoc.followLinkZoom = false; - } - }, - } - ); - return true; - } - return false; - }, - emptyFunction, - action(e => { - const newAxes = this.props.axes; - if (newAxes.includes(col)) newAxes.splice(newAxes.indexOf(col), 1); - else if (newAxes.length > 1) newAxes[1] = col; - else newAxes.push(col); - this.props.selectAxes(newAxes); - }) - ); - }}> + onPointerDown={e => this.columnPointerDown(e, col)}> {col} </th> ))} @@ -167,44 +219,27 @@ export class TableBox extends React.Component<TableBoxProps> { </thead> <tbody> {this._tableDataIds - ?.map(rowId => ({ record: this.props.records[rowId], rowId })) - .map(({ record, rowId }) => ( + .filter(rowId => this.startID <= rowId && rowId <= this.endID) + ?.map(rowId => ( <tr key={rowId} - className="table-row" - onClick={action(e => { - const highlited = Cast(this.props.layoutDoc.dataViz_highlitedRows, listSpec('number'), null); - const selected = Cast(this.props.layoutDoc.dataViz_selectedRows, listSpec('number'), null); - if (e.metaKey) { - // highlighting a row - if (highlited?.includes(rowId)) highlited.splice(highlited.indexOf(rowId), 1); - else highlited?.push(rowId); - if (!selected?.includes(rowId)) selected?.push(rowId); - } else { - // selecting a row - if (selected?.includes(rowId)) { - if (highlited?.includes(rowId)) highlited.splice(highlited.indexOf(rowId), 1); - selected.splice(selected.indexOf(rowId), 1); - } else selected?.push(rowId); - } - e.stopPropagation(); - })} + className={`tableBox-row ${this.columns[0]}`} + onClick={e => this.tableRowClick(e, rowId)} style={{ background: NumListCast(this.props.layoutDoc.dataViz_highlitedRows).includes(rowId) ? 'lightYellow' : NumListCast(this.props.layoutDoc.dataViz_selectedRows).includes(rowId) ? 'lightgrey' : '', - width: '110%', }}> {this.columns.map(col => { - // each cell const colSelected = this.props.axes.length > 1 ? this.props.axes[0] == col || this.props.axes[1] == col : this.props.axes.length > 0 ? this.props.axes[0] == col : false; return ( <td key={this.columns.indexOf(col)} style={{ border: colSelected ? '3px solid black' : '1px solid black', fontWeight: colSelected ? 'bolder' : 'normal' }}> - {record[col]} + <div className="tableBox-cell">{this.props.records[rowId][col]}</div> </td> ); })} </tr> ))} </tbody> + <div style={{ height: (this._tableDataIds.length - this.endID) * Number(DATA_VIZ_TABLE_ROW_HEIGHT) }} /> </table> </div> </div> diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index e4fc6c4a2..da665a502 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -52,6 +52,7 @@ import { LinkAnchorBox } from './LinkAnchorBox'; import { PresEffect, PresEffectDirection } from './trails'; import { PinProps, PresBox } from './trails/PresBox'; import React = require('react'); +import { KeyValueBox } from './KeyValueBox'; const { Howl } = require('howler'); interface Window { @@ -114,7 +115,7 @@ export interface DocComponentView { getAnchor?: (addAsAnnotation: boolean, pinData?: PinProps) => Doc; // returns an Anchor Doc that represents the current state of the doc's componentview (e.g., the current playhead location of a an audio/video box) restoreView?: (viewSpec: Doc) => boolean; scrollPreview?: (docView: DocumentView, doc: Doc, focusSpeed: number, options: DocFocusOptions) => Opt<number>; // returns the duration of the focus - brushView?: (view: { width: number; height: number; panX: number; panY: number }, transTime: number) => void; + brushView?: (view: { width: number; height: number; panX: number; panY: number }, transTime: number) => void; // highlight a region of a view (used by freeforms) getView?: (doc: Doc) => Promise<Opt<DocumentView>>; // returns a nested DocumentView for the specified doc or undefined addDocTab?: (doc: Doc, where: OpenWhere) => boolean; // determines how to add a document - used in following links to open the target ina local lightbox addDocument?: (doc: Doc | Doc[], annotationKey?: string) => boolean; // add a document (used only by collections) @@ -156,7 +157,6 @@ export interface DocumentViewSharedProps { contentBounds?: () => undefined | { x: number; y: number; r: number; b: number }; fitContentsToBox?: () => boolean; // used by freeformview to fit its contents to its panel. corresponds to _freeform_fitContentsToBox property on a Document suppressSetHeight?: boolean; - thumbShown?: () => boolean; setContentView?: (view: DocComponentView) => any; CollectionFreeFormDocumentView?: () => CollectionFreeFormDocumentView; PanelWidth: () => number; @@ -299,10 +299,11 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BorderRounding); } @computed get widgetDecorations() { - return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Decorations + (this.props.isSelected() ? ':selected' : '')); + TraceMobx(); + return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Decorations); } @computed get backgroundBoxColor() { - return this.thumbShown() ? undefined : this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor + ':box'); + return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor + ':box'); } @computed get docContents() { return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.DocContents); @@ -317,7 +318,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps return this.props?.styleProvider?.(this.layoutDoc, this.props, StyleProp.TitleHeight) || 0; } @computed get pointerEvents(): 'none' | 'all' | 'visiblePainted' | undefined { - return this.props.styleProvider?.(this.Document, this.props, StyleProp.PointerEvents + (this.props.isSelected() ? ':selected' : '')); + return this.props.styleProvider?.(this.Document, this.props, StyleProp.PointerEvents); } @computed get finalLayoutKey() { return StrCast(this.Document.layout_fieldKey, 'layout'); @@ -884,23 +885,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps : undefined; } isContentActive = (): boolean | undefined => this._isContentActive; - @observable _retryThumb = 1; - @computed get _thumbShown() { - const childHighlighted = () => false; - // Array.from(Doc.highlightedDocs.keys()) - // .concat(Array.from(Doc.brushManager.BrushedDoc.keys())) - // .some(doc => Doc.AreProtosEqual(DocCast(doc.annotationOn), this.rootDoc)); - const childOverlayed = () => Array.from(DocumentManager._overlayViews).some(view => Doc.AreProtosEqual(view.rootDoc, this.rootDoc)); - return !this.props.LayoutTemplateString && - !this.isContentActive() && - LightboxView.LightboxDoc !== this.rootDoc && - this.thumb && - !Doc.AreProtosEqual(DocumentLinksButton.StartLink, this.rootDoc) && - ((!childHighlighted() && !childOverlayed() && !Doc.isBrushedHighlightedDegree(this.rootDoc)) || this.rootDoc._type_collection === CollectionViewType.Docking) - ? true - : false; - } - thumbShown = () => this._thumbShown; childFilters = () => [...this.props.childFilters(), ...StrListCast(this.layoutDoc.childFilters)]; /// disable pointer events on content when there's an enabled onClick script (but not the browse script) and the contents aren't forced active, or if contents are marked inactive @@ -918,25 +902,11 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps pointerEvents: (isInk ? 'none' : this.contentPointerEvents()) ?? 'all', height: this.headerMargin ? `calc(100% - ${this.headerMargin}px)` : undefined, }}> - {!this._retryThumb || !this.thumbShown() ? null : ( - <img - style={{ background: 'white', top: 0, position: 'relative' }} - src={this.thumb} // + '?d=' + (new Date()).getTime()} - width={this.props.PanelWidth()} - height={this.props.PanelHeight()} - onError={(e: any) => { - setTimeout(action(() => (this._retryThumb = 0))); - // prettier-ignore - setTimeout(action(() => (this._retryThumb = 1)), 150 ); - }} - /> - )} <DocumentContentsView key={1} {...this.props} pointerEvents={this.contentPointerEvents} docViewPath={this.props.viewPath} - thumbShown={this.thumbShown} setContentView={this.setContentView} childFilters={this.childFilters} NativeDimScaling={this.props.NativeDimScaling} @@ -994,7 +964,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps @computed get allLinkEndpoints() { // the small blue dots that mark the endpoints of links TraceMobx(); - if (this.props.hideLinkAnchors || this.layoutDoc.layout_hideLinkAnchors || this.props.dontRegisterView || this.layoutDoc.layout_unrendered) return null; + if (this._componentView instanceof KeyValueBox || this.props.hideLinkAnchors || this.layoutDoc.layout_hideLinkAnchors || this.props.dontRegisterView || this.layoutDoc.layout_unrendered) return null; const filtered = DocUtils.FilterDocs(this.directLinks, this.props.childFilters?.() ?? [], []).filter(d => d.link_displayLine || Doc.UserDoc().showLinkLines); return filtered.map(link => ( <div className="documentView-anchorCont" key={link[Id]}> @@ -1232,10 +1202,10 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps } } @computed get highlighting() { - return this.props.styleProvider?.(this.props.Document, this.props, StyleProp.Highlighting); + return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Highlighting); } @computed get borderPath() { - return this.props.styleProvider?.(this.props.Document, this.props, StyleProp.BorderPath); + return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BorderPath); } render() { TraceMobx(); diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 1ab120af5..2f4f788d4 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -526,7 +526,6 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp } })} style={{ - display: !this.props.isContentActive() && this.props.thumbShown?.() ? 'none' : undefined, width: this.props.PanelWidth() ? undefined : `100%`, height: this.props.PanelWidth() ? undefined : `100%`, pointerEvents: this.layoutDoc._lockedPosition ? 'none' : undefined, diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index 9bcd04cf5..fd7d13655 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -28,6 +28,10 @@ export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps>() { @observable _x = 0; @observable _y = 0; + componentDidMount() { + this.props.setContentView?.(this); + } + @computed get linkSource() { return this.props.docViewPath()[this.props.docViewPath().length - 2].rootDoc; // this.props.styleProvider?.(this.dataDoc, this.props, StyleProp.LinkSource); } diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index 65c138975..50b070e7f 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -4,7 +4,7 @@ import { Button, EditableText, IconButton, Type } from 'browndash-components'; import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { Doc, DocListCast, Field, Opt } from '../../../../fields/Doc'; +import { Doc, DocListCast, Field, LinkedTo, Opt } from '../../../../fields/Doc'; import { DocCss, Highlight, Width } from '../../../../fields/DocSymbols'; import { Id } from '../../../../fields/FieldSymbols'; import { InkTool } from '../../../../fields/InkField'; @@ -251,7 +251,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps createNoteAnnotation = () => { const createFunc = undoable( action(() => { - const note = this._sidebarRef.current?.anchorMenuClick(this.getAnchor(true), ['latitude', 'longitude', '-linkedTo']); + const note = this._sidebarRef.current?.anchorMenuClick(this.getAnchor(true), ['latitude', 'longitude', LinkedTo]); if (note && this.selectedPin) { note.latitude = this.selectedPin.latitude; note.longitude = this.selectedPin.longitude; @@ -383,7 +383,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps // Removes filter Doc.setDocFilter(this.rootDoc, 'latitude', this.selectedPin.latitude, 'remove'); Doc.setDocFilter(this.rootDoc, 'longitude', this.selectedPin.longitude, 'remove'); - Doc.setDocFilter(this.rootDoc, '-linkedTo', `mapPin=${Field.toScriptString(DocCast(this.selectedPin))}`, 'remove'); + Doc.setDocFilter(this.rootDoc, LinkedTo, `mapPin=${Field.toScriptString(DocCast(this.selectedPin))}`, 'remove'); const temp = this.selectedPin; if (!this._unmounting) { @@ -415,7 +415,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps // Doc.setDocFilter(this.rootDoc, 'latitude', this.selectedPin.latitude, 'match'); // Doc.setDocFilter(this.rootDoc, 'longitude', this.selectedPin.longitude, 'match'); - Doc.setDocFilter(this.rootDoc, '-linkedTo', `mapPin=${Field.toScriptString(this.selectedPin)}`, 'check'); + Doc.setDocFilter(this.rootDoc, LinkedTo, `mapPin=${Field.toScriptString(this.selectedPin)}`, 'check'); this.recolorPin(this.selectedPin, 'green'); @@ -550,7 +550,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps // Removes filter Doc.setDocFilter(this.rootDoc, 'latitude', this.selectedPin.latitude, 'remove'); Doc.setDocFilter(this.rootDoc, 'longitude', this.selectedPin.longitude, 'remove'); - Doc.setDocFilter(this.rootDoc, '-linkedTo', `mapPin=${Field.toScriptString(DocCast(this.selectedPin))}`, 'remove'); + Doc.setDocFilter(this.rootDoc, LinkedTo, `mapPin=${Field.toScriptString(DocCast(this.selectedPin))}`, 'remove'); this.removePushpin(this.selectedPin); } diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index cf44649a2..537da5055 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -566,7 +566,6 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps className="pdfBox" onContextMenu={this.specificContextMenu} style={{ - display: this.props.thumbShown?.() ? 'none' : undefined, height: this.props.Document._layout_scrollTop && !this.Document._layout_fitWidth && window.screen.width > 600 ? (NumCast(this.Document._height) * this.props.PanelWidth()) / NumCast(this.Document._width) : undefined, }}> <div className="pdfBox-background" onPointerDown={e => this.sidebarBtnDown(e, false)} /> @@ -609,7 +608,6 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps static pdfpromise = new Map<string, Promise<Pdfjs.PDFDocumentProxy>>(); render() { TraceMobx(); - if (this.props.thumbShown?.()) return null; const pdfView = this.renderPdfView; const href = this.pdfUrl?.url.href; diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index af20ff061..58a765d61 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -94,19 +94,6 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps @computed get webField() { return Cast(this.rootDoc[this.props.fieldKey], WebField)?.url; } - @computed get webThumb() { - return ( - this.props.thumbShown?.() && - ImageCast( - this.layoutDoc['thumb-frozen'], - ImageCast( - this.layoutDoc.thumbScrollTop === this.layoutDoc._layout_scrollTop && this.layoutDoc.thumbNativeWidth === NumCast(this.layoutDoc.nativeWidth) && this.layoutDoc.thumbNativeHeight === NumCast(this.layoutDoc.nativeHeight) - ? this.layoutDoc.thumb - : undefined - ) - )?.url - ); - } constructor(props: any) { super(props); @@ -372,7 +359,6 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps @action webClipDown = (e: React.PointerEvent) => { const mainContBounds = Utils.GetScreenTransform(this._mainCont.current!); - const scale = (this.props.NativeDimScaling?.() || 1) * mainContBounds.scale; const word = getWordAtPoint(e.target, e.clientX, e.clientY); this._setPreviewCursor?.(e.clientX, e.clientY, false, true, this.rootDoc); MarqueeAnnotator.clearAnnotations(this._savedAnnotations); @@ -940,7 +926,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps width: !this.layoutDoc.layout_forceReflow ? NumCast(this.layoutDoc[this.fieldKey + '_nativeWidth']) || `100%` : '100%', transform: `scale(${this.zoomScaling()}) translate(${-NumCast(this.layoutDoc.freeform_panX)}px, ${-NumCast(this.layoutDoc.freeform_panY)}px)`, }}> - {this._hackHide || (this.webThumb && !this._webPageHasBeenRendered && LightboxView.LightboxDoc !== this.rootDoc) ? null : this.urlContent} + {this._hackHide ? null : this.urlContent} </div> ); } @@ -968,6 +954,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps return this._showSidebar || this.layoutDoc._layout_showSidebar ? true : false; } + childPointerEvents = () => (this.props.isContentActive() ? 'all' : undefined); @computed get webpage() { const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1; const pointerEvents = this.layoutDoc._lockedPosition ? 'none' : (this.props.pointerEvents?.() as any); @@ -999,7 +986,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps removeDocument={this.removeDocument} moveDocument={this.moveDocument} addDocument={this.addDocumentWrapper} - childPointerEvents={this.props.isContentActive() ? 'all' : undefined} + childPointerEvents={this.childPointerEvents} pointerEvents={this.annotationPointerEvents} /> ); @@ -1090,7 +1077,6 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps style={{ pointerEvents: this.pointerEvents(), // position: SnappingManager.GetIsDragging() ? 'absolute' : undefined, - display: !this.props.isContentActive() && this.props.thumbShown?.() ? 'none' : undefined, }}> <div className="webBox-background" style={{ backgroundColor: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor) }} /> <div diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index eab62c20b..46cd6db8f 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -2115,7 +2115,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps width: `${100 / scale}%`, height: `${100 / scale}%`, }), - // display: !this.props.isContentActive() && this.props.thumbShown?.() ? 'none' : undefined, transition: 'inherit', // overflowY: this.layoutDoc._layout_autoHeight ? "hidden" : undefined, color: this.fontColor, |
