From 8f1161cc7b58ed30933dc0f5c75c1f49fb00472c Mon Sep 17 00:00:00 2001 From: xuke444 <40614413+xuke444@users.noreply.github.com> Date: Thu, 15 Sep 2022 15:12:42 -0700 Subject: [PATCH] clean up dataset explorer (#1721) * clean up dataset explorer Signed-off-by: Ke Xu * add tong and ruby to app code owner Signed-off-by: Ke Xu Signed-off-by: Ke Xu --- .eslintrc/.eslintrc.custom.eslintrc | 9 +- .vscode/settings.json | 1 + CODEOWNERS | 2 +- apps/dashboard/.eslintrc.json | 10 +- libs/causality/.eslintrc.json | 10 +- .../CausalIndividualChart.tsx | 4 - libs/core-ui/.eslintrc.json | 10 +- .../core-ui/src/lib/components/AxisConfig.tsx | 6 - .../src/lib/components/AxisConfigDialog.tsx | 84 +++---- .../src/lib/components/OverallMetricChart.tsx | 4 - libs/counterfactuals/.eslintrc.json | 10 +- .../src/lib/CounterfactualChart.tsx | 4 - libs/dataset-explorer/.eslintrc.json | 10 +- .../src/lib/DatasetExplorerTab.tsx | 214 ++++-------------- libs/dataset-explorer/src/lib/SidePanel.tsx | 81 ++++++- .../src/lib/generateDefaultChartAxes.ts | 46 ++++ libs/error-analysis/.eslintrc.json | 10 +- libs/fairness/.eslintrc.json | 10 +- libs/interpret-text/.eslintrc.json | 10 +- libs/interpret-vision/.eslintrc.json | 10 +- libs/interpret/.eslintrc.json | 10 +- .../Controls/WhatIfTab/WhatIfTab.tsx | 2 - libs/localization/.eslintrc.json | 6 + libs/mlchartlib/.eslintrc.json | 10 +- libs/model-assessment/.eslintrc.json | 10 +- 25 files changed, 235 insertions(+), 348 deletions(-) create mode 100644 libs/dataset-explorer/src/lib/generateDefaultChartAxes.ts diff --git a/.eslintrc/.eslintrc.custom.eslintrc b/.eslintrc/.eslintrc.custom.eslintrc index 7a0826e6f8..a48d41d887 100644 --- a/.eslintrc/.eslintrc.custom.eslintrc +++ b/.eslintrc/.eslintrc.custom.eslintrc @@ -208,7 +208,14 @@ "no-octal-escape": "error", "no-redeclare": "error", "no-regex-spaces": "error", - "no-restricted-syntax": ["error", "WithStatement"], + "no-restricted-syntax": [ + "error", + "WithStatement", + { + "message": "Please don't use bind. Prefer use arrow function.", + "selector": "MemberExpression > Identifier[name='bind']" + } + ], "no-script-url": "error", "no-self-assign": "error", "no-self-compare": "error", diff --git a/.vscode/settings.json b/.vscode/settings.json index ad812f35f1..2275e706b0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -45,6 +45,7 @@ "editor.defaultFormatter": "esbenp.prettier-vscode" }, "cSpell.words": [ + "abbridged", "automl", "bdist", "bgcolor", diff --git a/CODEOWNERS b/CODEOWNERS index 6f45208a96..dbe8cdc831 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -8,7 +8,7 @@ /responsibleai @gaugup @imatiach-msft @xuke444 @kicha0 @RubyZ10 @vinuthakaranth @tongyu-microsoft # App -/apps @xuke444 @vinuthakaranth @romanlutz +/apps @tongyu-microsoft @romanlutz @vinuthakaranth @xuke444 @RubyZ10 #causal ui /libs/causality @tongyu-microsoft @romanlutz @vinuthakaranth @xuke444 @RubyZ10 diff --git a/apps/dashboard/.eslintrc.json b/apps/dashboard/.eslintrc.json index 47f66dd42d..fc254bd8ed 100644 --- a/apps/dashboard/.eslintrc.json +++ b/apps/dashboard/.eslintrc.json @@ -4,15 +4,7 @@ "overrides": [ { "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": { - "no-restricted-syntax": [ - "error", - { - "message": "Please don't use bind. Prefer use arrow function.", - "selector": "MemberExpression > Identifier[name='bind']" - } - ] - } + "rules": {} }, { "files": ["main.tsx"], diff --git a/libs/causality/.eslintrc.json b/libs/causality/.eslintrc.json index fed26cfaa7..133546f4d1 100644 --- a/libs/causality/.eslintrc.json +++ b/libs/causality/.eslintrc.json @@ -4,15 +4,7 @@ "overrides": [ { "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": { - "no-restricted-syntax": [ - "error", - { - "message": "Please don't use bind. Prefer use arrow function.", - "selector": "MemberExpression > Identifier[name='bind']" - } - ] - } + "rules": {} }, { "files": ["*.ts", "*.tsx"], diff --git a/libs/causality/src/lib/CausalAnalysisDashboard/Controls/CausalAnalysisView/CausalIndividualView/CausalIndividualChart.tsx b/libs/causality/src/lib/CausalAnalysisDashboard/Controls/CausalAnalysisView/CausalIndividualView/CausalIndividualChart.tsx index 672bc1113b..7235c73d2c 100644 --- a/libs/causality/src/lib/CausalAnalysisDashboard/Controls/CausalAnalysisView/CausalIndividualView/CausalIndividualChart.tsx +++ b/libs/causality/src/lib/CausalAnalysisDashboard/Controls/CausalAnalysisView/CausalIndividualView/CausalIndividualChart.tsx @@ -126,7 +126,6 @@ export class CausalIndividualChart extends React.PureComponent< this.state.chartProps.yAxis.property ].label } - jointDataset={this.context.jointDataset} orderedGroupTitles={[ ColumnCategories.Index, ColumnCategories.Dataset, @@ -139,7 +138,6 @@ export class CausalIndividualChart extends React.PureComponent< this.state.chartProps.chartType === ChartTypes.Scatter } onAccept={this.onYSet} - telemetryHook={this.props.telemetryHook} /> @@ -168,7 +166,6 @@ export class CausalIndividualChart extends React.PureComponent< this.state.chartProps.xAxis.property ].label } - jointDataset={this.context.jointDataset} orderedGroupTitles={[ ColumnCategories.Index, ColumnCategories.Dataset, @@ -187,7 +184,6 @@ export class CausalIndividualChart extends React.PureComponent< this.state.chartProps.chartType === ChartTypes.Scatter } onAccept={this.onXSet} - telemetryHook={this.props.telemetryHook} /> diff --git a/libs/core-ui/.eslintrc.json b/libs/core-ui/.eslintrc.json index 14ac8464fb..0f8d11bab1 100644 --- a/libs/core-ui/.eslintrc.json +++ b/libs/core-ui/.eslintrc.json @@ -4,15 +4,7 @@ "overrides": [ { "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": { - "no-restricted-syntax": [ - "error", - { - "message": "Please don't use bind. Prefer use arrow function.", - "selector": "MemberExpression > Identifier[name='bind']" - } - ] - } + "rules": {} }, { "files": ["*.ts", "*.tsx"], diff --git a/libs/core-ui/src/lib/components/AxisConfig.tsx b/libs/core-ui/src/lib/components/AxisConfig.tsx index abc6a557e8..5af78c4408 100644 --- a/libs/core-ui/src/lib/components/AxisConfig.tsx +++ b/libs/core-ui/src/lib/components/AxisConfig.tsx @@ -5,8 +5,6 @@ import { DefaultButton } from "@fluentui/react"; import React from "react"; import { ISelectorConfig } from "../util/IGenericChartProps"; -import { ITelemetryEvent } from "../util/ITelemetryEvent"; -import { JointDataset } from "../util/JointDataset"; import { ColumnCategories } from "../util/JointDatasetUtils"; import { AxisConfigDialog } from "./AxisConfigDialog"; @@ -14,14 +12,12 @@ import { AxisConfigDialog } from "./AxisConfigDialog"; export interface IAxisConfigProps { buttonText: string; buttonTitle: string; - jointDataset: JointDataset; orderedGroupTitles: ColumnCategories[]; selectedColumn: ISelectorConfig; canBin: boolean; mustBin: boolean; canDither: boolean; onAccept: (newConfig: ISelectorConfig) => void; - telemetryHook?: (message: ITelemetryEvent) => void; } export interface IAxisConfigState { @@ -49,14 +45,12 @@ export class AxisConfig extends React.PureComponent< {this.state.dialogOpen && ( )} diff --git a/libs/core-ui/src/lib/components/AxisConfigDialog.tsx b/libs/core-ui/src/lib/components/AxisConfigDialog.tsx index 3ec1c93a82..aaaa1c2957 100644 --- a/libs/core-ui/src/lib/components/AxisConfigDialog.tsx +++ b/libs/core-ui/src/lib/components/AxisConfigDialog.tsx @@ -18,8 +18,12 @@ import _ from "lodash"; import React from "react"; import { cohortKey } from "../cohortKey"; +import { + ModelAssessmentContext, + defaultModelAssessmentContext +} from "../Context/ModelAssessmentContext"; import { ISelectorConfig } from "../util/IGenericChartProps"; -import { ITelemetryEvent, TelemetryLevels } from "../util/ITelemetryEvent"; +import { TelemetryLevels } from "../util/ITelemetryEvent"; import { JointDataset } from "../util/JointDataset"; import { ColumnCategories } from "../util/JointDatasetUtils"; import { TelemetryEventName } from "../util/TelemetryEventName"; @@ -33,7 +37,6 @@ import { } from "./AxisConfigDialogUtils"; export interface IAxisConfigDialogProps { - jointDataset: JointDataset; orderedGroupTitles: ColumnCategories[]; selectedColumn: ISelectorConfig; canBin: boolean; @@ -41,63 +44,66 @@ export interface IAxisConfigDialogProps { canDither: boolean; onAccept: (newConfig: ISelectorConfig) => void; onCancel: () => void; - telemetryHook?: (message: ITelemetryEvent) => void; } export interface IAxisConfigDialogState { selectedColumn: ISelectorConfig; binCount?: number; selectedFilterGroup?: string; + dataArray: IComboBoxOption[]; + classArray: IComboBoxOption[]; } export class AxisConfigDialog extends React.PureComponent< IAxisConfigDialogProps, IAxisConfigDialogState > { + public static contextType = ModelAssessmentContext; private static readonly MIN_HIST_COLS = 2; private static readonly MAX_HIST_COLS = 40; private static readonly DEFAULT_BIN_COUNT = 5; - private readonly dataArray: IComboBoxOption[] = new Array( - this.props.jointDataset.datasetFeatureCount - ) - .fill(0) - .map((_, index) => { - const key = JointDataset.DataLabelRoot + index.toString(); - return { - key, - text: this.props.jointDataset.metaDict[key].abbridgedLabel - }; - }); - private readonly classArray: IComboBoxOption[] = new Array( - this.props.jointDataset.predictionClassCount - ) - .fill(0) - .map((_, index) => { - const key = JointDataset.ProbabilityYRoot + index.toString(); - return { - key, - text: this.props.jointDataset.metaDict[key].abbridgedLabel - }; - }); - public constructor(props: IAxisConfigDialogProps) { - super(props); - this.state = { + public context: React.ContextType = + defaultModelAssessmentContext; + + public componentDidMount(): void { + this.setState({ binCount: getBinCountForProperty( - this.props.jointDataset.metaDict[this.props.selectedColumn.property], + this.context.jointDataset.metaDict[this.props.selectedColumn.property], this.props.canBin, AxisConfigDialog.DEFAULT_BIN_COUNT ), + classArray: new Array(this.context.jointDataset.predictionClassCount) + .fill(0) + .map((_, index) => { + const key = JointDataset.ProbabilityYRoot + index.toString(); + return { + key, + text: this.context.jointDataset.metaDict[key].abbridgedLabel + }; + }), + dataArray: new Array(this.context.jointDataset.datasetFeatureCount) + .fill(0) + .map((_, index) => { + const key = JointDataset.DataLabelRoot + index.toString(); + return { + key, + text: this.context.jointDataset.metaDict[key].abbridgedLabel + }; + }), selectedColumn: _.cloneDeep(this.props.selectedColumn), selectedFilterGroup: extractSelectionKey( this.props.selectedColumn.property ) - }; + }); } public render(): React.ReactNode { + if (!this.state) { + return React.Fragment; + } const selectedMeta = - this.props.jointDataset.metaDict[this.state.selectedColumn.property]; + this.context.jointDataset.metaDict[this.state.selectedColumn.property]; const isDataColumn = this.state.selectedColumn.property.includes( JointDataset.DataLabelRoot ); @@ -119,6 +125,7 @@ export class AxisConfigDialog extends React.PureComponent< {isDataColumn && ( { if (this.state.binCount) { - this.props.jointDataset.addBin( + this.context.jointDataset.addBin( this.state.selectedColumn.property, this.state.binCount ); } this.props.onAccept(this.state.selectedColumn); - this.props.telemetryHook?.({ + this.context.telemetryHook?.({ level: TelemetryLevels.ButtonClick, type: TelemetryEventName.NewAxisConfigSelected }); @@ -251,9 +259,9 @@ export class AxisConfigDialog extends React.PureComponent< private setDefaultStateForKey(property: string): void { const dither = this.props.canDither && - this.props.jointDataset.metaDict[property]?.treatAsCategorical; + this.context.jointDataset.metaDict[property]?.treatAsCategorical; const binCount = getBinCountForProperty( - this.props.jointDataset.metaDict[property], + this.context.jointDataset.metaDict[property], this.props.canBin, AxisConfigDialog.DEFAULT_BIN_COUNT ); diff --git a/libs/core-ui/src/lib/components/OverallMetricChart.tsx b/libs/core-ui/src/lib/components/OverallMetricChart.tsx index 7be3fef98e..10bb44ac55 100644 --- a/libs/core-ui/src/lib/components/OverallMetricChart.tsx +++ b/libs/core-ui/src/lib/components/OverallMetricChart.tsx @@ -121,7 +121,6 @@ export class OverallMetricChart extends React.PureComponent<
{this.state.yDialogOpen && ( )} {this.state.xDialogOpen && ( )}
diff --git a/libs/counterfactuals/.eslintrc.json b/libs/counterfactuals/.eslintrc.json index fed26cfaa7..133546f4d1 100644 --- a/libs/counterfactuals/.eslintrc.json +++ b/libs/counterfactuals/.eslintrc.json @@ -4,15 +4,7 @@ "overrides": [ { "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": { - "no-restricted-syntax": [ - "error", - { - "message": "Please don't use bind. Prefer use arrow function.", - "selector": "MemberExpression > Identifier[name='bind']" - } - ] - } + "rules": {} }, { "files": ["*.ts", "*.tsx"], diff --git a/libs/counterfactuals/src/lib/CounterfactualChart.tsx b/libs/counterfactuals/src/lib/CounterfactualChart.tsx index a19ef5ab7b..a3990015ba 100644 --- a/libs/counterfactuals/src/lib/CounterfactualChart.tsx +++ b/libs/counterfactuals/src/lib/CounterfactualChart.tsx @@ -103,7 +103,6 @@ export class CounterfactualChart extends React.PureComponent< )} {this.state.yDialogOpen && ( )} {this.state.xDialogOpen && ( )} diff --git a/libs/dataset-explorer/.eslintrc.json b/libs/dataset-explorer/.eslintrc.json index fed26cfaa7..133546f4d1 100644 --- a/libs/dataset-explorer/.eslintrc.json +++ b/libs/dataset-explorer/.eslintrc.json @@ -4,15 +4,7 @@ "overrides": [ { "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": { - "no-restricted-syntax": [ - "error", - { - "message": "Please don't use bind. Prefer use arrow function.", - "selector": "MemberExpression > Identifier[name='bind']" - } - ] - } + "rules": {} }, { "files": ["*.ts", "*.tsx"], diff --git a/libs/dataset-explorer/src/lib/DatasetExplorerTab.tsx b/libs/dataset-explorer/src/lib/DatasetExplorerTab.tsx index fb6f546314..b60c23c592 100644 --- a/libs/dataset-explorer/src/lib/DatasetExplorerTab.tsx +++ b/libs/dataset-explorer/src/lib/DatasetExplorerTab.tsx @@ -5,14 +5,10 @@ import { getTheme, IDropdownOption, Dropdown, - DefaultButton, Text, - IChoiceGroupOption, Stack } from "@fluentui/react"; import { - AxisConfigDialog, - JointDataset, ColumnCategories, cohortKey, ChartTypes, @@ -25,13 +21,15 @@ import { BasicHighChart, TelemetryLevels, TelemetryEventName, - ITelemetryEvent + ITelemetryEvent, + AxisConfig } from "@responsible-ai/core-ui"; import { localization } from "@responsible-ai/localization"; import _ from "lodash"; import React from "react"; import { datasetExplorerTabStyles } from "./DatasetExplorerTab.styles"; +import { generateDefaultChartAxes } from "./generateDefaultChartAxes"; import { generatePlotlyProps } from "./generatePlotlyProps"; import { getDatasetOption } from "./getDatasetOption"; import { SidePanel } from "./SidePanel"; @@ -41,9 +39,6 @@ export interface IDatasetExplorerTabProps { } export interface IDatasetExplorerTabState { - xDialogOpen: boolean; - yDialogOpen: boolean; - colorDialogOpen: boolean; selectedCohortIndex: number; chartProps?: IGenericChartProps; } @@ -62,10 +57,7 @@ export class DatasetExplorerTab extends React.Component< super(props); this.state = { - colorDialogOpen: false, - selectedCohortIndex: 0, - xDialogOpen: false, - yDialogOpen: false + selectedCohortIndex: 0 }; } @@ -73,7 +65,7 @@ export class DatasetExplorerTab extends React.Component< const initialCohortIndex = 0; this.setState({ - chartProps: this.generateDefaultChartAxes(), + chartProps: generateDefaultChartAxes(this.context.jointDataset), selectedCohortIndex: initialCohortIndex }); } @@ -165,61 +157,6 @@ export class DatasetExplorerTab extends React.Component< )} - - {this.state.yDialogOpen && ( - - )} - {this.state.xDialogOpen && ( - - )} - {this.state.colorDialogOpen && this.state.chartProps.colorAxis && ( - - )} -
@@ -227,14 +164,21 @@ export class DatasetExplorerTab extends React.Component<
-
- @@ -293,6 +253,9 @@ export class DatasetExplorerTab extends React.Component< ); } + private onChartPropsChange = (chartProps: IGenericChartProps): void => { + this.setState({ chartProps }); + }; private setSelectedCohort = ( _: React.FormEvent, @@ -304,22 +267,6 @@ export class DatasetExplorerTab extends React.Component< } }; - private onChartTypeChange = ( - _ev?: React.SyntheticEvent, - item?: IChoiceGroupOption - ): void => { - const newProps = _.cloneDeep(this.state.chartProps); - if (item?.key === undefined || !newProps) { - return; - } - newProps.chartType = item.key as ChartTypes; - if (newProps.yAxis.property === ColumnCategories.None) { - newProps.yAxis = this.generateDefaultYAxis(); - } - this.setState({ chartProps: newProps }); - this.logButtonClick(TelemetryEventName.DatasetExplorerNewChartTypeSelected); - }; - private logButtonClick = (eventName: TelemetryEventName): void => { this.props.telemetryHook?.({ level: TelemetryLevels.ButtonClick, @@ -327,45 +274,13 @@ export class DatasetExplorerTab extends React.Component< }); }; - private readonly setXOpen = (): void => { - if (this.state.xDialogOpen === false) { - this.setState({ xDialogOpen: true }); - return; - } - this.setState({ xDialogOpen: false }); - }; - - private readonly setXClose = (): void => { - this.setState({ xDialogOpen: false }); - }; - - private readonly setColorOpen = (): void => { - this.setState({ colorDialogOpen: true }); - }; - - private readonly setColorClose = (): void => { - this.setState({ colorDialogOpen: false }); - }; - - private readonly setYOpen = (): void => { - if (this.state.yDialogOpen === false) { - this.setState({ yDialogOpen: true }); - return; - } - this.setState({ yDialogOpen: false }); - }; - - private readonly setYClose = (): void => { - this.setState({ yDialogOpen: false }); - }; - private onXSet = (value: ISelectorConfig): void => { if (!this.state.chartProps) { return; } const newProps = _.cloneDeep(this.state.chartProps); newProps.xAxis = value; - this.setState({ chartProps: newProps, xDialogOpen: false }); + this.setState({ chartProps: newProps }); }; private onYSet = (value: ISelectorConfig): void => { @@ -374,49 +289,6 @@ export class DatasetExplorerTab extends React.Component< } const newProps = _.cloneDeep(this.state.chartProps); newProps.yAxis = value; - this.setState({ chartProps: newProps, yDialogOpen: false }); - }; - - private onColorSet = (value: ISelectorConfig): void => { - if (!this.state.chartProps) { - return; - } - const newProps = _.cloneDeep(this.state.chartProps); - newProps.colorAxis = value; - this.setState({ chartProps: newProps, colorDialogOpen: false }); + this.setState({ chartProps: newProps }); }; - - private generateDefaultChartAxes(): IGenericChartProps | undefined { - if (!this.context.jointDataset.hasDataset) { - return; - } - const chartProps: IGenericChartProps = { - chartType: ChartTypes.Histogram, - colorAxis: { - options: {}, - property: this.context.jointDataset.hasPredictedY - ? JointDataset.PredictedYLabel - : JointDataset.IndexLabel - }, - xAxis: { - options: {}, - property: JointDataset.IndexLabel - }, - yAxis: this.generateDefaultYAxis() - }; - return chartProps; - } - - private generateDefaultYAxis(): ISelectorConfig { - const yKey = `${JointDataset.DataLabelRoot}0`; - const yIsDithered = - this.context.jointDataset.metaDict[yKey]?.treatAsCategorical; - return { - options: { - bin: false, - dither: yIsDithered - }, - property: yKey - }; - } } diff --git a/libs/dataset-explorer/src/lib/SidePanel.tsx b/libs/dataset-explorer/src/lib/SidePanel.tsx index a2ab35d6b2..9c33d82b9d 100644 --- a/libs/dataset-explorer/src/lib/SidePanel.tsx +++ b/libs/dataset-explorer/src/lib/SidePanel.tsx @@ -15,27 +15,34 @@ import { ChartTypes, IGenericChartProps, InteractiveLegend, - FluentUIStyles + FluentUIStyles, + AxisConfigDialog, + ISelectorConfig, + TelemetryLevels, + TelemetryEventName } from "@responsible-ai/core-ui"; import { localization } from "@responsible-ai/localization"; import _ from "lodash"; import React from "react"; import { datasetExplorerTabStyles } from "./DatasetExplorerTab.styles"; +import { generateDefaultYAxis } from "./generateDefaultChartAxes"; export interface ISidePanelProps { chartProps: IGenericChartProps; jointDataset: JointDataset; cohorts: Cohort[]; selectedCohortIndex: number; - setColorOpen(): void; - onChartTypeChange( - ev?: React.SyntheticEvent, - item?: IChoiceGroupOption - ): void; + onChartPropChange: (p: IGenericChartProps) => void; +} +interface ISidePanelState { + colorDialogOpen: boolean; } -export class SidePanel extends React.Component { +export class SidePanel extends React.Component< + ISidePanelProps, + ISidePanelState +> { private readonly chartOptions: IChoiceGroupOption[] = [ { key: ChartTypes.Histogram, @@ -46,6 +53,12 @@ export class SidePanel extends React.Component { text: localization.Interpret.DatasetExplorer.individualDatapoints } ]; + public constructor(props: ISidePanelProps) { + super(props); + this.state = { + colorDialogOpen: false + }; + } public render(): React.ReactNode { const classNames = datasetExplorerTabStyles(); const colorSeries = this.buildColorLegend(); @@ -57,8 +70,23 @@ export class SidePanel extends React.Component { label={localization.Interpret.DatasetExplorer.chartType} selectedKey={this.props.chartProps.chartType} options={this.chartOptions} - onChange={this.props.onChartTypeChange} + onChange={this.onChartTypeChange} /> + {this.state.colorDialogOpen && this.props.chartProps.colorAxis && ( + + )} {this.props.chartProps.chartType === ChartTypes.Scatter && ( { ); } + private readonly setColorOpen = (): void => { + this.setState({ colorDialogOpen: true }); + }; + + private onChartTypeChange = ( + _ev?: React.SyntheticEvent, + item?: IChoiceGroupOption + ): void => { + const newProps = _.cloneDeep(this.props.chartProps); + if (item?.key === undefined || !newProps) { + return; + } + newProps.chartType = item.key as ChartTypes; + if (newProps.yAxis.property === ColumnCategories.None) { + newProps.yAxis = generateDefaultYAxis(this.context.jointDataset); + } + this.props.onChartPropChange(newProps); + this.context.telemetryHook?.({ + level: TelemetryLevels.ButtonClick, + type: TelemetryEventName.DatasetExplorerNewChartTypeSelected + }); + }; + private onColorSet = (value: ISelectorConfig): void => { + if (!this.props.chartProps) { + return; + } + const newProps = _.cloneDeep(this.props.chartProps); + newProps.colorAxis = value; + this.props.onChartPropChange(newProps); + }; + + private readonly setColorClose = (): void => { + this.setState({ colorDialogOpen: false }); + }; + private buildColorLegend(): string[] | undefined { if (!this.props.chartProps) { return; diff --git a/libs/dataset-explorer/src/lib/generateDefaultChartAxes.ts b/libs/dataset-explorer/src/lib/generateDefaultChartAxes.ts new file mode 100644 index 0000000000..c69e6c9f5f --- /dev/null +++ b/libs/dataset-explorer/src/lib/generateDefaultChartAxes.ts @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { + IGenericChartProps, + ChartTypes, + JointDataset, + ISelectorConfig +} from "@responsible-ai/core-ui"; + +export function generateDefaultChartAxes( + jointDataset: JointDataset +): IGenericChartProps | undefined { + if (!jointDataset.hasDataset) { + return; + } + const chartProps: IGenericChartProps = { + chartType: ChartTypes.Histogram, + colorAxis: { + options: {}, + property: jointDataset.hasPredictedY + ? JointDataset.PredictedYLabel + : JointDataset.IndexLabel + }, + xAxis: { + options: {}, + property: JointDataset.IndexLabel + }, + yAxis: generateDefaultYAxis(jointDataset) + }; + return chartProps; +} + +export function generateDefaultYAxis( + jointDataset: JointDataset +): ISelectorConfig { + const yKey = `${JointDataset.DataLabelRoot}0`; + const yIsDithered = jointDataset.metaDict[yKey]?.treatAsCategorical; + return { + options: { + bin: false, + dither: yIsDithered + }, + property: yKey + }; +} diff --git a/libs/error-analysis/.eslintrc.json b/libs/error-analysis/.eslintrc.json index fed26cfaa7..133546f4d1 100644 --- a/libs/error-analysis/.eslintrc.json +++ b/libs/error-analysis/.eslintrc.json @@ -4,15 +4,7 @@ "overrides": [ { "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": { - "no-restricted-syntax": [ - "error", - { - "message": "Please don't use bind. Prefer use arrow function.", - "selector": "MemberExpression > Identifier[name='bind']" - } - ] - } + "rules": {} }, { "files": ["*.ts", "*.tsx"], diff --git a/libs/fairness/.eslintrc.json b/libs/fairness/.eslintrc.json index fed26cfaa7..133546f4d1 100644 --- a/libs/fairness/.eslintrc.json +++ b/libs/fairness/.eslintrc.json @@ -4,15 +4,7 @@ "overrides": [ { "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": { - "no-restricted-syntax": [ - "error", - { - "message": "Please don't use bind. Prefer use arrow function.", - "selector": "MemberExpression > Identifier[name='bind']" - } - ] - } + "rules": {} }, { "files": ["*.ts", "*.tsx"], diff --git a/libs/interpret-text/.eslintrc.json b/libs/interpret-text/.eslintrc.json index fed26cfaa7..133546f4d1 100644 --- a/libs/interpret-text/.eslintrc.json +++ b/libs/interpret-text/.eslintrc.json @@ -4,15 +4,7 @@ "overrides": [ { "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": { - "no-restricted-syntax": [ - "error", - { - "message": "Please don't use bind. Prefer use arrow function.", - "selector": "MemberExpression > Identifier[name='bind']" - } - ] - } + "rules": {} }, { "files": ["*.ts", "*.tsx"], diff --git a/libs/interpret-vision/.eslintrc.json b/libs/interpret-vision/.eslintrc.json index 442a641d2f..9d9c0db55b 100644 --- a/libs/interpret-vision/.eslintrc.json +++ b/libs/interpret-vision/.eslintrc.json @@ -4,15 +4,7 @@ "overrides": [ { "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": { - "no-restricted-syntax": [ - "error", - { - "message": "Please don't use bind. Prefer use arrow function.", - "selector": "MemberExpression > Identifier[name='bind']" - } - ] - } + "rules": {} }, { "files": ["*.ts", "*.tsx"], diff --git a/libs/interpret/.eslintrc.json b/libs/interpret/.eslintrc.json index fed26cfaa7..133546f4d1 100644 --- a/libs/interpret/.eslintrc.json +++ b/libs/interpret/.eslintrc.json @@ -4,15 +4,7 @@ "overrides": [ { "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": { - "no-restricted-syntax": [ - "error", - { - "message": "Please don't use bind. Prefer use arrow function.", - "selector": "MemberExpression > Identifier[name='bind']" - } - ] - } + "rules": {} }, { "files": ["*.ts", "*.tsx"], diff --git a/libs/interpret/src/lib/MLIDashboard/Controls/WhatIfTab/WhatIfTab.tsx b/libs/interpret/src/lib/MLIDashboard/Controls/WhatIfTab/WhatIfTab.tsx index 028d62aee8..52035d288d 100644 --- a/libs/interpret/src/lib/MLIDashboard/Controls/WhatIfTab/WhatIfTab.tsx +++ b/libs/interpret/src/lib/MLIDashboard/Controls/WhatIfTab/WhatIfTab.tsx @@ -367,7 +367,6 @@ export class WhatIfTab extends React.PureComponent< > {this.state.yDialogOpen && ( Identifier[name='bind']" - } - ] - } + "rules": {} }, { "files": ["*.ts", "*.tsx"], diff --git a/libs/model-assessment/.eslintrc.json b/libs/model-assessment/.eslintrc.json index fed26cfaa7..133546f4d1 100644 --- a/libs/model-assessment/.eslintrc.json +++ b/libs/model-assessment/.eslintrc.json @@ -4,15 +4,7 @@ "overrides": [ { "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": { - "no-restricted-syntax": [ - "error", - { - "message": "Please don't use bind. Prefer use arrow function.", - "selector": "MemberExpression > Identifier[name='bind']" - } - ] - } + "rules": {} }, { "files": ["*.ts", "*.tsx"],