77
88import style from "./hiplot.scss" ;
99import React from "react" ;
10- import { HiPlotLoadStatus , IDatasets } from "./types" ;
10+ import { Datapoint , HiPlotLoadStatus , IDatasets } from "./types" ;
1111import { HiPlotDataControlProps , RestoreDataBtn , ExcludeDataBtn , ExportDataCSVBtn , KeepDataBtn } from "./controls" ;
1212import { DataProviderClass , DataProviderComponentClass , DataProviderProps } from "./plugin" ;
1313
@@ -22,6 +22,7 @@ import { PersistentState } from "./lib/savedstate";
2222
2323
2424interface HeaderBarProps extends IDatasets , HiPlotDataControlProps {
25+ weightColumn ?: string ;
2526 loadStatus : HiPlotLoadStatus ; // Should not allow to load an xp when already loading another xp
2627 persistentState : PersistentState ;
2728 onLoadExperiment : ( load_promise : Promise < any > ) => void ;
@@ -33,37 +34,64 @@ interface HeaderBarProps extends IDatasets, HiPlotDataControlProps {
3334interface HeaderBarState {
3435 isTextareaFocused : boolean ;
3536 hasTutorial : boolean ;
37+ selectedPct : string ;
38+ selectedPctWeighted : string ;
3639} ;
3740
3841export class HeaderBar extends React . Component < HeaderBarProps , HeaderBarState > {
3942 dataProviderRef = React . createRef < DataProviderClass > ( ) ;
40- selected_count_ref : React . RefObject < HTMLElement > = React . createRef ( ) ;
41- selected_pct_ref : React . RefObject < HTMLElement > = React . createRef ( ) ;
42- total_count_ref : React . RefObject < HTMLElement > = React . createRef ( ) ;
4343 controls_root_ref : React . RefObject < HTMLDivElement > = React . createRef ( ) ;
4444
4545 constructor ( props : HeaderBarProps ) {
4646 super ( props ) ;
4747 this . state = {
4848 isTextareaFocused : false ,
4949 hasTutorial : false ,
50+ selectedPct : '???' ,
51+ selectedPctWeighted : '???' ,
5052 } ;
5153 }
5254 recomputeMetrics ( ) {
53- if ( ! this . selected_count_ref . current ) {
55+ const newSelectedPct = ( 100 * this . props . rows_selected . length / this . props . rows_filtered . length ) . toPrecision ( 3 ) ;
56+ if ( newSelectedPct != this . state . selectedPct ) {
57+ this . setState ( {
58+ selectedPct : ( 100 * this . props . rows_selected . length / this . props . rows_filtered . length ) . toPrecision ( 3 )
59+ } ) ;
60+ }
61+ }
62+ recomputeSelectedWeightedSum ( ) {
63+ if ( ! this . props . weightColumn ) {
64+ this . setState ( {
65+ selectedPctWeighted : '???' ,
66+ } ) ;
5467 return ;
5568 }
56- const selected_count = this . props . rows_selected . length ;
57- const total_count = this . props . rows_filtered . length ;
58- this . selected_count_ref . current . innerText = '' + selected_count ;
59- this . selected_pct_ref . current . innerText = '' + ( 100 * selected_count / total_count ) . toPrecision ( 3 ) ;
60- this . total_count_ref . current . innerText = '' + total_count ;
69+ const getWeight = function ( dp : Datapoint ) : number {
70+ const w = parseFloat ( dp [ this . props . weightColumn ] ) ;
71+ return ! isNaN ( w ) && isFinite ( w ) && w > 0.0 ? w : 1.0 ;
72+ } . bind ( this ) ;
73+ var totalWeightFiltered = 0.0 , totalWeightSelected = 0.0 ;
74+ this . props . rows_filtered . forEach ( function ( dp : Datapoint ) {
75+ totalWeightFiltered += getWeight ( dp ) ;
76+ } ) ;
77+ this . props . rows_selected . forEach ( function ( dp : Datapoint ) {
78+ totalWeightSelected += getWeight ( dp ) ;
79+ } ) ;
80+ const pctage = ( 100 * totalWeightSelected / totalWeightFiltered ) ;
81+ console . assert ( ! isNaN ( pctage ) , { "pctage" : pctage , "totalWeightFiltered" : totalWeightFiltered , "totalWeightSelected" : totalWeightSelected } ) ;
82+ this . setState ( {
83+ selectedPctWeighted : pctage . toPrecision ( 3 )
84+ } ) ;
6185 }
6286 componentDidMount ( ) {
6387 this . recomputeMetrics ( ) ;
88+ this . recomputeSelectedWeightedSum ( ) ;
6489 }
65- componentDidUpdate ( ) {
90+ componentDidUpdate ( prevProps : HeaderBarProps , prevState : HeaderBarState ) : void {
6691 this . recomputeMetrics ( ) ;
92+ if ( prevProps . weightColumn != this . props . weightColumn || this . props . rows_selected != prevProps . rows_selected || this . props . rows_filtered != prevProps . rows_filtered ) {
93+ this . recomputeSelectedWeightedSum ( ) ;
94+ }
6795 }
6896 onToggleTutorial ( ) {
6997 this . setState ( function ( prevState , prevProps ) {
@@ -107,9 +135,15 @@ export class HeaderBar extends React.Component<HeaderBarProps, HeaderBarState> {
107135 </ div >
108136 < div className = { style . controlGroup } >
109137 < div style = { { "fontFamily" : "monospace" , "fontSize" : "14px" } } >
110- Selected: < strong ref = { this . selected_count_ref } style = { { "minWidth" : "4em" , "textAlign" : "right" , "display" : "inline-block" } } > ??</ strong >
111- /< strong ref = { this . total_count_ref } style = { { "minWidth" : "4em" , "textAlign" : "left" , "display" : "inline-block" } } > ??</ strong > (
112- < span style = { { "minWidth" : "3em" , "textAlign" : "right" , "display" : "inline-block" } } ref = { this . selected_pct_ref } > ??</ span > %)
138+ Selected: < strong style = { { "minWidth" : "4em" , "textAlign" : "right" , "display" : "inline-block" } } > { this . props . rows_selected . length } </ strong >
139+ /< strong style = { { "minWidth" : "4em" , "textAlign" : "left" , "display" : "inline-block" } } > { this . props . rows_filtered . length } </ strong > (
140+ { ! this . props . weightColumn &&
141+ < React . Fragment > < span style = { { "minWidth" : "3em" , "textAlign" : "right" , "display" : "inline-block" } } > { this . state . selectedPct } </ span > %</ React . Fragment >
142+ }
143+ { this . props . weightColumn &&
144+ < React . Fragment > < span style = { { "minWidth" : "3em" , "textAlign" : "right" , "display" : "inline-block" } } > { this . state . selectedPctWeighted } </ span > % weighted</ React . Fragment >
145+ }
146+ )
113147 </ div >
114148 </ div >
115149 </ React . Fragment >
0 commit comments