Skip to content

Commit 8864666

Browse files
committed
update client/openapi/console.yaml
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> fix(branding): update favicon fix(branding): update favicon chore(artifacts): add attestation component, update hook chore: add mutation hook and mock data add attestation results
1 parent c827553 commit 8864666

File tree

17 files changed

+254
-134
lines changed

17 files changed

+254
-134
lines changed

branding/favicon-rh.svg

Lines changed: 19 additions & 0 deletions
Loading

branding/favicon.ico

-15 KB
Binary file not shown.

branding/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"name": "RHTAS Console UI",
44
"icons": [
55
{
6-
"src": "favicon.ico",
6+
"src": "favicon-rh.svg",
77
"sizes": "64x64 32x32 24x24 16x16",
88
"type": "image/x-icon"
99
}

client/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<meta name="theme-color" content="#000000"/>
1010
<meta name="version" content="2.0.0"/>
1111
<link rel="manifest" href="/manifest.json"/>
12-
<link rel="icon" href="/favicon.ico"/>
12+
<link rel="icon" href="/favicon-rh.svg"/>
1313
<base href="/"/>
1414
<script>
1515
window._env = "<%= _env %>";

client/openapi/console.yaml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,25 @@ components:
644644
required:
645645
- mediaType
646646
- size
647+
Signatures:
648+
type: array
649+
items:
650+
$ref: '#/components/schemas/Signature'
651+
Signature:
652+
type: object
653+
description: A cryptographic signature with its associated certificate chain
654+
properties:
655+
signature:
656+
type: string
657+
description: A single cryptographic signature encoded as a string
658+
certificateChain:
659+
type: array
660+
description: The X.509 certificate chain associated with this signature
661+
items:
662+
type: string
663+
required:
664+
- signature
665+
- certificateChain
647666
ImageMetadataResponse:
648667
type: object
649668
properties:
@@ -657,6 +676,14 @@ components:
657676
type: string
658677
description: The container image's digest (e.g., SHA256 hash)
659678
example: sha256:abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890
679+
signatures:
680+
$ref: '#/components/schemas/Signatures'
681+
attestations:
682+
type: array
683+
description: A list of signed attestations associated with the image
684+
items:
685+
type: string
686+
description: A single signed attestation payload or reference
660687
required:
661688
- artifact
662689
- metadata

client/src/app/pages/Artifacts/Artifacts.tsx

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,10 @@ import {
1414
Popover,
1515
TextInput,
1616
} from "@patternfly/react-core";
17-
import { useFetchArtifactsImageData, useVerifyArtifact } from "@app/queries/artifacts";
17+
import { useFetchArtifactsImageData } from "@app/queries/artifacts";
1818
import { LoadingWrapper } from "@app/components/LoadingWrapper";
1919
import { ArtifactResults } from "./components/ArtifactResults";
2020
import { Controller, useForm } from "react-hook-form";
21-
2221
import { ExclamationCircleIcon } from "@patternfly/react-icons";
2322

2423
const PLACEHOLDER_URI = "docker.io/library/nginx:latest";
@@ -37,14 +36,6 @@ export const Artifacts = () => {
3736
fetchError: fetchErrorArtifactMetadata,
3837
} = useFetchArtifactsImageData({ uri: artifactUri });
3938

40-
const {
41-
mutate: verifyArtifact,
42-
isPending: isVerifying,
43-
error: verifyError,
44-
data: verifyResult,
45-
reset: resetVerify,
46-
} = useVerifyArtifact();
47-
4839
const {
4940
control,
5041
handleSubmit,
@@ -62,8 +53,6 @@ export const Artifacts = () => {
6253
const uri = data.searchInput?.trim();
6354
if (!uri) return;
6455
setArtifactUri(uri);
65-
// kick off verification (transitional: SAN not required yet in our draft type)
66-
verifyArtifact({ uri });
6756
};
6857

6958
const query = watch("searchInput");

client/src/app/pages/Artifacts/components/ArtifactResults.tsx

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,17 @@ import {
1616
import { ArtifactResultsSummary } from "./ArtifactResultsSummary";
1717
import { ArtifactResultsSignatures } from "./ArtifactResultsSignatures";
1818
import { useState } from "react";
19+
import { ArtifactResultsAttestations } from "./ArtifactResultsAttestations";
1920

2021
export interface IArtifactResultsProps {
2122
artifact: ImageMetadataResponse;
2223
}
2324

2425
export const ArtifactResults = ({ artifact }: IArtifactResultsProps) => {
25-
// temporary workaround until API merged
26-
const artifactSignatures: string[] = ["a", "b"];
2726
const [activeTabKey, setActiveTabKey] = useState<string | number>(0);
2827

2928
const handleTabClick = (
30-
event: React.MouseEvent<unknown> | React.KeyboardEvent | MouseEvent,
29+
_event: React.MouseEvent<unknown> | React.KeyboardEvent | MouseEvent,
3130
tabIndex: string | number
3231
) => {
3332
setActiveTabKey(tabIndex);
@@ -39,7 +38,7 @@ export const ArtifactResults = ({ artifact }: IArtifactResultsProps) => {
3938
<Card style={{ margin: "1.5em auto 2em", overflowY: "hidden" }}>
4039
<CardHeader>
4140
<Content component={ContentVariants.h4} style={{ overflow: "hidden", textOverflow: "ellipsis" }}>
42-
<Flex className="example-border">
41+
<Flex className="border">
4342
<FlexItem>
4443
Artifact: <Button variant="plain">{artifact.image}</Button>
4544
</FlexItem>
@@ -53,18 +52,18 @@ export const ArtifactResults = ({ artifact }: IArtifactResultsProps) => {
5352
<ArtifactResultsSummary artifact={artifact} />
5453
</Panel>
5554
<Panel style={{ marginTop: "1.25em" }}>
56-
<Tabs
57-
activeKey={activeTabKey}
58-
onSelect={handleTabClick}
59-
aria-label="Tabs in the default example"
60-
role="region"
61-
>
62-
<Tab eventKey={0} title={<TabTitleText>Signatures</TabTitleText>} aria-label="Default content - users">
55+
<Tabs activeKey={activeTabKey} onSelect={handleTabClick} aria-label="Artifact results" role="region">
56+
<Tab
57+
eventKey={0}
58+
title={<TabTitleText>Signatures</TabTitleText>}
59+
aria-label="Default content - signatures"
60+
>
6361
{/** SIGNATURES */}
64-
<ArtifactResultsSignatures signatures={artifactSignatures} />
62+
<ArtifactResultsSignatures signatures={artifact.signatures} />
6563
</Tab>
6664
<Tab eventKey={1} title={<TabTitleText>Attestations</TabTitleText>}>
67-
Attestations
65+
{/** ATTESTATIONS */}
66+
<ArtifactResultsAttestations attestations={artifact.attestations} />
6867
</Tab>
6968
</Tabs>
7069
</Panel>
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import {
2+
ClipboardCopy,
3+
Content,
4+
ContentVariants,
5+
DataList,
6+
DataListCell,
7+
DataListContent,
8+
DataListItem,
9+
DataListItemCells,
10+
DataListItemRow,
11+
DataListToggle,
12+
Panel,
13+
} from "@patternfly/react-core";
14+
import { useState } from "react";
15+
16+
export const ArtifactResultsAttestations = ({ attestations }: { attestations?: string[] }) => {
17+
console.table(attestations);
18+
const [expandedIndex, setExpandedIndex] = useState<number | null>(null);
19+
20+
const handleToggleAttestationItem = (index: number) => {
21+
setExpandedIndex((prev) => (prev === index ? null : index));
22+
};
23+
24+
return (
25+
<DataList aria-label="Attestations list" isCompact>
26+
{attestations?.map((attestation, idx) => {
27+
const isExpanded = expandedIndex === idx;
28+
return (
29+
<DataListItem aria-labelledby={`att-item-${idx}`} key={`att-${idx}`} isExpanded={isExpanded}>
30+
<DataListItemRow>
31+
<DataListToggle
32+
onClick={() => handleToggleAttestationItem(idx)}
33+
isExpanded={isExpanded}
34+
id={`att-toggle-${idx}`}
35+
aria-controls={`att-expand-${idx}`}
36+
/>
37+
<DataListItemCells
38+
dataListCells={[
39+
<DataListCell key="identity">
40+
<span id="compact-item1">[email protected]</span>
41+
</DataListCell>,
42+
<DataListCell key="digest">
43+
<ClipboardCopy hoverTip="Copy" clickTip="Copied" variant="inline-compact" isCode>
44+
sha256:77db
45+
</ClipboardCopy>
46+
</DataListCell>,
47+
<DataListCell key="signatureType">DSSE</DataListCell>,
48+
<DataListCell key="integratedTime">4 months ago </DataListCell>,
49+
<DataListCell key="verificationStatus">Signature ✓ / Rekor ✓ / Chain ✓</DataListCell>,
50+
]}
51+
/>
52+
</DataListItemRow>
53+
<DataListContent
54+
aria-label="Attestation expandable content details"
55+
id={`att-expand-${idx}`}
56+
isHidden={!isExpanded}
57+
>
58+
<Panel>
59+
<Content component={ContentVariants.h6} style={{ margin: "1em auto" }}>
60+
Attestation
61+
</Content>
62+
</Panel>
63+
</DataListContent>
64+
</DataListItem>
65+
);
66+
})}
67+
</DataList>
68+
);
69+
};

client/src/app/pages/Artifacts/components/ArtifactResultsSignatures.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { DataList } from "@patternfly/react-core";
22
import { ArtifactSignatureItem } from "./ArtifactSignatureItem";
3+
import type { Signatures } from "@app/client";
34

4-
export const ArtifactResultsSignatures = ({ signatures }: { signatures: string[] }) => {
5+
export const ArtifactResultsSignatures = ({ signatures }: { signatures?: Signatures }) => {
56
console.table(signatures);
6-
77
return (
88
<DataList aria-label="Signatures list" isCompact>
9-
{signatures.map((signature, id) => (
9+
{signatures?.map((signature, id) => (
1010
<ArtifactSignatureItem signature={signature} key={id} />
1111
))}
1212
</DataList>

client/src/app/pages/Artifacts/components/ArtifactResultsSummary.tsx

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@ import {
1313
Button,
1414
Label,
1515
} from "@patternfly/react-core";
16-
import { LockIcon, PlusCircleIcon } from "@patternfly/react-icons";
16+
import { PlusCircleIcon } from "@patternfly/react-icons";
1717

1818
import type { IArtifactResultsProps } from "./ArtifactResults";
1919

2020
export const ArtifactResultsSummary = ({ artifact }: IArtifactResultsProps) => {
2121
const summaryCards = [
22-
<Card key="card-1" isPlain>
22+
<Card key="artifact-summary" isPlain>
2323
<CardBody>
24-
<DescriptionList aria-label="Term help text" isCompact isHorizontal columnModifier={{ default: "2Col" }}>
24+
<DescriptionList aria-label="Digest help text" isCompact isHorizontal columnModifier={{ default: "2Col" }}>
2525
<DescriptionListGroup>
2626
<DescriptionListTermHelpText>
2727
<Popover headerContent={<div>Digest</div>} bodyContent={<div>ref + resolved canonical digest</div>}>
@@ -43,14 +43,7 @@ export const ArtifactResultsSummary = ({ artifact }: IArtifactResultsProps) => {
4343
<DescriptionListDescription>{artifact.metadata.mediaType}</DescriptionListDescription>
4444
</DescriptionListGroup>
4545
<DescriptionListGroup>
46-
<DescriptionListTermHelpText>
47-
<Popover
48-
headerContent={<div>Identities</div>}
49-
bodyContent={<div>Deduped list of signature identities used</div>}
50-
>
51-
<DescriptionListTermHelpTextButton> Size </DescriptionListTermHelpTextButton>
52-
</Popover>
53-
</DescriptionListTermHelpText>
46+
<DescriptionListTermHelpText>Size</DescriptionListTermHelpText>
5447
<DescriptionListDescription>{artifact.metadata.size}</DescriptionListDescription>
5548
</DescriptionListGroup>
5649
<DescriptionListGroup>
@@ -93,19 +86,27 @@ export const ArtifactResultsSummary = ({ artifact }: IArtifactResultsProps) => {
9386
</Popover>
9487
</DescriptionListTermHelpText>
9588
<DescriptionListDescription>
96-
<Label className="pf-v6-u-mb-sm" icon={<LockIcon />} color="blue">
89+
<Label className="pf-v6-u-mb-sm" color="blue">
9790
2 Signatures
9891
</Label>
9992
</DescriptionListDescription>
10093
</DescriptionListGroup>
10194
<DescriptionListGroup>
10295
<DescriptionListTermHelpText>
103-
<Popover headerContent={<div>Attestation</div>} bodyContent={<div>A signed document</div>}>
96+
<Popover
97+
headerContent={<div>Attestation</div>}
98+
bodyContent={
99+
<div>
100+
An attestation is a signed document (usually in in-toto format) that describes an event, action, or
101+
property related to a software artifact.
102+
</div>
103+
}
104+
>
104105
<DescriptionListTermHelpTextButton> Attestations </DescriptionListTermHelpTextButton>
105106
</Popover>
106107
</DescriptionListTermHelpText>
107108
<DescriptionListDescription>
108-
<Label className="pf-v6-u-mb-sm" icon={<LockIcon />} color="green">
109+
<Label className="pf-v6-u-mb-sm" color="green">
109110
2 Attestations
110111
</Label>
111112
</DescriptionListDescription>
@@ -117,7 +118,7 @@ export const ArtifactResultsSummary = ({ artifact }: IArtifactResultsProps) => {
117118
</Popover>
118119
</DescriptionListTermHelpText>
119120
<DescriptionListDescription>
120-
<Label className="pf-v6-u-mb-sm" icon={<LockIcon />} color="orange">
121+
<Label className="pf-v6-u-mb-sm" color="orange">
121122
4 Rekor Entries
122123
</Label>
123124
</DescriptionListDescription>

0 commit comments

Comments
 (0)