Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion data/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -17906,7 +17906,6 @@ input UpdateDeploymentInput
openToPublic: Boolean
tags: [String!]
defaultDeploymentStrategy: DeploymentStrategyInput
activeRevisionId: ID
replicaCount: Int
name: String
preferredDomainName: String
Expand Down
193 changes: 100 additions & 93 deletions react/src/components/DeploymentAccessTokensTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
} from 'antd';
import {
BAICard,
BAIDeleteConfirmModal,
BAIFetchKeyButton,
BAIFlex,
BAIModal,
Expand Down Expand Up @@ -253,8 +254,12 @@ const DeploymentAccessTokensTable: React.FC<
}) => {
'use memo';
const { t } = useTranslation();
const { message, modal } = App.useApp();
const { message } = App.useApp();
const { logger } = useBAILogger();
const [deletingToken, setDeletingToken] = useState<{
id: string;
token: string;
} | null>(null);

const { deployment: listData } =
useLazyLoadQuery<DeploymentAccessTokensTabListQuery>(
Expand Down Expand Up @@ -301,100 +306,102 @@ const DeploymentAccessTokensTable: React.FC<
`);

return (
<BAITable<AccessTokenNode>
scroll={{ x: 'max-content' }}
rowKey="id"
loading={isPendingRefetch || isDeletingToken}
dataSource={accessTokens}
pagination={false}
columns={[
{
key: 'token',
title: t('deployment.accessToken.Token'),
dataIndex: 'token',
render: (_text, row) => {
if (!row) return '-';
return (
<BAINameActionCell
title={
<BAIText
copyable={{ text: row.token }}
ellipsis
code
style={{ maxWidth: 120 }}
>
{row.token}
</BAIText>
}
showActions="always"
actions={[
{
key: 'delete',
title: t('deployment.accessToken.Delete'),
icon: <DeleteOutlined />,
type: 'danger',
disabled: isDeleteDisabled,
onClick: () => {
modal.confirm({
title: t('deployment.accessToken.Delete'),
content: t('deployment.accessToken.DeleteConfirm'),
okText: t('button.Delete'),
okButtonProps: { danger: true },
onOk: () => {
commitDelete({
variables: {
input: {
id: toLocalId(row.id) ?? row.id,
},
},
onCompleted: (_res, errors) => {
if (errors && errors.length > 0) {
logger.error(errors[0]);
message.error(
errors[0]?.message ??
t('dialog.ErrorOccurred'),
);
return;
}
message.success(
t('deployment.accessToken.Deleted'),
);
onAfterDelete();
},
onError: (err) => {
logger.error(err);
message.error(
err.message ?? t('dialog.ErrorOccurred'),
);
},
});
},
});
<>
<BAITable<AccessTokenNode>
scroll={{ x: 'max-content' }}
rowKey="id"
loading={isPendingRefetch || isDeletingToken}
dataSource={accessTokens}
pagination={false}
columns={[
{
key: 'token',
title: t('deployment.accessToken.Token'),
dataIndex: 'token',
render: (_text, row) => {
if (!row) return '-';
return (
<BAINameActionCell
title={
<BAIText
copyable={{ text: row.token }}
ellipsis
code
style={{ maxWidth: 120 }}
>
{row.token}
</BAIText>
}
showActions="always"
actions={[
{
key: 'delete',
title: t('deployment.accessToken.Delete'),
icon: <DeleteOutlined />,
type: 'danger',
disabled: isDeleteDisabled,
onClick: () =>
setDeletingToken({
id: row.id,
token: row.token ?? '',
}),
},
},
]}
/>
);
]}
/>
);
},
},
},
{
key: 'createdAt',
title: t('deployment.CreatedAt'),
dataIndex: 'createdAt',
render: (_text, row) =>
row?.createdAt ? dayjs(row.createdAt).format('ll LT') : '-',
},
{
key: 'expiresAt',
title: t('deployment.accessToken.Expiration'),
dataIndex: 'expiresAt',
render: (_text, row) =>
row?.expiresAt
? dayjs(row.expiresAt).format('ll LT')
: t('deployment.accessToken.NoExpiration'),
},
]}
/>
{
key: 'createdAt',
title: t('deployment.CreatedAt'),
dataIndex: 'createdAt',
render: (_text, row) =>
row?.createdAt ? dayjs(row.createdAt).format('ll LT') : '-',
},
{
key: 'expiresAt',
title: t('deployment.accessToken.Expiration'),
dataIndex: 'expiresAt',
render: (_text, row) =>
row?.expiresAt
? dayjs(row.expiresAt).format('ll LT')
: t('deployment.accessToken.NoExpiration'),
},
]}
/>
<BAIDeleteConfirmModal
open={!!deletingToken}
items={
deletingToken
? [{ key: deletingToken.id, label: deletingToken.token }]
: []
}
okButtonProps={{ loading: isDeletingToken }}
onOk={() => {
if (!deletingToken) return;
commitDelete({
variables: {
input: { id: toLocalId(deletingToken.id) ?? deletingToken.id },
},
onCompleted: (_res, errors) => {
if (errors && errors.length > 0) {
logger.error(errors[0]);
message.error(errors[0]?.message ?? t('dialog.ErrorOccurred'));
return;
}
message.success(t('deployment.accessToken.Deleted'));
setDeletingToken(null);
onAfterDelete();
},
onError: (err) => {
logger.error(err);
message.error(err.message ?? t('dialog.ErrorOccurred'));
},
});
}}
onCancel={() => setDeletingToken(null)}
/>
</>
);
};

Expand Down
44 changes: 35 additions & 9 deletions react/src/components/DeploymentConfigurationSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
import { DeploymentConfigurationSectionQuery } from '../__generated__/DeploymentConfigurationSectionQuery.graphql';
import { useWebUINavigate } from '../hooks';
import DeploymentRevisionDetailDrawer from './DeploymentRevisionDetailDrawer';
import { useFolderExplorerOpener } from './FolderExplorerOpener';
import SourceCodeView from './SourceCodeView';
import {
CheckOutlined,
CloseOutlined,
EditOutlined,
FolderOpenOutlined,
LoadingOutlined,
} from '@ant-design/icons';
import {
Expand Down Expand Up @@ -58,7 +60,7 @@ type ModelDef = {

const descriptionsProps = {
bordered: true,
column: { xxl: 3, xl: 2, lg: 2, md: 1, sm: 1, xs: 1 },
column: { xs: 1, sm: 1, md: 2, lg: 2, xl: 2, xxl: 2 },
} as const;

const renderFallback = () => (
Expand Down Expand Up @@ -220,6 +222,7 @@ const DeploymentRevisionInfoContent: React.FC<{
'use memo';
const { t } = useTranslation();
const { token } = theme.useToken();
const { open: openFolderExplorer } = useFolderExplorerOpener();

const currentRevision = deployment?.currentRevision;
const deployingRevision = deployment?.deployingRevision;
Expand Down Expand Up @@ -249,14 +252,37 @@ const DeploymentRevisionInfoContent: React.FC<{
key: 'model-folder',
label: t('deployment.ModelFolder'),
children: mountConfig?.vfolder?.name ? (
<BAIFlex direction="column" align="start">
<Typography.Text>{mountConfig.vfolder.name}</Typography.Text>
{mountConfig.mountDestination && (
<Typography.Text type="secondary">
{mountConfig.mountDestination}
</Typography.Text>
)}
</BAIFlex>
(() => {
const localId = toLocalId(mountConfig.vfolder.id);
return (
<BAIFlex direction="column" align="start">
<BAIFlex gap="xs" align="center">
<Typography.Text>{mountConfig.vfolder.name}</Typography.Text>
<Button
type="link"
size="small"
icon={<FolderOpenOutlined />}
aria-label={t('modelService.OpenFolder')}
title={t('modelService.OpenFolder')}
disabled={!localId}
style={{ padding: 0 }}
onClick={() => {
if (localId) openFolderExplorer(localId);
}}
/>
</BAIFlex>
{mountConfig.mountDestination && (
<Typography.Text type="secondary">
{mountConfig.mountDestination}
</Typography.Text>
)}
</BAIFlex>
);
})()
) : mountConfig?.vfolderId ? (
<Typography.Text type="secondary">
{mountConfig.vfolderId}
</Typography.Text>
) : (
renderFallback()
),
Expand Down
16 changes: 5 additions & 11 deletions react/src/components/DeploymentLauncherPageContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,6 @@ export interface DeploymentLauncherPageContentProps {
changed: Partial<DeploymentLauncherFormValue>,
all: DeploymentLauncherFormValue,
) => void;
/** Called when the user clicks the Cancel button in the footer. */
onCancel?: () => void;
/** Called when the user clicks the submit button on the review step. */
onSubmit?: () => Promise<void>;
/** When true the submit button shows a loading spinner and is disabled. */
Expand Down Expand Up @@ -230,7 +228,6 @@ const DeploymentLauncherPageContent: React.FC<
deploymentFrgmt,
runtimeVariants = [],
onValuesChange,
onCancel,
onSubmit,
isSubmitting,
serializerRef,
Expand Down Expand Up @@ -471,6 +468,10 @@ const DeploymentLauncherPageContent: React.FC<
revision?.clusterConfig?.size ?? DEFAULT_FORM_VALUES.clusterSize,
resourceGroup: revision?.resourceConfig?.resourceGroupName ?? '',
desiredReplicaCount: deployment.replicaState.desiredReplicaCount,
// TODO(needs-backend): FR-2787 — resourcePresetId is not exposed in the
// ModelRevision schema, so the preset selector cannot be pre-populated in
// edit mode. Once the backend exposes resourcePresetName/id on the
// revision, add it here.
} satisfies Partial<DeploymentLauncherFormValue>);
}
return _.merge({}, DEFAULT_FORM_VALUES, {
Expand Down Expand Up @@ -921,18 +922,11 @@ const DeploymentLauncherPageContent: React.FC<
hidden on the first step. */}
<BAIFlex
direction="row"
justify="between"
justify="end"
gap="sm"
style={{ marginTop: token.marginMD }}
data-test-id="deployment-launcher-tour-step-navigation"
>
<BAIFlex gap="sm">
{onCancel && (
<Button onClick={onCancel} disabled={isSubmitting}>
{t('button.Cancel')}
</Button>
)}
</BAIFlex>
<BAIFlex direction="row" gap="sm">
{!isFirstStep && (
<Button
Expand Down
8 changes: 7 additions & 1 deletion react/src/components/DeploymentReplicasTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ const DeploymentReplicasTab: React.FC<DeploymentReplicasTabProps> = ({
{
current: parseAsInteger.withDefault(1),
pageSize: parseAsInteger.withDefault(10),
order: parseAsStringLiteral(availableReplicaSorterValues),
order: parseAsStringLiteral(availableReplicaSorterValues).withDefault(
'-createdAt',
),
rFilter: parseAsString,
},
{
Expand Down Expand Up @@ -237,6 +239,9 @@ const DeploymentReplicasTab: React.FC<DeploymentReplicasTabProps> = ({
title: t('deployment.HealthStatus'),
dataIndex: 'livenessStatus',
render: (value: string | null | undefined) => (
// TODO(needs-backend): FR-2787 — expose failure reason / error message
// from the replica once the backend adds a `failureReason` field to
// `ModelReplica` so unhealthy replicas surface actionable error info.
<ReplicaStatusTag status={toReplicaTagStatus(value)} />
),
},
Expand Down Expand Up @@ -292,6 +297,7 @@ const DeploymentReplicasTab: React.FC<DeploymentReplicasTabProps> = ({
title: t('deployment.CreatedAt'),
dataIndex: 'createdAt',
sorter: isEnableSorter('createdAt'),
defaultSortOrder: 'descend',
render: (value: string | null | undefined) =>
value ? dayjs(value).format('lll') : '-',
},
Expand Down
Loading
Loading