/* * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 */ import './index.scss'; import React, { useCallback, useMemo } from 'react'; import { Criteria, Direction, EuiBasicTable, EuiButton, EuiButtonIcon, EuiCopy, EuiEmptyPrompt, EuiHealth, EuiSpacer, EuiLink, EuiText, EuiToolTip, } from '@elastic/eui'; import { MODEL_STATE } from '../../../common'; export interface ModelDeploymentTableSort { field: 'name' | 'model_state' | 'id'; direction: Direction; } export interface ModelDeploymentTableCriteria { pagination?: { currentPage: number; pageSize: number }; sort?: ModelDeploymentTableSort; } export interface ModelDeploymentItem { id: string; name: string; model_state?: MODEL_STATE; respondingNodesCount: number | undefined; planningNodesCount: number | undefined; notRespondingNodesCount: number | undefined; planningWorkerNodes: string[]; } export interface ModelDeploymentTableProps { items: ModelDeploymentItem[]; loading?: boolean; noTable?: boolean; pagination?: { currentPage: number; pageSize: number; totalRecords: number | undefined; }; sort: ModelDeploymentTableSort; onChange: (criteria: ModelDeploymentTableCriteria) => void; onViewDetail?: (modelDeploymentItem: ModelDeploymentItem) => void; onResetSearchClick?: () => void; } export const ModelDeploymentTable = ({ sort, items, loading, noTable, pagination: paginationInProps, onChange, onViewDetail, onResetSearchClick, }: ModelDeploymentTableProps) => { const columns = useMemo( () => [ { field: 'name', name: 'Name', width: '27.5%', sortable: true, truncateText: true, }, { field: 'model_state', name: 'Status', width: '34.5%', sortable: true, truncateText: true, render: ( _model_state: string, { planningNodesCount, respondingNodesCount, notRespondingNodesCount }: ModelDeploymentItem ) => { if ( planningNodesCount === undefined || respondingNodesCount === undefined || notRespondingNodesCount === undefined ) { return '-'; } if (respondingNodesCount === 0) { return (
Not responding on {planningNodesCount} of{' '} {planningNodesCount} nodes
); } if (notRespondingNodesCount === 0) { return (
Responding on {planningNodesCount} of{' '} {planningNodesCount} nodes
); } return (
Partially responding on{' '} {respondingNodesCount} of {planningNodesCount} nodes
); }, }, { field: 'source', name: 'Source', width: '7%', sortable: false, truncateText: true, }, { field: 'id', name: 'Model ID', width: '21%', sortable: true, render: (id: string) => ( {(copy) => ( {id} )} ), }, { field: 'id', name: 'Action', align: 'right' as const, width: '10%', render: (id: string, modelDeploymentItem: ModelDeploymentItem) => { return ( { onViewDetail?.(modelDeploymentItem); }} role="button" aria-label="view detail" iconType="inspect" /> ); }, }, ], [onViewDetail] ); const sorting = useMemo(() => ({ sort }), [sort]); const pagination = useMemo( () => paginationInProps ? { pageIndex: paginationInProps.currentPage - 1, pageSize: paginationInProps.pageSize, totalItemCount: paginationInProps.totalRecords || 0, pageSizeOptions: [10, 20, 50], showPerPageOptions: true, } : undefined, [paginationInProps] ); const handleChange = useCallback( (criteria: Criteria) => { onChange({ ...(criteria.page ? { pagination: { currentPage: criteria.page.index + 1, pageSize: criteria.page.size } } : {}), ...(criteria.sort ? { sort: criteria.sort as ModelDeploymentTableSort } : {}), }); }, [onChange] ); return ( <> {noTable ? (
Deployed models will appear here. For more information, see{' '} Machine Learning Documentation . } aria-label="no deployed models" />
) : ( 0 ? pagination : undefined} noItemsMessage={
{loading ? ( Loading deployed models... } aria-label="loading models" /> ) : ( } body={ <> There are no results to your search. Reset the search criteria to view the deployed models. } actions={ <> Reset search } aria-label="no models results" /> )}
} /> )} ); };