aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/DataVizBox
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/DataVizBox')
-rw-r--r--src/client/views/nodes/DataVizBox/DataVizBox.tsx26
-rw-r--r--src/client/views/nodes/DataVizBox/components/Chart.scss2
-rw-r--r--src/client/views/nodes/DataVizBox/components/Histogram.tsx105
-rw-r--r--src/client/views/nodes/DataVizBox/components/LineChart.tsx70
-rw-r--r--src/client/views/nodes/DataVizBox/components/PieChart.tsx93
-rw-r--r--src/client/views/nodes/DataVizBox/components/TableBox.tsx86
6 files changed, 203 insertions, 179 deletions
diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
index 1cb0a50f3..e31c04c40 100644
--- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx
+++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
@@ -35,7 +35,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);
+ var records = DataVizBox.dataset.get(CsvCast(this.dataDoc[this.fieldKey]).url.href);
return records?.filter(record => Object.keys(record).some(key => record[key])) ?? [];
}
@@ -75,7 +75,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
};
getAnchor = (addAsAnnotation?: boolean, pinProps?: PinProps) => {
const anchor = !pinProps
- ? this.rootDoc
+ ? this.Document
: this._vizRenderer?.getAnchor(pinProps) ??
Docs.Create.ConfigDocument({
// when we clear selection -> we should have it so chartBox getAnchor returns undefined
@@ -98,31 +98,31 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
};
componentDidMount() {
- this.props.setContentView?.(this);
- if (!DataVizBox.dataset.has(CsvCast(this.rootDoc[this.fieldKey]).url.href)) this.fetchData();
+ this._props.setContentView?.(this);
+ if (!DataVizBox.dataset.has(CsvCast(this.dataDoc[this.fieldKey]).url.href)) this.fetchData();
}
fetchData = () => {
- DataVizBox.dataset.set(CsvCast(this.rootDoc[this.fieldKey]).url.href, []); // assign temporary dataset as a lock to prevent duplicate server requests
+ DataVizBox.dataset.set(CsvCast(this.dataDoc[this.fieldKey]).url.href, []); // assign temporary dataset as a lock to prevent duplicate server requests
fetch('/csvData?uri=' + this.dataUrl?.url.href) //
- .then(res => res.json().then(action(res => !res.errno && DataVizBox.dataset.set(CsvCast(this.rootDoc[this.fieldKey]).url.href, res))));
+ .then(res => res.json().then(action(res => !res.errno && DataVizBox.dataset.set(CsvCast(this.dataDoc[this.fieldKey]).url.href, res))));
};
// toggles for user to decide which chart type to view the data in
@computed get renderVizView() {
- const scale = this.props.NativeDimScaling?.() || 1;
+ const scale = this._props.NativeDimScaling?.() || 1;
const sharedProps = {
- rootDoc: this.rootDoc,
+ Document: this.Document,
layoutDoc: this.layoutDoc,
records: this.records,
axes: this.axes,
- height: (this.props.PanelHeight() / scale - 32) /* height of 'change view' button */ * 0.9,
- width: (this.props.PanelWidth() / scale) * 0.9,
+ height: (this._props.PanelHeight() / scale - 32) /* height of 'change view' button */ * 0.9,
+ width: (this._props.PanelWidth() / scale) * 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.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)}
@@ -131,7 +131,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
}
render() {
- const scale = this.props.NativeDimScaling?.() || 1;
+ const scale = this._props.NativeDimScaling?.() || 1;
return !this.records.length ? (
// displays how to get data into the DataVizBox if its empty
@@ -140,7 +140,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
<div
className="dataViz"
style={{
- pointerEvents: this.props.isContentActive() === true ? 'all' : 'none',
+ pointerEvents: this._props.isContentActive() === true ? 'all' : 'none',
width: `${100 / scale}%`,
height: `${100 / scale}%`,
transform: `scale(${scale})`,
diff --git a/src/client/views/nodes/DataVizBox/components/Chart.scss b/src/client/views/nodes/DataVizBox/components/Chart.scss
index c788a64c2..c0c0f10a2 100644
--- a/src/client/views/nodes/DataVizBox/components/Chart.scss
+++ b/src/client/views/nodes/DataVizBox/components/Chart.scss
@@ -1,4 +1,4 @@
-@import '../../../global/globalCssVariables';
+@import '../../../global/globalCssVariables.module.scss';
.chart-container {
display: flex;
flex-direction: column;
diff --git a/src/client/views/nodes/DataVizBox/components/Histogram.tsx b/src/client/views/nodes/DataVizBox/components/Histogram.tsx
index e67e2bf31..d786e84ad 100644
--- a/src/client/views/nodes/DataVizBox/components/Histogram.tsx
+++ b/src/client/views/nodes/DataVizBox/components/Histogram.tsx
@@ -1,7 +1,7 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { ColorPicker, EditableText, IconButton, Size, Type } from 'browndash-components';
import * as d3 from 'd3';
-import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
+import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { FaFillDrip } from 'react-icons/fa';
@@ -10,14 +10,14 @@ import { List } from '../../../../../fields/List';
import { listSpec } from '../../../../../fields/Schema';
import { Cast, DocCast, StrCast } from '../../../../../fields/Types';
import { Docs } from '../../../../documents/Documents';
-import { LinkManager } from '../../../../util/LinkManager';
import { undoable } from '../../../../util/UndoManager';
import { PinProps, PresBox } from '../../trails';
import { scaleCreatorNumerical, yAxisCreator } from '../utils/D3Utils';
import './Chart.scss';
+import { ObservableReactComponent } from '../../../ObservableReactComponent';
export interface HistogramProps {
- rootDoc: Doc;
+ Document: Doc;
layoutDoc: Doc;
axes: string[];
records: { [key: string]: any }[];
@@ -34,7 +34,7 @@ export interface HistogramProps {
}
@observer
-export class Histogram extends React.Component<HistogramProps> {
+export class Histogram extends ObservableReactComponent<HistogramProps> {
private _disposers: { [key: string]: IReactionDisposer } = {};
private _histogramRef: React.RefObject<HTMLDivElement> = React.createRef();
private _histogramSvg: d3.Selection<SVGGElement, unknown, null, undefined> | undefined;
@@ -46,46 +46,51 @@ export class Histogram extends React.Component<HistogramProps> {
private selectedData: any = undefined; // Selection of selected bar
private hoverOverData: any = undefined; // Selection of bar being hovered over
+ constructor(props: any) {
+ super(props);
+ makeObservable(this);
+ }
+
@computed get _tableDataIds() {
- return !this.parentViz ? this.props.records.map((rec, i) => i) : NumListCast(this.parentViz.dataViz_selectedRows);
+ 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() {
- return !this.parentViz ? this.props.records : this._tableDataIds.map(rowId => this.props.records[rowId]);
+ 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() {
- if (this.props.axes.length < 1) return [];
- if (this.props.axes.length < 2) {
- var ax0 = this.props.axes[0];
- if (/\d/.test(this.props.records[0][ax0])) {
+ if (this._props.axes.length < 1) return [];
+ if (this._props.axes.length < 2) {
+ var ax0 = this._props.axes[0];
+ if (/\d/.test(this._props.records[0][ax0])) {
this.numericalXData = true;
}
- return this._tableData.map(record => ({ [ax0]: record[this.props.axes[0]] }));
+ return this._tableData.map(record => ({ [ax0]: record[this._props.axes[0]] }));
}
- var ax0 = this.props.axes[0];
- var ax1 = this.props.axes[1];
- if (/\d/.test(this.props.records[0][ax0])) {
+ var ax0 = this._props.axes[0];
+ var ax1 = this._props.axes[1];
+ if (/\d/.test(this._props.records[0][ax0])) {
this.numericalXData = true;
}
- if (/\d/.test(this.props.records[0][ax1])) {
+ if (/\d/.test(this._props.records[0][ax1])) {
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[this._props.axes[0]], [ax1]: record[this._props.axes[1]] }));
}
@computed get defaultGraphTitle() {
- var ax0 = this.props.axes[0];
- var ax1 = this.props.axes.length > 1 ? this.props.axes[1] : undefined;
- if (this.props.axes.length < 2 || !ax1 || !/\d/.test(this.props.records[0][ax1]) || !this.numericalYData) {
+ var ax0 = this._props.axes[0];
+ var ax1 = this._props.axes.length > 1 ? this._props.axes[1] : undefined;
+ if (this._props.axes.length < 2 || !ax1 || !/\d/.test(this._props.records[0][ax1]) || !this.numericalYData) {
return ax0 + ' Histogram';
} else return ax0 + ' by ' + ax1 + ' Histogram';
}
@computed get parentViz() {
- return DocCast(this.props.rootDoc.dataViz_parentViz);
- // return LinkManager.Instance.getAllRelatedLinks(this.props.rootDoc) // out of all links
- // .filter(link => link.link_anchor_1 == this.props.rootDoc.dataViz_parentViz) // get links where this chart doc is the target of the link
+ return DocCast(this._props.Document.dataViz_parentViz);
+ // return LinkManager.Instance.getAllRelatedLinks(this._props.Document) // out of all links
+ // .filter(link => link.link_anchor_1 == this._props.Document.dataViz_parentViz) // get links where this chart doc is the target of the link
// .map(link => DocCast(link.link_anchor_1)); // then return the source of the link
}
@@ -115,16 +120,16 @@ export class Histogram extends React.Component<HistogramProps> {
const anchor = Docs.Create.ConfigDocument({
title: 'histogram doc selection' + this._currSelected,
});
- PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this.props.rootDoc);
+ PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this._props.Document);
return anchor;
};
@computed get height() {
- return this.props.height - this.props.margin.top - this.props.margin.bottom;
+ return this._props.height - this._props.margin.top - this._props.margin.bottom;
}
@computed get width() {
- return this.props.width - this.props.margin.left - this.props.margin.right;
+ return this._props.width - this._props.margin.left - this._props.margin.right;
}
// cleans data by converting numerical data to numbers and taking out empty cells
@@ -212,10 +217,10 @@ export class Histogram extends React.Component<HistogramProps> {
.select(this._histogramRef.current)
.append('svg')
.attr('class', 'graph')
- .attr('width', width + this.props.margin.right + this.props.margin.left)
- .attr('height', height + this.props.margin.top + this.props.margin.bottom)
+ .attr('width', width + this._props.margin.right + this._props.margin.left)
+ .attr('height', height + this._props.margin.top + this._props.margin.bottom)
.append('g')
- .attr('transform', 'translate(' + this.props.margin.left + ',' + this.props.margin.top + ')'));
+ .attr('transform', 'translate(' + this._props.margin.left + ',' + this._props.margin.top + ')'));
var x = d3
.scaleLinear()
.domain(this.numericalXData ? [startingPoint!, endingPoint!] : [0, numBins])
@@ -383,7 +388,7 @@ export class Histogram extends React.Component<HistogramProps> {
)
.attr('fill', d => {
var barColor;
- const barColors = StrListCast(this.props.layoutDoc.dataViz_histogram_barColors).map(each => each.split('::'));
+ 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 {
@@ -391,24 +396,24 @@ export class Histogram extends React.Component<HistogramProps> {
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);
+ return barColor ? StrCast(barColor) : StrCast(this._props.layoutDoc.dataViz_histogram_defaultColor);
});
};
@action changeSelectedColor = (color: string) => {
this.curBarSelected.attr('fill', color);
- const barName = StrCast(this._currSelected[this.props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, ''));
+ const barName = StrCast(this._currSelected[this._props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, ''));
- const barColors = Cast(this.props.layoutDoc.dataViz_histogram_barColors, listSpec('string'), null);
+ 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(/\</g, ''));
+ this.curBarSelected.attr('fill', this._props.layoutDoc.dataViz_histogram_defaultColor);
+ const barName = StrCast(this._currSelected[this._props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, ''));
- const barColors = Cast(this.props.layoutDoc.dataViz_histogram_barColors, listSpec('string'), null);
+ 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));
};
@@ -417,7 +422,7 @@ export class Histogram extends React.Component<HistogramProps> {
if (svg)
svg.selectAll('rect').attr('fill', (d: any) => {
var barColor;
- const barColors = StrListCast(this.props.layoutDoc.dataViz_histogram_barColors).map(each => each.split('::'));
+ 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 {
@@ -425,7 +430,7 @@ export class Histogram extends React.Component<HistogramProps> {
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);
+ return barColor ? StrCast(barColor) : StrCast(this._props.layoutDoc.dataViz_histogram_defaultColor);
});
};
@@ -434,14 +439,14 @@ export class Histogram extends React.Component<HistogramProps> {
this._histogramData;
var curSelectedBarName = '';
var titleAccessor: any = '';
- if (this.props.axes.length == 2) titleAccessor = 'dataViz_histogram_title' + this.props.axes[0] + '-' + this.props.axes[1];
- else if (this.props.axes.length > 0) titleAccessor = 'dataViz_histogram_title' + 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<string>();
+ if (this._props.axes.length == 2) titleAccessor = 'dataViz_histogram_title' + this._props.axes[0] + '-' + this._props.axes[1];
+ else if (this._props.axes.length > 0) titleAccessor = 'dataViz_histogram_title' + 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<string>();
var selected = 'none';
if (this._currSelected) {
- curSelectedBarName = StrCast(this._currSelected![this.props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, ''));
+ curSelectedBarName = StrCast(this._currSelected![this._props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, ''));
selected = '{ ';
Object.keys(this._currSelected).forEach(key =>
key //
@@ -451,17 +456,17 @@ export class Histogram extends React.Component<HistogramProps> {
selected = selected.substring(0, selected.length - 2) + ' }';
}
var selectedBarColor;
- var barColors = StrListCast(this.props.layoutDoc.histogramBarColors).map(each => each.split('::'));
+ var barColors = StrListCast(this._props.layoutDoc.histogramBarColors).map(each => each.split('::'));
barColors.forEach(each => each[0] === curSelectedBarName && (selectedBarColor = each[1]));
if (this._histogramData.length > 0 || !this.parentViz) {
- return this.props.axes.length >= 1 ? (
+ return this._props.axes.length >= 1 ? (
<div className="chart-container">
<div className="graph-title">
<EditableText
- val={StrCast(this.props.layoutDoc[titleAccessor])}
+ val={StrCast(this._props.layoutDoc[titleAccessor])}
setVal={undoable(
- action(val => (this.props.layoutDoc[titleAccessor] = val as string)),
+ action(val => (this._props.layoutDoc[titleAccessor] = val as string)),
'Change Graph Title'
)}
color={'black'}
@@ -473,9 +478,9 @@ export class Histogram extends React.Component<HistogramProps> {
tooltip={'Change Default Bar Color'}
type={Type.SEC}
icon={<FaFillDrip />}
- 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={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')}
size={Size.XSMALL}
/>
</div>
diff --git a/src/client/views/nodes/DataVizBox/components/LineChart.tsx b/src/client/views/nodes/DataVizBox/components/LineChart.tsx
index 3de7a0c4a..abb95aa4c 100644
--- a/src/client/views/nodes/DataVizBox/components/LineChart.tsx
+++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx
@@ -1,6 +1,6 @@
import { EditableText, Size } from 'browndash-components';
import * as d3 from 'd3';
-import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
+import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { Doc, DocListCast, NumListCast, StrListCast } from '../../../../../fields/Doc';
@@ -14,6 +14,7 @@ import { PinProps, PresBox } from '../../trails';
import { DataVizBox } from '../DataVizBox';
import { createLineGenerator, drawLine, minMaxRange, scaleCreatorNumerical, xAxisCreator, xGrid, yAxisCreator, yGrid } from '../utils/D3Utils';
import './Chart.scss';
+import { ObservableReactComponent } from '../../../ObservableReactComponent';
export interface DataPoint {
x: number;
@@ -23,7 +24,7 @@ export interface SelectedDataPoint extends DataPoint {
elem?: d3.Selection<d3.BaseType, unknown, SVGGElement, unknown>;
}
export interface LineChartProps {
- rootDoc: Doc;
+ Document: Doc;
layoutDoc: Doc;
axes: string[];
records: { [key: string]: any }[];
@@ -40,33 +41,38 @@ export interface LineChartProps {
}
@observer
-export class LineChart extends React.Component<LineChartProps> {
+export class LineChart extends ObservableReactComponent<LineChartProps> {
private _disposers: { [key: string]: IReactionDisposer } = {};
private _lineChartRef: React.RefObject<HTMLDivElement> = React.createRef();
private _lineChartSvg: d3.Selection<SVGGElement, unknown, null, undefined> | undefined;
@observable _currSelected: SelectedDataPoint | undefined = undefined;
// TODO: nda - some sort of mapping that keeps track of the annotated points so we can easily remove when annotations list updates
+ constructor(props:any) {
+ super(props);
+ makeObservable(this);
+ }
+
@computed get _tableDataIds() {
- return !this.parentViz ? this.props.records.map((rec, i) => i) : NumListCast(this.parentViz.dataViz_selectedRows);
+ 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() {
- return !this.parentViz ? this.props.records : this._tableDataIds.map(rowId => this.props.records[rowId]);
+ return !this.parentViz ? this._props.records : this._tableDataIds.map(rowId => this._props.records[rowId]);
}
@computed get _lineChartData() {
- var guids = StrListCast(this.props.layoutDoc.dataViz_rowIds);
- if (this.props.axes.length <= 1) return [];
- return this._tableData.map(record => ({ x: Number(record[this.props.axes[0]]), y: Number(record[this.props.axes[1]]) })).sort((a, b) => (a.x < b.x ? -1 : 1));
+ var guids = StrListCast(this._props.layoutDoc.dataViz_rowIds);
+ if (this._props.axes.length <= 1) return [];
+ return this._tableData.map(record => ({ x: Number(record[this._props.axes[0]]), y: Number(record[this._props.axes[1]]) })).sort((a, b) => (a.x < b.x ? -1 : 1));
}
@computed get graphTitle() {
- return this.props.axes[1] + ' vs. ' + this.props.axes[0] + ' Line Chart';
+ return this._props.axes[1] + ' vs. ' + this._props.axes[0] + ' Line Chart';
}
@computed get parentViz() {
- return DocCast(this.props.rootDoc.dataViz_parentViz);
- // return LinkManager.Instance.getAllRelatedLinks(this.props.rootDoc) // out of all links
+ return DocCast(this._props.Document.dataViz_parentViz);
+ // return LinkManager.Instance.getAllRelatedLinks(this._props.Document) // out of all links
// .filter(link => {
- // return link.link_anchor_1 == this.props.rootDoc.dataViz_parentViz;
+ // return link.link_anchor_1 == this._props.Document.dataViz_parentViz;
// }) // get links where this chart doc is the target of the link
// .map(link => DocCast(link.link_anchor_1)); // then return the source of the link
}
@@ -74,7 +80,7 @@ export class LineChart extends React.Component<LineChartProps> {
// return selected x and y axes
// otherwise, use the selection of whatever is linked to us
const incomingVizBox = DocumentManager.Instance.getFirstDocumentView(this.parentViz)?.ComponentView as DataVizBox;
- const highlitedRowIds = NumListCast(incomingVizBox?.rootDoc?.dataViz_highlitedRows);
+ const highlitedRowIds = NumListCast(incomingVizBox?.layoutDoc?.dataViz_highlitedRows);
return this._tableData.filter((record, i) => highlitedRowIds.includes(this._tableDataIds[i])); // get all the datapoints they have selected field set by incoming anchor
}
@computed get rangeVals(): { xMin?: number; xMax?: number; yMin?: number; yMax?: number } {
@@ -94,7 +100,7 @@ export class LineChart extends React.Component<LineChartProps> {
{ fireImmediately: true }
);
this._disposers.annos = reaction(
- () => DocListCast(this.props.dataDoc[this.props.fieldKey + '_annotations']),
+ () => DocListCast(this._props.dataDoc[this._props.fieldKey + '_annotations']),
annotations => {
// modify how d3 renders so that anything in this annotations list would be potentially highlighted in some way
// could be blue colored to make it look like anchor
@@ -114,7 +120,7 @@ export class LineChart extends React.Component<LineChartProps> {
// redraw annotations when the chart data has changed, or the local or inherited selection has changed
this.clearAnnotations();
selected && this.drawAnnotations(Number(selected.x), Number(selected.y), true);
- incomingHighlited?.forEach((record: any) => this.drawAnnotations(Number(record[this.props.axes[0]]), Number(record[this.props.axes[1]])));
+ incomingHighlited?.forEach((record: any) => this.drawAnnotations(Number(record[this._props.axes[0]]), Number(record[this._props.axes[1]])));
},
{ fireImmediately: true }
);
@@ -170,23 +176,23 @@ export class LineChart extends React.Component<LineChartProps> {
//
title: 'line doc selection' + this._currSelected?.x,
});
- PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this.props.rootDoc);
+ PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this._props.Document);
anchor.config_dataVizSelection = this._currSelected ? new List<number>([this._currSelected.x, this._currSelected.y]) : undefined;
return anchor;
};
@computed get height() {
- return this.props.height - this.props.margin.top - this.props.margin.bottom;
+ return this._props.height - this._props.margin.top - this._props.margin.bottom;
}
@computed get width() {
- return this.props.width - this.props.margin.left - this.props.margin.right;
+ return this._props.width - this._props.margin.left - this._props.margin.right;
}
@computed get defaultGraphTitle() {
- var ax0 = this.props.axes[0];
- var ax1 = this.props.axes.length > 1 ? this.props.axes[1] : undefined;
- if (this.props.axes.length < 2 || !/\d/.test(this.props.records[0][ax0]) || !ax1) {
+ var ax0 = this._props.axes[0];
+ var ax1 = this._props.axes.length > 1 ? this._props.axes[1] : undefined;
+ if (this._props.axes.length < 2 || !/\d/.test(this._props.records[0][ax0]) || !ax1) {
return ax0 + ' Line Chart';
} else return ax1 + ' by ' + ax0 + ' Line Chart';
}
@@ -210,7 +216,7 @@ export class LineChart extends React.Component<LineChartProps> {
// TODO: nda - get rid of svg element in the list?
if (this._currSelected && this._currSelected.x == x && this._currSelected.y == y) this._currSelected = undefined;
else this._currSelected = x !== undefined && y !== undefined ? { x, y } : undefined;
- this.props.records.forEach(record => record[this.props.axes[0]] === x && record[this.props.axes[1]] === y && (record.selected = true));
+ this._props.records.forEach(record => record[this._props.axes[0]] === x && record[this._props.axes[1]] === y && (record.selected = true));
}
drawDataPoints(data: DataPoint[], idx: number, xScale: d3.ScaleLinear<number, number, never>, yScale: d3.ScaleLinear<number, number, never>) {
@@ -245,7 +251,7 @@ export class LineChart extends React.Component<LineChartProps> {
const yScale = scaleCreatorNumerical(0, yMax, height, 0);
// adding svg
- const margin = this.props.margin;
+ const margin = this._props.margin;
const svg = (this._lineChartSvg = d3
.select(this._lineChartRef.current)
.append('svg')
@@ -317,7 +323,7 @@ export class LineChart extends React.Component<LineChartProps> {
svg.append('text')
.attr('transform', 'translate(' + width / 2 + ' ,' + (height + 40) + ')')
.style('text-anchor', 'middle')
- .text(this.props.axes[0]);
+ .text(this._props.axes[0]);
svg.append('text')
.attr('transform', 'rotate(-90)' + ' ' + 'translate( 0, ' + -10 + ')')
.attr('x', -(height / 2))
@@ -325,7 +331,7 @@ export class LineChart extends React.Component<LineChartProps> {
.attr('height', 20)
.attr('width', 20)
.style('text-anchor', 'middle')
- .text(this.props.axes[1]);
+ .text(this._props.axes[1]);
};
private updateTooltip(
@@ -346,18 +352,18 @@ export class LineChart extends React.Component<LineChartProps> {
render() {
var titleAccessor: any = '';
- if (this.props.axes.length == 2) titleAccessor = 'dataViz_lineChart_title' + this.props.axes[0] + '-' + this.props.axes[1];
- else if (this.props.axes.length > 0) titleAccessor = 'dataViz_lineChart_title' + this.props.axes[0];
- if (!this.props.layoutDoc[titleAccessor]) this.props.layoutDoc[titleAccessor] = this.defaultGraphTitle;
- const selectedPt = this._currSelected ? `{ ${this.props.axes[0]}: ${this._currSelected.x} ${this.props.axes[1]}: ${this._currSelected.y} }` : 'none';
+ if (this._props.axes.length == 2) titleAccessor = 'dataViz_lineChart_title' + this._props.axes[0] + '-' + this._props.axes[1];
+ else if (this._props.axes.length > 0) titleAccessor = 'dataViz_lineChart_title' + this._props.axes[0];
+ if (!this._props.layoutDoc[titleAccessor]) this._props.layoutDoc[titleAccessor] = this.defaultGraphTitle;
+ const selectedPt = this._currSelected ? `{ ${this._props.axes[0]}: ${this._currSelected.x} ${this._props.axes[1]}: ${this._currSelected.y} }` : 'none';
if (this._lineChartData.length > 0 || !this.parentViz || this.parentViz.length == 0) {
- return this.props.axes.length >= 2 && /\d/.test(this.props.records[0][this.props.axes[0]]) && /\d/.test(this.props.records[0][this.props.axes[1]]) ? (
+ return this._props.axes.length >= 2 && /\d/.test(this._props.records[0][this._props.axes[0]]) && /\d/.test(this._props.records[0][this._props.axes[1]]) ? (
<div className="chart-container">
<div className="graph-title">
<EditableText
- val={StrCast(this.props.layoutDoc[titleAccessor])}
+ val={StrCast(this._props.layoutDoc[titleAccessor])}
setVal={undoable(
- action(val => (this.props.layoutDoc[titleAccessor] = val as string)),
+ action(val => (this._props.layoutDoc[titleAccessor] = val as string)),
'Change Graph Title'
)}
color={'black'}
diff --git a/src/client/views/nodes/DataVizBox/components/PieChart.tsx b/src/client/views/nodes/DataVizBox/components/PieChart.tsx
index 7303eb184..9e7265b26 100644
--- a/src/client/views/nodes/DataVizBox/components/PieChart.tsx
+++ b/src/client/views/nodes/DataVizBox/components/PieChart.tsx
@@ -1,6 +1,7 @@
+import { Checkbox } from '@mui/material';
import { ColorPicker, EditableText, Size, Type } from 'browndash-components';
import * as d3 from 'd3';
-import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
+import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { FaFillDrip } from 'react-icons/fa';
@@ -12,10 +13,10 @@ import { Docs } from '../../../../documents/Documents';
import { undoable } from '../../../../util/UndoManager';
import { PinProps, PresBox } from '../../trails';
import './Chart.scss';
-import { Checkbox } from '@material-ui/core';
+import { ObservableReactComponent } from '../../../ObservableReactComponent';
export interface PieChartProps {
- rootDoc: Doc;
+ Document: Doc;
layoutDoc: Doc;
axes: string[];
records: { [key: string]: any }[];
@@ -32,7 +33,7 @@ export interface PieChartProps {
}
@observer
-export class PieChart extends React.Component<PieChartProps> {
+export class PieChart extends ObservableReactComponent<PieChartProps> {
private _disposers: { [key: string]: IReactionDisposer } = {};
private _piechartRef: React.RefObject<HTMLDivElement> = React.createRef();
private _piechartSvg: d3.Selection<SVGGElement, unknown, null, undefined> | undefined;
@@ -41,44 +42,49 @@ export class PieChart extends React.Component<PieChartProps> {
private hoverOverData: any = undefined; // Selection of slice being hovered over
@observable _currSelected: any | undefined = undefined; // Object of selected slice
+ constructor(props: any) {
+ super(props);
+ makeObservable(this);
+ }
+
@computed get _tableDataIds() {
- return !this.parentViz ? this.props.records.map((rec, i) => i) : NumListCast(this.parentViz.dataViz_selectedRows);
+ 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() {
- return !this.parentViz ? this.props.records : this._tableDataIds.map(rowId => this.props.records[rowId]);
+ return !this.parentViz ? this._props.records : this._tableDataIds.map(rowId => this._props.records[rowId]);
}
// organized by specified number percentages/ratios if one column is selected and it contains numbers
// otherwise, assume data is organized by categories
@computed get byCategory() {
- return !/\d/.test(this.props.records[0][this.props.axes[0]]) || this.props.layoutDoc.dataViz_pie_asHistogram;
+ return !/\d/.test(this._props.records[0][this._props.axes[0]]) || this._props.layoutDoc.dataViz_pie_asHistogram;
}
// filters all data to just display selected data if brushed (created from an incoming link)
@computed get _pieChartData() {
- if (this.props.axes.length < 1) return [];
+ if (this._props.axes.length < 1) return [];
- const ax0 = this.props.axes[0];
- if (this.props.axes.length < 2) {
- return this._tableData.map(record => ({ [ax0]: record[this.props.axes[0]] }));
+ const ax0 = this._props.axes[0];
+ if (this._props.axes.length < 2) {
+ return this._tableData.map(record => ({ [ax0]: record[this._props.axes[0]] }));
}
- const ax1 = this.props.axes[1];
- return this._tableData.map(record => ({ [ax0]: record[this.props.axes[0]], [ax1]: record[this.props.axes[1]] }));
+ const ax1 = this._props.axes[1];
+ return this._tableData.map(record => ({ [ax0]: record[this._props.axes[0]], [ax1]: record[this._props.axes[1]] }));
}
@computed get defaultGraphTitle() {
- var ax0 = this.props.axes[0];
- var ax1 = this.props.axes.length > 1 ? this.props.axes[1] : undefined;
- if (this.props.axes.length < 2 || !/\d/.test(this.props.records[0][ax0]) || !ax1) {
+ var ax0 = this._props.axes[0];
+ var ax1 = this._props.axes.length > 1 ? this._props.axes[1] : undefined;
+ if (this._props.axes.length < 2 || !/\d/.test(this._props.records[0][ax0]) || !ax1) {
return ax0 + ' Pie Chart';
}
return ax1 + ' by ' + ax0 + ' Pie Chart';
}
@computed get parentViz() {
- return DocCast(this.props.rootDoc.dataViz_parentViz);
- // return LinkManager.Instance.getAllRelatedLinks(this.props.rootDoc) // out of all links
- // .filter(link => link.link_anchor_1 == this.props.rootDoc.dataViz_parentViz) // get links where this chart doc is the target of the link
+ return DocCast(this._props.Document.dataViz_parentViz);
+ // return LinkManager.Instance.getAllRelatedLinks(this._props.Document) // out of all links
+ // .filter(link => link.link_anchor_1 == this._props.Document.dataViz_parentViz) // get links where this chart doc is the target of the link
// .map(link => DocCast(link.link_anchor_1)); // then return the source of the link
}
@@ -101,16 +107,16 @@ export class PieChart extends React.Component<PieChartProps> {
//
title: 'piechart doc selection' + this._currSelected,
});
- PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this.props.rootDoc);
+ PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: pinProps?.pinData }, this._props.Document);
return anchor;
};
@computed get height() {
- return this.props.height - this.props.margin.top - this.props.margin.bottom;
+ return this._props.height - this._props.margin.top - this._props.margin.bottom;
}
@computed get width() {
- return this.props.width - this.props.margin.left - this.props.margin.right;
+ return this._props.width - this._props.margin.left - this._props.margin.right;
}
// cleans data by converting numerical data to numbers and taking out empty cells
@@ -181,7 +187,7 @@ export class PieChart extends React.Component<PieChartProps> {
var percentField = Object.keys(dataSet[0])[0];
var descriptionField = Object.keys(dataSet[0])[1]!;
- var radius = Math.min(width, height - this.props.margin.top - this.props.margin.bottom) / 2;
+ var radius = Math.min(width, height - this._props.margin.top - this._props.margin.bottom) / 2;
// converts data into Objects
var data = this.data(dataSet);
@@ -209,10 +215,10 @@ export class PieChart extends React.Component<PieChartProps> {
.select(this._piechartRef.current)
.append('svg')
.attr('class', 'graph')
- .attr('width', width + this.props.margin.right + this.props.margin.left)
- .attr('height', height + this.props.margin.top + this.props.margin.bottom)
+ .attr('width', width + this._props.margin.right + this._props.margin.left)
+ .attr('height', height + this._props.margin.top + this._props.margin.bottom)
.append('g'));
- let g = svg.append('g').attr('transform', 'translate(' + (width / 2 + this.props.margin.left) + ',' + height / 2 + ')');
+ let g = svg.append('g').attr('transform', 'translate(' + (width / 2 + this._props.margin.left) + ',' + height / 2 + ')');
var pie = d3.pie();
var arc = d3.arc().innerRadius(0).outerRadius(radius);
@@ -249,7 +255,7 @@ export class PieChart extends React.Component<PieChartProps> {
} catch (error) {}
possibleDataPointVals.push(dataPointVal);
});
- const sliceColors = StrListCast(this.props.layoutDoc.dataViz_pie_sliceColors).map(each => each.split('::'));
+ const sliceColors = StrListCast(this._props.layoutDoc.dataViz_pie_sliceColors).map(each => each.split('::'));
arcs.append('path')
.attr('fill', (d, i) => {
var dataPoint;
@@ -261,7 +267,7 @@ export class PieChart extends React.Component<PieChartProps> {
}
var sliceColor;
if (dataPoint) {
- const sliceTitle = dataPoint[this.props.axes[0]];
+ const sliceTitle = dataPoint[this._props.axes[0]];
const accessByName = StrCast(sliceTitle) ? StrCast(sliceTitle).replace(/\$/g, '').replace(/\%/g, '').replace(/\#/g, '').replace(/\</g, '') : sliceTitle;
sliceColors.forEach(each => each[0] == accessByName && (sliceColor = each[1]));
}
@@ -277,6 +283,7 @@ export class PieChart extends React.Component<PieChartProps> {
return 'slice';
}
)
+ // @ts-ignore
.attr('d', arc)
.on('click', onPointClick)
.on('mouseover', onHover)
@@ -308,10 +315,10 @@ export class PieChart extends React.Component<PieChartProps> {
@action changeSelectedColor = (color: string) => {
this.curSliceSelected.attr('fill', color);
- const sliceTitle = this._currSelected[this.props.axes[0]];
+ const sliceTitle = this._currSelected[this._props.axes[0]];
const sliceName = StrCast(sliceTitle) ? StrCast(sliceTitle).replace(/\$/g, '').replace(/\%/g, '').replace(/\#/g, '').replace(/\</g, '') : sliceTitle;
- const sliceColors = Cast(this.props.layoutDoc.dataViz_pie_sliceColors, listSpec('string'), null);
+ const sliceColors = Cast(this._props.layoutDoc.dataViz_pie_sliceColors, listSpec('string'), null);
sliceColors.map(each => {
if (each.split('::')[0] == sliceName) sliceColors.splice(sliceColors.indexOf(each), 1);
});
@@ -319,20 +326,20 @@ export class PieChart extends React.Component<PieChartProps> {
};
@action changeHistogramCheckBox = () => {
- this.props.layoutDoc.dataViz_pie_asHistogram = !this.props.layoutDoc.dataViz_pie_asHistogram;
+ this._props.layoutDoc.dataViz_pie_asHistogram = !this._props.layoutDoc.dataViz_pie_asHistogram;
this.drawChart(this._pieChartData, this.width, this.height);
};
render() {
var titleAccessor: any = '';
- if (this.props.axes.length == 2) titleAccessor = 'dataViz_pie_title' + this.props.axes[0] + '-' + this.props.axes[1];
- else if (this.props.axes.length > 0) titleAccessor = 'dataViz_pie_title' + this.props.axes[0];
- if (!this.props.layoutDoc[titleAccessor]) this.props.layoutDoc[titleAccessor] = this.defaultGraphTitle;
- if (!this.props.layoutDoc.dataViz_pie_sliceColors) this.props.layoutDoc.dataViz_pie_sliceColors = new List<string>();
+ if (this._props.axes.length == 2) titleAccessor = 'dataViz_pie_title' + this._props.axes[0] + '-' + this._props.axes[1];
+ else if (this._props.axes.length > 0) titleAccessor = 'dataViz_pie_title' + this._props.axes[0];
+ if (!this._props.layoutDoc[titleAccessor]) this._props.layoutDoc[titleAccessor] = this.defaultGraphTitle;
+ if (!this._props.layoutDoc.dataViz_pie_sliceColors) this._props.layoutDoc.dataViz_pie_sliceColors = new List<string>();
var selected: string;
var curSelectedSliceName = '';
if (this._currSelected) {
- const sliceTitle = this._currSelected[this.props.axes[0]];
+ const sliceTitle = this._currSelected[this._props.axes[0]];
curSelectedSliceName = StrCast(sliceTitle) ? StrCast(sliceTitle).replace(/\$/g, '').replace(/\%/g, '').replace(/\#/g, '').replace(/\</g, '') : sliceTitle;
selected = '{ ';
Object.keys(this._currSelected).map(key => {
@@ -342,19 +349,19 @@ export class PieChart extends React.Component<PieChartProps> {
selected += ' }';
} else selected = 'none';
var selectedSliceColor;
- var sliceColors = StrListCast(this.props.layoutDoc.dataViz_pie_sliceColors).map(each => each.split('::'));
+ var sliceColors = StrListCast(this._props.layoutDoc.dataViz_pie_sliceColors).map(each => each.split('::'));
sliceColors.forEach(each => {
if (each[0] == curSelectedSliceName!) selectedSliceColor = each[1];
});
if (this._pieChartData.length > 0 || !this.parentViz) {
- return this.props.axes.length >= 1 ? (
+ return this._props.axes.length >= 1 ? (
<div className="chart-container">
<div className="graph-title">
<EditableText
- val={StrCast(this.props.layoutDoc[titleAccessor])}
+ val={StrCast(this._props.layoutDoc[titleAccessor])}
setVal={undoable(
- action(val => (this.props.layoutDoc[titleAccessor] = val as string)),
+ action(val => (this._props.layoutDoc[titleAccessor] = val as string)),
'Change Graph Title'
)}
color={'black'}
@@ -362,9 +369,9 @@ export class PieChart extends React.Component<PieChartProps> {
fillWidth
/>
</div>
- {this.props.axes.length === 1 && /\d/.test(this.props.records[0][this.props.axes[0]]) ? (
- <div className={'asHistogram-checkBox'} style={{ width: this.props.width }}>
- <Checkbox color="primary" onChange={this.changeHistogramCheckBox} checked={this.props.layoutDoc.dataViz_pie_asHistogram as boolean} />
+ {this._props.axes.length === 1 && /\d/.test(this._props.records[0][this._props.axes[0]]) ? (
+ <div className={'asHistogram-checkBox'} style={{ width: this._props.width }}>
+ <Checkbox color="primary" onChange={this.changeHistogramCheckBox} checked={this._props.layoutDoc.dataViz_pie_asHistogram as boolean} />
Organize data as histogram
</div>
) : null}
diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
index 147dfb182..f77c138df 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, observable, reaction } from 'mobx';
+import { action, computed, IReactionDisposer, makeObservable, observable, reaction, trace } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { Doc, Field, NumListCast } from '../../../../../fields/Doc';
@@ -10,11 +10,11 @@ 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';
-
+import { ObservableReactComponent } from '../../../ObservableReactComponent';
+const { default: { DATA_VIZ_TABLE_ROW_HEIGHT } } = require('../../../global/globalCssVariables.module.scss'); // prettier-ignore
interface TableBoxProps {
- rootDoc: Doc;
+ Document: Doc;
layoutDoc: Doc;
records: { [key: string]: any }[];
selectAxes: (axes: string[]) => void;
@@ -31,13 +31,17 @@ interface TableBoxProps {
}
@observer
-export class TableBox extends React.Component<TableBoxProps> {
+export class TableBox extends ObservableReactComponent<TableBoxProps> {
_inputChangedDisposer?: IReactionDisposer;
_containerRef: HTMLDivElement | null = null;
@observable _scrollTop = -1;
@observable _tableHeight = 0;
@observable _tableContainerHeight = 0;
+ constructor(props: any) {
+ super(props);
+ makeObservable(this);
+ }
componentDidMount() {
// if the tableData changes (ie., when records are selected by the parent (input) visulization),
@@ -49,17 +53,17 @@ export class TableBox extends React.Component<TableBoxProps> {
this._inputChangedDisposer?.();
}
@computed get _tableDataIds() {
- return !this.parentViz ? this.props.records.map((rec, i) => i) : NumListCast(this.parentViz.dataViz_selectedRows);
+ 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() {
- return !this.parentViz ? this.props.records : this._tableDataIds.map(rowId => this.props.records[rowId]);
+ return !this.parentViz ? this._props.records : this._tableDataIds.map(rowId => this._props.records[rowId]);
}
@computed get parentViz() {
- return DocCast(this.props.rootDoc.dataViz_parentViz);
- // return LinkManager.Instance.getAllRelatedLinks(this.props.rootDoc) // out of all links
- // .filter(link => link.link_anchor_1 == this.props.rootDoc.dataViz_parentViz) // get links where this chart doc is the target of the link
+ return DocCast(this._props.Document.dataViz_parentViz);
+ // return LinkManager.Instance.getAllRelatedLinks(this._props.Document) // out of all links
+ // .filter(link => link.link_anchor_1 == this._props.Document.dataViz_parentViz) // get links where this chart doc is the target of the link
// .map(link => DocCast(link.link_anchor_1)); // then return the source of the link
}
@@ -69,33 +73,35 @@ export class TableBox extends React.Component<TableBoxProps> {
// updates the 'dataViz_selectedRows' and 'dataViz_highlightedRows' fields to no longer include rows that aren't in the table
filterSelectedRowsDown = () => {
- const selected = NumListCast(this.props.layoutDoc.dataViz_selectedRows);
- this.props.layoutDoc.dataViz_selectedRows = new List<number>(selected.filter(rowId => this._tableDataIds.includes(rowId))); // filters through selected to remove guids that were removed in the incoming data
- const highlighted = NumListCast(this.props.layoutDoc.dataViz_highlitedRows);
- 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
+ const selected = NumListCast(this._props.layoutDoc.dataViz_selectedRows);
+ this._props.layoutDoc.dataViz_selectedRows = new List<number>(selected.filter(rowId => this._tableDataIds.includes(rowId))); // filters through selected to remove guids that were removed in the incoming data
+ const highlighted = NumListCast(this._props.layoutDoc.dataViz_highlitedRows);
+ 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;
+ return this._props.docView?.()?._props.ScreenToLocalTransform().Scale || 1;
}
@computed get rowHeight() {
+ console.log('scale = ' + this.viewScale + ' table = ' + this._tableHeight + ' ids = ' + this._tableDataIds.length);
return (this.viewScale * this._tableHeight) / this._tableDataIds.length;
}
@computed get startID() {
return this.rowHeight ? Math.floor(this._scrollTop / this.rowHeight) : 0;
}
@computed get endID() {
+ console.log('start = ' + this.startID + ' container = ' + this._tableContainerHeight + ' scale = ' + this.viewScale + ' row = ' + this.rowHeight);
return Math.ceil(this.startID + (this._tableContainerHeight * this.viewScale) / (this.rowHeight || 1));
}
@action handleScroll = () => {
- if (!this.props.docView?.()?.ContentDiv?.hidden) {
+ 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);
+ 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);
@@ -119,26 +125,26 @@ export class TableBox extends React.Component<TableBoxProps> {
e,
e => {
// dragging off a column to create a brushed DataVizBox
- const sourceAnchorCreator = () => this.props.docView?.()!.rootDoc!;
+ const sourceAnchorCreator = () => this._props.docView?.()!.Document!;
const targetCreator = (annotationOn: Doc | undefined) => {
- const embedding = Doc.MakeEmbedding(this.props.docView?.()!.rootDoc!);
+ const embedding = Doc.MakeEmbedding(this._props.docView?.()!.Document!);
embedding._dataViz = DataVizView.TABLE;
embedding._dataViz_axes = new List<string>([col, col]);
- embedding._dataViz_parentViz = this.props.rootDoc;
+ embedding._dataViz_parentViz = this._props.Document;
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);
+ 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, {
+ 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.followLinkToggle = e.annoDragData.dropDocument.annotationOn === this._props.Document;
// e.annoDragData.linkSourceDoc.followLinkZoom = false;
}
},
@@ -149,11 +155,11 @@ export class TableBox extends React.Component<TableBoxProps> {
},
emptyFunction,
action(e => {
- const newAxes = this.props.axes;
+ 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);
+ this._props.selectAxes(newAxes);
})
);
};
@@ -165,14 +171,14 @@ export class TableBox extends React.Component<TableBoxProps> {
className="tableBox"
tabIndex={0}
onKeyDown={e => {
- if (this.props.layoutDoc && e.key === 'a' && (e.ctrlKey || e.metaKey)) {
+ if (this._props.layoutDoc && e.key === 'a' && (e.ctrlKey || e.metaKey)) {
e.stopPropagation();
- this.props.layoutDoc.dataViz_selectedRows = new List<number>(this._tableDataIds);
+ this._props.layoutDoc.dataViz_selectedRows = new List<number>(this._tableDataIds);
}
}}>
<div className="selectAll-buttons">
- <Button onClick={action(() => (this.props.layoutDoc.dataViz_selectedRows = new List<number>(this._tableDataIds)))} text="Select All" type={Type.SEC} color={'black'} />
- <Button onClick={action(() => (this.props.layoutDoc.dataViz_selectedRows = new List<number>()))} text="Deselect All" type={Type.SEC} color={'black'} />
+ <Button onClick={action(() => (this._props.layoutDoc.dataViz_selectedRows = new List<number>(this._tableDataIds)))} text="Select All" type={Type.SEC} color={'black'} />
+ <Button onClick={action(() => (this._props.layoutDoc.dataViz_selectedRows = new List<number>()))} text="Deselect All" type={Type.SEC} color={'black'} />
</div>
<div
className={`tableBox-container ${this.columns[0]}`}
@@ -180,7 +186,7 @@ export class TableBox extends React.Component<TableBoxProps> {
onScroll={this.handleScroll}
ref={action((r: HTMLDivElement | null) => {
this._containerRef = r;
- if (!this.props.docView?.()?.ContentDiv?.hidden && 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)
@@ -195,7 +201,7 @@ export class TableBox extends React.Component<TableBoxProps> {
<table
className="tableBox-table"
ref={action((r: HTMLTableElement | null) => {
- if (!this.props.docView?.()?.ContentDiv?.hidden && r) {
+ if (!this._props.docView?.()?.ContentDiv?.hidden && r) {
this._tableHeight = r?.getBoundingClientRect().height ?? 0;
}
})}>
@@ -206,8 +212,8 @@ export class TableBox extends React.Component<TableBoxProps> {
<th
key={this.columns.indexOf(col)}
style={{
- color: this.props.axes.slice().reverse().lastElement() === col ? 'darkgreen' : this.props.axes.lastElement() === col ? 'darkred' : undefined,
- background: this.props.axes.slice().reverse().lastElement() === col ? '#E3fbdb' : this.props.axes.lastElement() === col ? '#Fbdbdb' : undefined,
+ color: this._props.axes.slice().reverse().lastElement() === col ? 'darkgreen' : this._props.axes.lastElement() === col ? 'darkred' : undefined,
+ background: this._props.axes.slice().reverse().lastElement() === col ? '#E3fbdb' : this._props.axes.lastElement() === col ? '#Fbdbdb' : undefined,
fontWeight: 'bolder',
border: '3px solid black',
}}
@@ -226,13 +232,13 @@ export class TableBox extends React.Component<TableBoxProps> {
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' : '',
+ background: NumListCast(this._props.layoutDoc.dataViz_highlitedRows).includes(rowId) ? 'lightYellow' : NumListCast(this._props.layoutDoc.dataViz_selectedRows).includes(rowId) ? 'lightgrey' : '',
}}>
{this.columns.map(col => {
- 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;
+ 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' }}>
- <div className="tableBox-cell">{this.props.records[rowId][col]}</div>
+ <div className="tableBox-cell">{this._props.records[rowId][col]}</div>
</td>
);
})}