From 1bfee961f5ee06679da44187d8ffb8f7223b6c76 Mon Sep 17 00:00:00 2001 From: Raul Kele Date: Tue, 13 Dec 2022 12:17:54 +0200 Subject: [PATCH] feat: Implemented mobile responsiveness across app Signed-off-by: Raul Kele --- src/App.css | 6 + src/__mocks__/MockThemeProvider.jsx | 10 ++ src/__tests__/Explore/Explore.test.js | 9 +- src/__tests__/RepoPage/Repo.test.js | 31 +++-- src/__tests__/RepoPage/RepoPage.test.js | 10 +- src/__tests__/TagPage/TagDetails.test.js | 51 +++++---- src/__tests__/TagPage/TagPage.test.js | 8 ++ src/assets/zotLogoSmall.png | Bin 0 -> 12007 bytes src/components/Explore.jsx | 51 +++++++-- src/components/ExploreHeader.jsx | 17 ++- src/components/FilterDialog.jsx | 66 +++++++++++ src/components/Header.jsx | 96 ++++------------ src/components/Home.jsx | 65 +++-------- src/components/RepoCard.jsx | 17 +-- src/components/RepoDetails.jsx | 108 +++++++++++------- src/components/TagCard.jsx | 12 +- src/components/TagDetails.jsx | 107 ++++++++++------- src/index.js | 7 ++ ....js => vulnerabilityAndSignatureCheck.jsx} | 0 19 files changed, 400 insertions(+), 271 deletions(-) create mode 100644 src/__mocks__/MockThemeProvider.jsx create mode 100644 src/assets/zotLogoSmall.png create mode 100644 src/components/FilterDialog.jsx rename src/utilities/{vulnerabilityAndSignatureCheck.js => vulnerabilityAndSignatureCheck.jsx} (100%) diff --git a/src/App.css b/src/App.css index 77e16735..92cb2771 100644 --- a/src/App.css +++ b/src/App.css @@ -72,3 +72,9 @@ -webkit-animation-name: bounce; animation-name: bounce; } + +@media (max-width: 480px) { + .hide-on-mobile { + display: none; + } +} \ No newline at end of file diff --git a/src/__mocks__/MockThemeProvider.jsx b/src/__mocks__/MockThemeProvider.jsx new file mode 100644 index 00000000..e0bf1d53 --- /dev/null +++ b/src/__mocks__/MockThemeProvider.jsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { createTheme, ThemeProvider } from '@mui/material/styles'; + +const theme = createTheme(); + +function MockThemeProvier({ children }) { + return {children}; +} + +export default MockThemeProvier; diff --git a/src/__tests__/Explore/Explore.test.js b/src/__tests__/Explore/Explore.test.js index a4994919..ace7f837 100644 --- a/src/__tests__/Explore/Explore.test.js +++ b/src/__tests__/Explore/Explore.test.js @@ -6,6 +6,7 @@ import React from 'react'; import { createSearchParams, MemoryRouter } from 'react-router-dom'; import filterConstants from 'utilities/filterConstants.js'; import { sortByCriteria } from 'utilities/sortCriteria.js'; +import MockThemeProvier from '__mocks__/MockThemeProvider'; // router mock const mockedUsedNavigate = jest.fn(); @@ -17,9 +18,11 @@ jest.mock('react-router-dom', () => ({ const StateExploreWrapper = (props) => { const queryString = props.search || ''; return ( - - - + + + + + ); }; const mockImageList = { diff --git a/src/__tests__/RepoPage/Repo.test.js b/src/__tests__/RepoPage/Repo.test.js index 440f7dea..6ae94450 100644 --- a/src/__tests__/RepoPage/Repo.test.js +++ b/src/__tests__/RepoPage/Repo.test.js @@ -3,6 +3,15 @@ import RepoDetails from 'components/RepoDetails'; import React from 'react'; import { api } from 'api'; import { createSearchParams } from 'react-router-dom'; +import MockThemeProvier from '__mocks__/MockThemeProvider'; + +const RepoDetailsThemeWrapper = () => { + return ( + + + + ); +}; // uselocation mock const mockUseLocationValue = { @@ -190,44 +199,44 @@ afterEach(() => { describe('Repo details component', () => { it('fetches repo detailed data and renders', async () => { jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockRepoDetailsData } }); - render(); + render(); expect(await screen.findByText('test')).toBeInTheDocument(); }); it('renders vulnerability icons', async () => { jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockRepoDetailsData } }); - render(); + render(); expect(await screen.findAllByTestId('critical-vulnerability-icon')).toHaveLength(1); jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockRepoDetailsNone } }); - render(); + render(); expect(await screen.findAllByTestId('none-vulnerability-icon')).toHaveLength(1); jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockRepoDetailsUnknown } }); - render(); + render(); expect(await screen.findAllByTestId('unknown-vulnerability-icon')).toHaveLength(1); jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockRepoDetailsFailed } }); - render(); + render(); expect(await screen.findAllByTestId('failed-vulnerability-icon')).toHaveLength(1); jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockRepoDetailsLow } }); - render(); + render(); expect(await screen.findAllByTestId('low-vulnerability-icon')).toHaveLength(1); jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockRepoDetailsMedium } }); - render(); + render(); expect(await screen.findAllByTestId('medium-vulnerability-icon')).toHaveLength(1); jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockRepoDetailsHigh } }); - render(); + render(); expect(await screen.findAllByTestId('high-vulnerability-icon')).toHaveLength(1); }); it("should log error if data can't be fetched", async () => { jest.spyOn(api, 'get').mockRejectedValue({ status: 500, data: {} }); const error = jest.spyOn(console, 'error').mockImplementation(() => {}); - render(); + render(); await waitFor(() => expect(error).toBeCalledTimes(1)); }); it('should switch between tabs', async () => { jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockRepoDetailsData } }); - render(); + render(); expect(await screen.findByTestId('overview-container')).toBeInTheDocument(); fireEvent.click(await screen.findByText(/tags/i)); expect(await screen.findByTestId('tags-container')).toBeInTheDocument(); @@ -236,7 +245,7 @@ describe('Repo details component', () => { it('should render platform chips and they should redirect to explore page', async () => { jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockRepoDetailsData } }); - render(); + render(); const osChip = await screen.findByText(/linux/i); fireEvent.click(osChip); expect(mockUseNavigate).toHaveBeenCalledWith({ diff --git a/src/__tests__/RepoPage/RepoPage.test.js b/src/__tests__/RepoPage/RepoPage.test.js index 92bf0285..13464959 100644 --- a/src/__tests__/RepoPage/RepoPage.test.js +++ b/src/__tests__/RepoPage/RepoPage.test.js @@ -2,6 +2,7 @@ import { render, screen } from '@testing-library/react'; import RepoPage from 'pages/RepoPage'; import React from 'react'; import { BrowserRouter, Route, Routes } from 'react-router-dom'; +import MockThemeProvier from '__mocks__/MockThemeProvider'; jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), @@ -28,7 +29,14 @@ it('renders the repository page component', () => { render( - } /> + + + + } + /> ); diff --git a/src/__tests__/TagPage/TagDetails.test.js b/src/__tests__/TagPage/TagDetails.test.js index 9b054dac..019d95e4 100644 --- a/src/__tests__/TagPage/TagDetails.test.js +++ b/src/__tests__/TagPage/TagDetails.test.js @@ -1,8 +1,17 @@ +import React from 'react'; import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { api } from 'api'; import TagDetails from 'components/TagDetails'; -import React from 'react'; +import MockThemeProvier from '__mocks__/MockThemeProvider'; + +const TagDetailsThemeWrapper = () => { + return ( + + + + ); +}; const mockImage = { Image: { @@ -222,7 +231,7 @@ afterEach(() => { describe('Tags details', () => { it('should show tabs and allow nagivation between them', async () => { jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImage } }); - render(); + render(); const dependenciesTab = await screen.findByTestId('dependencies-tab'); fireEvent.click(dependenciesTab); expect(await screen.findByTestId('depends-on-container')).toBeInTheDocument(); @@ -232,52 +241,49 @@ describe('Tags details', () => { it("should log an error when data can't be fetched", async () => { jest.spyOn(api, 'get').mockRejectedValue({ status: 500, data: {} }); const error = jest.spyOn(console, 'error').mockImplementation(() => {}); - render(); + render(); await waitFor(() => expect(error).toBeCalledTimes(1)); }); it('should show tag details metadata', async () => { jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImage } }); - render(); + render(); expect(await screen.findByTestId('tagDetailsMetadata-container')).toBeInTheDocument(); }); it('renders vulnerability icons', async () => { jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImage } }); - render(); + render(); expect(await screen.findByTestId('critical-vulnerability-icon')).toBeInTheDocument(); jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImageNone } }); - render(); + render(); expect(await screen.findByTestId('none-vulnerability-icon')).toBeInTheDocument(); jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImageUnknown } }); - render(); + render(); expect(await screen.findByTestId('unknown-vulnerability-icon')).toBeInTheDocument(); jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImageFailed } }); - render(); + render(); expect(await screen.findByTestId('failed-vulnerability-icon')).toBeInTheDocument(); jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImageLow } }); - render(); + render(); expect(await screen.findByTestId('low-vulnerability-icon')).toBeInTheDocument(); jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImageMedium } }); - render(); + render(); expect(await screen.findByTestId('medium-vulnerability-icon')).toBeInTheDocument(); jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImageHigh } }); - render(); + render(); expect(await screen.findByTestId('high-vulnerability-icon')).toBeInTheDocument(); }); it('should copy the docker pull string to clipboard', async () => { - jest - .spyOn(api, 'get') - - .mockResolvedValue({ status: 200, data: { data: mockImage } }); - render(); + jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImage } }); + render(); const dropdown = await screen.findByText('Pull Image'); expect(dropdown).toBeInTheDocument(); userEvent.click(dropdown); @@ -287,11 +293,8 @@ describe('Tags details', () => { }); it('should copy the podman pull string to clipboard', async () => { - jest - .spyOn(api, 'get') - - .mockResolvedValue({ status: 200, data: { data: mockImage } }); - render(); + jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImage } }); + render(); const dropdown = await screen.findByText('Pull Image'); expect(dropdown).toBeInTheDocument(); userEvent.click(dropdown); @@ -307,7 +310,7 @@ describe('Tags details', () => { .spyOn(api, 'get') .mockResolvedValue({ status: 200, data: { data: mockImage } }); - render(); + render(); const dropdown = await screen.findByText('Pull Image'); expect(dropdown).toBeInTheDocument(); userEvent.click(dropdown); @@ -320,7 +323,7 @@ describe('Tags details', () => { it('should show pull tabs in dropdown and allow nagivation between them', async () => { jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImage } }); - render(); + render(); const dropdown = await screen.findByText('Pull Image'); expect(dropdown).toBeInTheDocument(); userEvent.click(dropdown); @@ -333,7 +336,7 @@ describe('Tags details', () => { it('should show the copied successfully button for 3 seconds', async () => { jest.spyOn(api, 'get').mockResolvedValue({ status: 200, data: { data: mockImage } }); - render(); + render(); const dropdown = await screen.findByText('Pull Image'); expect(dropdown).toBeInTheDocument(); userEvent.click(dropdown); diff --git a/src/__tests__/TagPage/TagPage.test.js b/src/__tests__/TagPage/TagPage.test.js index ad5abcc5..6126f770 100644 --- a/src/__tests__/TagPage/TagPage.test.js +++ b/src/__tests__/TagPage/TagPage.test.js @@ -16,6 +16,14 @@ jest.mock( } ); +jest.mock( + 'components/ExploreHeader', + () => + function ExploreHeader() { + return
; + } +); + it('renders the tags page component', async () => { render( diff --git a/src/assets/zotLogoSmall.png b/src/assets/zotLogoSmall.png new file mode 100644 index 0000000000000000000000000000000000000000..92ab98b233c3497341d79562959d2eb4135bd10f GIT binary patch literal 12007 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 Lqas}@X%g~3>M5{Q literal 0 HcmV?d00001 diff --git a/src/components/Explore.jsx b/src/components/Explore.jsx index 76ae1e4f..7e4a19de 100644 --- a/src/components/Explore.jsx +++ b/src/components/Explore.jsx @@ -7,7 +7,7 @@ import Loading from './Loading'; import Typography from '@mui/material/Typography'; import Sticky from 'react-sticky-el'; import Alert from '@mui/material/Alert'; -import { Container, FormControl, Grid, InputLabel, MenuItem, Select, Stack } from '@mui/material'; +import { Container, FormControl, Grid, InputLabel, MenuItem, Select, Stack, Button } from '@mui/material'; import makeStyles from '@mui/styles/makeStyles'; @@ -21,8 +21,9 @@ import { isEmpty } from 'lodash'; import filterConstants from 'utilities/filterConstants.js'; import { sortByCriteria } from 'utilities/sortCriteria.js'; import { EXPLORE_PAGE_SIZE } from 'utilities/paginationConstants.js'; +import FilterDialog from './FilterDialog.jsx'; -const useStyles = makeStyles(() => ({ +const useStyles = makeStyles((theme) => ({ gridWrapper: { paddingTop: '2rem', paddingBottom: '2rem' @@ -52,6 +53,13 @@ const useStyles = makeStyles(() => ({ borderRadius: '0.375em', width: '25%', textAlign: 'left' + }, + filterButton: { + borderRadius: '0.4rem', + marginBottom: '1rem', + [theme.breakpoints.up('md')]: { + display: 'none' + } } })); @@ -73,6 +81,9 @@ function Explore() { const abortController = useMemo(() => new AbortController(), []); const classes = useStyles(); + // Filterdialog props + const [filterDialogOpen, setFilterDialogOpen] = useState(false); + const buildFilterQuery = () => { let filter = {}; // workaround until backend bugfix @@ -194,6 +205,10 @@ function Explore() { setSortFilter(event.target.value); }; + const handleFilterDialogOpen = () => { + setFilterDialogOpen(true); + }; + const renderRepoCards = () => { return ( exploreData && @@ -250,7 +265,7 @@ function Explore() { const renderListBottom = () => { if (isLoading) { - return ; + return filterDialogOpen ?
: ; } if (!isLoading && !isEndOfList) { return
; @@ -262,16 +277,21 @@ function Explore() { - - + + - + Showing {exploreData?.length} results out of {totalItems} + {!isLoading && ( + + )} Sort @@ -292,20 +312,20 @@ function Explore() { - + {renderFilterCards()} - + {!(exploreData && exploreData.length) && !isLoading ? (
- + Looks like we don't have anything matching that search. Try searching something else.
) : ( - + {renderRepoCards()} {renderListBottom()} @@ -313,6 +333,13 @@ function Explore() {
+
); } diff --git a/src/components/ExploreHeader.jsx b/src/components/ExploreHeader.jsx index 969d1374..19d87b70 100644 --- a/src/components/ExploreHeader.jsx +++ b/src/components/ExploreHeader.jsx @@ -10,7 +10,7 @@ import ArrowBackIcon from '@mui/icons-material/ArrowBack'; import makeStyles from '@mui/styles/makeStyles'; import React from 'react'; -const useStyles = makeStyles(() => { +const useStyles = makeStyles((theme) => { return { exploreHeader: { backgroundColor: '#FFFFFF', @@ -20,12 +20,18 @@ const useStyles = makeStyles(() => { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', - padding: '2rem' + padding: '2rem', + [theme.breakpoints.down('md')]: { + padding: '1rem' + } }, explore: { color: '#52637A', fontSize: '1rem', - letterSpacing: '0.009375rem' + letterSpacing: '0.009375rem', + [theme.breakpoints.down('md')]: { + fontSize: '0.8rem' + } } }; }); @@ -42,7 +48,10 @@ function ExploreHeader() { return (
- navigate(-1)} /> + navigate(-1)} + /> diff --git a/src/components/FilterDialog.jsx b/src/components/FilterDialog.jsx new file mode 100644 index 00000000..aa1f49f2 --- /dev/null +++ b/src/components/FilterDialog.jsx @@ -0,0 +1,66 @@ +import React from 'react'; +import { makeStyles } from '@mui/styles'; +import { + Dialog, + DialogContent, + DialogContentText, + DialogTitle, + FormControl, + Select, + MenuItem, + DialogActions, + Button +} from '@mui/material'; +import { sortByCriteria } from 'utilities/sortCriteria.js'; + +const useStyles = makeStyles(() => ({})); + +function FilterDialog(props) { + const { + open, + setOpen, + sortValue, + setSortValue, + renderFilterCards + // imageFilters, + // setImageFilters, + // osFilters, + // setOsFilters, + // archFilters, + // setArchFilters + } = props; + + const classes = useStyles(); + + const handleSortChange = (event) => { + setSortValue(event.target.value); + }; + + const handleClose = () => { + setOpen(false); + }; + + return ( + + Filter + + Sort results + + + + {renderFilterCards()} + + + + + + ); +} + +export default FilterDialog; diff --git a/src/components/Header.jsx b/src/components/Header.jsx index f8bae5f5..77ff62e7 100644 --- a/src/components/Header.jsx +++ b/src/components/Header.jsx @@ -3,25 +3,13 @@ import React from 'react'; import { Link, useLocation } from 'react-router-dom'; // components -import { - AppBar, - Toolbar, - Popper, - MenuList, - MenuItem, - ClickAwayListener, - Paper, - Grow, - Stack, - Grid - //IconButton -} from '@mui/material'; +import { AppBar, Toolbar, Stack, Grid } from '@mui/material'; // styling import makeStyles from '@mui/styles/makeStyles'; import logo from '../assets/zotLogo.svg'; -//import placeholderProfileButton from '../assets/Profile_button_placeholder.svg'; -import { useState, useRef, useEffect } from 'react'; +import logoxs from '../assets/zotLogoSmall.png'; +import { useState, useEffect } from 'react'; import SearchSuggestion from './SearchSuggestion'; const useStyles = makeStyles(() => ({ @@ -39,13 +27,16 @@ const useStyles = makeStyles(() => ({ flexDirection: 'row', alignItems: 'center', justifyContent: 'center', - paddingLeft: 0, + padding: 0, backgroundColor: '#fff', height: '100%', width: '100%', borderBottom: '0.0625rem solid #BDBDBD', boxShadow: '0rem 0.3125rem 0.625rem rgba(131, 131, 131, 0.08)' }, + headerContainer: { + minWidth: '60%' + }, searchIcon: { color: '#52637A', paddingRight: '3%' @@ -66,7 +57,8 @@ const useStyles = makeStyles(() => ({ }, logoWrapper: {}, logo: { - width: '130px' + maxWidth: '130px', + maxHeight: '50px' }, userAvatar: { height: 46, @@ -78,7 +70,8 @@ const useStyles = makeStyles(() => ({ grid: { display: 'flex', flexDirection: 'row', - justifyContent: 'center' + justifyContent: 'center', + alignItems: 'center' } })); @@ -119,73 +112,32 @@ function Header() { const path = useLocation().pathname; // const navigate = useNavigate(); - const [open, setOpen] = useState(false); - const anchorRef = useRef(null); - - const handleToggle = () => { - setOpen((prevOpen) => !prevOpen); - }; - - const handleClose = (event) => { - localStorage.removeItem('token'); - window.location.reload(); - if (anchorRef.current && anchorRef.current.contains(event.target)) { - return; - } - - setOpen(false); - }; return ( - + - zot + {/* zot */} + + + zot + {path !== '/' && } - +
{''}
- {/* - - */} - - {({ TransitionProps, placement }) => ( - - - - - Logout - - - - - )} -
diff --git a/src/components/Home.jsx b/src/components/Home.jsx index 73a98678..695e2cf4 100644 --- a/src/components/Home.jsx +++ b/src/components/Home.jsx @@ -37,15 +37,6 @@ const useStyles = makeStyles(() => ({ textAlign: 'center', letterSpacing: '-0.02rem' }, - titleRed: { - fontWeight: '700', - color: '#D83C0E', - width: '100%', - display: 'inline', - fontSize: '2.5rem', - textAlign: 'center', - letterSpacing: '-0.02rem' - }, sectionTitle: { fontWeight: '700', color: '#000000DE', @@ -63,8 +54,7 @@ const useStyles = makeStyles(() => ({ viewAll: { color: '#00000099', cursor: 'pointer', - textAlign: 'right', - width: '100%' + textAlign: 'left' } })); @@ -128,29 +118,6 @@ function Home() { ); }; - // const renderBookmarks = () => { - // return ( - // homeData && - // homeData.slice(0, 2).map((item, index) => { - // return ( - // - // ); - // }) - // ); - // }; - const renderRecentlyUpdated = () => { return ( homeData && @@ -185,31 +152,25 @@ function Home() { - - Most popular images - - handleClickViewAll(sortByCriteria.downloads.value)} - > - View all - +
+ + Most popular images + +
+
handleClickViewAll(sortByCriteria.downloads.value)}> + View all +
{renderMostPopular()} {/* currently most popular will be by downloads until stars are implemented */} - {/* - Bookmarks - - {renderBookmarks()} */} diff --git a/src/components/RepoCard.jsx b/src/components/RepoCard.jsx index 74b2268d..874f9353 100644 --- a/src/components/RepoCard.jsx +++ b/src/components/RepoCard.jsx @@ -168,7 +168,7 @@ function RepoCard(props) { > - + - - - {/* { return }} deleteIcon={vulnerabilityCheck()} /> */} +
+ +
+
+ +
@@ -197,12 +200,12 @@ function RepoCard(props) { {platformChips()}
- + {{getVendor()}} - + {getVersion()} @@ -214,7 +217,7 @@ function RepoCard(props) { - + ({ +const useStyles = makeStyles((theme) => ({ pageWrapper: { backgroundColor: '#FFFFFF', height: '100vh' @@ -37,7 +37,6 @@ const useStyles = makeStyles(() => ({ }, repoName: { fontWeight: '700', - fontSize: '2.5rem', color: '#0F2139', textAlign: 'left' }, @@ -56,7 +55,10 @@ const useStyles = makeStyles(() => ({ tabs: { marginTop: '3rem', padding: '0.5rem', - height: '100%' + height: '100%', + [theme.breakpoints.down('md')]: { + padding: '0' + } }, tabContent: { height: '100%' @@ -67,11 +69,18 @@ const useStyles = makeStyles(() => ({ }, tabPanel: { height: '100%', - paddingLeft: '0rem!important' + paddingLeft: '0rem!important', + [theme.breakpoints.down('md')]: { + padding: '1.5rem 0' + } }, metadata: { marginTop: '8rem', - paddingLeft: '1.5rem' + paddingLeft: '1.5rem', + [theme.breakpoints.down('md')]: { + marginTop: '1rem', + paddingLeft: '0' + } }, card: { marginBottom: 2, @@ -106,7 +115,27 @@ const useStyles = makeStyles(() => ({ boxShadow: 'none!important' }, header: { - paddingLeft: '2rem' + paddingLeft: '2rem', + [theme.breakpoints.down('md')]: { + padding: '0' + } + }, + repoTitle: { + textAlign: 'left', + fontSize: '1rem', + lineHeight: '1.5rem', + color: 'rgba(0, 0, 0, 0.6)', + padding: '0.5rem 0 0 4rem', + [theme.breakpoints.down('md')]: { + padding: '0.5rem 0 0 0' + } + }, + platformChipsContainer: { + alignItems: 'center', + padding: '0.5rem 0 0 4rem', + [theme.breakpoints.down('md')]: { + padding: '0.5rem 0 0 0' + } } })); @@ -205,7 +234,7 @@ function RepoDetails() { color: 'rgba(0, 0, 0, 0.6)', fontSize: '1rem', lineHeight: '150%', - marginTop: '5%', + marginTop: '1.3rem', alignSelf: 'stretch' }} > @@ -225,47 +254,46 @@ function RepoDetails() { - - - + + + - - {name} - - - - {/* */} + !isEmpty(repoDetailData?.logo) + ? `data:image/png;base64, ${repoDetailData?.logo}` + : randomImage() + } + alt="icon" + /> + + {name} + + + + + + {/* */} + - + {repoDetailData?.title || 'Title not available'} - + {platformChips()} - + - + - + DIGEST - + OS/Arch - + Size - + {digest?.substr(0, 12)} - + {platform?.Os}/{platform?.Arch} - + {transform.formatBytes(size)} diff --git a/src/components/TagDetails.jsx b/src/components/TagDetails.jsx index 31a578b5..b0602de6 100644 --- a/src/components/TagDetails.jsx +++ b/src/components/TagDetails.jsx @@ -42,7 +42,7 @@ import Loading from './Loading'; import { dockerPull, podmanPull, skopeoPull } from 'utilities/pullStrings'; import { VulnerabilityIconCheck, SignatureIconCheck } from 'utilities/vulnerabilityAndSignatureCheck'; -const useStyles = makeStyles(() => ({ +const useStyles = makeStyles((theme) => ({ pageWrapper: { backgroundColor: '#FFFFFF', height: '100vh' @@ -55,7 +55,6 @@ const useStyles = makeStyles(() => ({ }, repoName: { fontWeight: '700', - fontSize: '2.5rem', color: '#0F2139', textAlign: 'left' }, @@ -64,13 +63,28 @@ const useStyles = makeStyles(() => ({ width: '3rem', objectFit: 'fill' }, + digest: { + textAlign: 'left', + fontSize: '1rem', + lineHeight: '1.5rem', + color: 'rgba(0, 0, 0, 0.6)', + padding: '0.5rem 0 0 4rem', + maxWidth: '100%', + [theme.breakpoints.down('md')]: { + padding: '0.5rem 0 0 0', + fontSize: '0.5rem' + } + }, media: { borderRadius: '3.125em' }, tabs: { marginTop: '3rem', padding: '0.5rem', - height: '100%' + height: '100%', + [theme.breakpoints.down('md')]: { + padding: '0' + } }, tabContent: { height: '100%' @@ -86,11 +100,17 @@ const useStyles = makeStyles(() => ({ tabPanel: { height: '100%', paddingLeft: '0rem!important', - marginRight: '2rem!important' + [theme.breakpoints.down('md')]: { + padding: '1.5rem 0' + } }, metadata: { marginTop: '8rem', - paddingLeft: '1.5rem' + paddingLeft: '1.5rem', + [theme.breakpoints.down('md')]: { + marginTop: '1rem', + paddingLeft: '0' + } }, pull: { paddingLeft: '1.5rem', @@ -123,7 +143,10 @@ const useStyles = makeStyles(() => ({ boxShadow: 'none!important' }, header: { - paddingLeft: '2rem' + paddingLeft: '2rem', + [theme.breakpoints.down('md')]: { + padding: '0' + } }, tabBox: { padding: '0.5rem' @@ -259,41 +282,46 @@ function TagDetails() { - - - - - {reponame}:{tag} - - - - {/* */} - - + + + + + {reponame}:{tag} + + + + + + + {/* */} + + + DIGEST: {imageDetailData?.digest} - + {isCopied ? (