From 9200e09939ba3d23bcf79efda008a7a990d29b95 Mon Sep 17 00:00:00 2001 From: srichman333 Date: Thu, 11 Jan 2024 02:37:07 -0500 Subject: toggle scheme dataviz box as live --- src/client/views/nodes/DataVizBox/DataVizBox.scss | 4 ++ src/client/views/nodes/DataVizBox/DataVizBox.tsx | 61 ++++++++++++++++------ .../views/nodes/DataVizBox/components/Chart.scss | 2 - 3 files changed, 49 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.scss b/src/client/views/nodes/DataVizBox/DataVizBox.scss index a3132dc6e..6b5738790 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.scss +++ b/src/client/views/nodes/DataVizBox/DataVizBox.scss @@ -29,6 +29,10 @@ } } + .liveSchema-checkBox { + margin-bottom: -35px; + } + .dataviz-sidebar { position: absolute; right: 0; diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index 5a55ca764..1aef98131 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -28,6 +28,7 @@ import { Histogram } from './components/Histogram'; import { LineChart } from './components/LineChart'; import { PieChart } from './components/PieChart'; import { TableBox } from './components/TableBox'; +import { Checkbox } from '@mui/material'; export enum DataVizView { TABLE = 'table', @@ -44,9 +45,9 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { private _annotationLayer: React.RefObject = React.createRef(); anchorMenuClick?: () => undefined | ((anchor: Doc) => void); crop: ((region: Doc | undefined, addCrop?: boolean) => Doc | undefined) | undefined; - @observable schemaDataVizChildren: any = undefined; @observable _marqueeing: number[] | undefined = undefined; @observable _savedAnnotations = new ObservableMap(); + @computed get annotationLayer() { TraceMobx(); return
; @@ -80,6 +81,11 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { // all datasets that have been retrieved from the server stored as a map from the dataset url to an array of records static dataset = new ObservableMap(); + + // when a dataset comes from schema view, this stores the original dataset to refer back to + // href : dataset + static datasetSchemaOG = new Map(); + private _vizRenderer: LineChart | Histogram | PieChart | undefined; private _sidebarRef = React.createRef(); @@ -322,30 +328,46 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { GPTPopup.Instance.addDoc = this.sidebarAddDocument; }; + @action + changeLiveSchemaCheckbox = () => { + this.layoutDoc.dataViz_schemaLive = !this.layoutDoc.dataViz_schemaLive + console.log(this.layoutDoc.dataViz_schemaLive) + this.updateSchemaViz(); + } + @action updateSchemaViz = () => { - const getFrom = DocCast(this.layoutDoc.dataViz_asSchema); - const keys = Cast(getFrom.schema_columnKeys, listSpec('string'))?.filter(key => key != 'text'); - if (!keys) return; - const children = DocListCast(getFrom[Doc.LayoutFieldKey(getFrom)]); - var current: { [key: string]: string }[] = []; - for (let i = 0; i < children.length; i++) { - var row: { [key: string]: string } = {}; - if (children[i]) { - for (let j = 0; j < keys.length; j++) { - var cell = children[i][keys[j]]; - if (cell && (cell as string)) cell = cell.toString().replace(/\,/g, ''); - row[keys[j]] = StrCast(cell); + const href = CsvCast(this.Document[this.fieldKey]).url.href; + if (this.layoutDoc.dataViz_schemaLive || !DataVizBox.datasetSchemaOG.has(href)){ + const getFrom = DocCast(this.layoutDoc.dataViz_asSchema); + const keys = Cast(getFrom.schema_columnKeys, listSpec('string'))?.filter(key => key != 'text'); + if (!keys) return; + const children = DocListCast(getFrom[Doc.LayoutFieldKey(getFrom)]); + + var current: { [key: string]: string }[] = []; + for (let i = 0; i < children.length; i++) { + var row: { [key: string]: string } = {}; + if (children[i]) { + for (let j = 0; j < keys.length; j++) { + var cell = children[i][keys[j]]; + if (cell && (cell as string)) cell = cell.toString().replace(/\,/g, ''); + row[keys[j]] = StrCast(cell); + } } + current.push(row); + } + + if (!DataVizBox.datasetSchemaOG.has(href)){ + DataVizBox.datasetSchemaOG.set(href, current); } - current.push(row); + DataVizBox.dataset.set(href, current); } - DataVizBox.dataset.set(CsvCast(this.Document[this.fieldKey]).url.href, current); + else DataVizBox.dataset.set(href, DataVizBox.datasetSchemaOG.get(href)); }; render() { + if (this.layoutDoc.dataViz_schemaLive == undefined) this.layoutDoc.dataViz_schemaLive = true; if (this.layoutDoc && this.layoutDoc.dataViz_asSchema) { - this.schemaDataVizChildren = DocListCast(DocCast(this.layoutDoc.dataViz_asSchema)[Doc.LayoutFieldKey(DocCast(this.layoutDoc.dataViz_asSchema))]).length; this.updateSchemaViz(); } @@ -393,6 +415,13 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { {this.renderVizView} */} + {(this.layoutDoc && this.layoutDoc.dataViz_asSchema)?( +
+ + Display Live Updates to Canvas +
+ ) : null} + {this.renderVizView}
Date: Fri, 12 Jan 2024 12:56:09 -0500 Subject: live schema toggle works on refresh --- .../collectionFreeForm/CollectionFreeFormView.tsx | 5 +- .../collectionSchema/CollectionSchemaView.scss | 6 ++- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 58 ++++++++++++++++------ 3 files changed, 51 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 8268a47d8..de4f01014 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -2005,15 +2005,14 @@ ScriptingGlobals.add(function datavizFromSchema(doc: Doc) { csvRows.push(eachRow); } const blob = new Blob([csvRows.join('\n')], { type: 'text/csv' }); - const options = { x: 0, y: -300, title: 'schemaTable', _width: 300, _height: 100, type: 'text/csv' }; + const options = { x: 0, y: 0, title: 'schemaTable', _width: 300, _height: 100, type: 'text/csv' }; const file = new File([blob], 'schemaTable', options); const loading = Docs.Create.LoadingDocument(file, options); loading.presentation_openInLightbox = true; DocUtils.uploadFileToDoc(file, {}, loading); if (view.ComponentView?.addDocument) { - // loading.dataViz_fromSchema = true; - loading.dataViz_asSchema = view.layoutDoc; + loading._dataViz_asSchema = view.layoutDoc; SchemaCSVPopUp.Instance.setView(view); SchemaCSVPopUp.Instance.setTarget(view.layoutDoc); SchemaCSVPopUp.Instance.setDataVizDoc(loading); diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss index 02131ae22..da9da8fbe 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss @@ -18,17 +18,21 @@ .schema-add { position: relative; - height: 30; + height: 35; display: flex; align-items: center; + top: -10px; width: 100%; text-align: right; background: lightgray; .editableView-container-editing { width: 100%; + height: 35px; + margin: 20px; } .editableView-input { width: 100%; + margin: 20px; float: right; text-align: right; background: yellow; diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index 1aef98131..6d060f535 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -1,6 +1,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Colors, Toggle, ToggleType, Type } from 'browndash-components'; -import { ObservableMap, action, computed, observable, runInAction } from 'mobx'; +import { ObservableMap, action, computed, makeObservable, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { emptyFunction, returnEmptyString, returnFalse, returnOne, setupMoveUpEvents } from '../../../../Utils'; @@ -11,7 +11,7 @@ import { listSpec } from '../../../../fields/Schema'; import { Cast, CsvCast, DocCast, NumCast, StrCast } from '../../../../fields/Types'; import { CsvField } from '../../../../fields/URLField'; import { TraceMobx } from '../../../../fields/util'; -import { Docs } from '../../../documents/Documents'; +import { DocUtils, Docs } from '../../../documents/Documents'; import { DocumentManager } from '../../../util/DocumentManager'; import { UndoManager, undoable } from '../../../util/UndoManager'; import { ViewBoxAnnotatableComponent } from '../../DocComponent'; @@ -40,13 +40,13 @@ export enum DataVizView { @observer export class DataVizBox extends ViewBoxAnnotatableComponent() { private _mainCont: React.RefObject = React.createRef(); - private _ffref = React.createRef(); private _marqueeref = React.createRef(); private _annotationLayer: React.RefObject = React.createRef(); anchorMenuClick?: () => undefined | ((anchor: Doc) => void); crop: ((region: Doc | undefined, addCrop?: boolean) => Doc | undefined) | undefined; @observable _marqueeing: number[] | undefined = undefined; @observable _savedAnnotations = new ObservableMap(); + @observable schemaBoxLength: any = 0; @computed get annotationLayer() { TraceMobx(); @@ -81,10 +81,9 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { // all datasets that have been retrieved from the server stored as a map from the dataset url to an array of records static dataset = new ObservableMap(); - // when a dataset comes from schema view, this stores the original dataset to refer back to // href : dataset - static datasetSchemaOG = new Map(); + static datasetSchemaOG = new ObservableMap(); private _vizRenderer: LineChart | Histogram | PieChart | undefined; private _sidebarRef = React.createRef(); @@ -104,10 +103,10 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { return Cast(this.dataDoc[this.fieldKey], CsvField); } @computed.struct get axes() { - return StrListCast(this.layoutDoc.dataViz_axes); + return StrListCast(this.layoutDoc._dataViz_axes); } - selectAxes = (axes: string[]) => (this.layoutDoc.dataViz_axes = new List(axes)); + selectAxes = (axes: string[]) => (this.layoutDoc._dataViz_axes = new List(axes)); @action // pinned / linked anchor doc includes selected rows, graph titles, and graph colors restoreView = (data: Doc) => { @@ -331,19 +330,52 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { @action changeLiveSchemaCheckbox = () => { this.layoutDoc.dataViz_schemaLive = !this.layoutDoc.dataViz_schemaLive - console.log(this.layoutDoc.dataViz_schemaLive) this.updateSchemaViz(); } + @action + setDataset(href: any, data: any) { + DataVizBox.dataset.set(href, data); + } + @action updateSchemaViz = () => { const href = CsvCast(this.Document[this.fieldKey]).url.href; + if (this.layoutDoc.dataViz_schemaLive || !DataVizBox.datasetSchemaOG.has(href)){ const getFrom = DocCast(this.layoutDoc.dataViz_asSchema); const keys = Cast(getFrom.schema_columnKeys, listSpec('string'))?.filter(key => key != 'text'); if (!keys) return; const children = DocListCast(getFrom[Doc.LayoutFieldKey(getFrom)]); + if (!this.layoutDoc._dataViz_schemaOG){ + let csvRows = []; + csvRows.push(keys.join(',')); + for (let i = 0; i < children.length; i++) { + let eachRow = []; + for (let j = 0; j < keys.length; j++) { + var cell = children[i][keys[j]]; + if (cell && (cell as string)) cell = cell.toString().replace(/\,/g, ''); + eachRow.push(cell); + } + csvRows.push(eachRow); + } + const blob = new Blob([csvRows.join('\n')], { type: 'text/csv' }); + const options = { x: 0, y: 0, title: 'schemaTable for static dataviz', _width: 300, _height: 100, type: 'text/csv' }; + const file = new File([blob], 'schemaTable for static dataviz', options); + const loading = Docs.Create.LoadingDocument(file, options); + DocUtils.uploadFileToDoc(file, {}, loading); + this.layoutDoc._dataViz_schemaOG = loading; + } + + const ogDoc = this.layoutDoc._dataViz_schemaOG as Doc + const ogHref = CsvCast(ogDoc[this.fieldKey])? CsvCast(ogDoc[this.fieldKey]).url.href : undefined; + if (ogHref && !DataVizBox.datasetSchemaOG.has(href)){ + DataVizBox.datasetSchemaOG.set(href, []); + fetch('/csvData?uri=' + ogHref) + .then(res => res.json().then(action(res => !res.errno && DataVizBox.datasetSchemaOG.set(href, res)))); + } + var current: { [key: string]: string }[] = []; for (let i = 0; i < children.length; i++) { var row: { [key: string]: string } = {}; @@ -356,13 +388,11 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { } current.push(row); } - - if (!DataVizBox.datasetSchemaOG.has(href)){ - DataVizBox.datasetSchemaOG.set(href, current); - } - DataVizBox.dataset.set(href, current); + this.setDataset(href, current); + } + else { + this.setDataset(href, DataVizBox.datasetSchemaOG.get(href)); } - else DataVizBox.dataset.set(href, DataVizBox.datasetSchemaOG.get(href)); }; render() { -- cgit v1.2.3-70-g09d2 From db51496360e8eac55b5e83283370c4aeec7a11d8 Mon Sep 17 00:00:00 2001 From: srichman333 Date: Wed, 17 Jan 2024 15:01:30 -0500 Subject: cleaner --- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 + src/client/views/nodes/DataVizBox/DataVizBox.tsx | 116 +++++++++------------ .../views/nodes/DataVizBox/components/TableBox.tsx | 2 - 3 files changed, 52 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index de4f01014..881c80a1a 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1985,6 +1985,7 @@ ScriptingGlobals.add(function sendToBack(doc: Doc) { SelectionManager.Views.forEach(view => view.CollectionFreeFormView?.bringToFront(view.Document, true)); }); ScriptingGlobals.add(function datavizFromSchema(doc: Doc) { + // creating a dataviz doc to represent the schema table SelectionManager.Views.forEach(view => { if (!view.layoutDoc.schema_columnKeys) { view.layoutDoc.schema_columnKeys = new List(['title', 'type', 'author', 'author_date']); @@ -2011,6 +2012,7 @@ ScriptingGlobals.add(function datavizFromSchema(doc: Doc) { loading.presentation_openInLightbox = true; DocUtils.uploadFileToDoc(file, {}, loading); + // holds the doc in a popup until it is dragged onto a canvas if (view.ComponentView?.addDocument) { loading._dataViz_asSchema = view.layoutDoc; SchemaCSVPopUp.Instance.setView(view); diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index 6d060f535..981ec0aa1 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -1,6 +1,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Colors, Toggle, ToggleType, Type } from 'browndash-components'; -import { ObservableMap, action, computed, makeObservable, observable, runInAction } from 'mobx'; +import { ObservableMap, action, computed, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { emptyFunction, returnEmptyString, returnFalse, returnOne, setupMoveUpEvents } from '../../../../Utils'; @@ -17,7 +17,6 @@ import { UndoManager, undoable } from '../../../util/UndoManager'; import { ViewBoxAnnotatableComponent } from '../../DocComponent'; import { MarqueeAnnotator } from '../../MarqueeAnnotator'; import { SidebarAnnos } from '../../SidebarAnnos'; -import { CollectionFreeFormView } from '../../collections/collectionFreeForm'; import { AnchorMenu } from '../../pdf/AnchorMenu'; import { GPTPopup } from '../../pdf/GPTPopup/GPTPopup'; import { DocFocusOptions, DocumentView } from '../DocumentView'; @@ -339,59 +338,63 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { } @action + // handles when the dataviz doc was made by copying a schema table updateSchemaViz = () => { const href = CsvCast(this.Document[this.fieldKey]).url.href; - - if (this.layoutDoc.dataViz_schemaLive || !DataVizBox.datasetSchemaOG.has(href)){ - const getFrom = DocCast(this.layoutDoc.dataViz_asSchema); - const keys = Cast(getFrom.schema_columnKeys, listSpec('string'))?.filter(key => key != 'text'); - if (!keys) return; - const children = DocListCast(getFrom[Doc.LayoutFieldKey(getFrom)]); - - if (!this.layoutDoc._dataViz_schemaOG){ - let csvRows = []; - csvRows.push(keys.join(',')); - for (let i = 0; i < children.length; i++) { - let eachRow = []; - for (let j = 0; j < keys.length; j++) { - var cell = children[i][keys[j]]; - if (cell && (cell as string)) cell = cell.toString().replace(/\,/g, ''); - eachRow.push(cell); + const getFromDoc = DocCast(this.layoutDoc.dataViz_asSchema); + const children = DocListCast(getFromDoc[Doc.LayoutFieldKey(getFromDoc)]); + + if (children.length != this.schemaBoxLength) { + if (this.layoutDoc.dataViz_schemaLive || !DataVizBox.datasetSchemaOG.has(href)){ + const keys = Cast(getFromDoc.schema_columnKeys, listSpec('string'))?.filter(key => key != 'text'); + if (!keys) return; + + if (!this.layoutDoc._dataViz_schemaOG){ + // makes a copy of the original table for the "live" toggle + let csvRows = []; + csvRows.push(keys.join(',')); + for (let i = 0; i < children.length; i++) { + let eachRow = []; + for (let j = 0; j < keys.length; j++) { + var cell = children[i][keys[j]]; + if (cell && (cell as string)) cell = cell.toString().replace(/\,/g, ''); + eachRow.push(cell); + } + csvRows.push(eachRow); } - csvRows.push(eachRow); + const blob = new Blob([csvRows.join('\n')], { type: 'text/csv' }); + const options = { x: 0, y: 0, title: 'schemaTable for static dataviz', _width: 300, _height: 100, type: 'text/csv' }; + const file = new File([blob], 'schemaTable for static dataviz', options); + const loading = Docs.Create.LoadingDocument(file, options); + DocUtils.uploadFileToDoc(file, {}, loading); + this.layoutDoc._dataViz_schemaOG = loading; } - const blob = new Blob([csvRows.join('\n')], { type: 'text/csv' }); - const options = { x: 0, y: 0, title: 'schemaTable for static dataviz', _width: 300, _height: 100, type: 'text/csv' }; - const file = new File([blob], 'schemaTable for static dataviz', options); - const loading = Docs.Create.LoadingDocument(file, options); - DocUtils.uploadFileToDoc(file, {}, loading); - this.layoutDoc._dataViz_schemaOG = loading; - } - const ogDoc = this.layoutDoc._dataViz_schemaOG as Doc - const ogHref = CsvCast(ogDoc[this.fieldKey])? CsvCast(ogDoc[this.fieldKey]).url.href : undefined; - if (ogHref && !DataVizBox.datasetSchemaOG.has(href)){ - DataVizBox.datasetSchemaOG.set(href, []); - fetch('/csvData?uri=' + ogHref) - .then(res => res.json().then(action(res => !res.errno && DataVizBox.datasetSchemaOG.set(href, res)))); - } + const ogDoc = this.layoutDoc._dataViz_schemaOG as Doc + const ogHref = CsvCast(ogDoc[this.fieldKey])? CsvCast(ogDoc[this.fieldKey]).url.href : undefined; + if (ogHref && !DataVizBox.datasetSchemaOG.has(href)){ + DataVizBox.datasetSchemaOG.set(href, []); + fetch('/csvData?uri=' + ogHref) + .then(res => res.json().then(action(res => !res.errno && DataVizBox.datasetSchemaOG.set(href, res)))); + } - var current: { [key: string]: string }[] = []; - for (let i = 0; i < children.length; i++) { - var row: { [key: string]: string } = {}; - if (children[i]) { - for (let j = 0; j < keys.length; j++) { - var cell = children[i][keys[j]]; - if (cell && (cell as string)) cell = cell.toString().replace(/\,/g, ''); - row[keys[j]] = StrCast(cell); + var current: { [key: string]: string }[] = []; + for (let i = 0; i < children.length; i++) { + var row: { [key: string]: string } = {}; + if (children[i]) { + for (let j = 0; j < keys.length; j++) { + var cell = children[i][keys[j]]; + if (cell && (cell as string)) cell = cell.toString().replace(/\,/g, ''); + row[keys[j]] = StrCast(cell); + } } + current.push(row); } - current.push(row); + this.setDataset(href, current); + } + else { + this.setDataset(href, DataVizBox.datasetSchemaOG.get(href)); } - this.setDataset(href, current); - } - else { - this.setDataset(href, DataVizBox.datasetSchemaOG.get(href)); } }; @@ -425,26 +428,6 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { (this.layoutDoc._dataViz = DataVizView.PIECHART)} toggleStatus={this.layoutDoc._dataViz == -DataVizView.PIECHART} />
- {/* - {this.renderVizView} - */} - {(this.layoutDoc && this.layoutDoc.dataViz_asSchema)?(
@@ -453,6 +436,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { ) : null} {this.renderVizView} +
{ return this._props.docView?.()?.screenToViewTransform().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.max(Math.floor(this._scrollTop / this.rowHeight) - 1, 0) : 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 = () => { -- cgit v1.2.3-70-g09d2 From 99e57e5c98a69b1d95e87ecc7728164748886a0e Mon Sep 17 00:00:00 2001 From: srichman333 Date: Tue, 23 Jan 2024 12:24:22 -0500 Subject: non-numerical histogram fix --- src/client/views/nodes/DataVizBox/components/Histogram.tsx | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/components/Histogram.tsx b/src/client/views/nodes/DataVizBox/components/Histogram.tsx index 4a1fb2ed1..412957fb1 100644 --- a/src/client/views/nodes/DataVizBox/components/Histogram.tsx +++ b/src/client/views/nodes/DataVizBox/components/Histogram.tsx @@ -63,17 +63,17 @@ export class Histogram extends ObservableReactComponent { 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 (!/[A-Za-z-:]/.test(this._props.records[0][ax0])){ this.numericalXData = true; } 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])) { + if (!/[A-Za-z-:]/.test(this._props.records[0][ax0])) { this.numericalXData = true; } - if (/\d/.test(this._props.records[0][ax1])) { + if (!/[A-Za-z-:]/.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]] })); @@ -89,9 +89,6 @@ export class Histogram extends ObservableReactComponent { @computed get parentViz() { 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 } @computed get rangeVals(): { xMin?: number; xMax?: number; yMin?: number; yMax?: number } { -- cgit v1.2.3-70-g09d2 From aa3c70399ac2b6a337a9c85fb30f57f82ee44063 Mon Sep 17 00:00:00 2001 From: srichman333 Date: Tue, 23 Jan 2024 13:22:13 -0500 Subject: data has a title column --- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 8 ++++++-- .../nodes/DataVizBox/components/Histogram.tsx | 1 + .../nodes/DataVizBox/components/LineChart.tsx | 1 + .../views/nodes/DataVizBox/components/PieChart.tsx | 1 + .../views/nodes/DataVizBox/components/TableBox.tsx | 22 ++++++++++++++++------ 5 files changed, 25 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index 981ec0aa1..ea053b09d 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -104,8 +104,11 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { @computed.struct get axes() { return StrListCast(this.layoutDoc._dataViz_axes); } - selectAxes = (axes: string[]) => (this.layoutDoc._dataViz_axes = new List(axes)); + @computed.struct get titleCol() { + return StrCast(this.layoutDoc._dataViz_titleCol); + } + selectTitleCol = (titleCol: string) => (this.layoutDoc._dataViz_titleCol = titleCol); @action // pinned / linked anchor doc includes selected rows, graph titles, and graph colors restoreView = (data: Doc) => { @@ -271,6 +274,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { layoutDoc: this.layoutDoc, records: this.records, axes: this.axes, + titleCol: this.titleCol, //width: this.SidebarShown? this._props.PanelWidth()*.9/1.2: this._props.PanelWidth() * 0.9, height: (this._props.PanelHeight() / scale - 32) /* height of 'change view' button */ * 0.9, width: (this._props.PanelWidth() / scale) * 0.9, @@ -278,7 +282,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() { }; if (!this.records.length) return 'no data/visualization'; switch (this.dataVizView) { - case DataVizView.TABLE: return ; + case DataVizView.TABLE: return ; case DataVizView.LINECHART: return (this._vizRenderer = r ?? undefined)} vizBox={this} />; case DataVizView.HISTOGRAM: return (this._vizRenderer = r ?? undefined)} />; case DataVizView.PIECHART: return (this._vizRenderer = r ?? undefined)} diff --git a/src/client/views/nodes/DataVizBox/components/Histogram.tsx b/src/client/views/nodes/DataVizBox/components/Histogram.tsx index 412957fb1..44e8b97c6 100644 --- a/src/client/views/nodes/DataVizBox/components/Histogram.tsx +++ b/src/client/views/nodes/DataVizBox/components/Histogram.tsx @@ -20,6 +20,7 @@ export interface HistogramProps { Document: Doc; layoutDoc: Doc; axes: string[]; + titleCol: string; records: { [key: string]: any }[]; width: number; height: number; diff --git a/src/client/views/nodes/DataVizBox/components/LineChart.tsx b/src/client/views/nodes/DataVizBox/components/LineChart.tsx index 2a9a8b354..f23ab94a2 100644 --- a/src/client/views/nodes/DataVizBox/components/LineChart.tsx +++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx @@ -28,6 +28,7 @@ export interface LineChartProps { Document: Doc; layoutDoc: Doc; axes: string[]; + titleCol: string; records: { [key: string]: any }[]; width: number; height: number; diff --git a/src/client/views/nodes/DataVizBox/components/PieChart.tsx b/src/client/views/nodes/DataVizBox/components/PieChart.tsx index 1259a13ff..55c2208a3 100644 --- a/src/client/views/nodes/DataVizBox/components/PieChart.tsx +++ b/src/client/views/nodes/DataVizBox/components/PieChart.tsx @@ -19,6 +19,7 @@ export interface PieChartProps { Document: Doc; layoutDoc: Doc; axes: string[]; + titleCol: string; records: { [key: string]: any }[]; width: number; height: number; diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx index c5fda18ae..c20509029 100644 --- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx +++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx @@ -18,7 +18,9 @@ interface TableBoxProps { layoutDoc: Doc; records: { [key: string]: any }[]; selectAxes: (axes: string[]) => void; + selectTitleCol: (titleCol: string) => void; axes: string[]; + titleCol: string; width: number; height: number; margin: { @@ -153,11 +155,18 @@ export class TableBox extends ObservableReactComponent { }, 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); + if (e.shiftKey){ + if (this._props.titleCol == col) this._props.titleCol = ""; + else this._props.titleCol = col; + this._props.selectTitleCol(this._props.titleCol); + } + else{ + 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); + } }) ); }; @@ -234,7 +243,8 @@ export class TableBox extends ObservableReactComponent { 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; + var 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; + if (this._props.titleCol==col) colSelected = true; return (
{this._props.records[rowId][col]}
-- cgit v1.2.3-70-g09d2 From 16c4a0ad4f9c33e6e52241bef8e6b250237226ae Mon Sep 17 00:00:00 2001 From: srichman333 Date: Mon, 29 Jan 2024 13:00:31 -0500 Subject: show selected names for pie charts + line charts --- .../views/nodes/DataVizBox/components/LineChart.tsx | 15 +++++++++++++-- .../views/nodes/DataVizBox/components/PieChart.tsx | 16 +++++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/components/LineChart.tsx b/src/client/views/nodes/DataVizBox/components/LineChart.tsx index f23ab94a2..47ac751cd 100644 --- a/src/client/views/nodes/DataVizBox/components/LineChart.tsx +++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx @@ -47,7 +47,7 @@ export class LineChart extends ObservableReactComponent { private _disposers: { [key: string]: IReactionDisposer } = {}; private _lineChartRef: React.RefObject = React.createRef(); private _lineChartSvg: d3.Selection | undefined; - @observable _currSelected: SelectedDataPoint | undefined = undefined; + @observable _currSelected: any | 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); @@ -357,6 +357,17 @@ export class LineChart extends ObservableReactComponent { 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'; + var selectedTitle = ""; + if (this._currSelected && this._props.titleCol){ + selectedTitle+= "\n" + this._props.titleCol + ": " + this._tableData.forEach(each => { + var mapThisEntry = false; + if (this._currSelected.x==each[this._props.axes[0]] && this._currSelected.y==each[this._props.axes[1]]) mapThisEntry = true; + else if (this._currSelected.y==each[this._props.axes[0]] && this._currSelected.x==each[this._props.axes[1]]) mapThisEntry = true; + if (mapThisEntry) selectedTitle += each[this._props.titleCol] + ", "; + }) + selectedTitle = selectedTitle.slice(0,-1).slice(0,-1); + } 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]]) ? (
@@ -376,9 +387,9 @@ export class LineChart extends ObservableReactComponent { {selectedPt != 'none' ? (
{`Selected: ${selectedPt}`} + {`${selectedTitle}`} diff --git a/src/client/views/nodes/DataVizBox/components/PieChart.tsx b/src/client/views/nodes/DataVizBox/components/PieChart.tsx index 55c2208a3..f98d51123 100644 --- a/src/client/views/nodes/DataVizBox/components/PieChart.tsx +++ b/src/client/views/nodes/DataVizBox/components/PieChart.tsx @@ -340,14 +340,28 @@ export class PieChart extends ObservableReactComponent { var selected: string; var curSelectedSliceName = ''; if (this._currSelected) { + selected = '{ '; const sliceTitle = this._currSelected[this._props.axes[0]]; curSelectedSliceName = StrCast(sliceTitle) ? StrCast(sliceTitle).replace(/\$/g, '').replace(/\%/g, '').replace(/\#/g, '').replace(/\ { key != '' ? (selected += key + ': ' + this._currSelected[key] + ', ') : ''; }); selected = selected.substring(0, selected.length - 2); selected += ' }'; + if (this._props.titleCol!="" && (!this._currSelected["frequency"] || this._currSelected["frequency"]<10) && this._pieChartData){ + var percentField = Object.keys(this._pieChartData[0])[0]; + var descriptionField = Object.keys(this._pieChartData[0])[1]!; + selected+= "\n" + this._props.titleCol + ": " + this._tableData.forEach(each => { + if (this._currSelected[percentField]==each[percentField]) { + if (descriptionField){ + if (this._currSelected[descriptionField]==each[descriptionField]) selected+= each[this._props.titleCol] + ", "; + } + else selected+= each[this._props.titleCol] + ", "; + } + }) + selected = selected.slice(0,-1).slice(0,-1); + } } else selected = 'none'; var selectedSliceColor; var sliceColors = StrListCast(this._props.layoutDoc.dataViz_pie_sliceColors).map(each => each.split('::')); -- cgit v1.2.3-70-g09d2 From d252886fe97524603ee49e577a535a39f1e664ae Mon Sep 17 00:00:00 2001 From: srichman333 Date: Mon, 29 Jan 2024 13:15:27 -0500 Subject: show title of selected histogram bars --- src/client/views/nodes/DataVizBox/components/Histogram.tsx | 12 ++++++++++++ src/client/views/nodes/DataVizBox/components/PieChart.tsx | 10 ++++------ 2 files changed, 16 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/components/Histogram.tsx b/src/client/views/nodes/DataVizBox/components/Histogram.tsx index 44e8b97c6..c0e738cfa 100644 --- a/src/client/views/nodes/DataVizBox/components/Histogram.tsx +++ b/src/client/views/nodes/DataVizBox/components/Histogram.tsx @@ -452,6 +452,18 @@ export class Histogram extends ObservableReactComponent { : '' ); selected = selected.substring(0, selected.length - 2) + ' }'; + if (this._props.titleCol!="" && (!this._currSelected["frequency"] || this._currSelected["frequency"]<10)){ + selected+= "\n" + this._props.titleCol + ": " + this._tableData.forEach(each => { + if (this._currSelected[this._props.axes[0]]==each[this._props.axes[0]]) { + if (this._props.axes[1]){ + if (this._currSelected[this._props.axes[1]]==each[this._props.axes[1]]) selected+= each[this._props.titleCol] + ", "; + } + else selected+= each[this._props.titleCol] + ", "; + } + }) + selected = selected.slice(0,-1).slice(0,-1); + } } var selectedBarColor; var barColors = StrListCast(this._props.layoutDoc.histogramBarColors).map(each => each.split('::')); diff --git a/src/client/views/nodes/DataVizBox/components/PieChart.tsx b/src/client/views/nodes/DataVizBox/components/PieChart.tsx index f98d51123..54a83879c 100644 --- a/src/client/views/nodes/DataVizBox/components/PieChart.tsx +++ b/src/client/views/nodes/DataVizBox/components/PieChart.tsx @@ -348,14 +348,12 @@ export class PieChart extends ObservableReactComponent { }); selected = selected.substring(0, selected.length - 2); selected += ' }'; - if (this._props.titleCol!="" && (!this._currSelected["frequency"] || this._currSelected["frequency"]<10) && this._pieChartData){ - var percentField = Object.keys(this._pieChartData[0])[0]; - var descriptionField = Object.keys(this._pieChartData[0])[1]!; + if (this._props.titleCol!="" && (!this._currSelected["frequency"] || this._currSelected["frequency"]<10)){ selected+= "\n" + this._props.titleCol + ": " this._tableData.forEach(each => { - if (this._currSelected[percentField]==each[percentField]) { - if (descriptionField){ - if (this._currSelected[descriptionField]==each[descriptionField]) selected+= each[this._props.titleCol] + ", "; + if (this._currSelected[this._props.axes[0]]==each[this._props.axes[0]]) { + if (this._props.axes[1]){ + if (this._currSelected[this._props.axes[1]]==each[this._props.axes[1]]) selected+= each[this._props.titleCol] + ", "; } else selected+= each[this._props.titleCol] + ", "; } -- cgit v1.2.3-70-g09d2 From 9ceb805cec6fa3cab9236b46a1865bbf3436605c Mon Sep 17 00:00:00 2001 From: srichman333 Date: Mon, 29 Jan 2024 16:44:15 -0500 Subject: live schema toggle fix --- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index 742dc60d1..1cd72e29a 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -306,7 +306,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() im const ogHref = CsvCast(ogDoc[this.fieldKey])? CsvCast(ogDoc[this.fieldKey]).url.href : undefined; const href = CsvCast(this.Document[this.fieldKey]).url.href if (ogHref && !DataVizBox.datasetSchemaOG.has(href)){ // sets original dataset to the var - DataVizBox.datasetSchemaOG.set(href, []); + DataVizBox.datasetSchemaOG.set(href, current); fetch('/csvData?uri=' + ogHref) .then(res => res.json().then(action(res => !res.errno && DataVizBox.datasetSchemaOG.set(href, res)))); } -- cgit v1.2.3-70-g09d2 From 5b57029fa39c1ccee9d426be057161e92c5fa759 Mon Sep 17 00:00:00 2001 From: srichman333 Date: Mon, 29 Jan 2024 16:57:34 -0500 Subject: static schema as dataviz doesn't include itself --- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx index 1cd72e29a..66a08f13e 100644 --- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx +++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx @@ -286,7 +286,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() im if (!this.layoutDoc._dataViz_schemaOG){ // makes a copy of the original table for the "live" toggle let csvRows = []; csvRows.push(keys.join(',')); - for (let i = 0; i < children.length; i++) { + for (let i = 0; i < children.length-1; i++) { let eachRow = []; for (let j = 0; j < keys.length; j++) { var cell = children[i][keys[j]]; @@ -306,7 +306,9 @@ export class DataVizBox extends ViewBoxAnnotatableComponent() im const ogHref = CsvCast(ogDoc[this.fieldKey])? CsvCast(ogDoc[this.fieldKey]).url.href : undefined; const href = CsvCast(this.Document[this.fieldKey]).url.href if (ogHref && !DataVizBox.datasetSchemaOG.has(href)){ // sets original dataset to the var + const lastRow = current.pop(); DataVizBox.datasetSchemaOG.set(href, current); + current.push(lastRow!); fetch('/csvData?uri=' + ogHref) .then(res => res.json().then(action(res => !res.errno && DataVizBox.datasetSchemaOG.set(href, res)))); } -- cgit v1.2.3-70-g09d2 From 6d5a43b114b54820e3578862a5429eb096c71058 Mon Sep 17 00:00:00 2001 From: srichman333 Date: Wed, 31 Jan 2024 17:36:41 -0500 Subject: can select 3 columns (+ beginning of basic 2 columns displayed on y axis in linechart) --- .../views/nodes/DataVizBox/components/LineChart.tsx | 19 ++++++++++++++++--- .../views/nodes/DataVizBox/components/TableBox.tsx | 18 ++++++++++++++---- 2 files changed, 30 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/components/LineChart.tsx b/src/client/views/nodes/DataVizBox/components/LineChart.tsx index 47ac751cd..8d6671e65 100644 --- a/src/client/views/nodes/DataVizBox/components/LineChart.tsx +++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx @@ -272,12 +272,25 @@ export class LineChart extends ObservableReactComponent { const data = dataSet[0]; const lineGen = createLineGenerator(xScale, yScale); var validData = data.filter(d => { - var valid = true; Object.keys(data[0]).map(key => { - if (!d[key] || Number.isNaN(d[key])) valid = false; + if (!d[key] || Number.isNaN(d[key])) return false; }); - return valid; + return true; }); + + if (this._props.axes.length>2){ + var next = this._tableData.map(record => ({ x: Number(record[this._props.axes[0]]), y: Number(record[this._props.axes[2]]) })).sort((a, b) => (a.x < b.x ? -1 : 1)); + var validNext = next.filter(d => { + // Object.keys(next[0]).map(key => { + // if (!d[key] || Number.isNaN(d[key])) return false; + // }); + if (!d.x || Number.isNaN(d.x) || !d.y || Number.isNaN(d.y)) valid = false; + return true; + }); + drawLine(svg.append('path'), validNext, lineGen); + this.drawDataPoints(validNext, 0, xScale, yScale); + } + // draw the plot line drawLine(svg.append('path'), validData, lineGen); // draw the datapoint circle diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx index c20509029..1b239b5e5 100644 --- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx +++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx @@ -163,7 +163,7 @@ export class TableBox extends ObservableReactComponent { else{ const newAxes = this._props.axes; if (newAxes.includes(col)) newAxes.splice(newAxes.indexOf(col), 1); - else if (newAxes.length > 1) newAxes[1] = col; + else if (newAxes.length > 2) newAxes[newAxes.length-1] = col; else newAxes.push(col); this._props.selectAxes(newAxes); } @@ -220,8 +220,15 @@ export class TableBox extends ObservableReactComponent { 2 && this._props.axes.lastElement() === col) ? 'darkred' + : (this._props.axes.lastElement()===col || (this._props.axes.length>2 && this._props.axes[1]==col))? 'darkblue' : undefined, + background: this._props.axes.slice().reverse().lastElement() === col ? '#E3fbdb' + : (this._props.axes.length>2 && this._props.axes.lastElement() === col) ? '#Fbdbdb' + : (this._props.axes.lastElement()===col || (this._props.axes.length>2 && this._props.axes[1]==col))? '#c6ebf7' : undefined, + // blue: #ADD8E6 + // green: #E3fbdb + // red: #Fbdbdb fontWeight: 'bolder', border: '3px solid black', }} @@ -243,7 +250,10 @@ export class TableBox extends ObservableReactComponent { background: NumListCast(this._props.layoutDoc.dataViz_highlitedRows).includes(rowId) ? 'lightYellow' : NumListCast(this._props.layoutDoc.dataViz_selectedRows).includes(rowId) ? 'lightgrey' : '', }}> {this.columns.map(col => { - var 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; + var colSelected = false; + if (this._props.axes.length>2) colSelected = this._props.axes[0]==col || this._props.axes[1]==col || this._props.axes[2]==col; + else if (this._props.axes.length>1) colSelected = this._props.axes[0]==col || this._props.axes[1]==col; + else if (this._props.axes.length>0) colSelected = this._props.axes[0]==col; if (this._props.titleCol==col) colSelected = true; return ( -- cgit v1.2.3-70-g09d2 From 4a0f77ae19934273a34e3a57541e7e8c4172b469 Mon Sep 17 00:00:00 2001 From: srichman333 Date: Wed, 31 Jan 2024 17:56:11 -0500 Subject: 2 lines on line charts --- .../nodes/DataVizBox/components/LineChart.tsx | 47 +++++++++++++--------- 1 file changed, 27 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/components/LineChart.tsx b/src/client/views/nodes/DataVizBox/components/LineChart.tsx index 8d6671e65..dd6a6b007 100644 --- a/src/client/views/nodes/DataVizBox/components/LineChart.tsx +++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx @@ -236,21 +236,16 @@ export class LineChart extends ObservableReactComponent { } } - // TODO: nda - can use d3.create() to create html element instead of appending drawChart = (dataSet: any[][], rangeVals: { xMin?: number; xMax?: number; yMin?: number; yMax?: number }, width: number, height: number) => { // clearing tooltip and the current chart d3.select(this._lineChartRef.current).select('svg').remove(); d3.select(this._lineChartRef.current).select('.tooltip').remove(); - const { xMin, xMax, yMin, yMax } = rangeVals; + var { xMin, xMax, yMin, yMax } = rangeVals; if (xMin === undefined || xMax === undefined || yMin === undefined || yMax === undefined) { return; } - // creating the x and y scales - const xScale = scaleCreatorNumerical(xMin, xMax, 0, width); - const yScale = scaleCreatorNumerical(0, yMax, height, 0); - // adding svg const margin = this._props.margin; const svg = (this._lineChartSvg = d3 @@ -262,15 +257,40 @@ export class LineChart extends ObservableReactComponent { .append('g') .attr('transform', `translate(${margin.left}, ${margin.top})`)); + var validSecondData; + if (this._props.axes.length>2){ // for when there are 2 lines on the chart + var next = this._tableData.map(record => ({ x: Number(record[this._props.axes[0]]), y: Number(record[this._props.axes[2]]) })).sort((a, b) => (a.x < b.x ? -1 : 1)); + validSecondData = next.filter(d => { + if (!d.x || Number.isNaN(d.x) || !d.y || Number.isNaN(d.y)) return false; + return true; + }); + var secondDataRange = minMaxRange([validSecondData]); + if (secondDataRange.xMax!>xMax) xMax = secondDataRange.xMax; + if (secondDataRange.yMax!>yMax) yMax = secondDataRange.yMax; + if (secondDataRange.xMin! { Object.keys(data[0]).map(key => { if (!d[key] || Number.isNaN(d[key])) return false; @@ -278,19 +298,6 @@ export class LineChart extends ObservableReactComponent { return true; }); - if (this._props.axes.length>2){ - var next = this._tableData.map(record => ({ x: Number(record[this._props.axes[0]]), y: Number(record[this._props.axes[2]]) })).sort((a, b) => (a.x < b.x ? -1 : 1)); - var validNext = next.filter(d => { - // Object.keys(next[0]).map(key => { - // if (!d[key] || Number.isNaN(d[key])) return false; - // }); - if (!d.x || Number.isNaN(d.x) || !d.y || Number.isNaN(d.y)) valid = false; - return true; - }); - drawLine(svg.append('path'), validNext, lineGen); - this.drawDataPoints(validNext, 0, xScale, yScale); - } - // draw the plot line drawLine(svg.append('path'), validData, lineGen); // draw the datapoint circle -- cgit v1.2.3-70-g09d2 From a1939f7547413aa97c8d8967f57b4bb5aea0cdef Mon Sep 17 00:00:00 2001 From: srichman333 Date: Thu, 1 Feb 2024 00:15:05 -0500 Subject: 2 lines on line chart have a legend --- .../nodes/DataVizBox/components/LineChart.tsx | 34 ++++++++++++++++++---- src/client/views/nodes/DataVizBox/utils/D3Utils.ts | 4 +-- 2 files changed, 30 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DataVizBox/components/LineChart.tsx b/src/client/views/nodes/DataVizBox/components/LineChart.tsx index dd6a6b007..8268d22b6 100644 --- a/src/client/views/nodes/DataVizBox/components/LineChart.tsx +++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx @@ -269,8 +269,6 @@ export class LineChart extends ObservableReactComponent { if (secondDataRange.yMax!>yMax) yMax = secondDataRange.yMax; if (secondDataRange.xMin! { yAxisCreator(svg.append('g'), width, yScale); if (validSecondData) { - drawLine(svg.append('path'), validSecondData, lineGen); + drawLine(svg.append('path'), validSecondData, lineGen, true); this.drawDataPoints(validSecondData, 0, xScale, yScale); + svg.append('path').attr("stroke", "red"); + + // legend + var color = d3.scaleOrdinal() + .range(["black", "blue"]) + .domain([this._props.axes[1], this._props.axes[2]]) + svg.selectAll("mydots") + .data([this._props.axes[1], this._props.axes[2]]) + .enter() + .append("circle") + .attr("cx", 5) + .attr("cy", function(d,i){ return -30 + i*15}) + .attr("r", 7) + .style("fill", function(d){ return color(d)}) + svg.selectAll("mylabels") + .data([this._props.axes[1], this._props.axes[2]]) + .enter() + .append("text") + .attr("x", 25) + .attr("y", function(d,i){ return -30 + i*15}) + .style("fill", function(d){ return color(d)}) + .text(function(d){ return d}) + .attr("text-anchor", "left") + .style("alignment-baseline", "middle") } // get valid data points @@ -299,7 +321,7 @@ export class LineChart extends ObservableReactComponent { }); // draw the plot line - drawLine(svg.append('path'), validData, lineGen); + drawLine(svg.append('path'), validData, lineGen, false); // draw the datapoint circle this.drawDataPoints(validData, 0, xScale, yScale); @@ -312,7 +334,7 @@ export class LineChart extends ObservableReactComponent { const xPos = d3.pointer(e)[0]; const x0 = Math.min(data.length - 1, bisect(data, xScale.invert(xPos - 5))); // shift x by -5 so that you can reach points on the left-side axis const d0 = data[x0]; - if (!d0) return; + if (d0) this.updateTooltip(higlightFocusPt, xScale, d0, yScale, tooltip); this.updateTooltip(higlightFocusPt, xScale, d0, yScale, tooltip); }); @@ -348,7 +370,7 @@ export class LineChart extends ObservableReactComponent { svg.append('text') .attr('transform', 'rotate(-90)' + ' ' + 'translate( 0, ' + -10 + ')') .attr('x', -(height / 2)) - .attr('y', -20) + .attr('y', -30) .attr('height', 20) .attr('width', 20) .style('text-anchor', 'middle') diff --git a/src/client/views/nodes/DataVizBox/utils/D3Utils.ts b/src/client/views/nodes/DataVizBox/utils/D3Utils.ts index 10bfb0c64..336935d23 100644 --- a/src/client/views/nodes/DataVizBox/utils/D3Utils.ts +++ b/src/client/views/nodes/DataVizBox/utils/D3Utils.ts @@ -61,6 +61,6 @@ export const yGrid = (g: d3.Selection, wi ); }; -export const drawLine = (p: d3.Selection, dataPts: DataPoint[], lineGen: d3.Line) => { - p.datum(dataPts).attr('fill', 'none').attr('stroke', 'rgba(53, 162, 235, 0.5)').attr('stroke-width', 2).attr('class', 'line').attr('d', lineGen); +export const drawLine = (p: d3.Selection, dataPts: DataPoint[], lineGen: d3.Line, extra: boolean) => { + p.datum(dataPts).attr('fill', 'none').attr('stroke', 'rgba(53, 162, 235, 0.5)').attr('stroke-width', 2).attr('stroke', extra? 'blue' : 'black').attr('class', 'line').attr('d', lineGen); }; -- cgit v1.2.3-70-g09d2