Skip to content

Commit

Permalink
feat: new image parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
agatha197 committed Oct 29, 2024
1 parent 80bd516 commit f63248b
Show file tree
Hide file tree
Showing 25 changed files with 232 additions and 138 deletions.
10 changes: 4 additions & 6 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"Backendai",
"backendaiclient",
"backendaioptions",
"baseversion",
"cssinjs",
"cuda",
"FGPU",
Expand All @@ -19,17 +20,14 @@
"RNGD",
"shmem",
"superadmin",
"textbox",
"vaadin",
"vfolder",
"vfolders",
"Warboy",
"webcomponent",
"webui",
"wsproxy",
"vfolders",
"vfolder",
"filebrowser",
"vaadin",
"textbox"
"wsproxy"
],
"flagWords": [
"데이터레이크",
Expand Down
41 changes: 38 additions & 3 deletions react/data/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,18 @@ type Queries {
group_node(id: String!): GroupNode

"""Added in 24.03.0."""
group_nodes(filter: String, order: String, offset: Int, before: String, after: String, first: Int, last: Int): GroupConnection
group_nodes(
"""Added in 24.09.0."""
filter: String

"""Added in 24.09.0."""
order: String
offset: Int
before: String
after: String
first: Int
last: Int
): GroupConnection
group(
id: UUID!
domain_name: String
Expand Down Expand Up @@ -287,12 +298,24 @@ type ImageNode implements Node {

"""Added in 24.03.4. The undecoded id value stored in DB."""
row_id: UUID
name: String
name: String @deprecated(reason: "Deprecated since 24.09.1. use `namespace` instead")

"""Added in 24.09.1."""
namespace: String

"""Added in 24.09.1."""
base_image_name: String

"""Added in 24.03.10."""
project: String
humanized_name: String
tag: String

"""Added in 24.09.1."""
tags: [KVPair]

"""Added in 24.09.1."""
version: String
registry: String
architecture: String
is_local: Boolean
Expand Down Expand Up @@ -504,12 +527,24 @@ type Group {

type Image {
id: UUID
name: String
name: String @deprecated(reason: "Deprecated since 24.09.1. use `namespace` instead")

"""Added in 24.09.1."""
namespace: String

"""Added in 24.09.1."""
base_image_name: String

"""Added in 24.03.10."""
project: String
humanized_name: String
tag: String

"""Added in 24.09.1."""
tags: [KVPair]

"""Added in 24.09.1."""
version: String
registry: String
architecture: String
is_local: Boolean
Expand Down
232 changes: 124 additions & 108 deletions react/src/components/ImageList.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import Flex from '../components/Flex';
import { filterNonNullItems, getImageFullName } from '../helper';
import { useBackendAIImageMetaData, useUpdatableState } from '../hooks';
import { filterNonNullItems, getImageFullName, localeCompare } from '../helper';
import {
useBackendAIImageMetaData,
useSuspendedBackendaiClient,
useUpdatableState,
} from '../hooks';
import DoubleTag from './DoubleTag';
import ImageInstallModal from './ImageInstallModal';
import { ConstraintTags } from './ImageTags';
import ManageAppsModal from './ManageAppsModal';
Expand Down Expand Up @@ -52,13 +57,16 @@ const ImageList: React.FC<{ style?: React.CSSProperties }> = ({ style }) => {
const [imageSearch, setImageSearch] = useState('');
const [isPendingRefreshTransition, startRefreshTransition] = useTransition();
const [isPendingSearchTransition, startSearchTransition] = useTransition();
const baiClient = useSuspendedBackendaiClient();
const supportExtendedImageInfo =
baiClient?.supports('extended-image-info') ?? false;

const { images } = useLazyLoadQuery<ImageListQuery>(
graphql`
query ImageListQuery {
images {
id
name
name @deprecatedSince(version: "24.09.1.")
tag
registry
architecture
Expand All @@ -74,6 +82,13 @@ const ImageList: React.FC<{ style?: React.CSSProperties }> = ({ style }) => {
min
max
}
namespace @since(version: "24.09.1.")
base_image_name @since(version: "24.09.1.")
tags @since(version: "24.09.1.") {
key
value
}
version @since(version: "24.09.1.")
}
}
`,
Expand Down Expand Up @@ -122,136 +137,137 @@ const ImageList: React.FC<{ style?: React.CSSProperties }> = ({ style }) => {
title: t('environment.Registry'),
dataIndex: 'registry',
key: 'registry',
sorter: (a, b) =>
a?.registry && b?.registry ? a.registry.localeCompare(b.registry) : 0,
render: (text, row) => (
<TextHighlighter keyword={imageSearch}>{row.registry}</TextHighlighter>
sorter: (a, b) => localeCompare(a?.registry, b?.registry),
render: (text) => (
<TextHighlighter keyword={imageSearch}>{text}</TextHighlighter>
),
},
{
title: t('environment.Architecture'),
dataIndex: 'architecture',
key: 'architecture',
sorter: (a, b) =>
a?.architecture && b?.architecture
? a.architecture.localeCompare(b.architecture)
: 0,
render: (text, row) => (
<TextHighlighter keyword={imageSearch}>
{row.architecture}
</TextHighlighter>
sorter: true,
render: (text) => (
<TextHighlighter keyword={imageSearch}>{text}</TextHighlighter>
),
},
{
title: t('environment.Namespace'),
key: 'namespace',
dataIndex: 'namespace',
sorter: (a, b) => {
const namespaceA = getNamespace(getImageFullName(a) || '');
const namespaceB = getNamespace(getImageFullName(b) || '');
return namespaceA && namespaceB
? namespaceA.localeCompare(namespaceB)
: 0;
},
render: (text, row) => (
<TextHighlighter keyword={imageSearch}>
{getNamespace(getImageFullName(row) || '')}
</TextHighlighter>
dataIndex: supportExtendedImageInfo ? 'namespace' : 'name',
sorter: true,
render: (text) => (
<TextHighlighter keyword={imageSearch}>{text}</TextHighlighter>
),
},
{
title: t('environment.Language'),
title: supportExtendedImageInfo
? t('environment.BaseImageName')
: t('environment.Language'),
key: 'lang',
dataIndex: 'lang',
sorter: (a, b) => {
const langA = a?.name ? getLang(a?.name) : '';
const langB = b?.name ? getLang(b?.name) : '';
return langA && langB ? langA.localeCompare(langB) : 0;
},
render: (text, row) => (
<TextHighlighter keyword={imageSearch}>
{row.name ? getLang(row.name) : null}
</TextHighlighter>
dataIndex: supportExtendedImageInfo ? 'base_image_name' : 'lang',
sorter: true,
render: (text) => (
<TextHighlighter keyword={imageSearch}>{text}</TextHighlighter>
),
},
{
title: t('environment.Version'),
key: 'baseversion',
dataIndex: 'baseversion',
sorter: (a, b) => {
const baseversionA = getBaseVersion(getImageFullName(a) || '');
const baseversionB = getBaseVersion(getImageFullName(b) || '');
return baseversionA && baseversionB
? baseversionA.localeCompare(baseversionB)
: 0;
},
dataIndex: supportExtendedImageInfo ? 'version' : 'baseversion',
sorter: true,
render: (text, row) => (
<TextHighlighter keyword={imageSearch}>
{getBaseVersion(getImageFullName(row) || '')}
{supportExtendedImageInfo
? text
: getBaseVersion(getImageFullName(row) || '')}
</TextHighlighter>
),
},
{
title: t('environment.Base'),
key: 'baseimage',
dataIndex: 'baseimage',
sorter: (a, b) => {
const baseimageA =
!a?.tag || !a?.name ? '' : getBaseImages(a?.tag, a?.name)[0] || '';
const baseimageB =
!b?.tag || !b?.name ? '' : getBaseImages(b?.tag, b?.name)[0] || '';
if (baseimageA === '' && baseimageB === '') return 0;
if (baseimageA === '') return -1;
if (baseimageB === '') return 1;
return baseimageA.localeCompare(baseimageB);
},
render: (text, row) => (
<Flex direction="row" align="start">
{row?.tag && row?.name
? getBaseImages(row.tag, row.name).map((baseImage) => (
<Tag color="green">
<TextHighlighter keyword={imageSearch}>
{baseImage}
</TextHighlighter>
</Tag>
))
: null}
</Flex>
),
},
{
title: t('environment.Constraint'),
key: 'constraint',
dataIndex: 'constraint',
sorter: (a, b) => {
const requirementA =
a?.tag && b?.labels
? getConstraints(
a?.tag,
a?.labels as { key: string; value: string }[],
)[0] || ''
: '';
const requirementB =
b?.tag && b?.labels
? getConstraints(
b?.tag,
b?.labels as { key: string; value: string }[],
)[0] || ''
: '';
if (requirementA === '' && requirementB === '') return 0;
if (requirementA === '') return -1;
if (requirementB === '') return 1;
return requirementA.localeCompare(requirementB);
},
render: (text, row) =>
row?.tag ? (
<ConstraintTags
tag={row?.tag}
labels={row?.labels as { key: string; value: string }[]}
highlightKeyword={imageSearch}
/>
) : null,
},
...(supportExtendedImageInfo
? [
{
title: t('environment.Tags'),
key: 'tags',
dataIndex: 'tags',
render: (text: Array<{ key: string; value: string }>) => {
return (
<Flex direction="row" align="start">
{_.map(text, (tag) => (
<DoubleTag values={[tag.key, tag.value]} />
))}
</Flex>
);
},
},
]
: [
{
title: t('environment.Base'),
key: 'baseimage',
dataIndex: 'baseimage',
sorter: (a: EnvironmentImage, b: EnvironmentImage) => {
const baseimageA =
!a?.tag || !a?.name
? ''
: getBaseImages(a?.tag, a?.name)[0] || '';
const baseimageB =
!b?.tag || !b?.name
? ''
: getBaseImages(b?.tag, b?.name)[0] || '';
if (baseimageA === '' && baseimageB === '') return 0;
if (baseimageA === '') return -1;
if (baseimageB === '') return 1;
return baseimageA.localeCompare(baseimageB);
},
render: (text: string, row: EnvironmentImage) => (
<Flex direction="row" align="start">
{row?.tag && row?.name
? getBaseImages(row.tag, row.name).map((baseImage) => (
<Tag color="green">
<TextHighlighter keyword={imageSearch}>
{baseImage}
</TextHighlighter>
</Tag>
))
: null}
</Flex>
),
},
{
title: t('environment.Constraint'),
key: 'constraint',
dataIndex: 'constraint',
sorter: (a: EnvironmentImage, b: EnvironmentImage) => {
const requirementA =
a?.tag && b?.labels
? getConstraints(
a?.tag,
a?.labels as { key: string; value: string }[],
)[0] || ''
: '';
const requirementB =
b?.tag && b?.labels
? getConstraints(
b?.tag,
b?.labels as { key: string; value: string }[],
)[0] || ''
: '';
if (requirementA === '' && requirementB === '') return 0;
if (requirementA === '') return -1;
if (requirementB === '') return 1;
return requirementA.localeCompare(requirementB);
},
render: (text: string, row: EnvironmentImage) =>
row?.tag ? (
<ConstraintTags
tag={row?.tag}
labels={row?.labels as { key: string; value: string }[]}
highlightKeyword={imageSearch}
/>
) : null,
},
]),
{
title: t('environment.Digest'),
dataIndex: 'digest',
Expand Down
Loading

0 comments on commit f63248b

Please sign in to comment.