Skip to content

Commit

Permalink
feat(quay): fix sorting in quay table and tag details (#1044)
Browse files Browse the repository at this point in the history
* feat(quay): fix sorting in quay table and tag details

* chore(quay): update type assertions

* chore: update types to take advantage of generics
  • Loading branch information
Zaperex authored Jan 11, 2024
1 parent c4f2969 commit ceb16a9
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export function QuayRepository(_props: QuayRepositoryProps) {
<div data-testid="quay-repo-table" style={{ border: '1px solid #ddd' }}>
<Table
title={title}
options={{ paging: true, padding: 'dense' }}
options={{ sorting: true, paging: true, padding: 'dense' }}
data={data}
columns={columns}
emptyContent={
Expand Down
12 changes: 8 additions & 4 deletions plugins/quay/src/components/QuayRepository/tableHeading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import { Tooltip } from '@material-ui/core';
import makeStyles from '@material-ui/core/styles/makeStyles';

import { vulnerabilitySummary } from '../../lib/utils';
import type { Layer } from '../../types';
import type { QuayTagData } from '../../types';

export const columns: TableColumn[] = [
export const columns: TableColumn<QuayTagData>[] = [
{
title: 'Tag',
field: 'name',
Expand All @@ -23,7 +23,7 @@ export const columns: TableColumn[] = [
{
title: 'Security Scan',
field: 'securityScan',
render: (rowData: any): React.ReactNode => {
render: (rowData: QuayTagData): React.ReactNode => {
if (!rowData.securityStatus && !rowData.securityDetails) {
return (
<span data-testid="quay-repo-security-scan-progress">
Expand All @@ -43,15 +43,17 @@ export const columns: TableColumn[] = [
}

const tagManifest = rowData.manifest_digest_raw;
const retStr = vulnerabilitySummary(rowData.securityDetails as Layer);
const retStr = vulnerabilitySummary(rowData.securityDetails);
return <Link to={`tag/${tagManifest}`}>{retStr}</Link>;
},
id: 'securityScan',
sorting: false,
},
{
title: 'Size',
field: 'size',
type: 'numeric',
customSort: (a: QuayTagData, b: QuayTagData) => a.rawSize - b.rawSize,
},
{
title: 'Expires',
Expand All @@ -63,6 +65,8 @@ export const columns: TableColumn[] = [
title: 'Manifest',
field: 'manifest_digest',
type: 'string',
customSort: (a: QuayTagData, b: QuayTagData) =>
a.manifest_digest_raw.localeCompare(b.manifest_digest_raw),
},
];

Expand Down
35 changes: 19 additions & 16 deletions plugins/quay/src/components/QuayTagDetails/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,38 +25,44 @@ type QuayTagDetailsProps = {
// from: https://github.com/quay/quay/blob/f1d85588157eababc3cbf789002c5db521dbd616/web/src/routes/TagDetails/SecurityReport/SecurityReportTable.tsx#L43
const getVulnerabilityLink = (link: string) => link.split(' ')[0];

const columns: TableColumn[] = [
const columns: TableColumn<VulnerabilityListItem>[] = [
{
title: 'Advisory',
field: 'name',
render: (rowData: any): React.ReactNode => {
const row = rowData as Vulnerability;
render: (rowData: VulnerabilityListItem): React.ReactNode => {
return (
<div style={{ display: 'flex', alignItems: 'center' }}>
{row.Name}
{row.Link.trim().length > 0 ? (
<Link to={getVulnerabilityLink(row.Link)}>
{rowData.Name}
{rowData.Link.trim().length > 0 ? (
<Link to={getVulnerabilityLink(rowData.Link)}>
<LinkIcon style={{ marginLeft: '0.5rem' }} />
</Link>
) : null}
</div>
);
},
customSort: (a: VulnerabilityListItem, b: VulnerabilityListItem) =>
a.Name.localeCompare(b.Name, 'en'),
},
{
title: 'Severity',
field: 'Severity',
render: (rowData: any): React.ReactNode => {
const row = rowData as Vulnerability;
customSort: (a: VulnerabilityListItem, b: VulnerabilityListItem) => {
const severityA = VulnerabilityOrder[a.Severity];
const severityB = VulnerabilityOrder[b.Severity];

return severityA - severityB;
},
render: (rowData: VulnerabilityListItem): React.ReactNode => {
return (
<div style={{ display: 'flex', alignItems: 'center' }}>
<WarningIcon
htmlColor={SEVERITY_COLORS[row.Severity]}
htmlColor={SEVERITY_COLORS[rowData.Severity]}
style={{
marginRight: '0.5rem',
}}
/>
<span>{row.Severity}</span>
<span>{rowData.Severity}</span>
</div>
);
},
Expand All @@ -74,14 +80,11 @@ const columns: TableColumn[] = [
{
title: 'Fixed By',
field: 'FixedBy',
render: (rowData: any): React.ReactNode => {
const row = rowData as VulnerabilityListItem;
render: (rowData: VulnerabilityListItem): React.ReactNode => {
return (
<>
{row.FixedBy.length > 0 ? (
<>
<span>{row.FixedBy}</span>
</>
{rowData.FixedBy.length > 0 ? (
<span>{rowData.FixedBy}</span>
) : (
'(None)'
)}
Expand Down
5 changes: 3 additions & 2 deletions plugins/quay/src/hooks/quay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { Box, Chip, makeStyles } from '@material-ui/core';
import { formatByteSize, formatDate } from '@janus-idp/shared-react';

import { quayApiRef } from '../api';
import { Layer, Tag } from '../types';
import { Layer, QuayTagData, Tag } from '../types';

const useLocalStyles = makeStyles({
chip: {
Expand Down Expand Up @@ -68,7 +68,7 @@ export const useTags = (organization: string, repository: string) => {
return tagsResponse;
});

const data = useMemo(() => {
const data: QuayTagData[] = useMemo(() => {
return Object.values(tags)?.map(tag => {
const hashFunc = tag.manifest_digest.substring(0, 6);
const shortHash = tag.manifest_digest.substring(7, 19);
Expand All @@ -77,6 +77,7 @@ export const useTags = (organization: string, repository: string) => {
name: tag.name,
last_modified: formatDate(tag.last_modified),
size: formatByteSize(tag.size),
rawSize: tag.size,
manifest_digest: (
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Chip label={hashFunc} className={localClasses.chip} />
Expand Down
13 changes: 12 additions & 1 deletion plugins/quay/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,18 @@ export interface Tag {
export interface LabelsResponse {
labels: Label[];
}

export interface QuayTagData {
id: string;
name: string;
last_modified: string;
size: string;
rawSize: number;
manifest_digest: React.JSX.Element;
expiration?: string;
securityDetails: Layer;
securityStatus: string;
manifest_digest_raw: string;
}
export interface Label {
id: string;
key: string;
Expand Down

0 comments on commit ceb16a9

Please sign in to comment.