Skip to content

Commit

Permalink
Minor enhancements to bias chart (#1386) (#1399)
Browse files Browse the repository at this point in the history
* Adds refresh interval options that match openshift observability dashboard

* Show first chart from list, if none selected when user first navigates to bias tab

* Use search icon instead of plus for nothing selected empty state

* Fix error with calculation of 30 days constant

* Deleted charts are removed from session storage
  • Loading branch information
alexcreasy authored Jun 19, 2023
1 parent 7cd7cf2 commit 3b82db3
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 20 deletions.
9 changes: 8 additions & 1 deletion frontend/src/pages/modelServing/screens/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,18 @@ export const TimeframeStep: TimeframeStepType = {
[TimeframeTitle.ONE_HOUR]: 12,
[TimeframeTitle.ONE_DAY]: 24 * 12,
[TimeframeTitle.ONE_WEEK]: 7 * 24 * 12,
[TimeframeTitle.ONE_MONTH]: 30 * 7 * 24 * 12,
[TimeframeTitle.ONE_MONTH]: 30 * 24 * 12,
// [TimeframeTitle.UNLIMITED]: 30 * 7 * 24 * 12, // TODO: determine if we "zoom out" more
};

export const RefreshIntervalValue: RefreshIntervalValueType = {
[RefreshIntervalTitle.FIFTEEN_SECONDS]: 15 * 1000,
[RefreshIntervalTitle.THIRTY_SECONDS]: 30 * 1000,
[RefreshIntervalTitle.ONE_MINUTE]: 60 * 1000,
[RefreshIntervalTitle.FIVE_MINUTES]: 5 * 60 * 1000,
[RefreshIntervalTitle.FIFTEEN_MINUTES]: 15 * 60 * 1000,
[RefreshIntervalTitle.THIRTY_MINUTES]: 30 * 60 * 1000,
[RefreshIntervalTitle.ONE_HOUR]: 60 * 60 * 1000,
[RefreshIntervalTitle.TWO_HOURS]: 2 * 60 * 60 * 1000,
[RefreshIntervalTitle.ONE_DAY]: 24 * 60 * 60 * 1000,
};
32 changes: 15 additions & 17 deletions frontend/src/pages/modelServing/screens/metrics/BiasTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,38 +8,36 @@ import {
ToolbarGroup,
ToolbarItem,
} from '@patternfly/react-core';
import { useParams } from 'react-router-dom';
import MetricsPageToolbar from '~/pages/modelServing/screens/metrics/MetricsPageToolbar';
import BiasMetricConfigSelector from '~/pages/modelServing/screens/metrics/BiasMetricConfigSelector';
import { BiasMetricConfig } from '~/concepts/explainability/types';
import { useExplainabilityModelData } from '~/concepts/explainability/useExplainabilityModelData';
import TrustyChart from '~/pages/modelServing/screens/metrics/TrustyChart';
import { useBrowserStorage } from '~/components/browserStorage';
import EmptyBiasConfigurationCard from '~/pages/modelServing/screens/metrics/EmptyBiasConfigurationCard';
import EmptyBiasChartSelectionCard from '~/pages/modelServing/screens/metrics/EmptyBiasChartSelectionCard';
import DashboardExpandableSection from '~/concepts/dashboard/DashboardExpandableSection';
import useBiasChartsBrowserStorage from '~/pages/modelServing/screens/metrics/useBiasChartsBrowserStorage';

const SELECTED_CHARTS_STORAGE_KEY_PREFIX = 'odh.dashboard.xai.selected_bias_charts';
const OPEN_WRAPPER_STORAGE_KEY_PREFIX = `odh.dashboard.xai.bias_metric_chart_wrapper_open`;
const BiasTab: React.FC = () => {
const { inferenceService } = useParams();

const { biasMetricConfigs, loaded, loadError } = useExplainabilityModelData();

const [selectedBiasConfigs, setSelectedBiasConfigs] = useBrowserStorage<BiasMetricConfig[]>(
`${SELECTED_CHARTS_STORAGE_KEY_PREFIX}-${inferenceService}`,
[],
true,
true,
);
const [selectedBiasConfigs, setSelectedBiasConfigs] = useBiasChartsBrowserStorage();

const firstRender = React.useRef(true);

React.useEffect(() => {
if (loaded && !loadError) {
setSelectedBiasConfigs(
selectedBiasConfigs.filter((selection) =>
biasMetricConfigs.map((c) => c.id).includes(selection.id),
),
);
if (firstRender.current) {
// If the user has just navigated here AND they haven't previously selected any charts to display,
// don't show them the "No selected" empty state, instead show them the first available chart.
// However, the user still needs to be shown said empty state if they deselect all charts.
firstRender.current = false;
if (selectedBiasConfigs.length === 0 && biasMetricConfigs.length > 0) {
// If biasMetricConfigs is empty, the "No Configured Metrics" empty state will be shown, so no need
// to set anything.
setSelectedBiasConfigs([biasMetricConfigs[0]]);
}
}
}
}, [loaded, biasMetricConfigs, setSelectedBiasConfigs, selectedBiasConfigs, loadError]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
EmptyStateIcon,
Title,
} from '@patternfly/react-core';
import { PlusCircleIcon } from '@patternfly/react-icons';
import { SearchIcon } from '@patternfly/react-icons';
import {
EMPTY_BIAS_CHART_SELECTION_DESC,
EMPTY_BIAS_CHART_SELECTION_TITLE,
Expand All @@ -17,7 +17,7 @@ const EmptyBiasChartSelectionCard = () => (
<Card>
<CardBody>
<EmptyState>
<EmptyStateIcon icon={PlusCircleIcon} />
<EmptyStateIcon icon={SearchIcon} />
<Title headingLevel="h2" size="lg">
{EMPTY_BIAS_CHART_SELECTION_TITLE}
</Title>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { MetricTypes } from '~/api';
import { ExplainabilityContext } from '~/concepts/explainability/ExplainabilityContext';
import { BiasMetricConfig } from '~/concepts/explainability/types';
import DeleteModal from '~/pages/projects/components/DeleteModal';
import useBiasChartsBrowserStorage from '~/pages/modelServing/screens/metrics/useBiasChartsBrowserStorage';
import { byNotId } from '~/pages/modelServing/screens/metrics/utils';

type DeleteBiasConfigurationModalProps = {
configurationToDelete?: BiasMetricConfig;
Expand All @@ -19,6 +21,12 @@ const DeleteBiasConfigurationModal: React.FC<DeleteBiasConfigurationModalProps>
apiState: { api },
} = React.useContext(ExplainabilityContext);

const [selectedBiasConfigCharts, setSelectedBiasConfigCharts] = useBiasChartsBrowserStorage();

const deselectDeleted = (biasConfigId: string) => {
setSelectedBiasConfigCharts(selectedBiasConfigCharts.filter(byNotId(biasConfigId)));
};

const onBeforeClose = (deleted: boolean) => {
onClose(deleted);
setDeleting(false);
Expand All @@ -41,6 +49,7 @@ const DeleteBiasConfigurationModal: React.FC<DeleteBiasConfigurationModalProps>
: api.deleteSpdRequest;
deleteFunc({}, configurationToDelete.id)
.then(() => onBeforeClose(true))
.then(() => deselectDeleted(configurationToDelete.id))
.catch((e) => {
setError(e);
setDeleting(false);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { useParams } from 'react-router-dom';
import { useBrowserStorage } from '~/components/browserStorage';
import { BiasMetricConfig } from '~/concepts/explainability/types';
import { SetBrowserStorageHook } from '~/components/browserStorage/BrowserStorageContext';

const SELECTED_CHARTS_STORAGE_KEY_PREFIX = 'odh.dashboard.xai.selected_bias_charts';

const useBiasChartsBrowserStorage = (): [
BiasMetricConfig[],
SetBrowserStorageHook<BiasMetricConfig[]>,
] => {
const { inferenceService } = useParams();

const [selectedBiasConfigs, setSelectedBiasConfigs] = useBrowserStorage<BiasMetricConfig[]>(
`${SELECTED_CHARTS_STORAGE_KEY_PREFIX}-${inferenceService}`,
[],
true,
true,
);

return [selectedBiasConfigs, setSelectedBiasConfigs];
};

export default useBiasChartsBrowserStorage;
7 changes: 7 additions & 0 deletions frontend/src/pages/modelServing/screens/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,15 @@ export type TimeframeTimeType = {
export type TimeframeStepType = TimeframeTimeType;

export enum RefreshIntervalTitle {
FIFTEEN_SECONDS = '15 seconds',
THIRTY_SECONDS = '30 seconds',
ONE_MINUTE = '1 minute',
FIVE_MINUTES = '5 minutes',
FIFTEEN_MINUTES = '15 minutes',
THIRTY_MINUTES = '30 minutes',
ONE_HOUR = '1 hour',
TWO_HOURS = '2 hours',
ONE_DAY = '1 day',
}

export type RefreshIntervalValueType = {
Expand Down

0 comments on commit 3b82db3

Please sign in to comment.