diff --git a/src/__tests__/RepoPage/Repo.test.js b/src/__tests__/RepoPage/Repo.test.js index d9ede41c..82094e3d 100644 --- a/src/__tests__/RepoPage/Repo.test.js +++ b/src/__tests__/RepoPage/Repo.test.js @@ -248,7 +248,7 @@ describe('Repo details component', () => { jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockRepoDetailsWithMissingData } }); render(); expect(await screen.findByText('test')).toBeInTheDocument(); - expect(await screen.findByText(/timestamp n\/a/i)).toBeInTheDocument(); + expect((await screen.findAllByText(/timestamp n\/a/i)).length).toBeGreaterThan(0); }); it('renders vulnerability icons', async () => { @@ -288,15 +288,6 @@ describe('Repo details component', () => { await waitFor(() => expect(mockUseNavigate).toBeCalledWith('/home')); }); - it('should switch between tabs', async () => { - jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockRepoDetailsData } }); - render(); - expect(await screen.findByTestId('overview-container')).toBeInTheDocument(); - fireEvent.click(await screen.findByText(/tags/i)); - expect(await screen.findByTestId('tags-container')).toBeInTheDocument(); - expect(screen.queryByTestId('overview-container')).not.toBeInTheDocument(); - }); - it('should render platform chips and they should redirect to explore page', async () => { jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockRepoDetailsData } }); render(); diff --git a/src/__tests__/RepoPage/Tags.test.js b/src/__tests__/RepoPage/Tags.test.js index d42abb0b..635afe07 100644 --- a/src/__tests__/RepoPage/Tags.test.js +++ b/src/__tests__/RepoPage/Tags.test.js @@ -2,6 +2,15 @@ import { fireEvent, waitFor, render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import Tags from 'components/Repo/Tabs/Tags'; import React from 'react'; +import MockThemeProvier from '__mocks__/MockThemeProvider'; + +const TagsThemeWrapper = () => { + return ( + + + + ); +}; const mockedUsedNavigate = jest.fn(); jest.mock('react-router-dom', () => ({ @@ -59,7 +68,7 @@ const mockedTagsData = [ describe('Tags component', () => { it('should open and close details dropdown for tags', async () => { - render(); + render(); const openBtn = screen.getAllByText(/digest/i); fireEvent.click(openBtn[0]); expect(screen.getByText(/OS\/ARCH/i)).toBeInTheDocument(); @@ -68,7 +77,7 @@ describe('Tags component', () => { }); it('should navigate to tag page details when tag is clicked', async () => { - render(); + render(); const tagLink = await screen.findByText('latest'); fireEvent.click(tagLink); await waitFor(() => { @@ -77,7 +86,7 @@ describe('Tags component', () => { }); it('should navigate to specific manifest when clicking the digest', async () => { - render(); + render(); const openBtn = screen.getAllByText(/digest/i); await fireEvent.click(openBtn[0]); const tagLink = await screen.findByText(/sha256:adca4/i); @@ -90,8 +99,8 @@ describe('Tags component', () => { }); it('should filter tag list based on user input', async () => { - render(); - const tagFilterInput = await screen.findByPlaceholderText(/Search for Tags/i); + render(); + const tagFilterInput = await screen.findByPlaceholderText(/Search Tags/i); expect(await screen.findByText(/latest/i)).toBeInTheDocument(); expect(await screen.findByText(/bullseye/i)).toBeInTheDocument(); userEvent.type(tagFilterInput, 'bull'); @@ -100,7 +109,7 @@ describe('Tags component', () => { }); it('should sort tags based on the picked sort criteria', async () => { - render(); + render(); const selectFilter = await screen.findByText('Newest'); expect(selectFilter).toBeInTheDocument(); userEvent.click(selectFilter); diff --git a/src/__tests__/TagPage/DependsOn.test.js b/src/__tests__/TagPage/DependsOn.test.js index 9c88d328..50aa7399 100644 --- a/src/__tests__/TagPage/DependsOn.test.js +++ b/src/__tests__/TagPage/DependsOn.test.js @@ -3,6 +3,7 @@ import { api } from 'api'; import DependsOn from 'components/Tag/Tabs/DependsOn'; import React from 'react'; import { BrowserRouter, Routes, Route } from 'react-router-dom'; +import MockThemeProvier from '__mocks__/MockThemeProvider'; const mockDependenciesList = { data: { @@ -52,11 +53,13 @@ const mockDependenciesList = { const RouterDependsWrapper = () => { return ( - - - } /> - - + + + + } /> + + + ); }; diff --git a/src/__tests__/TagPage/IsDependentOn.test.js b/src/__tests__/TagPage/IsDependentOn.test.js index 1bbef960..b05c1077 100644 --- a/src/__tests__/TagPage/IsDependentOn.test.js +++ b/src/__tests__/TagPage/IsDependentOn.test.js @@ -3,6 +3,7 @@ import { api } from 'api'; import IsDependentOn from 'components/Tag/Tabs/IsDependentOn'; import React from 'react'; import { BrowserRouter, Routes, Route } from 'react-router-dom'; +import MockThemeProvier from '__mocks__/MockThemeProvider'; const mockDependentsList = { data: { @@ -52,11 +53,13 @@ const mockDependentsList = { const RouterDependsWrapper = () => { return ( - - - } /> - - + + + + } /> + + + ); }; diff --git a/src/api.js b/src/api.js index 1ee27461..7193a451 100644 --- a/src/api.js +++ b/src/api.js @@ -76,7 +76,7 @@ const endpoints = { (pageNumber - 1) * pageSize }}){Results {Name LastUpdated Size Platforms {Os Arch} NewestImage { Tag Vulnerabilities {MaxSeverity Count} Description Licenses Title Source IsSigned Documentation Vendor Labels} DownloadCount}}}`, detailedRepoInfo: (name) => - `/v2/_zot/ext/search?query={ExpandedRepoInfo(repo:"${name}"){Images {Manifests {Digest Platform {Os Arch} Size} Vulnerabilities {MaxSeverity Count} Tag LastUpdated Vendor } Summary {Name LastUpdated Size Platforms {Os Arch} Vendors NewestImage {RepoName IsSigned Vulnerabilities {MaxSeverity Count} Manifests {Digest} Tag Title Documentation DownloadCount Source Description Licenses}}}}`, + `/v2/_zot/ext/search?query={ExpandedRepoInfo(repo:"${name}"){Images {Manifests {Digest Platform {Os Arch} Size} Vulnerabilities {MaxSeverity Count} Tag LastUpdated Vendor } Summary {Name LastUpdated Size Platforms {Os Arch} Vendors NewestImage {RepoName IsSigned Vulnerabilities {MaxSeverity Count} Manifests {Digest} Tag Vendor Title Documentation DownloadCount Source Description Licenses}}}}`, detailedImageInfo: (name, tag) => `/v2/_zot/ext/search?query={Image(image: "${name}:${tag}"){RepoName IsSigned Vulnerabilities {MaxSeverity Count} Referrers {MediaType ArtifactType Size Digest Annotations{Key Value}} Tag Manifests {History {Layer {Size Digest} HistoryDescription {CreatedBy EmptyLayer}} Digest ConfigDigest LastUpdated Size Platform {Os Arch}} Vendor Licenses }}`, vulnerabilitiesForRepo: (name, { pageNumber = 1, pageSize = 15 }, searchTerm = '') => { diff --git a/src/components/Explore/Explore.jsx b/src/components/Explore/Explore.jsx index dcb51321..5a2329c2 100644 --- a/src/components/Explore/Explore.jsx +++ b/src/components/Explore/Explore.jsx @@ -34,11 +34,6 @@ const useStyles = makeStyles((theme) => ({ justifyContent: 'center', alignItems: 'center' }, - exploreText: { - color: '#C0C0C0', - display: 'flex', - alignItems: 'left' - }, resultsRow: { justifyContent: 'space-between', alignItems: 'center' diff --git a/src/components/Header/ExploreHeader.jsx b/src/components/Header/ExploreHeader.jsx index 7c383873..e76c0008 100644 --- a/src/components/Header/ExploreHeader.jsx +++ b/src/components/Header/ExploreHeader.jsx @@ -13,26 +13,31 @@ import React from 'react'; const useStyles = makeStyles((theme) => { return { exploreHeader: { - backgroundColor: '#FFFFFF', + backgroundColor: 'transparent', minHeight: 50, - paddingLeft: '3rem', + padding: '2.75rem 0 1.25rem 0', display: 'flex', flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-start', - padding: '2rem', [theme.breakpoints.down('md')]: { padding: '1rem' } }, explore: { - color: '#52637A', + color: theme.palette.secondary.dark, fontSize: '0.813rem', fontWeight: '600', letterSpacing: '0.009375rem', [theme.breakpoints.down('md')]: { fontSize: '0.8rem' } + }, + arrowIcon: { + color: theme.palette.secondary.dark, + marginRight: '1.75rem', + fontSize: { xs: '1.5rem', md: '2rem' }, + cursor: 'pointer' } }; }); @@ -49,10 +54,7 @@ function ExploreHeader() { return (
- navigate(-1)} - /> + navigate(-1)} /> diff --git a/src/components/Header/SearchSuggestion.jsx b/src/components/Header/SearchSuggestion.jsx index a30aad0d..88abac5b 100644 --- a/src/components/Header/SearchSuggestion.jsx +++ b/src/components/Header/SearchSuggestion.jsx @@ -283,6 +283,7 @@ function SearchSuggestion({ setSearchCurrentValue = () => {} }) { openMenu()} {...getInputProps()} diff --git a/src/components/Repo/RepoDetails.jsx b/src/components/Repo/RepoDetails.jsx index ac26b911..2453ce04 100644 --- a/src/components/Repo/RepoDetails.jsx +++ b/src/components/Repo/RepoDetails.jsx @@ -1,13 +1,16 @@ // react global import React, { useEffect, useMemo, useRef, useState } from 'react'; +// external +import { DateTime } from 'luxon'; + // utility import { api, endpoints } from '../../api'; import { useParams, useNavigate, createSearchParams } from 'react-router-dom'; // components import Tags from './Tabs/Tags.jsx'; -import { Box, Card, CardContent, CardMedia, Chip, Grid, Stack, Tab, Typography } from '@mui/material'; +import { Card, CardContent, CardMedia, Chip, Grid, Stack, Tooltip, Typography } from '@mui/material'; import makeStyles from '@mui/styles/makeStyles'; import { host } from '../../host'; @@ -16,19 +19,17 @@ import repocube1 from '../../assets/repocube-1.png'; import repocube2 from '../../assets/repocube-2.png'; import repocube3 from '../../assets/repocube-3.png'; import repocube4 from '../../assets/repocube-4.png'; -import { TabContext, TabList, TabPanel } from '@mui/lab'; import RepoDetailsMetadata from './RepoDetailsMetadata'; import Loading from '../Shared/Loading'; +import { Markdown } from 'utilities/MarkdowntojsxWrapper'; import { isEmpty, uniq } from 'lodash'; import { VulnerabilityIconCheck, SignatureIconCheck } from 'utilities/vulnerabilityAndSignatureCheck'; import { mapToRepoFromRepoInfo } from 'utilities/objectModels'; const useStyles = makeStyles((theme) => ({ pageWrapper: { - backgroundColor: '#FFFFFF', - display: 'flex', - flexFlow: 'column', + backgroundColor: 'transparent', height: '100%' }, container: { @@ -38,13 +39,14 @@ const useStyles = makeStyles((theme) => ({ backgroundColor: '#FFFFFF' }, repoName: { - fontWeight: '700', + fontWeight: '600', + fontSize: '1.5rem', color: '#0F2139', textAlign: 'left' }, avatar: { - height: '3rem', - width: '3rem', + height: '1.438rem', + width: '1.438rem', objectFit: 'fill' }, cardBtn: { @@ -54,31 +56,16 @@ const useStyles = makeStyles((theme) => ({ media: { borderRadius: '3.125em' }, - tabs: { - marginTop: '3rem', - padding: '0.5rem', + tags: { + marginTop: '1.5rem', height: '100%', [theme.breakpoints.down('md')]: { padding: '0' } }, - tabContent: { - height: '100%' - }, - selectedTab: { - background: '#D83C0E', - borderRadius: '1.5rem' - }, - tabPanel: { - height: '100%', - paddingLeft: '0rem!important', - [theme.breakpoints.down('md')]: { - padding: '1.5rem 0' - } - }, metadata: { - marginTop: '8rem', - paddingLeft: '1.5rem', + marginTop: '1.5rem', + paddingLeft: '1.25rem', [theme.breakpoints.down('md')]: { marginTop: '1rem', paddingLeft: '0' @@ -88,11 +75,10 @@ const useStyles = makeStyles((theme) => ({ marginBottom: 2, display: 'flex', flexDirection: 'row', - alignItems: 'start', + alignItems: 'flex-start', background: '#FFFFFF', border: '0.0625rem solid #E0E5EB', - borderRadius: '2rem', - flex: 'none', + borderRadius: '0.75rem', alignSelf: 'stretch', flexGrow: 0, order: 0, @@ -117,7 +103,6 @@ const useStyles = makeStyles((theme) => ({ boxShadow: 'none!important' }, header: { - paddingLeft: '2rem', [theme.breakpoints.down('md')]: { padding: '0' } @@ -127,17 +112,41 @@ const useStyles = makeStyles((theme) => ({ fontSize: '1rem', lineHeight: '1.5rem', color: 'rgba(0, 0, 0, 0.6)', - padding: '0.5rem 0 0 4rem', + padding: '1rem 0 0 0', [theme.breakpoints.down('md')]: { padding: '0.5rem 0 0 0' } }, platformChipsContainer: { alignItems: 'center', - padding: '0.5rem 0 0 1rem', + padding: '0.15rem 0 0 0', [theme.breakpoints.down('md')]: { padding: '0.5rem 0 0 0' } + }, + platformChips: { + backgroundColor: '#E0E5EB', + color: '#52637A', + fontSize: '0.813rem', + lineHeight: '0.813rem', + borderRadius: '0.375rem', + padding: '0.313rem 0.625rem' + }, + chipLabel: { + padding: '0' + }, + vendor: { + color: theme.palette.primary, + fontSize: '0.75rem', + maxWidth: '50%', + textOverflow: 'ellipsis', + lineHeight: '1.125rem' + }, + versionLast: { + color: theme.palette.secondary.dark, + fontSize: '0.75rem', + lineHeight: '1.125rem', + textOverflow: 'ellipsis' } })); @@ -156,7 +165,6 @@ function RepoDetails() { const [tags, setTags] = useState([]); const placeholderImage = useRef(randomImage()); const [isLoading, setIsLoading] = useState(true); - const [selectedTab, setSelectedTab] = useState('Overview'); // get url param from )); }; - const handleTabChange = (event, newValue) => { - setSelectedTab(newValue); + const getVendor = () => { + return `${repoDetailData.newestTag?.Vendor || 'Vendor not available'} •`; }; - - const renderOverview = () => { - return ( - - - - {repoDetailData.description || 'Description not available'} - - - - ); + const getVersion = () => { + return `published ${repoDetailData.newestTag?.Tag} •`; + }; + const getLast = () => { + const lastDate = repoDetailData.lastUpdated + ? DateTime.fromISO(repoDetailData.lastUpdated).toRelative({ unit: ['weeks', 'days', 'hours', 'minutes'] }) + : `Timestamp N/A`; + return lastDate; }; return ( @@ -244,87 +239,87 @@ function RepoDetails() { {isLoading ? ( ) : ( -
- - - - - - - + + + + + + + + - - {name} - + !isEmpty(repoDetailData?.logo) + ? `data:image/png;base64, ${repoDetailData?.logo}` + : placeholderImage.current + } + alt="icon" + /> + + {name} + + + + + + - - - - {/* */} + + {repoDetailData?.title || 'Title not available'} + + + {platformChips()} - - - {repoDetailData?.title || 'Title not available'} - - - {platformChips()} - + + + + {{getVendor()}} + + + + + {getVersion()} + + + + + {getLast()} + + + + - - - - - - - - - - - - - {renderOverview()} - - - - - - - - - - - - - - - -
+ + + + + + + + + + + + + + )} ); diff --git a/src/components/Repo/RepoDetailsMetadata.jsx b/src/components/Repo/RepoDetailsMetadata.jsx index 620ed3dd..ba69958d 100644 --- a/src/components/Repo/RepoDetailsMetadata.jsx +++ b/src/components/Repo/RepoDetailsMetadata.jsx @@ -5,26 +5,33 @@ import { Markdown } from 'utilities/MarkdowntojsxWrapper'; import React from 'react'; import transform from '../../utilities/transform'; -const useStyles = makeStyles(() => ({ +const useStyles = makeStyles((theme) => ({ card: { marginBottom: 2, display: 'flex', flexDirection: 'row', alignItems: 'start', background: '#FFFFFF', - boxShadow: '0rem 0.3125rem 0.625rem rgba(131, 131, 131, 0.08)', - borderRadius: '1.5rem', + border: '0', + borderRadius: '0.5rem', flex: 'none', alignSelf: 'stretch', flexGrow: 0, order: 0, width: '100%' }, + cardContent: { + '&:last-child': { + padding: '0.5rem 1rem' + } + }, metadataHeader: { - color: 'rgba(0, 0, 0, 0.6)' + color: theme.palette.secondary.dark, + fontSize: '0.75rem', + lineHeight: '1.125rem' }, metadataBody: { - color: 'rgba(0, 0, 0, 0.87)', + color: theme.palette.primary, fontFamily: 'Roboto', fontStyle: 'normal', fontWeight: 400, @@ -36,7 +43,7 @@ const useStyles = makeStyles(() => ({ function RepoDetailsMetadata(props) { const classes = useStyles(); - const { repoURL, totalDownloads, lastUpdated, size, license } = props; + const { repoURL, totalDownloads, lastUpdated, size, license, description } = props; const lastDate = lastUpdated ? DateTime.fromISO(lastUpdated).toRelative({ unit: ['weeks', 'days', 'hours', 'minutes'] }) @@ -45,7 +52,7 @@ function RepoDetailsMetadata(props) { - + Repository @@ -57,7 +64,7 @@ function RepoDetailsMetadata(props) { - + Total downloads @@ -70,7 +77,7 @@ function RepoDetailsMetadata(props) { - + Last publish @@ -84,7 +91,7 @@ function RepoDetailsMetadata(props) { - + Total size @@ -98,7 +105,7 @@ function RepoDetailsMetadata(props) { - + License @@ -111,6 +118,20 @@ function RepoDetailsMetadata(props) { + + + + + + Description + + + {description ? {description} : `Description not available`} + + + + + ); } diff --git a/src/components/Repo/Tabs/Tags.jsx b/src/components/Repo/Tabs/Tags.jsx index 466dce69..ab03d738 100644 --- a/src/components/Repo/Tabs/Tags.jsx +++ b/src/components/Repo/Tabs/Tags.jsx @@ -3,14 +3,14 @@ import React, { useState } from 'react'; // components import Typography from '@mui/material/Typography'; -import { Card, CardContent, Divider, Stack, InputBase, FormControl, Select, InputLabel, MenuItem } from '@mui/material'; +import { Card, CardContent, Stack, InputBase, FormControl, Select, InputLabel, MenuItem } from '@mui/material'; import SearchIcon from '@mui/icons-material/Search'; import { makeStyles } from '@mui/styles'; import TagCard from '../../Shared/TagCard'; import { tagsSortByCriteria } from 'utilities/sortCriteria'; const useStyles = makeStyles(() => ({ - tagCard: { + tagContainer: { marginBottom: 2, display: 'flex', flexDirection: 'row', @@ -24,20 +24,6 @@ const useStyles = makeStyles(() => ({ order: 0, width: '100%' }, - card: { - marginBottom: '2rem', - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - background: '#FFFFFF', - boxShadow: '0rem 0.3125rem 0.625rem rgba(131, 131, 131, 0.08)', - borderRadius: '1.875rem', - flex: 'none', - alignSelf: 'stretch', - flexGrow: 0, - order: 0, - width: '100%' - }, content: { textAlign: 'left', color: '#606060', @@ -49,13 +35,15 @@ const useStyles = makeStyles(() => ({ }, search: { position: 'relative', - minWidth: '100%', + maxWidth: '100%', flexDirection: 'row', - marginBottom: '1.7rem', - boxShadow: '0rem 0.3125rem 0.625rem rgba(131, 131, 131, 0.08)', - border: '0.125rem solid #E7E7E7', - borderRadius: '1rem', - zIndex: 1155 + alignItems: 'center', + justifyContent: 'space-between', + marginTop: '1rem', + marginBottom: '1rem', + boxShadow: 'none', + border: '0.063rem solid #E7E7E7', + borderRadius: '0.625rem' }, searchIcon: { color: '#52637A', @@ -63,8 +51,12 @@ const useStyles = makeStyles(() => ({ }, input: { color: '#464141', - marginLeft: 1, - width: '90%' + fontSize: '1rem', + paddingLeft: '1rem', + width: '90%', + '&::placeholder': { + opacity: '1' + } } })); @@ -73,6 +65,7 @@ export default function Tags(props) { const { tags } = props; const [tagsFilter, setTagsFilter] = useState(''); const [sortFilter, setSortFilter] = useState(tagsSortByCriteria.updateTimeDesc.value); + const renderTags = (tags) => { const selectedSort = Object.values(tagsSortByCriteria).find((sc) => sc.value === sortFilter); const filteredTags = tags.filter((t) => t.tag?.includes(tagsFilter)); @@ -106,7 +99,7 @@ export default function Tags(props) { }; return ( - +
- - + diff --git a/src/components/Shared/RepoCard.jsx b/src/components/Shared/RepoCard.jsx index 733495a1..1b3bc542 100644 --- a/src/components/Shared/RepoCard.jsx +++ b/src/components/Shared/RepoCard.jsx @@ -40,7 +40,7 @@ const randomImage = () => { return imageArray[randomIntFromInterval(0, 3)]; }; -const useStyles = makeStyles(() => ({ +const useStyles = makeStyles((theme) => ({ card: { marginBottom: '1rem', display: 'flex', @@ -112,7 +112,7 @@ const useStyles = makeStyles(() => ({ marginLeft: 10 }, vendor: { - color: '#14191F', + color: theme.palette.primary, fontSize: '0.75rem', maxWidth: '50%', textOverflow: 'ellipsis', @@ -127,7 +127,7 @@ const useStyles = makeStyles(() => ({ paddingTop: '1rem' }, versionLast: { - color: '#52637A', + color: theme.palette.secondary.dark, fontSize: '0.75rem', lineHeight: '1.125rem', textOverflow: 'ellipsis' diff --git a/src/components/Shared/TagCard.jsx b/src/components/Shared/TagCard.jsx index b31a8352..ad80d326 100644 --- a/src/components/Shared/TagCard.jsx +++ b/src/components/Shared/TagCard.jsx @@ -1,35 +1,22 @@ import React, { useState } from 'react'; import { makeStyles } from '@mui/styles'; import { useNavigate } from 'react-router-dom'; -import { Box, Card, CardContent, Collapse, Grid, Stack, Tooltip, Typography } from '@mui/material'; +import { Box, Card, CardContent, Collapse, Grid, Stack, Tooltip, Typography, Divider } from '@mui/material'; import { Markdown } from 'utilities/MarkdowntojsxWrapper'; import transform from 'utilities/transform'; import { DateTime } from 'luxon'; import { KeyboardArrowDown, KeyboardArrowRight } from '@mui/icons-material'; -const useStyles = makeStyles(() => ({ - tagCard: { - marginBottom: 2, - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - background: '#FFFFFF', - boxShadow: 'none!important', - borderRadius: '1.875rem', - flex: 'none', - alignSelf: 'stretch', - flexGrow: 0, - order: 0, - width: '100%' - }, +const useStyles = makeStyles((theme) => ({ card: { - marginBottom: '2rem', + marginBottom: '1rem', display: 'flex', flexDirection: 'row', alignItems: 'center', background: '#FFFFFF', - boxShadow: '0rem 0.3125rem 0.625rem rgba(131, 131, 131, 0.08)', - borderRadius: '1.875rem', + boxShadow: 'none', + border: '1px solid #E0E5EB', + borderRadius: '0.75rem', flex: 'none', alignSelf: 'stretch', flexGrow: 0, @@ -56,6 +43,30 @@ const useStyles = makeStyles(() => ({ fontWeight: '600', cursor: 'pointer', textAlign: 'center' + }, + tagHeading: { + color: '#828282', + fontSize: '1rem', + marginBottom: '0.5rem' + }, + tagName: { + color: '#1479FF', + fontSize: '1rem', + marginBottom: '0.5rem', + textDecorationLine: 'underline', + cursor: 'pointer' + }, + cardDivider: { + marginTop: '1rem', + marginBottom: '1rem', + border: '1px solid #E0E5EB' + }, + manifsetsTable: { + marginTop: '1rem' + }, + tableHeaderText: { + color: theme.palette.secondary.dark, + fontSize: '1rem' } })); @@ -81,22 +92,17 @@ export default function TagCard(props) { return ( - + Tag - goToTags()} - > + goToTags()}> {repoName && `${repoName}:`} {tag} - Pushed + Created @@ -104,6 +110,7 @@ export default function TagCard(props) { + setOpen(!open)}> {!open ? ( @@ -123,22 +130,30 @@ export default function TagCard(props) { - + - - DIGEST + + + DIGEST + - + OS/Arch - - Size + + COMPRESSED SIZE {manifests.map((el) => ( - + - - + + {el.platform?.Os}/{el.platform?.Arch} - + {transform.formatBytes(el.size)} diff --git a/src/pages/RepoPage.jsx b/src/pages/RepoPage.jsx index 1dc68d59..2f2e3f06 100644 --- a/src/pages/RepoPage.jsx +++ b/src/pages/RepoPage.jsx @@ -26,9 +26,7 @@ const useStyles = makeStyles(() => ({ height: '100vh' }, gridWrapper: { - paddingTop: 10, - paddingBottom: 10, - backgroundColor: '#fff', + backgroundColor: 'transparent', width: '100%', display: 'flex', flexFlow: 'column',