update cohort (#812)
move cohort info and buttons to sticky menu replace error stats with filters
This commit is contained in:
Родитель
873d121a4d
Коммит
cc50e02db0
|
@ -7,7 +7,7 @@ export function describeCreateCohort(dataShape: IInterpretData): void {
|
|||
it("should have no filter by default", () => {
|
||||
cy.get('button:contains("New cohort")')
|
||||
.click()
|
||||
.get('#cohortEditPanel span:contains("No filters added yet")')
|
||||
.get('#cohortEditPanel span:contains("No filters")')
|
||||
.should("exist");
|
||||
});
|
||||
it("should able to add filter", () => {
|
||||
|
@ -15,9 +15,7 @@ export function describeCreateCohort(dataShape: IInterpretData): void {
|
|||
cy.get('#cohortEditPanel [type="radio"]').first().check();
|
||||
cy.get('button:contains("Add filter")').click();
|
||||
|
||||
cy.get('#cohortEditPanel span:contains("No filters added yet")').should(
|
||||
"not.exist"
|
||||
);
|
||||
cy.get('#cohortEditPanel span:contains("No filters")').should("not.exist");
|
||||
});
|
||||
it("should able to add multiple filters", () => {
|
||||
cy.get('#cohortEditPanel [type="radio"]').first().check();
|
||||
|
@ -39,9 +37,7 @@ export function describeCreateCohort(dataShape: IInterpretData): void {
|
|||
.click()
|
||||
.get("#removeFilterBtn-0")
|
||||
.click();
|
||||
cy.get('#cohortEditPanel span:contains("No filters added yet")').should(
|
||||
"exist"
|
||||
);
|
||||
cy.get('#cohortEditPanel span:contains("No filters")').should("exist");
|
||||
});
|
||||
it("should show error message with no cohort name", () => {
|
||||
cy.get("#cohortEditPanel input:eq(0)").clear();
|
||||
|
|
|
@ -3,14 +3,15 @@
|
|||
|
||||
export * from "./lib/cohortKey";
|
||||
export * from "./lib/Cohort/Cohort";
|
||||
export * from "./lib/Cohort/CohortList/CohortList";
|
||||
export * from "./lib/Cohort/Constants";
|
||||
export * from "./lib/Cohort/ErrorCohort";
|
||||
export * from "./lib/Cohort/CohortStats";
|
||||
export * from "./lib/Cohort/ManualCohortManagement/CohortEditorFilterList";
|
||||
export * from "./lib/Cohort/CohortBasedComponent";
|
||||
export * from "./lib/Cohort/CohortInfo/CohortInfo";
|
||||
export * from "./lib/Cohort/CohortInfo/CohortInfoPanel";
|
||||
export * from "./lib/Cohort/CohortInfoSection/CohortInfoSection";
|
||||
export * from "./lib/Cohort/CohortSettingsPanel/CohortSettingsPanel";
|
||||
export * from "./lib/Cohort/CohortList/CohortListPanel";
|
||||
export * from "./lib/Cohort/EditCohort/EditCohort";
|
||||
export * from "./lib/Cohort/ManualCohortManagement/CohortBar";
|
||||
|
|
|
@ -18,8 +18,8 @@ import { JointDataset } from "../../util/JointDataset";
|
|||
export interface ICohortEditorFilterList {
|
||||
filters: IFilter[];
|
||||
jointDataset: JointDataset;
|
||||
editFilter(index: number): void;
|
||||
removeFilter(index: number): void;
|
||||
editFilter?(index: number): void;
|
||||
removeFilter?(index: number): void;
|
||||
}
|
||||
|
||||
export class CohortEditorFilterList extends React.Component<ICohortEditorFilterList> {
|
||||
|
@ -46,16 +46,20 @@ export class CohortEditorFilterList extends React.Component<ICohortEditorFilterL
|
|||
return (
|
||||
<div key={index}>
|
||||
{this.setFilterLabel(filter)}
|
||||
<IconButton
|
||||
id={`editFilerBtn-${index}`}
|
||||
iconProps={{ iconName: "Edit" }}
|
||||
onClick={(): void => this.props.editFilter(index)}
|
||||
/>
|
||||
<IconButton
|
||||
id={`removeFilterBtn-${index}`}
|
||||
iconProps={{ iconName: "Clear" }}
|
||||
onClick={(): void => this.props.removeFilter(index)}
|
||||
/>
|
||||
{this.props.editFilter && (
|
||||
<IconButton
|
||||
id={`editFilerBtn-${index}`}
|
||||
iconProps={{ iconName: "Edit" }}
|
||||
onClick={(): void => this.props.editFilter?.(index)}
|
||||
/>
|
||||
)}
|
||||
{this.props.removeFilter && (
|
||||
<IconButton
|
||||
id={`removeFilterBtn-${index}`}
|
||||
iconProps={{ iconName: "Clear" }}
|
||||
onClick={(): void => this.props.removeFilter?.(index)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import { ITheme } from "office-ui-fabric-react";
|
||||
import React from "react";
|
||||
|
||||
import { Cohort } from "../Cohort/Cohort";
|
||||
import { ErrorCohort } from "../Cohort/ErrorCohort";
|
||||
import {
|
||||
ICausalAnalysisData,
|
||||
|
@ -50,14 +51,12 @@ export interface IModelAssessmentContext {
|
|||
explanationAlgorithm?: string
|
||||
) => Promise<any[]>)
|
||||
| undefined;
|
||||
updateErrorCohorts(
|
||||
cohorts: ErrorCohort[],
|
||||
selectedCohort: ErrorCohort,
|
||||
baseCohort?: ErrorCohort
|
||||
): void;
|
||||
shiftErrorCohort(cohort: ErrorCohort): void;
|
||||
addCohort(cohort: Cohort): void;
|
||||
}
|
||||
|
||||
export const defaultModelAssessmentContext: IModelAssessmentContext = {
|
||||
addCohort: () => undefined,
|
||||
baseErrorCohort: {} as ErrorCohort,
|
||||
dataset: {} as IDataset,
|
||||
errorCohorts: [],
|
||||
|
@ -67,9 +66,9 @@ export const defaultModelAssessmentContext: IModelAssessmentContext = {
|
|||
requestLocalFeatureExplanations: undefined,
|
||||
requestPredictions: undefined,
|
||||
selectedErrorCohort: {} as ErrorCohort,
|
||||
shiftErrorCohort: () => undefined,
|
||||
telemetryHook: () => undefined,
|
||||
theme: {} as ITheme,
|
||||
updateErrorCohorts: () => undefined
|
||||
theme: {} as ITheme
|
||||
};
|
||||
const modelAssessmentContext = React.createContext<IModelAssessmentContext>(
|
||||
defaultModelAssessmentContext
|
||||
|
|
|
@ -333,6 +333,8 @@ export class ErrorAnalysisDashboard extends React.PureComponent<
|
|||
return (
|
||||
<ModelAssessmentContext.Provider
|
||||
value={{
|
||||
//error analysis does not have manual cohort adding
|
||||
addCohort: () => undefined,
|
||||
baseErrorCohort: this.state.baseCohort,
|
||||
dataset: {} as IDataset,
|
||||
errorCohorts: this.state.cohorts,
|
||||
|
@ -345,13 +347,13 @@ export class ErrorAnalysisDashboard extends React.PureComponent<
|
|||
this.props.requestLocalFeatureExplanations,
|
||||
requestPredictions: this.props.requestPredictions,
|
||||
selectedErrorCohort: this.state.selectedCohort,
|
||||
shiftErrorCohort: this.shiftErrorCohort,
|
||||
telemetryHook:
|
||||
this.props.telemetryHook ||
|
||||
((): void => {
|
||||
return;
|
||||
}),
|
||||
theme: this.props.theme,
|
||||
updateErrorCohorts: this.updateErrorCohorts
|
||||
theme: this.props.theme
|
||||
}}
|
||||
>
|
||||
<div className={classNames.page}>
|
||||
|
@ -768,14 +770,15 @@ export class ErrorAnalysisDashboard extends React.PureComponent<
|
|||
this.setState({ selectedWeightVector: weightOption });
|
||||
};
|
||||
|
||||
private updateErrorCohorts = (
|
||||
cohorts: ErrorCohort[],
|
||||
selectedCohort: ErrorCohort,
|
||||
baseCohort?: ErrorCohort
|
||||
): void => {
|
||||
private shiftErrorCohort = (selectedCohort: ErrorCohort): void => {
|
||||
console.log(selectedCohort);
|
||||
let cohorts = this.state.cohorts;
|
||||
cohorts = cohorts.filter(
|
||||
(cohort) => cohort.cohort.name !== selectedCohort.cohort.name
|
||||
);
|
||||
this.setState({
|
||||
baseCohort: baseCohort || this.state.baseCohort,
|
||||
cohorts,
|
||||
baseCohort: selectedCohort,
|
||||
cohorts: [...cohorts, selectedCohort],
|
||||
selectedCohort
|
||||
});
|
||||
};
|
||||
|
|
|
@ -84,6 +84,7 @@ export class NewExplanationDashboard extends React.PureComponent<
|
|||
return (
|
||||
<ModelAssessmentContext.Provider
|
||||
value={{
|
||||
addCohort: this.addCohort,
|
||||
baseErrorCohort: new ErrorCohort(
|
||||
this.state.cohorts[0],
|
||||
this.state.jointDataset
|
||||
|
@ -104,13 +105,13 @@ export class NewExplanationDashboard extends React.PureComponent<
|
|||
this.state.selectedCohort,
|
||||
this.state.jointDataset
|
||||
),
|
||||
shiftErrorCohort: this.shiftErrorCohort,
|
||||
telemetryHook:
|
||||
this.props.telemetryHook ||
|
||||
((): void => {
|
||||
return;
|
||||
}),
|
||||
theme: getTheme(),
|
||||
updateErrorCohorts: this.updateErrorCohorts
|
||||
theme: getTheme()
|
||||
}}
|
||||
>
|
||||
<div className={classNames.page}>
|
||||
|
@ -248,13 +249,15 @@ export class NewExplanationDashboard extends React.PureComponent<
|
|||
this.setState({ showingDataSizeWarning: false });
|
||||
};
|
||||
|
||||
private updateErrorCohorts = (
|
||||
cohorts: ErrorCohort[],
|
||||
selectedCohort: ErrorCohort
|
||||
): void => {
|
||||
private shiftErrorCohort = (cohort: ErrorCohort): void => {
|
||||
this.setState({
|
||||
cohorts: cohorts.map((c) => c.cohort),
|
||||
selectedCohort: selectedCohort.cohort
|
||||
selectedCohort: cohort.cohort
|
||||
});
|
||||
};
|
||||
|
||||
private addCohort = (cohort: Cohort): void => {
|
||||
this.setState((prev) => ({
|
||||
cohorts: [...prev.cohorts, cohort]
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
|
|
@ -672,7 +672,7 @@
|
|||
"_placeholderName.comment": "starting name for a new cohort",
|
||||
"_selectFilter.comment": "prompt to select an attribute to filter on",
|
||||
"addFilter": "Add filter",
|
||||
"addedFilters": "Added filters",
|
||||
"addedFilters": "Filters",
|
||||
"cancel": "Cancel",
|
||||
"cancelExistingCohort": "Are you sure you want to cancel editing cohort and go back?",
|
||||
"cancelNewCohort": "Are you sure you want to cancel creating a new cohort and go back?",
|
||||
|
@ -684,7 +684,7 @@
|
|||
"cohortNamePlaceholder": "Name your cohort",
|
||||
"defaultFilterState": "Select a filter to add parameters to your dataset cohort.",
|
||||
"delete": "Delete",
|
||||
"noAddedFilters": "No filters added yet",
|
||||
"noAddedFilters": "No filters",
|
||||
"placeholderName": "Cohort {0}",
|
||||
"save": "Save",
|
||||
"selectFilter": "Select filter"
|
||||
|
@ -1123,6 +1123,15 @@
|
|||
"zstat": "Z-score"
|
||||
}
|
||||
},
|
||||
"Cohort": {
|
||||
"apply": "Apply",
|
||||
"cancel": "Cancel",
|
||||
"cohortInfo": "Cohort info",
|
||||
"cohortList": "Cohort list",
|
||||
"selectCohort": "Select a cohort",
|
||||
"shiftCohort": "Shift cohort",
|
||||
"shiftCohortDescription": "Select a cohort from the cohort list. Apply the cohort to the dashboard."
|
||||
},
|
||||
"CohortInformation": {
|
||||
"ChangeGlobalCohort": "Change global cohort",
|
||||
"CreateNewCohort": "Create new cohort",
|
||||
|
@ -1164,7 +1173,7 @@
|
|||
"LocalExplanation": "Individual feature importance"
|
||||
},
|
||||
"MainMenu": {
|
||||
"DashboardSettings": "Dashboard settings",
|
||||
"DashboardSettings": "Dashboard navigation",
|
||||
"cohortInfo": "Cohort info",
|
||||
"cohortList": "Cohort list",
|
||||
"cohortSettings": "Cohort settings",
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {
|
||||
defaultModelAssessmentContext,
|
||||
ErrorCohort,
|
||||
IModelAssessmentContext,
|
||||
ModelAssessmentContext
|
||||
} from "@responsible-ai/core-ui";
|
||||
import { localization } from "@responsible-ai/localization";
|
||||
import { DefaultButton } from "office-ui-fabric-react";
|
||||
import React from "react";
|
||||
|
||||
import { ShiftCohort } from "./ShiftCohort";
|
||||
|
||||
interface IChangeGlobalCohortButtonState {
|
||||
shiftCohortVisible: boolean;
|
||||
}
|
||||
|
||||
export class ChangeGlobalCohortButton extends React.Component<
|
||||
Record<string, never>,
|
||||
IChangeGlobalCohortButtonState
|
||||
> {
|
||||
public static contextType = ModelAssessmentContext;
|
||||
public context: IModelAssessmentContext = defaultModelAssessmentContext;
|
||||
public constructor(props: Record<string, never>) {
|
||||
super(props);
|
||||
this.state = { shiftCohortVisible: false };
|
||||
}
|
||||
public render(): React.ReactNode {
|
||||
return (
|
||||
<>
|
||||
<DefaultButton
|
||||
text={
|
||||
localization.ModelAssessment.CohortInformation.ChangeGlobalCohort
|
||||
}
|
||||
onClick={this.toggleShiftCohortVisibility}
|
||||
/>
|
||||
{this.state.shiftCohortVisible && (
|
||||
<ShiftCohort
|
||||
onDismiss={this.toggleShiftCohortVisibility}
|
||||
onApply={this.shiftErrorCohort}
|
||||
defaultCohort={this.context.baseErrorCohort}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
private shiftErrorCohort = (cohort: ErrorCohort) => {
|
||||
this.context.shiftErrorCohort(cohort);
|
||||
this.toggleShiftCohortVisibility();
|
||||
};
|
||||
private toggleShiftCohortVisibility = () => {
|
||||
this.setState((prev) => ({ shiftCohortVisible: !prev.shiftCohortVisible }));
|
||||
};
|
||||
}
|
|
@ -1,30 +1,24 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import { localization } from "@responsible-ai/localization";
|
||||
import {
|
||||
DefaultButton,
|
||||
Panel,
|
||||
PanelType,
|
||||
Stack,
|
||||
Text
|
||||
} from "office-ui-fabric-react";
|
||||
import React from "react";
|
||||
|
||||
import {
|
||||
defaultModelAssessmentContext,
|
||||
ErrorCohort,
|
||||
IModelAssessmentContext,
|
||||
ModelAssessmentContext
|
||||
} from "../../Context/ModelAssessmentContext";
|
||||
import { CohortList } from "../CohortList/CohortList";
|
||||
import { ErrorCohort } from "../ErrorCohort";
|
||||
ModelAssessmentContext,
|
||||
CohortList
|
||||
} from "@responsible-ai/core-ui";
|
||||
import { localization } from "@responsible-ai/localization";
|
||||
import { Panel, PanelType, Stack, Text } from "office-ui-fabric-react";
|
||||
import React from "react";
|
||||
|
||||
import { ChangeGlobalCohortButton } from "./ChangeGlobalCohortButton";
|
||||
import { CreateGlobalCohortButton } from "./CreateGlobalCohortButton";
|
||||
|
||||
export interface ICohortSettingsPanelProps {
|
||||
errorCohorts: ErrorCohort[];
|
||||
isOpen: boolean;
|
||||
onDismiss: () => void;
|
||||
toggleShiftCohortVisibility: () => void;
|
||||
toggleCreateCohortVisibility: () => void;
|
||||
}
|
||||
|
||||
export class CohortSettingsPanel extends React.PureComponent<ICohortSettingsPanelProps> {
|
||||
|
@ -53,19 +47,8 @@ export class CohortSettingsPanel extends React.PureComponent<ICohortSettingsPane
|
|||
}
|
||||
</Text>
|
||||
<Stack horizontal tokens={{ childrenGap: 25 }}>
|
||||
<DefaultButton
|
||||
text={
|
||||
localization.ModelAssessment.CohortInformation
|
||||
.ChangeGlobalCohort
|
||||
}
|
||||
onClick={this.props.toggleShiftCohortVisibility}
|
||||
/>
|
||||
<DefaultButton
|
||||
text={
|
||||
localization.ModelAssessment.CohortInformation.CreateNewCohort
|
||||
}
|
||||
onClick={this.props.toggleCreateCohortVisibility}
|
||||
/>
|
||||
<ChangeGlobalCohortButton />
|
||||
<CreateGlobalCohortButton />
|
||||
</Stack>
|
||||
<CohortList
|
||||
errorCohorts={this.props.errorCohorts}
|
|
@ -0,0 +1,70 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {
|
||||
Cohort,
|
||||
CohortEditor,
|
||||
defaultModelAssessmentContext,
|
||||
IModelAssessmentContext,
|
||||
ModelAssessmentContext
|
||||
} from "@responsible-ai/core-ui";
|
||||
import { localization } from "@responsible-ai/localization";
|
||||
import { DefaultButton } from "office-ui-fabric-react";
|
||||
import React from "react";
|
||||
|
||||
interface ICreateGlobalCohortButtonState {
|
||||
createCohortVisible: boolean;
|
||||
}
|
||||
|
||||
export class CreateGlobalCohortButton extends React.Component<
|
||||
Record<string, never>,
|
||||
ICreateGlobalCohortButtonState
|
||||
> {
|
||||
public static contextType = ModelAssessmentContext;
|
||||
public context: IModelAssessmentContext = defaultModelAssessmentContext;
|
||||
public constructor(props: Record<string, never>) {
|
||||
super(props);
|
||||
this.state = { createCohortVisible: false };
|
||||
}
|
||||
public render(): React.ReactNode {
|
||||
return (
|
||||
<>
|
||||
<DefaultButton
|
||||
text={localization.ModelAssessment.CohortInformation.CreateNewCohort}
|
||||
onClick={this.toggleVisibility}
|
||||
/>
|
||||
{this.state.createCohortVisible && (
|
||||
<CohortEditor
|
||||
jointDataset={this.context.jointDataset}
|
||||
filterList={this.context.baseErrorCohort.cohort.filters}
|
||||
cohortName={`${localization.Interpret.Cohort.cohort} ${(
|
||||
this.context.errorCohorts.length + 1
|
||||
).toString()}`}
|
||||
onSave={this.addCohort}
|
||||
isNewCohort
|
||||
deleteIsDisabled
|
||||
closeCohortEditor={(): void => {
|
||||
this.setState((prev) => ({
|
||||
createCohortVisible: !prev.createCohortVisible
|
||||
}));
|
||||
}}
|
||||
closeCohortEditorPanel={(): void => {
|
||||
this.setState((prev) => ({
|
||||
createCohortVisible: !prev.createCohortVisible
|
||||
}));
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
private addCohort = (cohort: Cohort) => {
|
||||
this.context.addCohort(cohort);
|
||||
this.toggleVisibility();
|
||||
};
|
||||
private toggleVisibility = () => {
|
||||
this.setState((prev) => ({
|
||||
createCohortVisible: !prev.createCohortVisible
|
||||
}));
|
||||
};
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {
|
||||
CohortEditorFilterList,
|
||||
defaultModelAssessmentContext,
|
||||
ErrorCohort,
|
||||
ModelAssessmentContext
|
||||
} from "@responsible-ai/core-ui";
|
||||
import { localization } from "@responsible-ai/localization";
|
||||
import {
|
||||
IDropdownOption,
|
||||
PrimaryButton,
|
||||
DefaultButton,
|
||||
ContextualMenu,
|
||||
Dialog,
|
||||
DialogType,
|
||||
DialogFooter,
|
||||
Dropdown
|
||||
} from "office-ui-fabric-react";
|
||||
import React from "react";
|
||||
|
||||
export interface IShiftCohortProps {
|
||||
onDismiss: () => void;
|
||||
onApply: (selectedCohort: ErrorCohort) => void;
|
||||
defaultCohort?: ErrorCohort;
|
||||
}
|
||||
|
||||
export interface IShiftCohortState {
|
||||
options: IDropdownOption[];
|
||||
selectedCohort: number;
|
||||
savedCohorts: ErrorCohort[];
|
||||
}
|
||||
|
||||
export class ShiftCohort extends React.Component<
|
||||
IShiftCohortProps,
|
||||
IShiftCohortState
|
||||
> {
|
||||
public static contextType = ModelAssessmentContext;
|
||||
public context: React.ContextType<typeof ModelAssessmentContext> =
|
||||
defaultModelAssessmentContext;
|
||||
|
||||
public componentDidMount(): void {
|
||||
const savedCohorts = this.context.errorCohorts.filter(
|
||||
(errorCohort) => !errorCohort.isTemporary
|
||||
);
|
||||
const options: IDropdownOption[] = savedCohorts.map(
|
||||
(savedCohort: ErrorCohort, index: number) => {
|
||||
return { key: index, text: savedCohort.cohort.name };
|
||||
}
|
||||
);
|
||||
let defaultCohort = 0;
|
||||
if (this.props.defaultCohort) {
|
||||
const defaultCohortName = this.props.defaultCohort.cohort.name;
|
||||
const index = savedCohorts.findIndex((errorCohort) => {
|
||||
return errorCohort.cohort.name === defaultCohortName;
|
||||
});
|
||||
if (index !== -1) {
|
||||
defaultCohort = index;
|
||||
}
|
||||
}
|
||||
this.setState({
|
||||
options,
|
||||
savedCohorts,
|
||||
selectedCohort: defaultCohort
|
||||
});
|
||||
}
|
||||
|
||||
public render(): React.ReactNode {
|
||||
if (!this.state) {
|
||||
return React.Fragment;
|
||||
}
|
||||
const filters =
|
||||
this.state.savedCohorts[this.state.selectedCohort].cohort.filters;
|
||||
return (
|
||||
<Dialog
|
||||
hidden={false}
|
||||
onDismiss={this.props.onDismiss}
|
||||
dialogContentProps={{
|
||||
subText: localization.ModelAssessment.Cohort.shiftCohortDescription,
|
||||
title: localization.ModelAssessment.Cohort.shiftCohort,
|
||||
type: DialogType.close
|
||||
}}
|
||||
modalProps={{
|
||||
dragOptions: {
|
||||
closeMenuItemText: "Close",
|
||||
menu: ContextualMenu,
|
||||
moveMenuItemText: "Move"
|
||||
},
|
||||
isBlocking: true
|
||||
}}
|
||||
minWidth={740}
|
||||
maxWidth={1000}
|
||||
>
|
||||
<Dropdown
|
||||
placeholder={localization.ModelAssessment.Cohort.selectCohort}
|
||||
label={localization.ModelAssessment.Cohort.cohortList}
|
||||
selectedKey={this.state.selectedCohort}
|
||||
options={this.state.options}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
<CohortEditorFilterList
|
||||
filters={filters}
|
||||
jointDataset={this.context.jointDataset}
|
||||
/>
|
||||
<DialogFooter>
|
||||
<PrimaryButton
|
||||
onClick={this.shiftCohort}
|
||||
text={localization.ModelAssessment.Cohort.apply}
|
||||
/>
|
||||
<DefaultButton
|
||||
onClick={this.props.onDismiss}
|
||||
text={localization.ModelAssessment.Cohort.cancel}
|
||||
/>
|
||||
</DialogFooter>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
private onChange = (
|
||||
_: React.FormEvent<HTMLDivElement>,
|
||||
item?: IDropdownOption
|
||||
): void => {
|
||||
if (item) {
|
||||
this.setState({ selectedCohort: item.key as number });
|
||||
}
|
||||
};
|
||||
|
||||
private shiftCohort = (): void => {
|
||||
this.props.onApply(this.state.savedCohorts[this.state.selectedCohort]);
|
||||
};
|
||||
}
|
|
@ -102,7 +102,6 @@ export function buildInitialModelAssessmentContext(
|
|||
activeGlobalTabs,
|
||||
baseCohort: cohorts[0],
|
||||
cohorts,
|
||||
createCohortVisible: false,
|
||||
customPoints: [],
|
||||
dataChartConfig: undefined,
|
||||
dependenceProps: undefined,
|
||||
|
@ -127,7 +126,6 @@ export function buildInitialModelAssessmentContext(
|
|||
? WeightVectors.AbsAvg
|
||||
: 0,
|
||||
selectedWhatIfIndex: undefined,
|
||||
shiftCohortVisible: false,
|
||||
sortVector: undefined,
|
||||
treeViewState: createInitialTreeViewState(),
|
||||
weightVectorLabels,
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
// Licensed under the MIT License.
|
||||
|
||||
import {
|
||||
CohortSettingsPanel,
|
||||
defaultModelAssessmentContext,
|
||||
IModelAssessmentContext,
|
||||
ModelAssessmentContext
|
||||
|
@ -12,10 +11,14 @@ import {
|
|||
CommandBar,
|
||||
ICommandBarItemProps,
|
||||
IIconProps,
|
||||
IButtonStyles
|
||||
Stack,
|
||||
Text
|
||||
} from "office-ui-fabric-react";
|
||||
import React from "react";
|
||||
|
||||
import { ChangeGlobalCohortButton } from "../Cohort/ChangeGlobalCohortButton";
|
||||
import { CohortSettingsPanel } from "../Cohort/CohortSettingsPanel";
|
||||
import { CreateGlobalCohortButton } from "../Cohort/CreateGlobalCohortButton";
|
||||
import { IModelAssessmentDashboardTab } from "../ModelAssessmentDashboardState";
|
||||
|
||||
import { DashboardSettings } from "./DashboardSettings";
|
||||
|
@ -23,8 +26,6 @@ import { mainMenuStyles } from "./MainMenu.styles";
|
|||
|
||||
export interface IMainMenuProps {
|
||||
activeGlobalTabs: IModelAssessmentDashboardTab[];
|
||||
toggleShiftCohortVisibility: () => void;
|
||||
toggleCreateCohortVisibility: () => void;
|
||||
removeTab(index: number): void;
|
||||
}
|
||||
interface IMainMenuState {
|
||||
|
@ -34,10 +35,6 @@ interface IMainMenuState {
|
|||
|
||||
const settingsIcon: IIconProps = { iconName: "Settings" };
|
||||
|
||||
const buttonStyle: IButtonStyles = {
|
||||
root: { padding: "0px 4px" }
|
||||
};
|
||||
|
||||
export class MainMenu extends React.PureComponent<
|
||||
IMainMenuProps,
|
||||
IMainMenuState
|
||||
|
@ -45,51 +42,50 @@ export class MainMenu extends React.PureComponent<
|
|||
public static contextType = ModelAssessmentContext;
|
||||
public context: IModelAssessmentContext = defaultModelAssessmentContext;
|
||||
|
||||
private menuFarItems: ICommandBarItemProps[];
|
||||
private menuItems: ICommandBarItemProps[];
|
||||
public constructor(props: IMainMenuProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
cohortSettingsPanelVisible: false,
|
||||
dashboardSettingsVisible: false
|
||||
};
|
||||
}
|
||||
|
||||
public render(): React.ReactNode {
|
||||
const farItems: ICommandBarItemProps[] = [];
|
||||
const helpItems: ICommandBarItemProps[] = [
|
||||
this.menuFarItems = [
|
||||
{
|
||||
buttonStyles: buttonStyle,
|
||||
iconProps: settingsIcon,
|
||||
key: "cohortSettings",
|
||||
onClick: this.toggleCohortSettingsPanel,
|
||||
text: localization.ModelAssessment.MainMenu.cohortSettings
|
||||
},
|
||||
{
|
||||
buttonStyles: buttonStyle,
|
||||
iconProps: settingsIcon,
|
||||
key: "dashboardSettings",
|
||||
onClick: this.toggleDashboardSettings,
|
||||
text: localization.ModelAssessment.MainMenu.DashboardSettings
|
||||
}
|
||||
];
|
||||
farItems.push(...helpItems);
|
||||
this.menuItems = [
|
||||
{
|
||||
key: "cohort",
|
||||
onRender: this.renderCohort,
|
||||
text: ""
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
public render(): React.ReactNode {
|
||||
const classNames = mainMenuStyles();
|
||||
return (
|
||||
<>
|
||||
<div className={classNames.banner}>
|
||||
<div className={classNames.mainMenu}>
|
||||
<CommandBar
|
||||
items={[]}
|
||||
farItems={farItems}
|
||||
ariaLabel="Use left and right arrow keys to navigate between commands"
|
||||
/>
|
||||
<CommandBar items={this.menuItems} farItems={this.menuFarItems} />
|
||||
</div>
|
||||
</div>
|
||||
<CohortSettingsPanel
|
||||
errorCohorts={this.context.errorCohorts}
|
||||
isOpen={this.state?.cohortSettingsPanelVisible}
|
||||
onDismiss={this.toggleCohortSettingsPanel}
|
||||
toggleCreateCohortVisibility={this.props.toggleCreateCohortVisibility}
|
||||
toggleShiftCohortVisibility={this.props.toggleShiftCohortVisibility}
|
||||
/>
|
||||
<DashboardSettings
|
||||
isOpen={this.state.dashboardSettingsVisible}
|
||||
|
@ -101,6 +97,38 @@ export class MainMenu extends React.PureComponent<
|
|||
);
|
||||
}
|
||||
|
||||
private renderCohort = (): React.ReactNode => {
|
||||
const currentCohort = this.context.baseErrorCohort;
|
||||
const cohortName = currentCohort.cohort.name;
|
||||
// add (default) if it's the default cohort
|
||||
let cohortInfoTitle =
|
||||
localization.ModelAssessment.CohortInformation.GlobalCohort + cohortName;
|
||||
if (
|
||||
currentCohort.cohort.filters.length === 0 &&
|
||||
currentCohort.cohort.name === localization.Interpret.Cohort.defaultLabel
|
||||
) {
|
||||
cohortInfoTitle +=
|
||||
localization.ModelAssessment.CohortInformation.DefaultCohort;
|
||||
}
|
||||
const dataPointsCountString = `${
|
||||
localization.ModelAssessment.CohortInformation.DataPoints
|
||||
} = ${currentCohort.cohortStats.totalCohort.toString()}`;
|
||||
const filtersCountString = `${
|
||||
localization.ModelAssessment.CohortInformation.Filters
|
||||
} = ${currentCohort.cohort.filters.length.toString()}`;
|
||||
return (
|
||||
<Stack horizontal tokens={{ childrenGap: "l1" }}>
|
||||
<Text variant={"xLarge"}>{cohortInfoTitle}</Text>
|
||||
<Stack>
|
||||
<Text>{dataPointsCountString}</Text>
|
||||
<Text>{filtersCountString}</Text>
|
||||
</Stack>
|
||||
<ChangeGlobalCohortButton />
|
||||
<CreateGlobalCohortButton />
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
private toggleCohortSettingsPanel = (): void =>
|
||||
this.setState((prev) => ({
|
||||
cohortSettingsPanelVisible: !prev.cohortSettingsPanelVisible
|
||||
|
|
|
@ -7,9 +7,6 @@ import {
|
|||
ModelAssessmentContext,
|
||||
ErrorCohort,
|
||||
WeightVectorOption,
|
||||
CohortInfoSection,
|
||||
ShiftCohort,
|
||||
CohortEditor,
|
||||
CohortSource,
|
||||
Cohort,
|
||||
SaveCohort
|
||||
|
@ -77,6 +74,7 @@ export class ModelAssessmentDashboard extends CohortBasedComponent<
|
|||
return (
|
||||
<ModelAssessmentContext.Provider
|
||||
value={{
|
||||
addCohort: this.addCohort,
|
||||
baseErrorCohort: this.state.baseCohort,
|
||||
causalAnalysisData: this.props.causalAnalysisData?.[0],
|
||||
counterfactualData: this.props.counterfactualData?.[0],
|
||||
|
@ -97,49 +95,22 @@ export class ModelAssessmentDashboard extends CohortBasedComponent<
|
|||
this.props.requestLocalFeatureExplanations,
|
||||
requestPredictions: this.props.requestPredictions,
|
||||
selectedErrorCohort: this.state.selectedCohort,
|
||||
shiftErrorCohort: this.shiftErrorCohort,
|
||||
telemetryHook:
|
||||
this.props.telemetryHook ||
|
||||
((): void => {
|
||||
return;
|
||||
}),
|
||||
theme: this.props.theme,
|
||||
updateErrorCohorts: this.updateErrorCohorts
|
||||
theme: this.props.theme
|
||||
}}
|
||||
>
|
||||
<Stack className={modelAssessmentDashboardStyles.page}>
|
||||
<MainMenu
|
||||
activeGlobalTabs={this.state.activeGlobalTabs}
|
||||
removeTab={this.removeTab}
|
||||
toggleShiftCohortVisibility={(): void => {
|
||||
this.setState((prev) => ({
|
||||
shiftCohortVisible: !prev.shiftCohortVisible
|
||||
}));
|
||||
}}
|
||||
toggleCreateCohortVisibility={(): void => {
|
||||
this.setState((prev) => ({
|
||||
createCohortVisible: !prev.createCohortVisible
|
||||
}));
|
||||
}}
|
||||
/>
|
||||
<Stack.Item className={modelAssessmentDashboardStyles.mainContent}>
|
||||
<Stack tokens={{ childrenGap: "10px", padding: "50px 0 0 0" }}>
|
||||
<Stack.Item
|
||||
className={modelAssessmentDashboardStyles.section}
|
||||
styles={{ root: { boxShadow: DefaultEffects.elevation4 } }}
|
||||
>
|
||||
<CohortInfoSection
|
||||
toggleShiftCohortVisibility={(): void => {
|
||||
this.setState((prev) => ({
|
||||
shiftCohortVisible: !prev.shiftCohortVisible
|
||||
}));
|
||||
}}
|
||||
toggleCreateCohortVisibility={(): void => {
|
||||
this.setState((prev) => ({
|
||||
createCohortVisible: !prev.createCohortVisible
|
||||
}));
|
||||
}}
|
||||
/>
|
||||
</Stack.Item>
|
||||
{this.state.activeGlobalTabs[0]?.key !==
|
||||
GlobalTabKeys.ErrorAnalysisTab && (
|
||||
<Stack.Item
|
||||
|
@ -299,61 +270,6 @@ export class ModelAssessmentDashboard extends CohortBasedComponent<
|
|||
))}
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
{this.state.shiftCohortVisible && (
|
||||
<ShiftCohort
|
||||
isOpen={this.state.shiftCohortVisible}
|
||||
onDismiss={(): void => {
|
||||
this.setState((prev) => ({
|
||||
shiftCohortVisible: !prev.shiftCohortVisible
|
||||
}));
|
||||
}}
|
||||
onApply={(selectedCohort: ErrorCohort): void => {
|
||||
this.setState({
|
||||
baseCohort: selectedCohort,
|
||||
cohorts: this.state.cohorts,
|
||||
selectedCohort
|
||||
});
|
||||
}}
|
||||
defaultCohort={this.state.baseCohort}
|
||||
/>
|
||||
)}
|
||||
{this.state.createCohortVisible && (
|
||||
<CohortEditor
|
||||
jointDataset={this.state.jointDataset}
|
||||
filterList={this.state.baseCohort.cohort.filters}
|
||||
cohortName={`${localization.Interpret.Cohort.cohort} ${(
|
||||
this.state.cohorts.length + 1
|
||||
).toString()}`}
|
||||
onSave={(manuallyCreatedCohort: Cohort): void => {
|
||||
const newErrorCohort = new ErrorCohort(
|
||||
manuallyCreatedCohort,
|
||||
this.state.jointDataset,
|
||||
0,
|
||||
CohortSource.ManuallyCreated
|
||||
);
|
||||
let newCohorts = [...this.state.cohorts, newErrorCohort];
|
||||
newCohorts = newCohorts.filter((cohort) => !cohort.isTemporary);
|
||||
this.setState((prev) => ({
|
||||
baseCohort: newErrorCohort,
|
||||
cohorts: newCohorts,
|
||||
createCohortVisible: !prev.createCohortVisible,
|
||||
selectedCohort: newErrorCohort
|
||||
}));
|
||||
}}
|
||||
isNewCohort
|
||||
deleteIsDisabled
|
||||
closeCohortEditor={(): void => {
|
||||
this.setState((prev) => ({
|
||||
createCohortVisible: !prev.createCohortVisible
|
||||
}));
|
||||
}}
|
||||
closeCohortEditorPanel={(): void => {
|
||||
this.setState((prev) => ({
|
||||
createCohortVisible: !prev.createCohortVisible
|
||||
}));
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{this.state.saveCohortVisible && (
|
||||
<SaveCohort
|
||||
isOpen={this.state.saveCohortVisible}
|
||||
|
@ -422,18 +338,6 @@ export class ModelAssessmentDashboard extends CohortBasedComponent<
|
|||
this.setState({ activeGlobalTabs: tabs });
|
||||
};
|
||||
|
||||
private updateErrorCohorts = (
|
||||
cohorts: ErrorCohort[],
|
||||
selectedCohort: ErrorCohort,
|
||||
baseCohort?: ErrorCohort
|
||||
): void => {
|
||||
this.setState({
|
||||
baseCohort: baseCohort || this.state.baseCohort,
|
||||
cohorts,
|
||||
selectedCohort
|
||||
});
|
||||
};
|
||||
|
||||
private onWeightVectorChange = (weightOption: WeightVectorOption): void => {
|
||||
this.state.jointDataset.buildLocalFlattenMatrix(weightOption);
|
||||
this.state.cohorts.forEach((errorCohort) =>
|
||||
|
@ -467,4 +371,27 @@ export class ModelAssessmentDashboard extends CohortBasedComponent<
|
|||
});
|
||||
}
|
||||
};
|
||||
|
||||
private shiftErrorCohort = (cohort: ErrorCohort) => {
|
||||
this.setState({
|
||||
baseCohort: cohort,
|
||||
selectedCohort: cohort
|
||||
});
|
||||
};
|
||||
|
||||
private addCohort = (manuallyCreatedCohort: Cohort): void => {
|
||||
const newErrorCohort = new ErrorCohort(
|
||||
manuallyCreatedCohort,
|
||||
this.state.jointDataset,
|
||||
0,
|
||||
CohortSource.ManuallyCreated
|
||||
);
|
||||
let newCohorts = [...this.state.cohorts, newErrorCohort];
|
||||
newCohorts = newCohorts.filter((cohort) => !cohort.isTemporary);
|
||||
this.setState({
|
||||
baseCohort: newErrorCohort,
|
||||
cohorts: newCohorts,
|
||||
selectedCohort: newErrorCohort
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -43,8 +43,6 @@ export interface IModelAssessmentDashboardState
|
|||
selectedWeightVector: WeightVectorOption;
|
||||
weightVectorOptions: WeightVectorOption[];
|
||||
weightVectorLabels: Dictionary<string>;
|
||||
createCohortVisible: boolean;
|
||||
shiftCohortVisible: boolean;
|
||||
saveCohortVisible: boolean;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче