import { FileSkeletonRows } from '@/pages/llmodels/components/model-source/file-skeleton'; import { AutoTooltip, IconFont, TemplateCard } from '@gpustack/core-ui'; import { useIntl } from '@umijs/max'; import { Empty, Flex, Spin } from 'antd'; import _ from 'lodash'; import { Fragment } from 'react'; import styled from 'styled-components'; import { ListItem as TemplateItem } from '../../templates/config/types'; const GroupTitle = styled.div` font-size: 12px; font-weight: 500; color: var(--ant-color-text-tertiary); margin-bottom: -8px; `; const TemplateContent = styled.div` display: flex; flex-direction: column; gap: 8px; color: var(--ant-color-text-secondary); .name { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 8px; color: var(--ant-color-text); font-weight: 500; } .info { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 8px; color: var(--ant-color-text-tertiary); } .value { color: var(--ant-color-text-secondary); } .icon { color: var(--ant-color-text-quaternary); } `; const TypeGrid = styled.div` display: flex; flex-direction: column; gap: 16px; `; export interface TemplateGroup { key: string; label: React.ReactNode; items: TemplateItem[]; } interface TemplateSelectorProps { value?: number; loading?: boolean; onChange?: (value: number, item: TemplateItem) => void; groups?: TemplateGroup[]; } const TemplateSelector: React.FC = ({ value, onChange, loading, groups = [] }) => { const intl = useIntl(); const handleSelect = (item: TemplateItem) => { if (value === item.id) return; onChange?.(item.id, item); }; if (loading) { return ( {_.times(6, (index: number) => ( ))} ); } if (!groups.length) { return ; } const renderItem = (item: TemplateItem) => ( handleSelect(item)} >
{item.displayName || item.name || '-'}
{' '} {intl.formatMessage({ id: 'gpuservice.instance.template.image' })} : {item.spec?.image || '-'}
{' '} {intl.formatMessage({ id: 'gpuservice.instance.template.mount' })} : {item.spec?.volumeMount || '-'}
); // A single group renders flat — the header would only restate what // the whole list already is. const showGroupTitles = groups.length > 1; return ( {groups.map((group) => ( {showGroupTitles && {group.label}} {group.items.map(renderItem)} ))} ); }; export default TemplateSelector;