Skip to content

Commit 1489952

Browse files
committed
3171 Add the active model to the model menu
Signed-off-by: Colorado, Camilo <camilo.colorado@intel.com>
1 parent 2288b2c commit 1489952

File tree

7 files changed

+42
-69
lines changed

7 files changed

+42
-69
lines changed

application/ui/src/features/inspect/footer/footer.component.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,19 @@ const useDefaultModel = () => {
3131
const { projectId } = useProjectIdentifier();
3232
const patchPipeline = usePatchPipeline(projectId);
3333

34-
const selectedModelId = pipeline?.model?.id;
34+
const hasSelectedModel = pipeline?.model?.id !== undefined;
35+
const hasNonAvailableModels = models.length === 0;
3536

3637
useEffect(() => {
37-
if (selectedModelId !== undefined || models.length === 0 || patchPipeline.isPending) {
38+
if (hasSelectedModel || hasNonAvailableModels || patchPipeline.isPending) {
3839
return;
3940
}
4041

4142
patchPipeline.mutate({
4243
params: { path: { project_id: projectId } },
4344
body: { model_id: models[0].id },
4445
});
45-
}, [models, patchPipeline, projectId, selectedModelId]);
46+
}, [hasNonAvailableModels, hasSelectedModel, models, patchPipeline, projectId]);
4647
};
4748

4849
export const ProgressBarItem = () => {

application/ui/src/features/inspect/models/model-actions-menu.component.tsx

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useState } from 'react';
22

33
import { $api } from '@geti-inspect/api';
4-
import { useProjectIdentifier } from '@geti-inspect/hooks';
4+
import { usePatchPipeline, useProjectIdentifier } from '@geti-inspect/hooks';
55
import { ActionButton, AlertDialog, DialogContainer, Item, Menu, MenuTrigger, toast, type Key } from '@geti/ui';
66
import { MoreMenu } from '@geti/ui/icons';
77

@@ -12,13 +12,13 @@ import type { ModelData } from './model-types';
1212
interface ModelActionsMenuProps {
1313
model: ModelData;
1414
selectedModelId: string | undefined;
15-
onSetSelectedModelId: (modelId: string | undefined) => void;
1615
}
1716

1817
type DialogType = 'logs' | 'delete' | 'export' | null;
1918

