/* * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import style from "./hiplot.scss"; import React from "react"; import { Datapoint, HiPlotLoadStatus, IDatasets } from "./types"; import { HiPlotDataControlProps, RestoreDataBtn, ExcludeDataBtn, ExportDataCSVBtn, KeepDataBtn } from "./controls"; import { DataProviderClass, DataProviderComponentClass, DataProviderProps} from "./plugin"; //@ts-ignore import IconSVG from "../hiplot/static/icon.svg"; //@ts-ignore import IconSVGW from "../hiplot/static/icon-w.svg"; import { HiPlotTutorial } from "./tutorial/tutorial"; import { PersistentState } from "./lib/savedstate"; interface HeaderBarProps extends IDatasets, HiPlotDataControlProps { weightColumn?: string; loadStatus: HiPlotLoadStatus; // Should not allow to load an xp when already loading another xp persistentState: PersistentState; onLoadExperiment: (load_promise: Promise) => void; dark: boolean; dataProvider: DataProviderClass; }; interface HeaderBarState { isTextareaFocused: boolean; hasTutorial: boolean; selectedPct: string; selectedPctWeighted: string; }; export class HeaderBar extends React.Component { dataProviderRef = React.createRef(); controls_root_ref: React.RefObject = React.createRef(); constructor(props: HeaderBarProps) { super(props); this.state = { isTextareaFocused: false, hasTutorial: false, selectedPct: '???', selectedPctWeighted: '???', }; } recomputeMetrics() { const newSelectedPct = (100 * this.props.rows_selected.length / this.props.rows_filtered.length).toPrecision(3); if (newSelectedPct != this.state.selectedPct) { this.setState({ selectedPct: (100 * this.props.rows_selected.length / this.props.rows_filtered.length).toPrecision(3) }); } } recomputeSelectedWeightedSum() { if (!this.props.weightColumn) { this.setState({ selectedPctWeighted: '???', }); return; } const getWeight = function(dp: Datapoint): number { const w = parseFloat(dp[this.props.weightColumn]); return !isNaN(w) && isFinite(w) && w > 0.0 ? w : 1.0; }.bind(this); var totalWeightFiltered = 0.0, totalWeightSelected = 0.0; this.props.rows_filtered.forEach(function(dp: Datapoint) { totalWeightFiltered += getWeight(dp); }); this.props.rows_selected.forEach(function(dp: Datapoint) { totalWeightSelected += getWeight(dp); }); const pctage = (100 * totalWeightSelected / totalWeightFiltered); console.assert(!isNaN(pctage), {"pctage": pctage, "totalWeightFiltered": totalWeightFiltered, "totalWeightSelected": totalWeightSelected}); this.setState({ selectedPctWeighted: pctage.toPrecision(3) }); } componentDidMount() { this.recomputeMetrics(); this.recomputeSelectedWeightedSum(); } componentDidUpdate(prevProps: HeaderBarProps, prevState: HeaderBarState): void { this.recomputeMetrics(); if (prevProps.weightColumn != this.props.weightColumn || this.props.rows_selected != prevProps.rows_selected || this.props.rows_filtered != prevProps.rows_filtered) { this.recomputeSelectedWeightedSum(); } } onToggleTutorial() { this.setState(function(prevState, prevProps) { return { hasTutorial: !prevState.hasTutorial }; }); } onRefresh() { const promise = this.dataProviderRef.current.refresh(); if (promise !== null) { this.props.onLoadExperiment(promise); } } renderControls() { const dataProviderProps: React.ClassAttributes & DataProviderProps = { ref: this.dataProviderRef, persistentState: this.props.persistentState, loadStatus: this.props.loadStatus, hasFocus: this.state.isTextareaFocused, onFocusChange: (hasFocus: boolean) => this.setState({isTextareaFocused: hasFocus}), onLoadExperiment: this.props.onLoadExperiment, }; return ( {React.createElement(this.props.dataProvider, dataProviderProps)} {this.props.loadStatus == HiPlotLoadStatus.Loaded && !this.state.isTextareaFocused &&
{this.dataProviderRef.current && this.dataProviderRef.current.refresh && }
Selected: {this.props.rows_selected.length} /{this.props.rows_filtered.length} ( {!this.props.weightColumn && {this.state.selectedPct}% } {this.props.weightColumn && {this.state.selectedPctWeighted}% weighted } )
}
); } render() { return (
{this.renderControls()}
{this.state.hasTutorial && this.setState({hasTutorial: false})).bind(this)}/>}
); } }; interface ErrorDisplayProps { error: string; } export class ErrorDisplay extends React.Component { render() { return (

{this.props.error}

HiPlot encountered the error above - more information might be available in your browser's developer web console, or in the server output

); } }