aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/documents/Documents.ts4
-rw-r--r--src/client/views/MainView.tsx4
-rw-r--r--src/client/views/PropertiesView.scss2
-rw-r--r--src/client/views/PropertiesView.tsx6
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx2
-rw-r--r--src/client/views/nodes/DataVizBox/DataVizBox.tsx21
-rw-r--r--src/client/views/nodes/DataVizBox/components/Chart.scss17
-rw-r--r--src/client/views/nodes/DataVizBox/components/Histogram.tsx42
-rw-r--r--src/client/views/nodes/DataVizBox/components/LineChart.tsx17
-rw-r--r--src/client/views/nodes/DataVizBox/components/PieChart.tsx59
-rw-r--r--src/client/views/nodes/DataVizBox/components/TableBox.tsx251
-rw-r--r--src/fields/Doc.ts7
12 files changed, 242 insertions, 190 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 5b8973392..1186446e1 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -710,7 +710,7 @@ export namespace Docs {
DocumentType.DATAVIZ,
{
layout: { view: DataVizBox, dataField: defaultDataKey },
- options: { dataViz_title: '', dataViz: 'table', _layout_fitWidth: true, nativeDimModifiable: true },
+ options: { dataViz_title: '', dataViz_line: '', dataViz_pie: '', dataViz_histogram: '', dataViz: 'table', _layout_fitWidth: true, nativeDimModifiable: true },
},
],
[
@@ -1618,7 +1618,7 @@ export namespace DocUtils {
const documentList: ContextMenuProps[] = DocListCast(DocListCast(Doc.MyTools?.data)[0]?.data)
.filter(btnDoc => !btnDoc.hidden)
.map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null))
- .filter(doc => doc && doc !== Doc.UserDoc().emptyTrail && doc !== Doc.UserDoc().emptyDataViz)
+ .filter(doc => doc && doc !== Doc.UserDoc().emptyTrail && doc !== Doc.UserDoc().emptyNote && doc.title)
.map((dragDoc, i) => ({
description: ':' + StrCast(dragDoc.title).replace('Untitled ', ''),
event: undoable((args: { x: number; y: number }) => {
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index e50ef9dcf..c81bc70b8 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -813,8 +813,8 @@ export class MainView extends React.Component {
{this.dockingContent}
{this._hideUI ? null : (
- <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ right: this.propertiesWidth() - 1 }}>
- <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? 'chevron-left' : 'chevron-right'} color={this.colorScheme === ColorScheme.Dark ? Colors.WHITE : Colors.BLACK} size="sm" />
+ <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ background: SettingsManager.Instance.userBackgroundColor, right: this.propertiesWidth() - 1 }}>
+ <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? 'chevron-left' : 'chevron-right'} color={SettingsManager.Instance.userColor} size="sm" />
</div>
)}
<div className="properties-container" style={{ width: this.propertiesWidth() }}>
diff --git a/src/client/views/PropertiesView.scss b/src/client/views/PropertiesView.scss
index bb91ee53d..63b9b53c2 100644
--- a/src/client/views/PropertiesView.scss
+++ b/src/client/views/PropertiesView.scss
@@ -23,6 +23,8 @@
padding: 10px;
font-size: 24px;
font-weight: bold;
+ display: flex;
+ flex-direction: row;
}
overflow-x: hidden;
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 37b61ab41..9df04c862 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -1666,9 +1666,9 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
<div className="propertiesView-propAndInfoGrouping">
<div className="propertiesView-title" style={{ width: this.props.width }}>
Properties
- </div>
- <div className="propertiesView-info" onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation//properties/')}>
- <GrCircleInformation fill={SettingsManager.Instance.userColor} color={SettingsManager.Instance.userBackgroundColor} />{' '}
+ <div className="propertiesView-info" onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/properties')}>
+ <IconButton icon={<FontAwesomeIcon icon="info-circle" />} color={SettingsManager.Instance.userColor} />
+ </div>
</div>
</div>
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx
index 0f51fe6ff..71900c63f 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx
@@ -61,7 +61,7 @@ export class MarqueeOptionsMenu extends AntimodeMenu<AntimodeMenuProps> {
<IconButton
tooltip={"Pin selected region"}
onPointerDown={this.pinWithView}
- icon={presPinWithViewIcon}
+ icon={<FontAwesomeIcon icon="map-pin"/>}
color={this.userColor}
/>
</>
diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
index f9f241234..b9db5fe15 100644
--- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx
+++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
@@ -33,9 +33,10 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
static dataset = new ObservableMap<string, { [key: string]: string }[]>();
private _vizRenderer: LineChart | Histogram | PieChart | undefined;
- // all CSV records in the dataset
+ // all CSV records in the dataset (that aren't an empty row)
@computed.struct get records() {
- return DataVizBox.dataset.get(CsvCast(this.rootDoc[this.fieldKey]).url.href);
+ var records = DataVizBox.dataset.get(CsvCast(this.rootDoc[this.fieldKey]).url.href);
+ return records?.filter(record => Object.keys(record).some(key => record[key]));
}
// currently chosen visualization type: line, pie, histogram, table
@@ -57,11 +58,11 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
const changedView = this.dataVizView !== data.config_dataViz && (this.layoutDoc._dataViz = data.config_dataViz);
const changedAxes = this.axes.join('') !== StrListCast(data.config_dataVizAxes).join('') && (this.layoutDoc._dataViz_axes = new List<string>(StrListCast(data.config_dataVizAxes)));
this.layoutDoc.dataViz_selectedRows = Field.Copy(data.dataViz_selectedRows);
- this.layoutDoc.histogramBarColors = Field.Copy(data.histogramBarColors);
- this.layoutDoc.defaultHistogramColor = data.defaultHistogramColor;
- this.layoutDoc.pieSliceColors = Field.Copy(data.pieSliceColors);
+ this.layoutDoc.dataViz_histogram_barColors = Field.Copy(data.dataViz_histogram_barColors);
+ this.layoutDoc.dataViz_histogram_defaultColor = data.dataViz_histogram_defaultColor;
+ this.layoutDoc.dataViz_pie_sliceColors = Field.Copy(data.dataViz_pie_sliceColors);
Object.keys(this.layoutDoc).map(key => {
- if (key.startsWith('histogram_title') || key.startsWith('lineChart_title') || key.startsWith('pieChart_title')) {
+ if (key.startsWith('dataViz_histogram_title') || key.startsWith('dataViz_lineChart_title') || key.startsWith('dataViz_pieChart_title')) {
this.layoutDoc['_' + key] = data[key];
}
});
@@ -84,11 +85,11 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
anchor.config_dataViz = this.dataVizView;
anchor.config_dataVizAxes = this.axes.length ? new List<string>(this.axes) : undefined;
anchor.dataViz_selectedRows = Field.Copy(this.layoutDoc.dataViz_selectedRows);
- anchor.histogramBarColors = Field.Copy(this.layoutDoc.histogramBarColors);
- anchor.defaultHistogramColor = this.layoutDoc.defaultHistogramColor;
- anchor.pieSliceColors = Field.Copy(this.layoutDoc.pieSliceColors);
+ anchor.dataViz_histogram_barColors = Field.Copy(this.layoutDoc.dataViz_histogram_barColors);
+ anchor.dataViz_histogram_defaultColor = this.layoutDoc.dataViz_histogram_defaultColor;
+ anchor.dataViz_pie_sliceColors = Field.Copy(this.layoutDoc.dataViz_pie_sliceColors);
Object.keys(this.layoutDoc).map(key => {
- if (key.startsWith('histogram_title') || key.startsWith('lineChart_title') || key.startsWith('pieChart_title')) {
+ if (key.startsWith('dataViz_histogram_title') || key.startsWith('dataViz_lineChart_title') || key.startsWith('dataViz_pieChart_title')) {
anchor[key] = this.layoutDoc[key];
}
});
diff --git a/src/client/views/nodes/DataVizBox/components/Chart.scss b/src/client/views/nodes/DataVizBox/components/Chart.scss
index 35e5187b2..9359919c6 100644
--- a/src/client/views/nodes/DataVizBox/components/Chart.scss
+++ b/src/client/views/nodes/DataVizBox/components/Chart.scss
@@ -76,9 +76,22 @@
fill: red;
}
}
+.tableBox {
+ display: flex;
+ flex-direction: column;
+}
.table-container{
overflow: scroll;
- margin: 10px;
+ margin: 5px;
margin-left: 25px;
- margin-top: 25px;
+ margin-right: 10px;
+ margin-bottom: 0;
+}
+.selectAll-buttons {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-end;
+ margin-top: 5px;
+ margin-right: 10px;
+ float: right;
} \ No newline at end of file
diff --git a/src/client/views/nodes/DataVizBox/components/Histogram.tsx b/src/client/views/nodes/DataVizBox/components/Histogram.tsx
index 50facf03e..e67e2bf31 100644
--- a/src/client/views/nodes/DataVizBox/components/Histogram.tsx
+++ b/src/client/views/nodes/DataVizBox/components/Histogram.tsx
@@ -383,7 +383,7 @@ export class Histogram extends React.Component<HistogramProps> {
)
.attr('fill', d => {
var barColor;
- const barColors = StrListCast(this.props.layoutDoc.histogramBarColors).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,7 +391,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.defaultHistogramColor);
+ return barColor ? StrCast(barColor) : StrCast(this.props.layoutDoc.dataViz_histogram_defaultColor);
});
};
@@ -399,28 +399,46 @@ export class Histogram extends React.Component<HistogramProps> {
this.curBarSelected.attr('fill', color);
const barName = StrCast(this._currSelected[this.props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, ''));
- const barColors = Cast(this.props.layoutDoc.histogramBarColors, 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.defaultHistogramColor);
+ 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.histogramBarColors, 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));
};
+ updateBarColors = () => {
+ var svg = this._histogramSvg;
+ if (svg)
+ svg.selectAll('rect').attr('fill', (d: any) => {
+ var barColor;
+ const barColors = StrListCast(this.props.layoutDoc.dataViz_histogram_barColors).map(each => each.split('::'));
+ barColors.forEach(each => {
+ if (d[0] && d[0].toString() && each[0] == d[0].toString()) barColor = each[1];
+ else {
+ const range = StrCast(each[0]).split(' to ');
+ if (Number(range[0]) <= d[0] && d[0] <= Number(range[1])) barColor = each[1];
+ }
+ });
+ return barColor ? StrCast(barColor) : StrCast(this.props.layoutDoc.dataViz_histogram_defaultColor);
+ });
+ };
+
render() {
+ this.updateBarColors();
this._histogramData;
var curSelectedBarName = '';
var titleAccessor: any = '';
- if (this.props.axes.length == 2) titleAccessor = 'dataViz_title_histogram_' + this.props.axes[0] + '-' + this.props.axes[1];
- else if (this.props.axes.length > 0) titleAccessor = 'dataViz_title_histogram_' + this.props.axes[0];
+ 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.defaultHistogramColor) this.props.layoutDoc.defaultHistogramColor = '#69b3a2';
- if (!this.props.layoutDoc.histogramBarColors) this.props.layoutDoc.histogramBarColors = new List<string>();
+ 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, ''));
@@ -455,9 +473,9 @@ export class Histogram extends React.Component<HistogramProps> {
tooltip={'Change Default Bar Color'}
type={Type.SEC}
icon={<FaFillDrip />}
- selectedColor={StrCast(this.props.layoutDoc.defaultHistogramColor)}
- setFinalColor={undoable(color => (this.props.layoutDoc.defaultHistogramColor = color), 'Change Default Bar Color')}
- setSelectedColor={undoable(color => (this.props.layoutDoc.defaultHistogramColor = 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 6c9922c0a..a69d309dc 100644
--- a/src/client/views/nodes/DataVizBox/components/LineChart.tsx
+++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx
@@ -76,7 +76,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?.rootDoc?.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 } {
@@ -91,10 +91,6 @@ export class LineChart extends React.Component<LineChartProps> {
({ dataSet, w, h }) => {
if (dataSet) {
this.drawChart([dataSet], this.rangeVals, w, h);
- // redraw annotations when the chart data has changed, or the local or inherited selection has changed
- this.clearAnnotations();
- this._currSelected && this.drawAnnotations(Number(this._currSelected.x), Number(this._currSelected.y), true);
- this.incomingHighlited?.forEach((record: any) => this.drawAnnotations(Number(record[this.props.axes[0]]), Number(record[this.props.axes[1]])));
}
},
{ fireImmediately: true }
@@ -106,7 +102,7 @@ export class LineChart extends React.Component<LineChartProps> {
// could be blue colored to make it look like anchor
// this.drawAnnotations()
// loop through annotations and draw them
- annotations.forEach(a => this.drawAnnotations(Number(a.x), Number(a.y)));
+ // annotations.forEach(a => this.drawAnnotations(Number(a.x), Number(a.y)));
// this.drawAnnotations(annotations.x, annotations.y);
},
{ fireImmediately: true }
@@ -156,10 +152,6 @@ export class LineChart extends React.Component<LineChartProps> {
}
};
- removeAnnotations(dataX: number, dataY: number) {
- // loop through and remove any annotations that no longer exist
- }
-
@action
restoreView = (data: Doc) => {
const coords = Cast(data.config_dataVizSelection, listSpec('number'), null);
@@ -355,10 +347,9 @@ export class LineChart extends React.Component<LineChartProps> {
}
render() {
- this.componentDidMount();
var titleAccessor: any = '';
- if (this.props.axes.length == 2) titleAccessor = 'dataViz_title_lineChart_' + this.props.axes[0] + '-' + this.props.axes[1];
- else if (this.props.axes.length > 0) titleAccessor = 'dataViz_title_lineChart_' + this.props.axes[0];
+ 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) {
diff --git a/src/client/views/nodes/DataVizBox/components/PieChart.tsx b/src/client/views/nodes/DataVizBox/components/PieChart.tsx
index a8aa51897..4e23a114a 100644
--- a/src/client/views/nodes/DataVizBox/components/PieChart.tsx
+++ b/src/client/views/nodes/DataVizBox/components/PieChart.tsx
@@ -9,7 +9,6 @@ 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 './Chart.scss';
@@ -52,13 +51,10 @@ export class PieChart extends React.Component<PieChartProps> {
// 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() {
- if (this.props.axes.length === 1) {
- return !/\d/.test(this.props.records[0][this.props.axes[0]]);
- }
- return true;
+ return !/\d/.test(this.props.records[0][this.props.axes[0]]);
}
// filters all data to just display selected data if brushed (created from an incoming link)
- @computed get _piechartData() {
+ @computed get _pieChartData() {
if (this.props.axes.length < 1) return [];
const ax0 = this.props.axes[0];
@@ -90,7 +86,7 @@ export class PieChart extends React.Component<PieChartProps> {
}
componentDidMount = () => {
this._disposers.chartData = reaction(
- () => ({ dataSet: this._piechartData, w: this.width, h: this.height }),
+ () => ({ dataSet: this._pieChartData, w: this.width, h: this.height }),
({ dataSet, w, h }) => {
if (dataSet!.length > 0) {
this.drawChart(dataSet, w, h);
@@ -129,7 +125,7 @@ export class PieChart extends React.Component<PieChartProps> {
: validData.map((d: { [x: string]: any }) =>
this.byCategory
? d[field] //
- : +d[field].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '')
+ : +d[field].replace(/\$/g, '').replace(/\%/g, '').replace(/\#/g, '').replace(/\</g, '')
);
};
@@ -162,7 +158,7 @@ export class PieChart extends React.Component<PieChartProps> {
}
if (lineCrossCount % 2 != 0) {
// inside the slice of it crosses an odd number of edges
- var showSelected = this.byCategory ? pieDataSet[index] : this._piechartData[index];
+ var showSelected = this.byCategory ? pieDataSet[index] : this._pieChartData[index];
if (changeSelectedVariables) {
// for when a bar is selected - not just hovered over
sameAsCurrent = this._currSelected
@@ -246,15 +242,17 @@ export class PieChart extends React.Component<PieChartProps> {
// drawing the slices
var selected = this.selectedData;
var arcs = g.selectAll('arc').data(pie(data)).enter().append('g');
- const sliceColors = StrListCast(this.props.layoutDoc.pieSliceColors).map(each => each.split('::'));
- const possibleDataPointVals = pieDataSet.map((each: { [x: string]: any | { valueOf(): number } }) => {
+ const possibleDataPointVals: { [x: string]: any }[] = [];
+ pieDataSet.forEach((each: { [x: string]: any | { valueOf(): number } }) => {
+ var dataPointVal: { [x: string]: any } = {};
+ dataPointVal[percentField] = each[percentField];
+ if (descriptionField) dataPointVal[descriptionField] = each[descriptionField];
try {
- each[percentField] = Number(each[percentField].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, ''));
- } catch (error) {
- //return each[percentField] == d.data;
- }
- return each;
+ dataPointVal[percentField] = Number(dataPointVal[percentField].replace(/\$/g, '').replace(/\%/g, '').replace(/\#/g, '').replace(/\</g, ''));
+ } catch (error) {}
+ possibleDataPointVals.push(dataPointVal);
});
+ const sliceColors = StrListCast(this.props.layoutDoc.dataViz_pie_sliceColors).map(each => each.split('::'));
arcs.append('path')
.attr('fill', (d, i) => {
var dataPoint;
@@ -266,8 +264,9 @@ export class PieChart extends React.Component<PieChartProps> {
}
var sliceColor;
if (dataPoint) {
- var accessByName = dataPoint[this.props.axes[0]];
- sliceColors.forEach(each => each[0] == StrCast(accessByName) && (sliceColor = each[1]));
+ 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]));
}
return sliceColor ? StrCast(sliceColor) : d3.schemeSet3[i] ? d3.schemeSet3[i] : d3.schemeSet3[i % d3.schemeSet3.length];
})
@@ -301,9 +300,9 @@ export class PieChart extends React.Component<PieChartProps> {
.text(function (d) {
var dataPoint;
const possibleDataPoints = possibleDataPointVals.filter((pval: any) => pval[percentField] === Number(d.data));
- if (possibleDataPoints.length == 1) dataPoint = possibleDataPoints[0];
+ if (possibleDataPoints.length == 1) dataPoint = pieDataSet[possibleDataPointVals.indexOf(possibleDataPoints[0])];
else {
- dataPoint = possibleDataPoints[trackDuplicates[d.data.toString()]];
+ dataPoint = pieDataSet[possibleDataPointVals.indexOf(possibleDataPoints[trackDuplicates[d.data.toString()]])];
trackDuplicates[d.data.toString()] = trackDuplicates[d.data.toString()] + 1;
}
return dataPoint ? dataPoint[percentField]! + (!descriptionField ? '' : ' - ' + dataPoint[descriptionField])! : '';
@@ -312,9 +311,10 @@ export class PieChart extends React.Component<PieChartProps> {
@action changeSelectedColor = (color: string) => {
this.curSliceSelected.attr('fill', color);
- var sliceName = this._currSelected[this.props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, '');
+ 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.pieSliceColors, 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);
});
@@ -323,14 +323,15 @@ export class PieChart extends React.Component<PieChartProps> {
render() {
var titleAccessor: any = '';
- if (this.props.axes.length == 2) titleAccessor = 'dataViz_title_pieChart_' + this.props.axes[0] + '-' + this.props.axes[1];
- else if (this.props.axes.length > 0) titleAccessor = 'dataViz_title_pieChart_' + this.props.axes[0];
+ 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.pieSliceColors) this.props.layoutDoc.pieSliceColors = new List<string>();
+ if (!this.props.layoutDoc.dataViz_pie_sliceColors) this.props.layoutDoc.dataViz_pie_sliceColors = new List<string>();
var selected: string;
var curSelectedSliceName = '';
if (this._currSelected) {
- curSelectedSliceName = StrCast(this._currSelected![this.props.axes[0]].replace(/\$/g, '').replace(/\%/g, '').replace(/\</g, ''));
+ 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 => {
key != '' ? (selected += key + ': ' + this._currSelected[key] + ', ') : '';
@@ -339,12 +340,12 @@ export class PieChart extends React.Component<PieChartProps> {
selected += ' }';
} else selected = 'none';
var selectedSliceColor;
- var sliceColors = StrListCast(this.props.layoutDoc.pieSliceColors).map(each => each.split('::'));
- sliceColors.map(each => {
+ 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) {
+ if (this._pieChartData.length > 0 || !this.parentViz) {
return this.props.axes.length >= 1 ? (
<div className="chart-container">
<div className="graph-title">
diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
index 067dff07a..6688bcedb 100644
--- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx
+++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
@@ -5,12 +5,13 @@ import { Doc, Field, NumListCast, StrListCast } from '../../../../../fields/Doc'
import { List } from '../../../../../fields/List';
import { listSpec } from '../../../../../fields/Schema';
import { Cast, DocCast } from '../../../../../fields/Types';
-import { emptyFunction, setupMoveUpEvents, Utils } from '../../../../../Utils';
+import { emptyFunction, numberRange, setupMoveUpEvents, Utils } from '../../../../../Utils';
import { DragManager } from '../../../../util/DragManager';
import { LinkManager } from '../../../../util/LinkManager';
import { DocumentView } from '../../DocumentView';
import { DataVizView } from '../DataVizBox';
import './Chart.scss';
+import { Button, Type } from 'browndash-components';
interface TableBoxProps {
rootDoc: Doc;
@@ -64,128 +65,148 @@ export class TableBox extends React.Component<TableBoxProps> {
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 selected to remove guids that were removed in the incoming data
+ 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
};
render() {
if (this._tableData.length > 0) {
return (
<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">
- <thead>
- <tr className="table-row">
- {this.columns.map(col => (
- <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,
- 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.annoDragData.linkSourceDoc.followLinkToggle = e.annoDragData.dropDocument.annotationOn === this.props.rootDoc;
- // e.annoDragData.linkSourceDoc.followLinkZoom = false;
+ className="tableBox"
+ tabIndex={0}
+ onKeyDown={e => {
+ if (this.props.layoutDoc && e.key === 'a' && (e.ctrlKey || e.metaKey)) {
+ e.stopPropagation();
+ 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'} />
+ </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">
+ <thead>
+ <tr className="table-row">
+ {this.columns.map(col => (
+ <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,
+ 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.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);
- })
- );
- }}>
- {col}
- </th>
- ))}
- </tr>
- </thead>
- <tbody>
- {this._tableDataIds
- ?.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)) {
+ );
+ 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);
+ })
+ );
+ }}>
+ {col}
+ </th>
+ ))}
+ </tr>
+ </thead>
+ <tbody>
+ {this._tableDataIds
+ ?.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);
- selected.splice(selected.indexOf(rowId), 1);
- } else selected?.push(rowId);
- }
- e.stopPropagation();
- })}
- 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]}
- </td>
- );
- })}
- </tr>
- ))}
- </tbody>
- </table>
+ 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();
+ })}
+ 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]}
+ </td>
+ );
+ })}
+ </tr>
+ ))}
+ </tbody>
+ </table>
+ </div>
</div>
);
} else
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 1bfd9e9df..f242ab5be 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -1600,12 +1600,13 @@ export namespace Doc {
// prettier-ignore
export function toIcon(doc?: Doc, isOpen?: boolean) {
+ console.log(doc!.title, doc!.type)
switch (isOpen !== undefined ? DocumentType.COL: StrCast(doc?.type)) {
case DocumentType.IMG: return 'image';
case DocumentType.COMPARISON: return 'columns';
case DocumentType.RTF: return 'sticky-note';
case DocumentType.COL:
- const folder: IconProp = isOpen === true ? 'folder-open' : isOpen === false ? 'folder' : 'question';
+ const folder: IconProp = isOpen === true ? 'folder-open' : isOpen === false ? 'folder' : doc!.title=='Untitled Collection'? 'object-group': 'chalkboard';
const chevron: IconProp = isOpen === true ? 'chevron-down' : isOpen === false ? 'chevron-right' : 'question';
return !doc?.isFolder ? folder : chevron;
case DocumentType.WEB: return 'globe-asia';
@@ -1621,6 +1622,10 @@ export namespace Doc {
case DocumentType.PDF: return 'file-pdf';
case DocumentType.LINK: return 'link';
case DocumentType.MAP: return 'map-marker-alt';
+ case DocumentType.DATAVIZ: return 'chart-bar';
+ case DocumentType.EQUATION: return 'calculator';
+ case DocumentType.SIMULATION: return 'rocket';
+ case DocumentType.CONFIG: return 'question-circle';
default: return 'question';
}
}