aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx2
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx9
-rw-r--r--src/client/views/global/globalCssVariables.scss3
-rw-r--r--src/client/views/global/globalCssVariables.scss.d.ts1
-rw-r--r--src/client/views/nodes/DataVizBox/DataVizBox.scss4
-rw-r--r--src/client/views/nodes/DataVizBox/DataVizBox.tsx79
-rw-r--r--src/client/views/nodes/DataVizBox/components/Chart.scss26
-rw-r--r--src/client/views/nodes/DataVizBox/components/TableBox.scss22
-rw-r--r--src/client/views/nodes/DataVizBox/components/TableBox.tsx211
9 files changed, 175 insertions, 182 deletions
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 676e96714..3a8e8f2ef 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1082,7 +1082,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
case freeformScrollMode.Pan:
// if ctrl is selected then zoom
if (!e.ctrlKey && this.props.isContentActive(true)) {
- this.scrollPan({ deltaX: -e.deltaX, deltaY: e.shiftKey ? 0 : -Math.max(-1, Math.min(1, e.deltaY)) });
+ this.scrollPan({ deltaX: -e.deltaX, deltaY: e.shiftKey ? 0 : -e.deltaY });
break;
}
default:
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 4c502021d..a6a3280eb 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -6,10 +6,9 @@ import { Id } from '../../../../fields/FieldSymbols';
import { InkData, InkField, InkTool } from '../../../../fields/InkField';
import { List } from '../../../../fields/List';
import { RichTextField } from '../../../../fields/RichTextField';
-import { SchemaHeaderField } from '../../../../fields/SchemaHeaderField';
-import { Cast, DocCast, FieldValue, NumCast, StrCast } from '../../../../fields/Types';
+import { Cast, FieldValue, NumCast, StrCast } from '../../../../fields/Types';
import { ImageField } from '../../../../fields/URLField';
-import { distributeAcls, GetEffectiveAcl, SharingPermissions } from '../../../../fields/util';
+import { GetEffectiveAcl } from '../../../../fields/util';
import { intersectRect, lightOrDark, returnFalse, Utils } from '../../../../Utils';
import { CognitiveServices } from '../../../cognitive_services/CognitiveServices';
import { Docs, DocumentOptions, DocUtils } from '../../../documents/Documents';
@@ -24,10 +23,10 @@ import { pasteImageBitmap } from '../../nodes/WebBoxRenderer';
import { PreviewCursor } from '../../PreviewCursor';
import { SubCollectionViewProps } from '../CollectionSubView';
import { TabDocView } from '../TabDocView';
-import { TreeView } from '../TreeView';
import { MarqueeOptionsMenu } from './MarqueeOptionsMenu';
import './MarqueeView.scss';
import React = require('react');
+import { freeformScrollMode } from '../../../util/SettingsManager';
interface MarqueeViewProps {
getContainerTransform: () => Transform;
@@ -223,7 +222,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
if (!(e.nativeEvent as any).marqueeHit) {
(e.nativeEvent as any).marqueeHit = true;
// allow marquee if right click OR alt+left click OR in adding presentation slide & left key drag mode
- if (e.button === 2 || (e.button === 0 && e.altKey)) {
+ if (e.button === 2 || (e.button === 0 && (e.altKey || Doc.UserDoc().freeformScrollMode === freeformScrollMode.Pan))) {
// if (e.altKey || (MarqueeView.DragMarquee && this.props.active(true))) {
this.setPreviewCursor(e.clientX, e.clientY, true, false, this.props.Document);
// (!e.altKey) && e.stopPropagation(); // bcz: removed so that you can alt-click on button in a collection to switch link following behaviors.
diff --git a/src/client/views/global/globalCssVariables.scss b/src/client/views/global/globalCssVariables.scss
index ddd99c836..20ccd9ebd 100644
--- a/src/client/views/global/globalCssVariables.scss
+++ b/src/client/views/global/globalCssVariables.scss
@@ -74,6 +74,8 @@ $CAROUSEL3D_CENTER_SCALE: 1.3;
$CAROUSEL3D_SIDE_SCALE: 0.6;
$CAROUSEL3D_TOP: 15;
+$DATA_VIZ_TABLE_ROW_HEIGHT: 30;
+
:export {
contextMenuZindex: $contextMenu-zindex;
SCHEMA_DIVIDER_WIDTH: $SCHEMA_DIVIDER_WIDTH;
@@ -91,4 +93,5 @@ $CAROUSEL3D_TOP: 15;
CAROUSEL3D_CENTER_SCALE: $CAROUSEL3D_CENTER_SCALE;
CAROUSEL3D_SIDE_SCALE: $CAROUSEL3D_SIDE_SCALE;
CAROUSEL3D_TOP: $CAROUSEL3D_TOP;
+ DATA_VIZ_TABLE_ROW_HEIGHT: $DATA_VIZ_TABLE_ROW_HEIGHT;
}
diff --git a/src/client/views/global/globalCssVariables.scss.d.ts b/src/client/views/global/globalCssVariables.scss.d.ts
index efb702564..3db498e77 100644
--- a/src/client/views/global/globalCssVariables.scss.d.ts
+++ b/src/client/views/global/globalCssVariables.scss.d.ts
@@ -15,6 +15,7 @@ interface IGlobalScss {
CAROUSEL3D_CENTER_SCALE: string;
CAROUSEL3D_SIDE_SCALE: string;
CAROUSEL3D_TOP: string;
+ DATA_VIZ_TABLE_ROW_HEIGHT: string;
}
declare const globalCssVariables: IGlobalScss;
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..a6ce0b88c 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,22 @@
.tableBox {
display: flex;
flex-direction: column;
+ height: calc(100% - 40px); // bcz: hack 40px is the size of the button rows
+ .table {
+ height: 100%;
+ }
}
-.table-container{
+.table-container {
overflow: scroll;
margin: 5px;
margin-left: 25px;
margin-right: 10px;
margin-bottom: 0;
+ 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 +116,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..8f16df1dc 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={`table-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="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,29 @@ export class TableBox extends React.Component<TableBoxProps> {
</thead>
<tbody>
{this._tableDataIds
+ .filter(rowId => this.startID <= rowId && rowId <= this.endID)
?.map(rowId => ({ record: this.props.records[rowId], rowId }))
.map(({ record, 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={`table-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 style={{ textOverflow: 'ellipsis', width: '100%', whiteSpace: 'pre', maxWidth: 150, overflow: 'hidden' }}>{record[col]}</div>
</td>
);
})}
</tr>
))}
</tbody>
+ <div style={{ height: (this._tableDataIds.length - this.endID) * 40 }} />
</table>
</div>
</div>