20-
export const ModelActionsMenu = ({ model, selectedModelId, onSetSelectedModelId }: ModelActionsMenuProps) => {
19+
export const ModelActionsMenu = ({ model, selectedModelId }: ModelActionsMenuProps) => {
2120
const { projectId } = useProjectIdentifier();
21+
const patchPipeline = usePatchPipeline(projectId);
2222
const [openDialog, setOpenDialog] = useState<DialogType>(null);
2323

2424
const cancelJobMutation = $api.useMutation('post', '/api/jobs/{job_id}:cancel');
@@ -33,8 +33,9 @@ export const ModelActionsMenu = ({ model, selectedModelId, onSetSelectedModelId
3333
});
3434

3535
const hasJobActions = Boolean(model.job?.id);
36-
const canDeleteModel = model.status === 'Completed' && model.id !== selectedModelId;
37-
const canExportModel = model.status === 'Completed';
36+
const hasCompletedStatus = model.status === 'Completed';
37+
const canDeleteModel = hasCompletedStatus && model.id !== selectedModelId;
38+
const canExportModel = hasCompletedStatus;
3839
const shouldShowMenu = hasJobActions || canDeleteModel || canExportModel;
3940

4041
if (!shouldShowMenu) {
@@ -48,20 +49,17 @@ export const ModelActionsMenu = ({ model, selectedModelId, onSetSelectedModelId
4849
if (deleteModelMutation.isPending) {
4950
disabledMenuKeys.push('delete');
5051
}
52+
if (model.id === selectedModelId || patchPipeline.isPending) {
53+
disabledMenuKeys.push('activate');
54+
}
5155

5256
const handleCancelJob = () => {
5357
if (!model.job?.id) {
5458
return;
5559
}
5660

5761
void cancelJobMutation.mutateAsync(
58-
{
59-
params: {
60-
path: {
61-
job_id: model.job.id,
62-
},
63-
},
64-
},
62+
{ params: { path: { job_id: model.job.id } } },
6563
{
6664
onError: () => {
6765
toast({ type: 'error', message: 'Failed to cancel training job.' });
@@ -70,20 +68,17 @@ export const ModelActionsMenu = ({ model, selectedModelId, onSetSelectedModelId
7068
);
7169
};
7270

71+
const handleSetModel = (modelId?: string) => {
72+
patchPipeline.mutateAsync({ params: { path: { project_id: projectId } }, body: { model_id: modelId } });
73+
};
74+
7375
const handleDeleteModel = () => {
7476
void deleteModelMutation.mutateAsync(
75-
{
76-
params: {
77-
path: {
78-
project_id: projectId,
79-
model_id: model.id,
80-
},
81-
},
82-
},
77+
{ params: { path: { project_id: projectId, model_id: model.id } } },
8378
{
8479
onSuccess: () => {
8580
if (selectedModelId === model.id) {
86-
onSetSelectedModelId(undefined);
81+
handleSetModel(undefined);
8782
}
8883

8984
toast({ type: 'success', message: `Model "${model.name}" has been deleted.` });
@@ -119,8 +114,12 @@ export const ModelActionsMenu = ({ model, selectedModelId, onSetSelectedModelId
119114
if (actionKey === 'delete' && canDeleteModel) {
120115
setOpenDialog('delete');
121116
}
117+
if (actionKey === 'activate' && hasCompletedStatus) {
118+
handleSetModel(model.id);
119+
}
122120
}}
123121
>
122+
{hasCompletedStatus ? <Item key='activate'>Activate</Item> : null}
124123
{hasJobActions ? <Item key='logs'>View logs</Item> : null}
125124
{model.job?.status === 'pending' || model.job?.status === 'running' ? (
126125
<Item key='cancel'>Cancel training</Item>

application/ui/src/features/inspect/models/models-view.component.tsx

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useMemo } from 'react';
22

33
import { $api } from '@geti-inspect/api';
4-
import { usePipeline, useProjectIdentifier, useSetModelToPipeline } from '@geti-inspect/hooks';
4+
import { usePipeline, useProjectIdentifier } from '@geti-inspect/hooks';
55
import {
66
Cell,
77
Column,
@@ -39,7 +39,7 @@ const useModels = () => {
3939
export const ModelsView = () => {
4040
const { data: pipeline } = usePipeline();
4141
const { jobs = [] } = useProjectTrainingJobs();
42-
const setModelToPipelineMutation = useSetModelToPipeline();
42+
4343
const dateFormatter = useDateFormatter({ dateStyle: 'medium', timeStyle: 'short' });
4444
const selectedModelId = pipeline.model?.id;
4545
useRefreshModelsOnJobUpdates(jobs);
@@ -109,10 +109,6 @@ export const ModelsView = () => {
109109
return new Set<string>([selectedModelId]);
110110
}, [selectedModelId]);
111111

112-
const handleSetModel = (modelId?: string) => {
113-
setModelToPipelineMutation(modelId);
114-
};
115-
116112
return (
117113
<View backgroundColor='gray-100' height='100%'>
118114
{/* Models Table */}
@@ -122,22 +118,6 @@ export const ModelsView = () => {
122118
selectionStyle='highlight'
123119
selectionMode='single'
124120
selectedKeys={tableSelectedKeys}
125-
onSelectionChange={(key) => {
126-
if (typeof key === 'string') {
127-
return;
128-
}
129-
130-
const selectedId = key.values().next().value;
131-
if (selectedId === selectedModelId) {
132-
return;
133-
}
134-
135-
const selectedModel = models.find((model) => model.id === selectedId);
136-
137-
if (selectedModel?.status === 'Completed') {
138-
handleSetModel(selectedModel.id);
139-
}
140-
}}
141121
UNSAFE_className={classes.table}
142122
renderEmptyState={() => (
143123
<IllustratedMessage>
@@ -178,11 +158,7 @@ export const ModelsView = () => {
178158
<Cell>
179159
<Flex justifyContent='end' alignItems='center'>
180160
<Flex alignItems='center' gap='size-200'>
181-
<ModelActionsMenu
182-
model={model}
183-
selectedModelId={selectedModelId}
184-
onSetSelectedModelId={handleSetModel}
185-
/>
161+
<ModelActionsMenu model={model} selectedModelId={selectedModelId} />
186162
</Flex>
187163
</Flex>
188164
</Cell>

application/ui/src/features/inspect/stream/fps/fps.component.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export const Fps = ({ projectId }: FpsProp) => {
2525
const requestsPerSecond = metrics?.inference.throughput.avg_requests_per_second;
2626

2727
if (isEmpty(metrics) || isNil(requestsPerSecond)) {
28-
return <></>;
28+
return null;
2929
}
3030

3131
return (
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
.option {
2+
text-align: left;
23
background-color: var(--spectrum-global-color-gray-75);
34
border-radius: var(--spectrum-alias-border-radius-regular);
45
border: var(--spectrum-alias-border-size-thin) solid var(--spectrum-global-color-gray-200) !important;
6+
7+
span {
8+
text-align: left;
9+
}
10+
}
11+
12+
.active {
13+
border-left: var(--spectrum-global-dimension-size-50) solid var(--aqua) !important;
514
}

application/ui/src/features/inspect/toolbar/models-list/models-list.component.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// SPDX-License-Identifier: Apache-2.0
33

44
import { usePatchPipeline, usePipeline, useProjectIdentifier } from '@geti-inspect/hooks';
5-
import { Button, Content, Flex, IllustratedMessage, Text } from '@geti/ui';
5+
import { Button, Content, Flex, IllustratedMessage } from '@geti/ui';
66
import { clsx } from 'clsx';
77
import { isEmpty } from 'lodash-es';
88
import { NotFound } from 'packages/ui/icons';
@@ -27,7 +27,7 @@ export const ModelsList = () => {
2727
});
2828
};
2929

30-
if (isEmpty(modelsIds) || !selectedModelId) {
30+
if (isEmpty(modelsIds)) {
3131
return renderEmptyState();
3232
}
3333

@@ -36,13 +36,13 @@ export const ModelsList = () => {
3636
{models.map((model) => (
3737
<Button
3838
key={model.id}
39-
variant={model.id === selectedModelId ? 'accent' : 'secondary'}
39+
variant='secondary'
4040
onPress={() => handleSelectionChange(String(model.id))}
4141
isPending={patchPipeline.isPending}
4242
isDisabled={patchPipeline.isPending}
43-
UNSAFE_className={clsx(classes.option)}
43+
UNSAFE_className={clsx(classes.option, { [classes.active]: model.id === selectedModelId })}
4444
>
45-
<Text>{model.name}</Text>
45+
{model.name}
4646
</Button>
4747
))}
4848
</Flex>

application/ui/src/hooks/use-pipeline.hook.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -112,18 +112,6 @@ export const useConnectSinkToPipeline = () => {
112112
pipeline.mutateAsync({ params: { path: { project_id: projectId } }, body: { sink_id } });
113113
};
114114

115-
export const useSetModelToPipeline = () => {
116-
const { projectId } = useProjectIdentifier();
117-
const pipeline = usePatchPipeline(projectId);
118-
119-
return (modelId: string | undefined) => {
120-
pipeline.mutate({
121-
params: { path: { project_id: projectId } },
122-
body: { model_id: modelId },
123-
});
124-
};
125-
};
126-
127115
export const useActivePipeline = () => {
128116
return $api.useSuspenseQuery('get', '/api/active-pipeline');
129117
};

0 commit comments

Comments
 (0)