Refresh design with some touches across the UI (#2690)

Signed-off-by: Cintia Sanchez Garcia <cynthiasg@icloud.com>
This commit is contained in:
Cintia Sánchez García 2023-01-19 18:53:38 +01:00 committed by GitHub
parent 2c211d4b76
commit f4ea916d06
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
204 changed files with 2669 additions and 6178 deletions

View File

@ -82,6 +82,18 @@ body {
color: var(--color-font);
}
.swagger-ui input[type=email], .swagger-ui input[type=file], .swagger-ui input[type=password], .swagger-ui input[type=search], .swagger-ui input[type=text], .swagger-ui textarea {
border-radius: 0 !important;
}
.swagger-ui .opblock, .swagger-ui .opblock-body pre.microlight, .swagger-ui select, .swagger-ui .opblock .opblock-summary-method, .swagger-ui .btn, .swagger-ui .copy-to-clipboard {
border-radius: 0 !important;
}
.swagger-ui .model-box-control:focus, .swagger-ui .models-control:focus, .swagger-ui .opblock-summary-control:focus {
outline: none;
}
.swagger-ui .topbar .download-url-wrapper .select-label select {
border-color: var(--color-1-500);
}

View File

@ -6,15 +6,13 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="theme-color" content="#000000" />
<title>Artifact Hub Helm charts repository</title>
<link href="https://fonts.googleapis.com/css2?family=Lato:wght@300;400;700&display=swap" rel="stylesheet">
<style>
html, body {
background-color: #417598;
color: #ffffff;
margin: 0;
padding: 0;
font-family: "Lato", Roboto, "Helvetica Neue", Arial, sans-serif;
font-size: 1rem;
font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 1rem;
font-weight: 300;
height: 100%;
width: 100%;

View File

@ -79,4 +79,4 @@ oras push \
artifacthub-repo.yml:application/vnd.cncf.artifacthub.repository-metadata.layer.v1.yaml
```
*Please note that publishing an Artifact Hub repository metadata file requires that the registry supports [OCI artifacts](https://oras.land/implementors/).
*Please note that publishing an Artifact Hub repository metadata file requires that the registry supports [OCI artifacts](https://oras.land/implementors/).*

View File

@ -44,39 +44,6 @@
--color-code: #a3a3a6;
}
@font-face {
font-family: 'Lato';
font-style: normal;
font-weight: 300;
src: local('Lato Light'), local('Lato-Light'), url('/static/fonts/Lato/lato-300.woff2') format('woff2'),
url('/static/fonts/Lato/lato-300.woff') format('woff');
}
@font-face {
font-family: 'Lato';
font-style: normal;
font-weight: 700;
src: local('Lato Bold'), local('Lato-Bold'), url('/static/fonts/Lato/lato-700.woff2') format('woff2'),
url('/static/fonts/Lato/lato-700.woff') format('woff');
}
@font-face {
font-family: 'Lato';
font-style: normal;
font-weight: 400;
src: local('Lato Regular'), local('Lato-Regular'), url('/static/fonts/Lato/lato-regular.woff2') format('woff2'),
url('/static/fonts/Lato/lato-regular.woff') format('woff');
}
@font-face {
font-family: 'Roboto Mono';
font-style: normal;
font-weight: 400;
src: local('Roboto Mono'), local('RobotoMono-Regular'),
url('/static/fonts/Roboto_Mono/roboto-mono-regular.woff2') format('woff2'),
url('/static/fonts/Roboto_Mono/roboto-mono-regular.woff') format('woff');
}
body {
background-color: var(--body-bg);
color: var(--color-font);
@ -86,11 +53,11 @@ body {
}
body, .gdoc-mermaid, .gdoc-header {
font-family: 'Lato', Roboto, 'Helvetica Neue', Arial, sans-serif;
font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
}
code {
font-family: 'Roboto Mono', 'Courier New', monospace;
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}
.gdoc-header {
@ -126,7 +93,6 @@ code {
word-wrap: break-word;
background-color: var(--mid-gray) !important;
border: 1px solid rgba(28, 44, 53, 0.1) !important;
border-radius: 3px;
padding: 0 0.15rem;
}
@ -138,7 +104,6 @@ code {
.gdoc-markdown pre {
overflow-x: auto;
border-radius: 3px;
padding: .5rem 1rem;
tab-size: 4;
background-color: var(--bg-code) !important;
@ -172,7 +137,6 @@ code {
}
.gdoc-nav--main {
border-radius: .25rem;
background-color: var(--ah-white);
border: 1px solid var(--color-black-125);
box-shadow: 0 .125rem .25rem var(--color-black-75);

View File

@ -6,14 +6,13 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="theme-color" content="#000000" />
<title>Artifact Hub - maintenance page</title>
<link href="https://fonts.googleapis.com/css2?family=Lato:wght@300&display=swap" rel="stylesheet">
<style>
html, body {
background-color: #417598;
color: #ffffff;
margin: 0;
padding: 0;
font-family: "Lato", Roboto, "Helvetica Neue", Arial, sans-serif;
font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
font-size: 1rem;
font-weight: 300;
height: 100%;

View File

@ -3,7 +3,6 @@
}
.templateWrapper {
border-radius: 3px;
border-color: var(--color-black-15) !important;
background-color: var(--extra-light-gray);
}
@ -47,7 +46,6 @@
line-height: 18px;
padding: 0 5px;
border-color: var(--gray) !important;
border-radius: 3px;
}
.searchIcon {

View File

@ -312,7 +312,7 @@ const ContentDefaultModal = (props: Props) => {
<div className={styles.legend}>
<small className="text-muted text-uppercase">Kind:</small>
</div>
<span className={`text-truncate border fw-bold ${styles.label}`}>
<span className={`text-truncate border fw-semibold ${styles.label}`}>
{resource.kind}
</span>
</div>
@ -360,20 +360,18 @@ const ContentDefaultModal = (props: Props) => {
return (
<div className={`p-3 border-bottom ${styles.extraInfo}`}>
<div className="h6 fw-bold">{selectedItem.displayName || selectedItem.name}</div>
<div className="d-flex flex-row align-items-baseline mb-1">
<div className={styles.legend}>
<small className="text-muted text-uppercase">Name:</small>
</div>
<div className={`text-truncate ${styles.btnItemContent}`}>{selectedItem.name}</div>
<div className="mb-1">
<small className="text-muted text-uppercase me-2">Name:</small>
<span className={`text-truncate ${styles.btnItemContent}`}>
{selectedItem.name}
</span>
</div>
<div className="d-flex flex-row align-items-baseline mb-1">
<div className={styles.legend}>
<small className="text-muted text-uppercase">Description:</small>
</div>
<div className={styles.btnItemContent}>
<div className="mb-1">
<small className="text-muted text-uppercase me-2">Description:</small>
<span className={styles.btnItemContent}>
{selectedItem.description.replace(/\n/g, ' ')}
</div>
</span>
</div>
</div>
);

View File

@ -2,8 +2,6 @@
min-width: 60px;
width: 60px;
height: 60px;
border-color: var(--bs-white) !important;
box-shadow: 0px 0px 5px 0px var(--color-1-20);
}
.imageAsBg {
@ -31,5 +29,4 @@
width: 60px;
height: 60px;
border-color: var(--bs-white) !important;
box-shadow: 0px 0px 5px 0px var(--color-1-20);
}

View File

@ -5,9 +5,8 @@
.labelText {
background-color: var(--body-light-bg);
line-height: 18px;
padding: 0 5px 0 10px;
padding: 0 5px;
border-color: var(--color-black-15) !important;
border-radius: 3px;
}
.labelTextNoIcon {
@ -19,10 +18,6 @@
height: 20px;
line-height: 1rem;
color: var(--light-gray);
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
box-shadow: inset -1px 0 var(--color-black-25);
margin-right: -3px;
min-width: 20px;
}
@ -31,7 +26,6 @@
}
.onlyIcon {
border-radius: 3px !important;
width: 21px;
}
@ -39,54 +33,23 @@
stroke: var(--light-gray);
}
.iconWrapper:not(.onlyIcon)::before {
content: '';
position: absolute;
right: -3px;
top: calc(50% - 3px);
height: 6px;
width: 6px;
border-radius: 50%;
box-shadow: inset -1px 0 var(--color-black-25);
}
.default .iconWrapper {
background-color: var(--light-gray);
color: var(--bs-dark);
}
.default .iconWrapper::before {
background-color: var(--light-gray);
}
.warning .iconWrapper {
background-color: var(--bs-orange);
}
.warning .iconWrapper::before {
background-color: var(--bs-orange);
}
.success .iconWrapper {
background-color: var(--bs-success);
}
.success .iconWrapper::before {
background-color: var(--bs-success);
}
.danger .iconWrapper {
background-color: var(--bs-danger);
}
.danger .iconWrapper::before {
background-color: var(--bs-danger);
}
.custom .iconWrapper {
color: var(--light-gray);
}
.custom .iconWrapper::before {
background-color: inherit;
}

View File

@ -8,7 +8,7 @@
}
.content {
border-radius: 15px !important;
border-radius: 0 !important;
border-color: var(--color-1-500) !important;
box-shadow: 0px 0px 5px 0px var(--color-1-20) !important;
}
@ -52,7 +52,7 @@
.modal pre:not(:global(.customYAML)):not(:global(.diffTemplate)) {
padding: 16px !important;
border-radius: 3px;
border-radius: 0;
white-space: nowrap;
}
@ -71,6 +71,5 @@
padding: 0.25rem 0.5rem;
font-size: 0.875rem;
line-height: 1.5;
border-radius: 0.2rem;
}
}

View File

@ -16,14 +16,11 @@
min-width: 30px;
width: 30px;
height: 30px;
border-color: var(--color-1-10) !important;
box-shadow: 0px 0px 5px 0px var(--color-1-20);
}
.image {
max-width: calc(100% - 2px);
max-height: calc(100% - 2px);
max-width: 100%;
max-height: 100%;
}
.description {
@ -35,6 +32,10 @@
font-size: 0.85rem;
}
.icon {
top: 1px;
}
@media only screen and (max-width: 575.98px) {
.dropdown {
display: none !important;

View File

@ -96,7 +96,7 @@ const OrganizationInfo = (props: Props) => {
<div className={styles.content}>
<div className="d-flex flex-row align-items-center">
<div
className={`d-flex align-items-center justify-content-center overflow-hidden me-2 p-1 position-relative border border-2 rounded-circle bg-white ${styles.imageWrapper} imageWrapper`}
className={`d-flex align-items-center justify-content-center overflow-hidden me-2 position-relative ${styles.imageWrapper}`}
>
{organization.logoImageId ? (
<Image
@ -137,15 +137,15 @@ const OrganizationInfo = (props: Props) => {
</div>
</div>
<div className="d-flex flex-row align-items-start text-truncate">
<div className="d-flex flex-row align-items-baseline text-truncate">
{props.visibleLegend && (
<div className="d-flex flex-row align-items-baseline me-1 text-muted text-uppercase">
<small>Org:</small>
<div className={`d-flex flex-row align-items-baseline me-1 text-dark position-relative ${styles.icon}`}>
<MdBusiness />
</div>
)}
<button
className={`p-0 border-0 text-dark text-truncate flex-grow-1 bg-transparent position-relative ${styles.link} ${props.btnClassName}`}
className={`p-0 border-0 text-muted text-truncate flex-grow-1 bg-transparent position-relative ${styles.link} ${props.btnClassName}`}
onClick={(e) => {
e.preventDefault();
history.push({

View File

@ -1,11 +1,7 @@
.card {
box-shadow: 0px 0px 5px 0px var(--bs-light);
}
@media (hover: hover) {
.card:hover {
border-color: var(--color-black-50);
box-shadow: 0px 0px 5px 0px var(--color-black-75);
border-color: var(--color-black-25);
box-shadow: 0 0 0 2px var(--color-black-25);
}
}
@ -21,15 +17,145 @@
color: inherit;
}
.imageWrapper {
min-width: 70px;
width: 70px;
height: 70px;
}
.image {
max-width: 100%;
max-height: 100%;
}
.link {
color: var(--gray-dark);
}
.link:hover {
color: inherit;
}
.mx50 {
max-width: 50%;
}
.title {
font-size: 1.1rem;
}
.titleWrapper {
background-color: var(--body-bg);
padding: 0.6rem 1rem;
height: 70px;
margin-left: 0.75rem;
}
.rightInfo {
padding-left: 2.25rem;
}
[data-theme='dark'] .titleWrapper {
background-color: #2c2e31;
}
.subtitle {
font-size: 0.85rem;
line-height: 20px;
}
.subtitle span {
font-size: 0.75rem;
}
.kind {
font-size: 0.9rem;
color: var(--color-1-500);
}
.truncateWrapper {
min-width: 0;
}
.version {
font-size: 0.8rem;
max-width: 150px;
}
.date {
font-size: 75%;
}
.userInfo {
margin-top: -2px;
}
.userIcon {
font-size: 0.8rem;
top: -2px;
}
.licenseBtn {
top: -2px;
}
.labelsWrapper > div:not(:last-child) {
margin-right: 0.5rem;
}
.description {
font-size: 0.85rem;
}
@media (hover: hover) {
.link:hover {
text-decoration: underline;
}
}
@media only screen and (max-width: 575.98px) {
.lineClamp {
overflow: hidden;
text-overflow: unset;
white-space: inherit;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
word-wrap: normal;
max-height: 62px;
}
}
@media only screen and (max-width: 767.98px) {
.imageWrapper {
min-width: 50px;
width: 50px;
height: 50px;
}
.description {
font-size: 0.85rem;
}
.body {
padding: 1rem !important;
}
}
@media only screen and (min-width: 768px) {
.card {
min-height: 215px;
@media only screen and (min-width: 576px) {
.titleWrapper {
width: 600px;
}
}
@media only screen and (min-width: 992px) {
.labelsWrapper > div:not(:first-child) {
margin-right: 0;
margin-left: 0.5rem;
}
.labelsWrapper > div:first-child {
margin-right: 0;
}
}
@ -44,3 +170,15 @@
padding: 0 1rem;
}
}
@media only screen and (min-width: 1920px) {
.titleWrapper {
width: 400px;
}
}
@media only screen and (min-width: 768px) {
.card {
min-height: 215px;
}
}

View File

@ -1,10 +1,12 @@
import { render, screen } from '@testing-library/react';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { BrowserRouter as Router } from 'react-router-dom';
import { Package } from '../../types';
import calculateDiffInYears from '../../utils/calculateDiffInYears';
import { prepareQueryString } from '../../utils/prepareQueryString';
import PackageCard from './PackageCard';
jest.mock('../../utils/calculateDiffInYears');
const getMockPackage = (fixtureId: string): Package => {
return require(`./__fixtures__/PackageCard/${fixtureId}.json`) as Package;
@ -19,14 +21,11 @@ jest.mock('react-router-dom', () => ({
}),
}));
const mockSaveScrollPosition = jest.fn();
const defaultProps = {
saveScrollPosition: mockSaveScrollPosition,
searchUrlReferer: undefined,
};
describe('PackageCard', () => {
beforeEach(() => {
(calculateDiffInYears as jest.Mock).mockImplementation(() => 0.5);
});
afterEach(() => {
jest.resetAllMocks();
});
@ -35,7 +34,7 @@ describe('PackageCard', () => {
const mockPackage = getMockPackage('1');
const { asFragment } = render(
<Router>
<PackageCard {...defaultProps} package={mockPackage} />
<PackageCard package={mockPackage} />
</Router>
);
expect(asFragment()).toMatchSnapshot();
@ -46,7 +45,7 @@ describe('PackageCard', () => {
const mockPackage = getMockPackage('2');
render(
<Router>
<PackageCard {...defaultProps} package={mockPackage} />
<PackageCard package={mockPackage} />
</Router>
);
const image = screen.getByAltText(`Logo ${mockPackage.displayName}`);
@ -58,7 +57,7 @@ describe('PackageCard', () => {
render(
<Router>
<PackageCard {...defaultProps} package={mockPackage} />
<PackageCard package={mockPackage} />
</Router>
);
const image = screen.getByAltText(`Logo ${mockPackage.displayName}`);
@ -73,11 +72,10 @@ describe('PackageCard', () => {
render(
<Router>
<PackageCard {...defaultProps} package={mockPackage} />
<PackageCard package={mockPackage} />
</Router>
);
const title = screen.getByText(mockPackage.displayName!);
expect(title).toBeInTheDocument();
expect(screen.getByText(mockPackage.displayName!)).toBeInTheDocument();
});
it('renders name when display name is null', () => {
@ -85,7 +83,7 @@ describe('PackageCard', () => {
render(
<Router>
<PackageCard {...defaultProps} package={mockPackage} />
<PackageCard package={mockPackage} />
</Router>
);
expect(screen.getByText(mockPackage.name!)).toBeInTheDocument();
@ -98,26 +96,28 @@ describe('PackageCard', () => {
render(
<Router>
<PackageCard {...defaultProps} package={mockPackage} />
<PackageCard package={mockPackage} />
</Router>
);
const buttons = screen.getAllByTestId('repoLink');
expect(buttons).toHaveLength(2);
const icons = screen.getAllByAltText('Icon');
expect(icons).toHaveLength(16);
expect(icons).toHaveLength(12);
expect(icons[0]).toBeInTheDocument();
expect((icons[0] as HTMLImageElement).src).toBe('http://localhost/static/media/helm-chart.svg');
await userEvent.click(buttons[0]!);
expect(mockHistoryPush).toHaveBeenCalledTimes(1);
expect(mockHistoryPush).toHaveBeenCalledWith({
pathname: '/packages/search',
search: prepareQueryString({
pageNumber: 1,
filters: {
repo: [mockPackage.repository.name],
},
}),
await waitFor(() => {
expect(mockHistoryPush).toHaveBeenCalledTimes(1);
expect(mockHistoryPush).toHaveBeenCalledWith({
pathname: '/packages/search',
search: prepareQueryString({
pageNumber: 1,
filters: {
repo: [mockPackage.repository.name],
},
}),
});
});
});
@ -126,43 +126,105 @@ describe('PackageCard', () => {
render(
<Router>
<PackageCard {...defaultProps} package={mockPackage} />
<PackageCard package={mockPackage} />
</Router>
);
const button = screen.getByTestId('userLink');
expect(button).toBeInTheDocument();
await userEvent.click(button);
expect(mockHistoryPush).toHaveBeenCalledTimes(1);
expect(mockHistoryPush).toHaveBeenCalledWith({
pathname: '/packages/search',
search: prepareQueryString({
pageNumber: 1,
filters: {
user: [mockPackage.repository.userAlias!],
},
}),
await waitFor(() => {
expect(mockHistoryPush).toHaveBeenCalledTimes(1);
expect(mockHistoryPush).toHaveBeenCalledWith({
pathname: '/packages/search',
search: prepareQueryString({
pageNumber: 1,
filters: {
user: [mockPackage.repository.userAlias!],
},
}),
});
});
});
it('renders repo kind link', async () => {
const mockPackage = getMockPackage('8');
render(
<Router>
<PackageCard package={mockPackage} />
</Router>
);
const buttons = screen.getAllByTestId('repoIconLabelLink');
expect(buttons).toHaveLength(2);
await userEvent.click(buttons[0]);
await waitFor(() => {
expect(mockHistoryPush).toHaveBeenCalledTimes(1);
expect(mockHistoryPush).toHaveBeenCalledWith({
pathname: '/packages/search',
search: prepareQueryString({
pageNumber: 1,
filters: {
kind: ['1'],
},
}),
});
});
});
});
describe('Detail', () => {
it('opens detail page', async () => {
const mockPackage = getMockPackage('9');
const urlReferer = {
tsQueryWeb: 'test',
filters: {},
pageNumber: 1,
};
describe('Security Rating label', () => {
it('renders label', () => {
const mockPackage = getMockPackage('12');
render(
<Router>
<PackageCard {...defaultProps} package={mockPackage} searchUrlReferer={urlReferer} />
<PackageCard package={mockPackage} />
</Router>
);
const link = screen.getByRole('link');
expect(link).toBeInTheDocument();
await userEvent.click(link!);
expect(mockSaveScrollPosition).toHaveBeenCalledTimes(1);
expect(window.location.pathname).toBe('/packages/helm/test/test');
expect(screen.getByText('Images Security Rating')).toBeInTheDocument();
});
it('does not render label when package is older than 1 year', () => {
(calculateDiffInYears as jest.Mock).mockImplementation(() => 1.5);
const mockPackage = getMockPackage('12');
render(
<Router>
<PackageCard package={mockPackage} />
</Router>
);
expect(screen.queryByText('Images Security Rating')).toBeNull();
});
});
describe('when repository has a verified publisher', () => {
it('renders correct label', () => {
const mockPackage = getMockPackage('10');
render(
<Router>
<PackageCard package={mockPackage} />
</Router>
);
expect(screen.getAllByText('Verified Publisher')).toHaveLength(1);
});
});
describe('when repository has repository scanner disabled', () => {
it('renders correct label', () => {
const mockPackage = getMockPackage('11');
render(
<Router>
<PackageCard package={mockPackage} />
</Router>
);
expect(screen.getAllByText('Security scanner disabled')).toHaveLength(1);
});
});
});

View File

@ -1,40 +1,262 @@
import isUndefined from 'lodash/isUndefined';
import { Link } from 'react-router-dom';
import moment from 'moment';
import { useEffect, useState } from 'react';
import { AiOutlineStop } from 'react-icons/ai';
import { FaUser } from 'react-icons/fa';
import { Link, useHistory } from 'react-router-dom';
import { Package, SearchFiltersURL } from '../../types';
import { Package, RepositoryKind, SearchFiltersURL } from '../../types';
import buildPackageURL from '../../utils/buildPackageURL';
import calculateDiffInYears from '../../utils/calculateDiffInYears';
import cutString from '../../utils/cutString';
import isFuture from '../../utils/isFuture';
import isPackageOfficial from '../../utils/isPackageOfficial';
import { prepareQueryString } from '../../utils/prepareQueryString';
import Image from '../common/Image';
import Label from '../common/Label';
import OfficialBadge from '../common/OfficialBadge';
import OrganizationInfo from '../common/OrganizationInfo';
import ProductionBadge from '../common/ProductionBadge';
import RepositoryIconLabel from '../common/RepositoryIconLabel';
import RepositoryInfo from '../common/RepositoryInfo';
import ScannerDisabledRepositoryBadge from '../common/ScannerDisabledRepositoryBadge';
import SecurityRating from '../common/SecurityRating';
import SignedBadge from '../common/SignedBadge';
import StarBadge from '../common/StarBadge';
import VerifiedPublisherBadge from '../common/VerifiedPublisherBadge';
import styles from './PackageCard.module.css';
import PackageInfo from './PackageInfo';
interface Props {
package: Package;
cardWrapperClassName?: string;
className?: string;
saveScrollPosition?: () => void;
noBadges?: boolean;
searchUrlReferer?: SearchFiltersURL;
fromStarredPage?: boolean;
}
const PackageCard = (props: Props) => (
<div className={`col-12 col-xxl-6 py-sm-3 py-2 ${styles.cardWrapper}`} role="listitem">
<div className={`card cardWithHover h-100 mw-100 bg-white ${styles.card} ${props.className}`}>
<Link
className={`text-decoration-none text-reset h-100 bg-transparent ${styles.link}`}
onClick={() => {
if (!isUndefined(props.saveScrollPosition)) {
props.saveScrollPosition();
}
}}
to={{
pathname: buildPackageURL(props.package.normalizedName, props.package.repository, props.package.version!),
state: { searchUrlReferer: props.searchUrlReferer, fromStarredPage: props.fromStarredPage },
}}
>
<div className={`card-body d-flex flex-column h-100 ${styles.body}`}>
<PackageInfo package={props.package} breakpointForInfoSection="lg" />
</div>
</Link>
const PackageCard = (props: Props) => {
const history = useHistory();
const [isVersionOlderThanOneYear, setIsVersionOlderThanOneYear] = useState<boolean>(false);
const pkgTS = (
<>
{!isFuture(props.package.ts) && (
<small className={`text-muted text-nowrap ${styles.date}`}>
Updated {moment.unix(props.package.ts).fromNow()}
</small>
)}
</>
);
const starsAndKindInfo = (
<div className={`align-self-start d-flex align-items-center text-uppercase ms-auto ${styles.kind}`}>
<StarBadge className="me-2" starsNumber={props.package.stars} />
<RepositoryIconLabel
btnClassName={`position-relative ${styles.repoLabel}`}
kind={props.package.repository.kind}
deprecated={props.package.deprecated}
clickable
/>
</div>
</div>
);
);
useEffect(() => {
const diffInYears = calculateDiffInYears(props.package.ts);
setIsVersionOlderThanOneYear(diffInYears > 1);
}, [props.package]);
return (
<div className={`py-sm-3 py-2 ${styles.cardWrapper} ${props.cardWrapperClassName}`} role="listitem">
<div className={`card cardWithHover h-100 mw-100 bg-white ${styles.card} ${props.className}`}>
<Link
className={`text-decoration-none text-reset h-100 bg-transparent ${styles.link}`}
onClick={() => {
if (!isUndefined(props.saveScrollPosition)) {
props.saveScrollPosition();
}
}}
to={{
pathname: buildPackageURL(props.package.normalizedName, props.package.repository, props.package.version!),
state: { searchUrlReferer: props.searchUrlReferer, fromStarredPage: props.fromStarredPage },
}}
>
<div className={`card-body d-flex flex-column h-100 ${styles.body}`}>
<div className="d-flex align-items-start justify-content-between mw-100">
<div className={`d-flex align-items-stretch flex-grow-1 h-100 ${styles.truncateWrapper}`}>
<div
className={`my-2 my-md-0 d-flex align-items-center justify-content-center overflow-hidden position-relative ${styles.imageWrapper}`}
>
<Image
imageId={props.package.logoImageId}
alt={`Logo ${props.package.displayName || props.package.name}`}
className={styles.image}
kind={props.package.repository.kind}
/>
</div>
<div
className={`d-flex flex-column flex-grow-1 flex-sm-grow-0 justify-content-between ${styles.truncateWrapper} ${styles.titleWrapper}`}
>
<div className="text-truncate card-title mb-0">
<div className="d-flex flex-row align-items-center justify-content-between">
<div className={`text-truncate ${styles.title}`}>
{props.package.displayName || props.package.name}
</div>
</div>
</div>
<div className="d-block d-md-none">
<div className={`card-subtitle align-items-baseline ${styles.subtitle}`}>
<RepositoryInfo
repository={props.package.repository}
deprecated={props.package.deprecated}
className="d-inline d-md-none text-truncate w-100"
repoLabelClassName="d-none"
withLabels={false}
/>
</div>
</div>
<div className={`d-none d-md-block card-subtitle align-items-center ${styles.subtitle}`}>
<div className="d-flex flex-row align-items-center">
{props.package.repository.organizationName && (
<OrganizationInfo
className={`me-0 d-flex flex-row align-items-baseline text-left w-auto ${styles.mx50} `}
btnClassName="text-truncate mw-100"
organizationName={props.package.repository.organizationName}
organizationDisplayName={props.package.repository.organizationDisplayName}
deprecated={props.package.deprecated}
visibleLegend
/>
)}
{props.package.repository.userAlias && (
<div className={`d-flex flex-row align-items-baseline ${styles.userInfo}`}>
<div className={`text-dark me-1 position-relative ${styles.userIcon}`}>
<FaUser />
</div>
<span className="visually-hidden">{props.package.repository.userAlias}</span>
<button
data-testid="userLink"
className={`p-0 border-0 text-truncate text-muted mw-100 bg-transparent ${styles.link} ${styles.mx50}`}
onClick={(e) => {
e.preventDefault();
history.push({
pathname: '/packages/search',
search: prepareQueryString({
pageNumber: 1,
filters: {
user: [props.package.repository.userAlias!],
},
deprecated: props.package.deprecated,
}),
});
}}
aria-label={`Filter by ${props.package.repository.userAlias}`}
aria-hidden="true"
tabIndex={-1}
>
<div className="text-truncate">{props.package.repository.userAlias}</div>
</button>
</div>
)}
<div className={styles.mx50}>
<RepositoryInfo
repository={props.package.repository}
deprecated={props.package.deprecated}
className={`d-flex flex-row align-items-baseline ms-3 ${styles.truncateWrapper}`}
repoLabelClassName="d-none d-lg-inline"
withLabels={false}
/>
</div>
</div>
</div>
</div>
<div className={`d-none d-lg-flex flex-column align-items-end mb-auto ms-auto ${styles.rightInfo}`}>
{starsAndKindInfo}
<div className="mt-1">{pkgTS}</div>
<div className={`mt-1 text-truncate align-items-baseline position-relative ${styles.version}`}>
<div className="d-flex flex-row align-items-baseline text-truncate">
<span className="text-muted me-1">
{props.package.repository.kind === RepositoryKind.Container ? 'Tag' : 'Version'}{' '}
</span>
{cutString(props.package.version || '-', 16)}
</div>
</div>
</div>
</div>
</div>
{!isUndefined(props.package.description) && (
<div className={`mb-0 mb-md-1 mt-3 text-muted text-truncate ${styles.description} ${styles.lineClamp} `}>
{props.package.description}
</div>
)}
<div
className={`d-flex d-lg-none flex-row flex-wrap justify-content-between align-items-center mt-auto pt-3 pt-lg-0 mt-1 mt-lg-0 mt-xxl-1 mt-xxxl-0`}
>
{pkgTS}
<span>{starsAndKindInfo}</span>
</div>
{(isUndefined(props.noBadges) || !props.noBadges) && (
<div
className={`d-none d-sm-flex flex-wrap justify-content-lg-end mt-0 mt-md-auto ${styles.labelsWrapper}`}
>
<OfficialBadge official={isPackageOfficial(props.package)} className="d-inline mt-3" type="package" />
<ProductionBadge
productionOrganizationsCount={props.package.productionOrganizationsCount}
className="d-inline mt-3"
/>
<VerifiedPublisherBadge
verifiedPublisher={props.package.repository.verifiedPublisher}
className="d-inline mt-3"
/>
{props.package.deprecated && (
<Label text="Deprecated" icon={<AiOutlineStop />} labelStyle="danger" className="d-inline mt-3" />
)}
{props.package.signed && (
<SignedBadge
signed={props.package.signed}
signatures={props.package.signatures}
repositoryKind={props.package.repository.kind}
className="d-inline mt-3"
/>
)}
{/* Do not display security rating badge when version is older than 1 year */}
{!isVersionOlderThanOneYear && (
<SecurityRating
summary={props.package.securityReportSummary}
className="d-inline mt-3"
onlyBadge={false}
withLink={buildPackageURL(
props.package.normalizedName,
props.package.repository,
props.package.version!
)}
/>
)}
{(props.package.repository.scannerDisabled || props.package.allContainersImagesWhitelisted) && (
<ScannerDisabledRepositoryBadge
className="d-inline mt-3"
scannerDisabled={props.package.repository.scannerDisabled || false}
allContainersImagesWhitelisted={props.package.allContainersImagesWhitelisted || false}
withTooltip
/>
)}
</div>
)}
</div>
</Link>
</div>
</div>
);
};
export default PackageCard;

View File

@ -1,128 +0,0 @@
.imageWrapper {
min-width: 80px;
width: 80px;
height: 80px;
border-color: var(--color-1-10) !important;
box-shadow: 0px 0px 5px 0px var(--color-1-20);
}
.image {
max-width: calc(100% - 10px);
max-height: calc(100% - 10px);
}
.link {
color: var(--gray-dark);
}
.link:hover {
color: inherit;
}
.mx50 {
max-width: 50%;
}
.title {
font-size: 1.15rem;
}
.titleWrapper {
margin-top: -3px;
}
.subtitle {
font-size: 0.9rem;
line-height: 20px;
}
.subtitle span {
font-size: 0.75rem;
}
.kind {
font-size: 0.9rem;
color: var(--color-1-500);
}
.truncateWrapper {
min-width: 0;
}
.date {
font-size: 75%;
}
.lineClamp {
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
}
.lastLine {
top: -1px;
}
.licenseBtn {
top: -2px;
}
.labelsWrapper > div:not(:last-child) {
margin-right: 0.5rem;
}
.description {
font-size: 0.9rem;
}
@media (hover: hover) {
.link:hover {
text-decoration: underline;
}
}
@media only screen and (max-width: 575.98px) {
.lineClamp {
-webkit-line-clamp: 2;
word-wrap: normal;
}
}
@media only screen and (max-width: 767.98px) {
.imageWrapper {
min-width: 60px;
width: 60px;
height: 60px;
margin: 0;
}
.description {
font-size: 0.85rem;
}
.image {
max-width: calc(100% - 9px);
max-height: calc(100% - 9px);
}
}
@media only screen and (min-width: 992px) {
.labelsWrapper > div:not(:first-child) {
margin-right: 0;
margin-left: 0.5rem;
}
.labelsWrapper > div:first-child {
margin-right: 0;
}
}
@media only screen and (min-width: 1400px) and (max-width: 1991.98px) {
.title {
font-size: 1.05rem;
}
.imageWrapper {
margin: 0.25rem 0;
}
}

View File

@ -1,223 +0,0 @@
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { BrowserRouter as Router } from 'react-router-dom';
import { Package } from '../../types';
import calculateDiffInYears from '../../utils/calculateDiffInYears';
import { prepareQueryString } from '../../utils/prepareQueryString';
import PackageInfo from './PackageInfo';
jest.mock('../../utils/calculateDiffInYears');
const getMockPackage = (fixtureId: string): Package => {
return require(`./__fixtures__/PackageInfo/${fixtureId}.json`) as Package;
};
const mockHistoryPush = jest.fn();
jest.mock('react-router-dom', () => ({
...(jest.requireActual('react-router-dom') as {}),
useHistory: () => ({
push: mockHistoryPush,
}),
}));
describe('PackageInfo', () => {
beforeEach(() => {
(calculateDiffInYears as jest.Mock).mockImplementation(() => 0.5);
});
afterEach(() => {
jest.resetAllMocks();
});
it('creates snapshot', () => {
const mockPackage = getMockPackage('1');
const { asFragment } = render(
<Router>
<PackageInfo package={mockPackage} />
</Router>
);
expect(asFragment()).toMatchSnapshot();
});
describe('Image', () => {
it('renders package logo', () => {
const mockPackage = getMockPackage('2');
render(
<Router>
<PackageInfo package={mockPackage} />
</Router>
);
const image = screen.getByAltText(`Logo ${mockPackage.displayName}`);
expect(image).toBeInTheDocument();
});
it('renders placeholder when imageId is null', () => {
const mockPackage = getMockPackage('3');
render(
<Router>
<PackageInfo package={mockPackage} />
</Router>
);
const image = screen.getByAltText(`Logo ${mockPackage.displayName}`);
expect(image).toBeInTheDocument();
expect((image as HTMLImageElement).src).toBe('http://localhost/static/media/placeholder_pkg_helm.png');
});
});
describe('Title', () => {
it('renders display name', () => {
const mockPackage = getMockPackage('4');
render(
<Router>
<PackageInfo package={mockPackage} />
</Router>
);
expect(screen.getByText(mockPackage.displayName!)).toBeInTheDocument();
});
it('renders name when display name is null', () => {
const mockPackage = getMockPackage('5');
render(
<Router>
<PackageInfo package={mockPackage} />
</Router>
);
expect(screen.getByText(mockPackage.name!)).toBeInTheDocument();
});
});
describe('Repository button', () => {
it('renders repository link', async () => {
const mockPackage = getMockPackage('6');
render(
<Router>
<PackageInfo package={mockPackage} />
</Router>
);
const buttons = screen.getAllByTestId('repoLink');
expect(buttons).toHaveLength(2);
const icons = screen.getAllByAltText('Icon');
expect(icons).toHaveLength(16);
expect(icons[0]).toBeInTheDocument();
expect((icons[0] as HTMLImageElement).src).toBe('http://localhost/static/media/helm-chart.svg');
await userEvent.click(buttons[0]!);
expect(mockHistoryPush).toHaveBeenCalledTimes(1);
expect(mockHistoryPush).toHaveBeenCalledWith({
pathname: '/packages/search',
search: prepareQueryString({
pageNumber: 1,
filters: {
repo: [mockPackage.repository.name],
},
}),
});
});
it('renders user link', async () => {
const mockPackage = getMockPackage('7');
render(
<Router>
<PackageInfo package={mockPackage} />
</Router>
);
const button = screen.getByTestId('userLink');
expect(button).toBeInTheDocument();
await userEvent.click(button);
expect(mockHistoryPush).toHaveBeenCalledTimes(1);
expect(mockHistoryPush).toHaveBeenCalledWith({
pathname: '/packages/search',
search: prepareQueryString({
pageNumber: 1,
filters: {
user: [mockPackage.repository.userAlias!],
},
}),
});
});
it('renders repo kind link', async () => {
const mockPackage = getMockPackage('8');
render(
<Router>
<PackageInfo package={mockPackage} />
</Router>
);
const buttons = screen.getAllByTestId('repoIconLabelLink');
expect(buttons).toHaveLength(3);
await userEvent.click(buttons[0]);
expect(mockHistoryPush).toHaveBeenCalledTimes(1);
expect(mockHistoryPush).toHaveBeenCalledWith({
pathname: '/packages/search',
search: prepareQueryString({
pageNumber: 1,
filters: {
kind: ['1'],
},
}),
});
});
});
describe('Security Rating label', () => {
it('renders label', () => {
const mockPackage = getMockPackage('12');
render(
<Router>
<PackageInfo package={mockPackage} />
</Router>
);
expect(screen.getByText('Images Security Rating')).toBeInTheDocument();
});
it('does not render label when package is older than 1 year', () => {
(calculateDiffInYears as jest.Mock).mockImplementation(() => 1.5);
const mockPackage = getMockPackage('12');
render(
<Router>
<PackageInfo package={mockPackage} />
</Router>
);
expect(screen.queryByText('Images Security Rating')).toBeNull();
});
});
describe('when repository has a verified publisher', () => {
it('renders correct label', () => {
const mockPackage = getMockPackage('10');
render(
<Router>
<PackageInfo package={mockPackage} />
</Router>
);
expect(screen.getAllByText('Verified Publisher')).toHaveLength(1);
});
});
describe('when repository has repository scanner disabled', () => {
it('renders correct label', () => {
const mockPackage = getMockPackage('11');
render(
<Router>
<PackageInfo package={mockPackage} />
</Router>
);
expect(screen.getAllByText('Security scanner disabled')).toHaveLength(1);
});
});
});

View File

@ -1,270 +0,0 @@
import moment from 'moment';
import { useEffect, useState } from 'react';
import { AiOutlineStop } from 'react-icons/ai';
import { useHistory } from 'react-router-dom';
import { Package, RepositoryKind } from '../../types';
import buildPackageURL from '../../utils/buildPackageURL';
import calculateDiffInYears from '../../utils/calculateDiffInYears';
import cutString from '../../utils/cutString';
import isFuture from '../../utils/isFuture';
import isPackageOfficial from '../../utils/isPackageOfficial';
import { prepareQueryString } from '../../utils/prepareQueryString';
import License from '../package/License';
import Image from './Image';
import Label from './Label';
import OfficialBadge from './OfficialBadge';
import OrganizationInfo from './OrganizationInfo';
import styles from './PackageInfo.module.css';
import ProductionBadge from './ProductionBadge';
import RepositoryIconLabel from './RepositoryIconLabel';
import RepositoryInfo from './RepositoryInfo';
import ScannerDisabledRepositoryBadge from './ScannerDisabledRepositoryBadge';
import SecurityRating from './SecurityRating';
import SignedBadge from './SignedBadge';
import StarBadge from './StarBadge';
import VerifiedPublisherBadge from './VerifiedPublisherBadge';
interface Props {
package: Package;
breakpointForInfoSection?: string;
}
const PackageInfo = (props: Props) => {
const history = useHistory();
const [isVersionOlderThanOneYear, setIsVersionOlderThanOneYear] = useState<boolean>(false);
const pkgTS = (
<>
{!isFuture(props.package.ts) && (
<small className={`text-muted text-nowrap ${styles.date}`}>
Updated {moment.unix(props.package.ts).fromNow()}
</small>
)}
</>
);
const starsAndKindInfo = (
<div className={`align-self-start d-flex align-items-center text-uppercase ms-auto ${styles.kind}`}>
<StarBadge className="me-2" starsNumber={props.package.stars} />
<RepositoryIconLabel kind={props.package.repository.kind} deprecated={props.package.deprecated} clickable />
</div>
);
const packageImage = (
<div
className={`d-flex align-items-center justify-content-center overflow-hidden rounded-circle p-1 p-md-2 border position-relative bg-white ${styles.imageWrapper} imageWrapper`}
>
<Image
imageId={props.package.logoImageId}
alt={`Logo ${props.package.displayName || props.package.name}`}
className={styles.image}
kind={props.package.repository.kind}
/>
</div>
);
useEffect(() => {
const diffInYears = calculateDiffInYears(props.package.ts);
setIsVersionOlderThanOneYear(diffInYears > 1);
}, [props.package]);
return (
<>
<div className="d-flex align-items-start justify-content-between mw-100">
<div className={`d-flex align-items-stretch flex-grow-1 h-100 ${styles.truncateWrapper}`}>
{packageImage}
<div
className={`d-flex flex-column justify-content-between ms-3 my-1 my-md-0 flex-grow-1 ${styles.truncateWrapper} ${styles.titleWrapper}`}
>
<div className="text-truncate card-title mb-0">
<div className="d-flex flex-row align-items-center justify-content-between">
<div className={`text-truncate ${styles.title}`}>{props.package.displayName || props.package.name}</div>
<div className="d-none d-xxl-flex d-xxxl-none flex-column ms-2">{starsAndKindInfo}</div>
</div>
</div>
<div className="d-block d-md-none">
<div className={`card-subtitle align-items-baseline ${styles.subtitle}`}>
<RepositoryInfo
repository={props.package.repository}
deprecated={props.package.deprecated}
className="d-inline d-md-none text-truncate w-100"
repoLabelClassName="d-none"
withLabels={false}
/>
</div>
</div>
<div className={`d-none d-md-block card-subtitle align-items-baseline ${styles.subtitle}`}>
<div className="d-flex flex-row align-items-baseline">
{props.package.repository.organizationName && (
<OrganizationInfo
className={`me-0 d-flex flex-row align-items-baseline text-left w-auto ${styles.mx50} `}
btnClassName="text-truncate mw-100"
organizationName={props.package.repository.organizationName}
organizationDisplayName={props.package.repository.organizationDisplayName}
deprecated={props.package.deprecated}
visibleLegend
/>
)}
{props.package.repository.userAlias && (
<>
<span className="text-muted text-uppercase me-1">User: </span>
<span className="visually-hidden">{props.package.repository.userAlias}</span>
<button
data-testid="userLink"
className={`p-0 border-0 text-truncate text-dark mw-100 bg-transparent ${styles.link} ${styles.mx50}`}
onClick={(e) => {
e.preventDefault();
history.push({
pathname: '/packages/search',
search: prepareQueryString({
pageNumber: 1,
filters: {
user: [props.package.repository.userAlias!],
},
deprecated: props.package.deprecated,
}),
});
}}
aria-label={`Filter by ${props.package.repository.userAlias}`}
aria-hidden="true"
tabIndex={-1}
>
<div className="text-truncate">{props.package.repository.userAlias}</div>
</button>
</>
)}
<div className={styles.mx50}>
<RepositoryInfo
repository={props.package.repository}
deprecated={props.package.deprecated}
className={`d-flex flex-row align-items-baseline ms-3 ${styles.truncateWrapper}`}
repoLabelClassName="d-none d-lg-inline"
withLabels={false}
/>
</div>
</div>
</div>
<div
className={`d-none d-md-block card-subtitle text-truncate align-items-baseline position-relative ${styles.subtitle} ${styles.lastLine}`}
>
<div className="d-flex flex-row align-items-baseline text-truncate">
<span className="text-muted text-uppercase me-1">
{props.package.repository.kind === RepositoryKind.Container ? 'Tag' : 'Version'}:{' '}
</span>
{cutString(props.package.version || '-')}
{(() => {
switch (props.package.repository.kind) {
case RepositoryKind.Helm:
case RepositoryKind.Container:
return (
<>
{props.package.appVersion && (
<>
<span className="text-muted text-uppercase me-1 ms-3">App Version: </span>
{cutString(props.package.appVersion)}
</>
)}
</>
);
default:
return null;
}
})()}
{props.package.license && (
<div className={`d-none d-lg-flex d-xxl-none d-xxxl-flex flex-row text-truncate ${styles.mx50}`}>
<span className="text-muted text-uppercase me-1 ms-3">License:</span>
<License
license={props.package.license}
className="text-truncate"
linkClassName={`${styles.link} ${styles.subtitle} ${styles.licenseBtn} position-relative text-truncate mw-100`}
visibleIcon={false}
btnType
/>
</div>
)}
</div>
</div>
</div>
<div
className={`d-none d-${
props.breakpointForInfoSection || 'md'
}-flex d-xxl-none d-xxxl-flex flex-column align-items-end mb-auto ms-2`}
>
{starsAndKindInfo}
<div className="mt-1">{pkgTS}</div>
</div>
</div>
</div>
<div className={`mb-0 mb-md-1 mt-3 overflow-hidden ${styles.description} text-truncate`}>
{props.package.description}
</div>
<div className="d-none d-xxl-block d-xxxl-none text-end mt-2">{pkgTS}</div>
<div
className={`d-flex d-${
props.breakpointForInfoSection || 'md'
}-none d-xxl-none flex-row flex-wrap justify-content-between align-items-center mt-auto pt-2 pt-${
props.breakpointForInfoSection || 'md'
}-0 mt-1 mt-${props.breakpointForInfoSection || 'md'}-0 mt-xxl-1 mt-xxxl-0`}
>
{pkgTS}
<span>{starsAndKindInfo}</span>
</div>
<div className={`d-flex flex-wrap justify-content-lg-end mt-0 mt-md-auto ${styles.labelsWrapper}`}>
<OfficialBadge official={isPackageOfficial(props.package)} className="d-inline mt-3" type="package" />
<ProductionBadge
productionOrganizationsCount={props.package.productionOrganizationsCount}
className="d-inline mt-3"
/>
<VerifiedPublisherBadge
verifiedPublisher={props.package.repository.verifiedPublisher}
className="d-inline mt-3"
/>
{props.package.deprecated && (
<Label text="Deprecated" icon={<AiOutlineStop />} labelStyle="danger" className="d-inline mt-3" />
)}
{props.package.signed && (
<SignedBadge
signed={props.package.signed}
signatures={props.package.signatures}
repositoryKind={props.package.repository.kind}
className="d-inline mt-3"
/>
)}
{/* Do not display security rating badge when version is older than 1 year */}
{!isVersionOlderThanOneYear && (
<SecurityRating
summary={props.package.securityReportSummary}
className="d-inline mt-3"
onlyBadge={false}
withLink={buildPackageURL(props.package.normalizedName, props.package.repository, props.package.version!)}
/>
)}
{(props.package.repository.scannerDisabled || props.package.allContainersImagesWhitelisted) && (
<ScannerDisabledRepositoryBadge
className="d-inline mt-3"
scannerDisabled={props.package.repository.scannerDisabled || false}
allContainersImagesWhitelisted={props.package.allContainersImagesWhitelisted || false}
withTooltip
/>
)}
</div>
</>
);
};
export default PackageInfo;

View File

@ -18,7 +18,7 @@ const RSSLinkTitle = (props: Props) => (
<small>
<a
className="badge rounded-pill bg-secondary rssBadge ms-3"
className="badge bg-secondary rssBadge ms-3"
rel="alternate noopener noreferrer"
role="button"
target="_blank"

View File

@ -1,3 +1,7 @@
.btn {
line-height: normal !important;
}
.badge {
font-size: 75%;
text-transform: none;
@ -14,3 +18,7 @@
width: 12px;
top: -2px;
}
.text {
margin-top: -1px;
}

View File

@ -11,6 +11,7 @@ interface Props {
kind: RepositoryKind;
isPlural?: boolean;
className?: string;
btnClassName?: string;
iconClassName?: string;
noBackground?: boolean;
clickable?: boolean;
@ -27,8 +28,7 @@ const RepositoryIconLabel = (props: Props) => {
<span
className={classnames(
{
[`badge bg-light text-dark rounded-pill border ${styles.bg}`]:
isUndefined(props.noBackground) || !props.noBackground,
[`badge bg-light text-dark border ${styles.bg}`]: isUndefined(props.noBackground) || !props.noBackground,
},
styles.badge,
props.className
@ -38,7 +38,7 @@ const RepositoryIconLabel = (props: Props) => {
<div className={`position-relative ${styles.icon} ${props.iconClassName}`} aria-hidden="true">
{repo.icon}
</div>
<div className="ms-1">{props.isPlural ? repo.plural : repo.singular}</div>
<div className={`ms-1 ${styles.text}`}>{props.isPlural ? repo.plural : repo.singular}</div>
</div>
</span>
);
@ -52,7 +52,7 @@ const RepositoryIconLabel = (props: Props) => {
<button
data-testid="repoIconLabelLink"
className="btn btn-link m-0 p-0"
className={`btn btn-link m-0 p-0 border-0 ${styles.btn} ${props.btnClassName}`}
onClick={(e) => {
e.preventDefault();
history.push({

View File

@ -2,10 +2,6 @@
top: -1px;
}
.moreMarginTop {
top: 3px;
}
.dropdown {
width: 350px;
font-size: 0.85rem;
@ -45,8 +41,12 @@
border-bottom-color: var(--color-1-900) !important;
}
.icon {
top: -2px;
}
.repoLabel {
top: -1px;
top: -4px;
}
@media only screen and (max-width: 575.98px) {

View File

@ -1,7 +1,7 @@
import classnames from 'classnames';
import isUndefined from 'lodash/isUndefined';
import { useEffect, useRef, useState } from 'react';
import { MdInfoOutline } from 'react-icons/md';
import { FiPackage } from 'react-icons/fi';
import { useHistory } from 'react-router-dom';
import useOutsideClick from '../../hooks/useOutsideClick';
@ -10,7 +10,6 @@ import { prepareQueryString } from '../../utils/prepareQueryString';
import AttachedIconToText from './AttachedIconToText';
import ButtonCopyToClipboard from './ButtonCopyToClipboard';
import RepositoryIcon from './RepositoryIcon';
import RepositoryIconLabel from './RepositoryIconLabel';
import styles from './RepositoryInfo.module.css';
import VerifiedPublisherBadge from './VerifiedPublisherBadge';
@ -19,8 +18,6 @@ interface Props {
deprecated?: boolean | null;
className?: string;
repoLabelClassName?: string;
visibleInfoIcon?: boolean;
visibleIcon?: boolean;
withLabels: boolean;
}
@ -101,28 +98,19 @@ const RepositoryInfo = (props: Props) => {
</div>
</div>
<div className="d-flex flex-row text-truncate">
<div className="d-flex flex-row align-items-baseline me-1 text-muted text-uppercase">
<small>Repo:</small>
{props.visibleIcon && (
<RepositoryIconLabel
kind={props.repository.kind}
deprecated={props.deprecated}
className="ms-1"
clickable
/>
)}
<div className="d-flex flex-row align-items-baseline text-truncate">
<div className="d-flex flex-row align-items-baseline me-1 text-dark text-uppercase">
<div className={`position-relative ${styles.icon}`}>
<FiPackage />
</div>
</div>
<span className="visually-hidden">{props.repository.name}</span>
<button
data-testid="repoLink"
className={classnames(
'd-flex flex-row p-0 border-0 text-dark text-truncate bg-transparent position-relative',
styles.link,
{
[styles.moreMarginTop]: props.visibleIcon,
}
'd-flex flex-row p-0 border-0 text-muted text-truncate bg-transparent position-relative',
styles.link
)}
onClick={(e) => {
e.preventDefault();
@ -151,10 +139,6 @@ const RepositoryInfo = (props: Props) => {
>
<>
<div className="text-truncate">{props.repository.displayName || props.repository.name}</div>
{props.repository.url && props.visibleInfoIcon && (
<MdInfoOutline className={`d-none d-sm-inline-block ms-1 position-relative ${styles.infoIcon}`} />
)}
</>
</button>
</div>

View File

@ -0,0 +1,5 @@
[data-theme='dark'] .sampleQuery {
color: var(--font-color-light) !important;
border-color: var(--border-solid) !important;
background-color: #1a1d21 !important;
}

View File

@ -3,6 +3,7 @@ import { Fragment, memo } from 'react';
import { Link } from 'react-router-dom';
import getSampleQueries from '../../utils/getSampleQueries';
import styles from './SampleQueries.module.css';
interface Props {
className?: string;
@ -28,7 +29,7 @@ const SampleQueries = (props: Props) => {
{queries.map((query: SampleQuery, index: number) => (
<Fragment key={`sampleQuery_${index}`}>
<Link
className={`badge rounded-pill border fw-normal mx-2 mt-3 ${props.className}`}
className={`badge border fw-normal mx-2 mt-3 ${styles.sampleQuery} ${props.className}`}
to={{
pathname: '/packages/search',
search: `?${query.querystring}`,

View File

@ -1,12 +1,10 @@
.searchBar {
height: 36px;
border-radius: 18px;
box-shadow: 0 0 0 0.3rem var(--color-black-15);
}
.big {
height: 50px;
border-radius: 25px;
}
.iconWrapper {
@ -47,14 +45,11 @@
min-width: 50px;
width: 50px;
height: 50px;
border-color: var(--color-1-10) !important;
box-shadow: 0px 0px 3px 0px var(--color-1-20);
}
.image {
max-width: calc(100% - 7px);
max-height: calc(100% - 7px);
max-width: 100%;
max-height: 100%;
}
.activeDropdownItem {
@ -95,7 +90,6 @@
@media only screen and (max-width: 767.98px) {
.searchBar {
height: 30px;
border-radius: 15px;
}
.loading {
@ -104,7 +98,6 @@
.big {
height: 40px;
border-radius: 20px;
}
.big + .loading {

View File

@ -277,7 +277,7 @@ const SearchBar = (props: Props) => {
></button>
<div
className={classnames('position-absolute text-dark', styles.tipIcon, {
className={classnames('d-none d-sm-block position-absolute text-dark', styles.tipIcon, {
[styles.bigTipIcon]: props.size === 'big',
})}
>
@ -327,7 +327,7 @@ const SearchBar = (props: Props) => {
id={`sl-opt${index}`}
>
<div
className={`d-none d-md-flex align-items-center justify-content-center overflow-hidden rounded-circle p-1 border border-2 bg-white position-relative ${styles.imageWrapper} imageWrapper`}
className={`d-none d-md-flex align-items-center justify-content-center overflow-hidden position-relative ${styles.imageWrapper}`}
>
<Image
imageId={pkg.logoImageId}
@ -339,7 +339,9 @@ const SearchBar = (props: Props) => {
<div className={`ms-0 ms-md-3 flex-grow-1 ${styles.truncateWrapper}`}>
<div className="d-flex flex-row align-items-center">
<div className={`text-truncate fw-bold ${styles.title}`}>{pkg.displayName || pkg.name}</div>
<div className={`text-truncate fw-bold mt-1 ${styles.title}`}>
{pkg.displayName || pkg.name}
</div>
<div
className={`align-self-start d-flex align-items-center text-uppercase ms-auto ps-2 ${styles.midText}`}

View File

@ -1,6 +1,6 @@
.inputWrapper {
height: 36px;
border-radius: 18px;
margin: 0 0.3rem;
box-shadow: 0 0 0 0.3rem var(--color-black-15);
}
@ -60,14 +60,11 @@
min-width: 30px;
width: 30px;
height: 30px;
border-color: var(--color-1-10) !important;
box-shadow: 0px 0px 2px 0px var(--color-1-20);
}
.image {
max-width: calc(100% - 2px);
max-height: calc(100% - 2px);
max-width: 100%;
max-height: 100%;
}
.tableWrapper {

View File

@ -256,7 +256,7 @@ const SearchPackages = (props: Props) => {
<td className="align-middle">
<div className="d-flex flex-row align-items-center">
<div
className={`d-none d-sm-flex align-items-center justify-content-center overflow-hidden p-1 border border-2 bg-white rounded-circle ${styles.imageWrapper} imageWrapper`}
className={`d-none d-sm-flex align-items-center justify-content-center overflow-hidden ${styles.imageWrapper}`}
>
<Image
imageId={item.logoImageId}

View File

@ -1,7 +1,7 @@
.inputWrapper {
height: 36px;
border-radius: 18px;
box-shadow: 0 0 0 0.3rem var(--color-black-15);
margin: 0 0.3rem;
}
.iconWrapper {
@ -55,6 +55,7 @@
.icon {
height: 17px;
margin-top: -2px;
}
.tinyIcon {

View File

@ -1,7 +1,6 @@
.badge {
top: -2px;
width: 22px;
box-shadow: inset 0px 0px 2px 1px var(--color-black-25);
width: 20px;
}
.tooltip {

View File

@ -46,7 +46,7 @@ const SecurityRating = (props: Props) => {
props.onlyBadge ? (
<small>
<div
className={`badge rounded-pill text-light fw-bold ${styles.badge} ${className}`}
className={`badge text-light fw-bold ${styles.badge} ${className}`}
style={{
backgroundColor: severity.color,
}}
@ -66,13 +66,13 @@ const SecurityRating = (props: Props) => {
/>
)
}
tooltipWidth={285}
tooltipWidth={300}
tooltipClassName={`${styles.tooltip} ${props.tooltipClassName} ${props.onlyBadge ? styles.onlyBadgeTooltip : ''}`}
tooltipMessage={
<div className="d-flex flex-column">
<div className="d-flex flex-row align-items-center my-1">
<span
className={`badge rounded-pill text-light fw-bold me-2 ${styles.badge}`}
className={`badge text-light fw-semibold me-2 ${styles.badge}`}
style={{
backgroundColor: SEVERITY_RATING.default!.color,
}}
@ -83,7 +83,7 @@ const SecurityRating = (props: Props) => {
</div>
<div className="d-flex flex-row align-items-center my-1">
<span
className={`badge rounded-pill text-light fw-bold me-2 ${styles.badge}`}
className={`badge text-light fw-semibold me-2 ${styles.badge}`}
style={{
backgroundColor: SEVERITY_RATING[VulnerabilitySeverity.Low]!.color,
}}
@ -96,7 +96,7 @@ const SecurityRating = (props: Props) => {
</div>
<div className="d-flex flex-row align-items-center my-1">
<span
className={`badge rounded-pill text-light fw-bold me-2 ${styles.badge}`}
className={`badge text-light fw-semibold me-2 ${styles.badge}`}
style={{
backgroundColor: SEVERITY_RATING[VulnerabilitySeverity.Medium]!.color,
}}
@ -109,7 +109,7 @@ const SecurityRating = (props: Props) => {
</div>
<div className="d-flex flex-row align-items-center my-1">
<span
className={`badge rounded-pill text-light fw-bold me-2 ${styles.badge}`}
className={`badge text-light fw-semibold me-2 ${styles.badge}`}
style={{
backgroundColor: SEVERITY_RATING[VulnerabilitySeverity.High]!.color,
}}
@ -122,7 +122,7 @@ const SecurityRating = (props: Props) => {
</div>
<div className="d-flex flex-row align-items-center my-1">
<span
className={`badge rounded-pill text-light fw-bold me-2 ${styles.badge}`}
className={`badge text-light fw-semibold me-2 ${styles.badge}`}
style={{
backgroundColor: SEVERITY_RATING[VulnerabilitySeverity.Critical]!.color,
}}
@ -135,7 +135,7 @@ const SecurityRating = (props: Props) => {
</div>
<div className="d-flex flex-row align-items-center my-1">
<span
className={`badge rounded-pill text-light fw-bold me-2 ${styles.badge}`}
className={`badge text-light fw-semibold me-2 ${styles.badge}`}
style={{
backgroundColor: SEVERITY_RATING[VulnerabilitySeverity.UnKnown]!.color,
}}

View File

@ -2,6 +2,7 @@
background-color: var(--badge-bg);
border-color: var(--gray) !important;
height: 19px;
line-height: 0.8rem;
}
.size-xs {

View File

@ -16,7 +16,7 @@ const StarBadge = (props: Props) => {
return (
<div
data-testid="starBadge"
className={classnames('badge rounded-pill bg-light text-dark border', styles.badge, props.className, {
className={classnames('badge bg-light text-dark border', styles.badge, props.className, {
[styles[`size-${props.size}`]]: !isUndefined(props.size),
})}
aria-label={`${props.starsNumber} stars`}

View File

@ -1,6 +1,5 @@
.list {
border-color: var(--color-black-15) !important;
border-radius: 3px;
z-index: 100;
top: 31px;
}

View File

@ -6,6 +6,13 @@
"description": "desc",
"logoImageId": "imageId",
"appVersion": "1.0.0",
"securityReportSummary": {
"low": 0,
"high": 7,
"medium": 1,
"unknown": 0,
"critical": 1
},
"repository": {
"repositoryId": "0acb228c-17ab-4e50-85e9-ffc7102ea423",
"kind": 0,

View File

@ -12,13 +12,13 @@ exports[`OrganizationInfo creates snapshot 1`] = `
/>
</div>
<div
class="d-flex flex-row align-items-start text-truncate"
class="d-flex flex-row align-items-baseline text-truncate"
>
<button
aria-expanded="false"
aria-hidden="true"
aria-label="Organization info"
class="p-0 border-0 text-dark text-truncate flex-grow-1 bg-transparent position-relative link undefined"
class="p-0 border-0 text-muted text-truncate flex-grow-1 bg-transparent position-relative link undefined"
tabindex="-1"
>
<div

View File

@ -3,7 +3,7 @@
exports[`PackageCard creates snapshot 1`] = `
<DocumentFragment>
<div
class="col-12 col-xxl-6 py-sm-3 py-2 cardWrapper"
class="py-sm-3 py-2 cardWrapper undefined"
role="listitem"
>
<div
@ -23,7 +23,7 @@ exports[`PackageCard creates snapshot 1`] = `
class="d-flex align-items-stretch flex-grow-1 h-100 truncateWrapper"
>
<div
class="d-flex align-items-center justify-content-center overflow-hidden rounded-circle p-1 p-md-2 border position-relative bg-white imageWrapper imageWrapper"
class="my-2 my-md-0 d-flex align-items-center justify-content-center overflow-hidden position-relative imageWrapper"
>
<img
alt="Logo Pretty name"
@ -34,7 +34,7 @@ exports[`PackageCard creates snapshot 1`] = `
/>
</div>
<div
class="d-flex flex-column justify-content-between ms-3 my-1 my-md-0 flex-grow-1 truncateWrapper titleWrapper"
class="d-flex flex-column flex-grow-1 flex-sm-grow-0 justify-content-between truncateWrapper titleWrapper"
>
<div
class="text-truncate card-title mb-0"
@ -47,91 +47,6 @@ exports[`PackageCard creates snapshot 1`] = `
>
Pretty name
</div>
<div
class="d-none d-xxl-flex d-xxxl-none flex-column ms-2"
>
<div
class="align-self-start d-flex align-items-center text-uppercase ms-auto kind"
>
<div
class="d-none d-md-inline-block"
>
<span
class="visually-hidden"
>
Helm chart
</span>
<button
aria-hidden="true"
aria-label="Filter by Helm chart repository kind"
class="btn btn-link m-0 p-0"
data-testid="repoIconLabelLink"
tabindex="-1"
>
<span
class="badge bg-light text-dark rounded-pill border bg badge"
>
<div
class="d-flex flex-row align-items-center"
>
<div
aria-hidden="true"
class="position-relative icon undefined"
>
<img
alt="Icon"
class="mw-100 mh-100 iconLight"
src="/static/media/helm-chart.svg"
/>
<img
alt="Icon"
class="mw-100 mh-100 iconDark"
src="/static/media/helm-chart-light.svg"
/>
</div>
<div
class="ms-1"
>
Helm chart
</div>
</div>
</span>
</button>
</div>
<div
class="d-flex d-md-none fs-6"
>
<span
class="badge bg-light text-dark rounded-pill border bg badge"
>
<div
class="d-flex flex-row align-items-center"
>
<div
aria-hidden="true"
class="position-relative icon undefined"
>
<img
alt="Icon"
class="mw-100 mh-100 iconLight"
src="/static/media/helm-chart.svg"
/>
<img
alt="Icon"
class="mw-100 mh-100 iconDark"
src="/static/media/helm-chart-light.svg"
/>
</div>
<div
class="ms-1"
>
Helm chart
</div>
</div>
</span>
</div>
</div>
</div>
</div>
</div>
<div
@ -282,14 +197,45 @@ exports[`PackageCard creates snapshot 1`] = `
</div>
</div>
<div
class="d-flex flex-row text-truncate"
class="d-flex flex-row align-items-baseline text-truncate"
>
<div
class="d-flex flex-row align-items-baseline me-1 text-muted text-uppercase"
class="d-flex flex-row align-items-baseline me-1 text-dark text-uppercase"
>
<small>
Repo:
</small>
<div
class="position-relative icon"
>
<svg
fill="none"
height="1em"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<line
x1="16.5"
x2="7.5"
y1="9.4"
y2="4.21"
/>
<path
d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"
/>
<polyline
points="3.27 6.96 12 12.01 20.73 6.96"
/>
<line
x1="12"
x2="12"
y1="22.08"
y2="12"
/>
</svg>
</div>
</div>
<span
class="visually-hidden"
@ -300,7 +246,7 @@ exports[`PackageCard creates snapshot 1`] = `
aria-expanded="false"
aria-hidden="true"
aria-label="Filter by repo stable"
class="d-flex flex-row p-0 border-0 text-dark text-truncate bg-transparent position-relative link"
class="d-flex flex-row p-0 border-0 text-muted text-truncate bg-transparent position-relative link"
data-testid="repoLink"
tabindex="-1"
>
@ -315,34 +261,50 @@ exports[`PackageCard creates snapshot 1`] = `
</div>
</div>
<div
class="d-none d-md-block card-subtitle align-items-baseline subtitle"
class="d-none d-md-block card-subtitle align-items-center subtitle"
>
<div
class="d-flex flex-row align-items-baseline"
class="d-flex flex-row align-items-center"
>
<span
class="text-muted text-uppercase me-1"
>
User:
</span>
<span
class="visually-hidden"
>
user
</span>
<button
aria-hidden="true"
aria-label="Filter by user"
class="p-0 border-0 text-truncate text-dark mw-100 bg-transparent link mx50"
data-testid="userLink"
tabindex="-1"
<div
class="d-flex flex-row align-items-baseline userInfo"
>
<div
class="text-truncate"
class="text-dark me-1 position-relative userIcon"
>
<svg
fill="currentColor"
height="1em"
stroke="currentColor"
stroke-width="0"
viewBox="0 0 448 512"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M224 256c70.7 0 128-57.3 128-128S294.7 0 224 0 96 57.3 96 128s57.3 128 128 128zm89.6 32h-16.7c-22.2 10.2-46.9 16-72.9 16s-50.6-5.8-72.9-16h-16.7C60.2 288 0 348.2 0 422.4V464c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48v-41.6c0-74.2-60.2-134.4-134.4-134.4z"
/>
</svg>
</div>
<span
class="visually-hidden"
>
user
</div>
</button>
</span>
<button
aria-hidden="true"
aria-label="Filter by user"
class="p-0 border-0 text-truncate text-muted mw-100 bg-transparent link mx50"
data-testid="userLink"
tabindex="-1"
>
<div
class="text-truncate"
>
user
</div>
</button>
</div>
<div
class="mx50"
>
@ -488,14 +450,45 @@ exports[`PackageCard creates snapshot 1`] = `
</div>
</div>
<div
class="d-flex flex-row text-truncate"
class="d-flex flex-row align-items-baseline text-truncate"
>
<div
class="d-flex flex-row align-items-baseline me-1 text-muted text-uppercase"
class="d-flex flex-row align-items-baseline me-1 text-dark text-uppercase"
>
<small>
Repo:
</small>
<div
class="position-relative icon"
>
<svg
fill="none"
height="1em"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<line
x1="16.5"
x2="7.5"
y1="9.4"
y2="4.21"
/>
<path
d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"
/>
<polyline
points="3.27 6.96 12 12.01 20.73 6.96"
/>
<line
x1="12"
x2="12"
y1="22.08"
y2="12"
/>
</svg>
</div>
</div>
<span
class="visually-hidden"
@ -506,7 +499,7 @@ exports[`PackageCard creates snapshot 1`] = `
aria-expanded="false"
aria-hidden="true"
aria-label="Filter by repo stable"
class="d-flex flex-row p-0 border-0 text-dark text-truncate bg-transparent position-relative link"
class="d-flex flex-row p-0 border-0 text-muted text-truncate bg-transparent position-relative link"
data-testid="repoLink"
tabindex="-1"
>
@ -521,29 +514,9 @@ exports[`PackageCard creates snapshot 1`] = `
</div>
</div>
</div>
<div
class="d-none d-md-block card-subtitle text-truncate align-items-baseline position-relative subtitle lastLine"
>
<div
class="d-flex flex-row align-items-baseline text-truncate"
>
<span
class="text-muted text-uppercase me-1"
>
Version:
</span>
-
<span
class="text-muted text-uppercase me-1 ms-3"
>
App Version:
</span>
1.0.0
</div>
</div>
</div>
<div
class="d-none d-lg-flex d-xxl-none d-xxxl-flex flex-column align-items-end mb-auto ms-2"
class="d-none d-lg-flex flex-column align-items-end mb-auto ms-auto rightInfo"
>
<div
class="align-self-start d-flex align-items-center text-uppercase ms-auto kind"
@ -559,12 +532,12 @@ exports[`PackageCard creates snapshot 1`] = `
<button
aria-hidden="true"
aria-label="Filter by Helm chart repository kind"
class="btn btn-link m-0 p-0"
class="btn btn-link m-0 p-0 border-0 btn position-relative repoLabel"
data-testid="repoIconLabelLink"
tabindex="-1"
>
<span
class="badge bg-light text-dark rounded-pill border bg badge"
class="badge bg-light text-dark border bg badge"
>
<div
class="d-flex flex-row align-items-center"
@ -585,7 +558,7 @@ exports[`PackageCard creates snapshot 1`] = `
/>
</div>
<div
class="ms-1"
class="ms-1 text"
>
Helm chart
</div>
@ -597,7 +570,7 @@ exports[`PackageCard creates snapshot 1`] = `
class="d-flex d-md-none fs-6"
>
<span
class="badge bg-light text-dark rounded-pill border bg badge"
class="badge bg-light text-dark border bg badge"
>
<div
class="d-flex flex-row align-items-center"
@ -618,7 +591,7 @@ exports[`PackageCard creates snapshot 1`] = `
/>
</div>
<div
class="ms-1"
class="ms-1 text"
>
Helm chart
</div>
@ -635,25 +608,30 @@ exports[`PackageCard creates snapshot 1`] = `
Updated Invalid date
</small>
</div>
<div
class="mt-1 text-truncate align-items-baseline position-relative version"
>
<div
class="d-flex flex-row align-items-baseline text-truncate"
>
<span
class="text-muted me-1"
>
Version
</span>
-
</div>
</div>
</div>
</div>
</div>
<div
class="mb-0 mb-md-1 mt-3 overflow-hidden description text-truncate"
class="mb-0 mb-md-1 mt-3 text-muted text-truncate description lineClamp "
>
desc
</div>
<div
class="d-none d-xxl-block d-xxxl-none text-end mt-2"
>
<small
class="text-muted text-nowrap date"
>
Updated Invalid date
</small>
</div>
<div
class="d-flex d-lg-none d-xxl-none flex-row flex-wrap justify-content-between align-items-center mt-auto pt-2 pt-lg-0 mt-1 mt-lg-0 mt-xxl-1 mt-xxxl-0"
class="d-flex d-lg-none flex-row flex-wrap justify-content-between align-items-center mt-auto pt-3 pt-lg-0 mt-1 mt-lg-0 mt-xxl-1 mt-xxxl-0"
>
<small
class="text-muted text-nowrap date"
@ -675,12 +653,12 @@ exports[`PackageCard creates snapshot 1`] = `
<button
aria-hidden="true"
aria-label="Filter by Helm chart repository kind"
class="btn btn-link m-0 p-0"
class="btn btn-link m-0 p-0 border-0 btn position-relative repoLabel"
data-testid="repoIconLabelLink"
tabindex="-1"
>
<span
class="badge bg-light text-dark rounded-pill border bg badge"
class="badge bg-light text-dark border bg badge"
>
<div
class="d-flex flex-row align-items-center"
@ -701,7 +679,7 @@ exports[`PackageCard creates snapshot 1`] = `
/>
</div>
<div
class="ms-1"
class="ms-1 text"
>
Helm chart
</div>
@ -713,7 +691,7 @@ exports[`PackageCard creates snapshot 1`] = `
class="d-flex d-md-none fs-6"
>
<span
class="badge bg-light text-dark rounded-pill border bg badge"
class="badge bg-light text-dark border bg badge"
>
<div
class="d-flex flex-row align-items-center"
@ -734,7 +712,7 @@ exports[`PackageCard creates snapshot 1`] = `
/>
</div>
<div
class="ms-1"
class="ms-1 text"
>
Helm chart
</div>
@ -745,8 +723,65 @@ exports[`PackageCard creates snapshot 1`] = `
</span>
</div>
<div
class="d-flex flex-wrap justify-content-lg-end mt-0 mt-md-auto labelsWrapper"
/>
class="d-none d-sm-flex flex-wrap justify-content-lg-end mt-0 mt-md-auto labelsWrapper"
>
<div
class="d-inline mt-3"
>
<button
aria-hidden="true"
aria-label="Open security report"
class="btn btn-link text-reset p-0 position-relative link"
tabindex="-1"
>
<div
class="position-relative undefined"
>
<div
data-testid="elementWithTooltip"
>
<div
class="fw-bold undefined"
>
<div
class="d-flex flex-row align-items-center overflow-hidden labelWrapper custom"
>
<div
class="text-center border border-end-0 position-relative labelIconWrapper iconWrapper"
data-testid="label-wrapper"
style="background-color: rgb(150, 0, 3);"
>
<span
class=""
>
<span
class="position-relative ratingLetter"
>
F
</span>
</span>
</div>
<div
class="text-nowrap border fw-bold labelText"
>
<span
class="d-none d-sm-inline"
>
Images Security Rating
</span>
<span
class="d-inline d-sm-none"
>
Security Rating
</span>
</div>
</div>
</div>
</div>
</div>
</button>
</div>
</div>
</div>
</a>
</div>

View File

@ -1,794 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`PackageInfo creates snapshot 1`] = `
<DocumentFragment>
<div
class="d-flex align-items-start justify-content-between mw-100"
>
<div
class="d-flex align-items-stretch flex-grow-1 h-100 truncateWrapper"
>
<div
class="d-flex align-items-center justify-content-center overflow-hidden rounded-circle p-1 p-md-2 border position-relative bg-white imageWrapper imageWrapper"
>
<img
alt="Logo Pretty name"
aria-hidden="true"
class="image"
src="/image/imageId"
srcset="/image/imageId@1x 1x, /image/imageId@2x 2x, /image/imageId@3x 3x, /image/imageId@4x 4x"
/>
</div>
<div
class="d-flex flex-column justify-content-between ms-3 my-1 my-md-0 flex-grow-1 truncateWrapper titleWrapper"
>
<div
class="text-truncate card-title mb-0"
>
<div
class="d-flex flex-row align-items-center justify-content-between"
>
<div
class="text-truncate title"
>
Pretty name
</div>
<div
class="d-none d-xxl-flex d-xxxl-none flex-column ms-2"
>
<div
class="align-self-start d-flex align-items-center text-uppercase ms-auto kind"
>
<div
class="d-none d-md-inline-block"
>
<span
class="visually-hidden"
>
Helm chart
</span>
<button
aria-hidden="true"
aria-label="Filter by Helm chart repository kind"
class="btn btn-link m-0 p-0"
data-testid="repoIconLabelLink"
tabindex="-1"
>
<span
class="badge bg-light text-dark rounded-pill border bg badge"
>
<div
class="d-flex flex-row align-items-center"
>
<div
aria-hidden="true"
class="position-relative icon undefined"
>
<img
alt="Icon"
class="mw-100 mh-100 iconLight"
src="/static/media/helm-chart.svg"
/>
<img
alt="Icon"
class="mw-100 mh-100 iconDark"
src="/static/media/helm-chart-light.svg"
/>
</div>
<div
class="ms-1"
>
Helm chart
</div>
</div>
</span>
</button>
</div>
<div
class="d-flex d-md-none fs-6"
>
<span
class="badge bg-light text-dark rounded-pill border bg badge"
>
<div
class="d-flex flex-row align-items-center"
>
<div
aria-hidden="true"
class="position-relative icon undefined"
>
<img
alt="Icon"
class="mw-100 mh-100 iconLight"
src="/static/media/helm-chart.svg"
/>
<img
alt="Icon"
class="mw-100 mh-100 iconDark"
src="/static/media/helm-chart-light.svg"
/>
</div>
<div
class="ms-1"
>
Helm chart
</div>
</div>
</span>
</div>
</div>
</div>
</div>
</div>
<div
class="d-block d-md-none"
>
<div
class="card-subtitle align-items-baseline subtitle"
>
<div
class="d-inline d-md-none text-truncate w-100"
>
<div
class="position-absolute"
>
<div
class="dropdown-menu dropdown-menu-left text-wrap dropdown"
role="complementary"
>
<div
class="content"
>
<div
class="d-flex flex-column"
>
<div
class="d-flex flex-row align-items-center"
>
<small
class="text-muted text-uppercase me-1"
>
Repo:
</small>
<img
alt="Icon"
class="me-1 w-auto repoIconMini iconLight"
src="/static/media/helm-chart.svg"
/>
<img
alt="Icon"
class="me-1 w-auto repoIconMini iconDark"
src="/static/media/helm-chart-light.svg"
/>
<div
class="text-reset text-truncate labelContent"
>
stable
</div>
</div>
<div
class="mt-2 d-flex flex-row align-items-baseline"
>
<small
class="text-muted text-uppercase me-1"
>
Url:
</small>
<div
class="text-reset text-break labelContent"
data-testid="repoUrl"
>
<div
class="d-flex flex-row flex-wrap undefined"
data-testid="attachedIconToTextWrapper"
style="line-height: 21px;"
>
<div
class="d-inline"
>
r
</div>
<div
class="d-inline"
>
e
</div>
<div
class="d-inline"
>
p
</div>
<div
class="d-inline"
>
o
</div>
<div
class="d-inline"
>
U
</div>
<div
class="d-inline"
>
r
</div>
<div
class="d-inline"
>
l
</div>
<div
class="d-inline-block"
>
<div
class="position-relative d-inline"
>
<button
aria-label="Copy repository url to clipboard"
class="btn btn-sm bg-transparent"
type="button"
>
<div
aria-hidden="true"
class="d-flex flex-row align-items-center"
>
<svg
fill="none"
height="1em"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<rect
height="13"
rx="2"
ry="2"
width="13"
x="9"
y="9"
/>
<path
d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"
/>
</svg>
</div>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div
class="d-flex flex-row text-truncate"
>
<div
class="d-flex flex-row align-items-baseline me-1 text-muted text-uppercase"
>
<small>
Repo:
</small>
</div>
<span
class="visually-hidden"
>
stable
</span>
<button
aria-expanded="false"
aria-hidden="true"
aria-label="Filter by repo stable"
class="d-flex flex-row p-0 border-0 text-dark text-truncate bg-transparent position-relative link"
data-testid="repoLink"
tabindex="-1"
>
<div
class="text-truncate"
>
stable
</div>
</button>
</div>
</div>
</div>
</div>
<div
class="d-none d-md-block card-subtitle align-items-baseline subtitle"
>
<div
class="d-flex flex-row align-items-baseline"
>
<span
class="text-muted text-uppercase me-1"
>
User:
</span>
<span
class="visually-hidden"
>
user
</span>
<button
aria-hidden="true"
aria-label="Filter by user"
class="p-0 border-0 text-truncate text-dark mw-100 bg-transparent link mx50"
data-testid="userLink"
tabindex="-1"
>
<div
class="text-truncate"
>
user
</div>
</button>
<div
class="mx50"
>
<div
class="d-flex flex-row align-items-baseline ms-3 truncateWrapper"
>
<div
class="position-absolute"
>
<div
class="dropdown-menu dropdown-menu-left text-wrap dropdown"
role="complementary"
>
<div
class="content"
>
<div
class="d-flex flex-column"
>
<div
class="d-flex flex-row align-items-center"
>
<small
class="text-muted text-uppercase me-1"
>
Repo:
</small>
<img
alt="Icon"
class="me-1 w-auto repoIconMini iconLight"
src="/static/media/helm-chart.svg"
/>
<img
alt="Icon"
class="me-1 w-auto repoIconMini iconDark"
src="/static/media/helm-chart-light.svg"
/>
<div
class="text-reset text-truncate labelContent"
>
stable
</div>
</div>
<div
class="mt-2 d-flex flex-row align-items-baseline"
>
<small
class="text-muted text-uppercase me-1"
>
Url:
</small>
<div
class="text-reset text-break labelContent"
data-testid="repoUrl"
>
<div
class="d-flex flex-row flex-wrap undefined"
data-testid="attachedIconToTextWrapper"
style="line-height: 21px;"
>
<div
class="d-inline"
>
r
</div>
<div
class="d-inline"
>
e
</div>
<div
class="d-inline"
>
p
</div>
<div
class="d-inline"
>
o
</div>
<div
class="d-inline"
>
U
</div>
<div
class="d-inline"
>
r
</div>
<div
class="d-inline"
>
l
</div>
<div
class="d-inline-block"
>
<div
class="position-relative d-inline"
>
<button
aria-label="Copy repository url to clipboard"
class="btn btn-sm bg-transparent"
type="button"
>
<div
aria-hidden="true"
class="d-flex flex-row align-items-center"
>
<svg
fill="none"
height="1em"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<rect
height="13"
rx="2"
ry="2"
width="13"
x="9"
y="9"
/>
<path
d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"
/>
</svg>
</div>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div
class="d-flex flex-row text-truncate"
>
<div
class="d-flex flex-row align-items-baseline me-1 text-muted text-uppercase"
>
<small>
Repo:
</small>
</div>
<span
class="visually-hidden"
>
stable
</span>
<button
aria-expanded="false"
aria-hidden="true"
aria-label="Filter by repo stable"
class="d-flex flex-row p-0 border-0 text-dark text-truncate bg-transparent position-relative link"
data-testid="repoLink"
tabindex="-1"
>
<div
class="text-truncate"
>
stable
</div>
</button>
</div>
</div>
</div>
</div>
</div>
<div
class="d-none d-md-block card-subtitle text-truncate align-items-baseline position-relative subtitle lastLine"
>
<div
class="d-flex flex-row align-items-baseline text-truncate"
>
<span
class="text-muted text-uppercase me-1"
>
Version:
</span>
-
<span
class="text-muted text-uppercase me-1 ms-3"
>
App Version:
</span>
1.0.0
</div>
</div>
</div>
<div
class="d-none d-md-flex d-xxl-none d-xxxl-flex flex-column align-items-end mb-auto ms-2"
>
<div
class="align-self-start d-flex align-items-center text-uppercase ms-auto kind"
>
<div
class="d-none d-md-inline-block"
>
<span
class="visually-hidden"
>
Helm chart
</span>
<button
aria-hidden="true"
aria-label="Filter by Helm chart repository kind"
class="btn btn-link m-0 p-0"
data-testid="repoIconLabelLink"
tabindex="-1"
>
<span
class="badge bg-light text-dark rounded-pill border bg badge"
>
<div
class="d-flex flex-row align-items-center"
>
<div
aria-hidden="true"
class="position-relative icon undefined"
>
<img
alt="Icon"
class="mw-100 mh-100 iconLight"
src="/static/media/helm-chart.svg"
/>
<img
alt="Icon"
class="mw-100 mh-100 iconDark"
src="/static/media/helm-chart-light.svg"
/>
</div>
<div
class="ms-1"
>
Helm chart
</div>
</div>
</span>
</button>
</div>
<div
class="d-flex d-md-none fs-6"
>
<span
class="badge bg-light text-dark rounded-pill border bg badge"
>
<div
class="d-flex flex-row align-items-center"
>
<div
aria-hidden="true"
class="position-relative icon undefined"
>
<img
alt="Icon"
class="mw-100 mh-100 iconLight"
src="/static/media/helm-chart.svg"
/>
<img
alt="Icon"
class="mw-100 mh-100 iconDark"
src="/static/media/helm-chart-light.svg"
/>
</div>
<div
class="ms-1"
>
Helm chart
</div>
</div>
</span>
</div>
</div>
<div
class="mt-1"
>
<small
class="text-muted text-nowrap date"
>
Updated Invalid date
</small>
</div>
</div>
</div>
</div>
<div
class="mb-0 mb-md-1 mt-3 overflow-hidden description text-truncate"
>
desc
</div>
<div
class="d-none d-xxl-block d-xxxl-none text-end mt-2"
>
<small
class="text-muted text-nowrap date"
>
Updated Invalid date
</small>
</div>
<div
class="d-flex d-md-none d-xxl-none flex-row flex-wrap justify-content-between align-items-center mt-auto pt-2 pt-md-0 mt-1 mt-md-0 mt-xxl-1 mt-xxxl-0"
>
<small
class="text-muted text-nowrap date"
>
Updated Invalid date
</small>
<span>
<div
class="align-self-start d-flex align-items-center text-uppercase ms-auto kind"
>
<div
class="d-none d-md-inline-block"
>
<span
class="visually-hidden"
>
Helm chart
</span>
<button
aria-hidden="true"
aria-label="Filter by Helm chart repository kind"
class="btn btn-link m-0 p-0"
data-testid="repoIconLabelLink"
tabindex="-1"
>
<span
class="badge bg-light text-dark rounded-pill border bg badge"
>
<div
class="d-flex flex-row align-items-center"
>
<div
aria-hidden="true"
class="position-relative icon undefined"
>
<img
alt="Icon"
class="mw-100 mh-100 iconLight"
src="/static/media/helm-chart.svg"
/>
<img
alt="Icon"
class="mw-100 mh-100 iconDark"
src="/static/media/helm-chart-light.svg"
/>
</div>
<div
class="ms-1"
>
Helm chart
</div>
</div>
</span>
</button>
</div>
<div
class="d-flex d-md-none fs-6"
>
<span
class="badge bg-light text-dark rounded-pill border bg badge"
>
<div
class="d-flex flex-row align-items-center"
>
<div
aria-hidden="true"
class="position-relative icon undefined"
>
<img
alt="Icon"
class="mw-100 mh-100 iconLight"
src="/static/media/helm-chart.svg"
/>
<img
alt="Icon"
class="mw-100 mh-100 iconDark"
src="/static/media/helm-chart-light.svg"
/>
</div>
<div
class="ms-1"
>
Helm chart
</div>
</div>
</span>
</div>
</div>
</span>
</div>
<div
class="d-flex flex-wrap justify-content-lg-end mt-0 mt-md-auto labelsWrapper"
>
<div
class="d-inline mt-3"
>
<button
aria-hidden="true"
aria-label="Open security report"
class="btn btn-link text-reset p-0 position-relative link"
tabindex="-1"
>
<div
class="position-relative undefined"
>
<div
data-testid="elementWithTooltip"
>
<div
class="fw-bold undefined"
>
<div
class="d-flex flex-row align-items-center overflow-hidden labelWrapper custom"
>
<div
class="text-center border border-end-0 position-relative labelIconWrapper iconWrapper"
data-testid="label-wrapper"
style="background-color: rgb(150, 0, 3);"
>
<span
class=""
>
<span
class="position-relative ratingLetter"
>
F
</span>
</span>
</div>
<div
class="text-nowrap border fw-bold labelText"
>
<span
class="d-none d-sm-inline"
>
Images Security Rating
</span>
<span
class="d-inline d-sm-none"
>
Security Rating
</span>
</div>
</div>
</div>
</div>
</div>
</button>
</div>
</div>
</DocumentFragment>
`;

View File

@ -16,7 +16,7 @@ exports[`RSSLinkTitle creates snapshot 1`] = `
</div>
<small>
<a
class="badge rounded-pill bg-secondary rssBadge ms-3"
class="badge bg-secondary rssBadge ms-3"
href="/api/v1/packages/helm/stable/test/feed/rss"
rel="alternate noopener noreferrer"
role="button"

View File

@ -9,7 +9,7 @@ exports[`RepositoryIconLabel creates snapshot 1`] = `
class="d-flex fs-6"
>
<span
class="badge bg-light text-dark rounded-pill border bg badge"
class="badge bg-light text-dark border bg badge"
>
<div
class="d-flex flex-row align-items-center"
@ -30,7 +30,7 @@ exports[`RepositoryIconLabel creates snapshot 1`] = `
/>
</div>
<div
class="ms-1"
class="ms-1 text"
>
Helm chart
</div>
@ -42,7 +42,7 @@ exports[`RepositoryIconLabel creates snapshot 1`] = `
class="d-flex d-md-none fs-6"
>
<span
class="badge bg-light text-dark rounded-pill border bg badge"
class="badge bg-light text-dark border bg badge"
>
<div
class="d-flex flex-row align-items-center"
@ -63,7 +63,7 @@ exports[`RepositoryIconLabel creates snapshot 1`] = `
/>
</div>
<div
class="ms-1"
class="ms-1 text"
>
Helm chart
</div>

View File

@ -197,14 +197,45 @@ exports[`RepositoryInfo creates snapshot 1`] = `
</div>
</div>
<div
class="d-flex flex-row text-truncate"
class="d-flex flex-row align-items-baseline text-truncate"
>
<div
class="d-flex flex-row align-items-baseline me-1 text-muted text-uppercase"
class="d-flex flex-row align-items-baseline me-1 text-dark text-uppercase"
>
<small>
Repo:
</small>
<div
class="position-relative icon"
>
<svg
fill="none"
height="1em"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<line
x1="16.5"
x2="7.5"
y1="9.4"
y2="4.21"
/>
<path
d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"
/>
<polyline
points="3.27 6.96 12 12.01 20.73 6.96"
/>
<line
x1="12"
x2="12"
y1="22.08"
y2="12"
/>
</svg>
</div>
</div>
<span
class="visually-hidden"
@ -215,7 +246,7 @@ exports[`RepositoryInfo creates snapshot 1`] = `
aria-expanded="false"
aria-hidden="true"
aria-label="Filter by repo Stable"
class="d-flex flex-row p-0 border-0 text-dark text-truncate bg-transparent position-relative link"
class="d-flex flex-row p-0 border-0 text-muted text-truncate bg-transparent position-relative link"
data-testid="repoLink"
tabindex="-1"
>

View File

@ -4,35 +4,35 @@ exports[`SampleQueries creates snapshot 1`] = `
<DocumentFragment>
<a
aria-label="Filter by OLM operators for databases"
class="badge rounded-pill border fw-normal mx-2 mt-3 undefined"
class="badge border fw-normal mx-2 mt-3 sampleQuery undefined"
href="/packages/search?kind=3&ts_query_web=database"
>
OLM operators for databases
</a>
<a
aria-label="Filter by Helm Charts provided by Bitnami"
class="badge rounded-pill border fw-normal mx-2 mt-3 undefined"
class="badge border fw-normal mx-2 mt-3 sampleQuery undefined"
href="/packages/search?kind=0&org=bitnami"
>
Helm Charts provided by Bitnami
</a>
<a
aria-label="Filter by Packages of any kind related to etcd"
class="badge rounded-pill border fw-normal mx-2 mt-3 undefined"
class="badge border fw-normal mx-2 mt-3 sampleQuery undefined"
href="/packages/search?ts_query_web=etcd"
>
Packages of any kind related to etcd
</a>
<a
aria-label="Filter by Falco rules for CVE"
class="badge rounded-pill border fw-normal mx-2 mt-3 undefined"
class="badge border fw-normal mx-2 mt-3 sampleQuery undefined"
href="/packages/search?kind=1&ts_query_web=cve"
>
Falco rules for CVE
</a>
<a
aria-label="Filter by OLM operators in the monitoring category"
class="badge rounded-pill border fw-normal mx-2 mt-3 undefined"
class="badge border fw-normal mx-2 mt-3 sampleQuery undefined"
href="/packages/search?kind=3&ts_query=monitoring"
>
OLM operators in the monitoring category

View File

@ -66,7 +66,7 @@ exports[`SearchBar creates snapshot 1`] = `
type="button"
/>
<div
class="position-absolute text-dark tipIcon bigTipIcon"
class="d-none d-sm-block position-absolute text-dark tipIcon bigTipIcon"
>
<button
aria-label="Open search tips modal"

View File

@ -4,7 +4,7 @@ exports[`StarBadge creates snapshot 1`] = `
<DocumentFragment>
<div
aria-label="1 stars"
class="badge rounded-pill bg-light text-dark border badge"
class="badge bg-light text-dark border badge"
data-testid="starBadge"
>
<div

View File

@ -4,7 +4,6 @@
width: 700px;
max-width: 80%;
border-color: var(--color-1-500) !important;
border-radius: 15px;
z-index: 1100;
}

View File

@ -14,8 +14,6 @@
.section {
border-color: transparent !important;
border-top-left-radius: 0.25rem !important;
border-top-right-radius: 0.25rem !important;
}
.section:hover {
@ -25,7 +23,11 @@
.activeSection {
border-color: var(--color-1-20) !important;
border-bottom-color: transparent !important;
background-color: var(--body-bg) !important;
background-color: #2c2e31 !important;
}
[data-theme='light'] .activeSection {
background-color: var(--extra-light-gray) !important;
}
.activeSection::before {
@ -33,11 +35,9 @@
position: absolute;
top: -1px;
height: 4px;
left: 0;
right: 0;
left: -1px;
right: -1px;
background-color: var(--color-1-700);
border-top-left-radius: 0.25rem;
border-top-right-radius: 0.25rem;
}
@media only screen and (max-width: 767.98px) {

View File

@ -70,7 +70,7 @@ const UserContext = () => {
<small className={`text-uppercase text-muted ${styles.legendCtx}`}>Control panel context</small>
<div className="d-flex flex-row align-items-center">
<button
className={`btn btn-primary rounded-pill btn-sm pe-3 position-relative lh-1 ${styles.ctxBtn}`}
className={`btn btn-primary btn-sm pe-3 position-relative lh-1 ${styles.ctxBtn}`}
type="button"
onClick={() => {
fetchOrganizations();

View File

@ -19,7 +19,7 @@ exports[`UserContext creates snapshot 1`] = `
<button
aria-expanded="false"
aria-label="Open context"
class="btn btn-primary rounded-pill btn-sm pe-3 position-relative lh-1 ctxBtn"
class="btn btn-primary btn-sm pe-3 position-relative lh-1 ctxBtn"
type="button"
>
<div

View File

@ -37,17 +37,33 @@ exports[`ControlPanelView renders correctly 1`] = `
class="icon"
>
<svg
fill="currentColor"
fill="none"
height="1em"
stroke="currentColor"
stroke-width="0"
viewBox="0 0 16 16"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<line
x1="16.5"
x2="7.5"
y1="9.4"
y2="4.21"
/>
<path
d="M1 4.27v7.47c0 .45.3.84.75.97l6.5 1.73c.16.05.34.05.5 0l6.5-1.73c.45-.13.75-.52.75-.97V4.27c0-.45-.3-.84-.75-.97l-6.5-1.74a1.4 1.4 0 0 0-.5 0L1.75 3.3c-.45.13-.75.52-.75.97zm7 9.09l-6-1.59V5l6 1.61v6.75zM2 4l2.5-.67L11 5.06l-2.5.67L2 4zm13 7.77l-6 1.59V6.61l2-.55V8.5l2-.53V5.53L15 5v6.77zm-2-7.24L6.5 2.8l2-.53L15 4l-2 .53z"
fill-rule="evenodd"
d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"
/>
<polyline
points="3.27 6.96 12 12.01 20.73 6.96"
/>
<line
x1="12"
x2="12"
y1="22.08"
y2="12"
/>
</svg>
</span>
@ -159,7 +175,7 @@ exports[`ControlPanelView renders correctly 1`] = `
<button
aria-expanded="false"
aria-label="Open context"
class="btn btn-primary rounded-pill btn-sm pe-3 position-relative lh-1 ctxBtn"
class="btn btn-primary btn-sm pe-3 position-relative lh-1 ctxBtn"
type="button"
>
<div

View File

@ -17,14 +17,11 @@
min-width: 40px;
width: 40px;
height: 40px;
border-color: var(--color-1-10) !important;
box-shadow: 0px 0px 5px 0px var(--color-1-20);
}
.image {
max-width: calc(100% - 2px);
max-height: calc(100% - 2px);
max-width: 100%;
max-height: 100%;
}
@media only screen and (max-width: 767.98px) {

View File

@ -13,17 +13,10 @@
right: 4px;
}
.imageWrapper {
.image {
min-width: 40px;
width: 40px;
height: 40px;
border-color: var(--color-1-10) !important;
box-shadow: 0px 0px 5px 0px var(--color-1-20);
}
.image {
max-width: calc(100% - 2px);
max-height: calc(100% - 2px);
}
.link {

View File

@ -26,7 +26,6 @@
.code {
background-color: var(--code-bg-md);
border: 1px solid var(--color-1-20);
border-radius: 3px;
padding: 0 0.15rem;
color: var(--color-font);
}

View File

@ -30,7 +30,7 @@ exports[`Repository Card - packages section creates snapshot 1`] = `
class="d-flex fs-6"
>
<span
class="badge bg-light text-dark rounded-pill border bg badge"
class="badge bg-light text-dark border bg badge"
>
<div
class="d-flex flex-row align-items-center"
@ -51,7 +51,7 @@ exports[`Repository Card - packages section creates snapshot 1`] = `
/>
</div>
<div
class="ms-1"
class="ms-1 text"
>
Helm charts
</div>
@ -63,7 +63,7 @@ exports[`Repository Card - packages section creates snapshot 1`] = `
class="d-flex d-md-none fs-6"
>
<span
class="badge bg-light text-dark rounded-pill border bg badge"
class="badge bg-light text-dark border bg badge"
>
<div
class="d-flex flex-row align-items-center"
@ -84,7 +84,7 @@ exports[`Repository Card - packages section creates snapshot 1`] = `
/>
</div>
<div
class="ms-1"
class="ms-1 text"
>
Helm charts
</div>

View File

@ -187,7 +187,7 @@ const EnableTwoFactorAuthenticationModal = (props: Props) => {
be used once.{' '}
<span className="fw-bold">Please treat them as passwords and store them safely</span>.
</div>
<div className={`border rounded position-relative p-2 p-sm-4 ${styles.codesWrapper}`}>
<div className={`border position-relative p-2 p-sm-4 ${styles.codesWrapper}`}>
<BlockCodeButtons
filename="artifacthub-recovery-codes.txt"
content={setUp.recoveryCodes.join('\n')}
@ -229,7 +229,7 @@ const EnableTwoFactorAuthenticationModal = (props: Props) => {
</div>
<div className="text-center mb-4">
<div className="border rounded d-inline-block p-1 my-1">
<div className="border d-inline-block p-1 my-1">
<img className={styles.qrCode} src={setUp.qrCode} alt="QR code" />
</div>
</div>

View File

@ -25,13 +25,11 @@
min-width: 25px;
width: 25px;
height: 25px;
border-color: var(--color-1-10) !important;
box-shadow: 0px 0px 2px 0px var(--color-1-20);
}
.image {
max-width: calc(100% - 2px);
max-height: calc(100% - 2px);
max-width: 100%;
max-height: 100%;
}
.icon {

View File

@ -14,14 +14,11 @@
min-width: 30px;
width: 30px;
height: 30px;
border-color: var(--color-1-10) !important;
box-shadow: 0px 0px 2px 0px var(--color-1-20);
}
.image {
max-width: calc(100% - 2px);
max-height: calc(100% - 2px);
max-width: 100%;
max-height: 100%;
}
.closeButton {

View File

@ -174,7 +174,7 @@ const SubscriptionModal = (props: Props) => {
{!isNull(packageItem) ? (
<div
data-testid="activePackageItem"
className={`border border-secondary w-100 rounded mt-1 ${styles.packageWrapper}`}
className={`border border-secondary w-100 mt-1 ${styles.packageWrapper}`}
>
<div className="d-flex flex-row flex-nowrap align-items-stretch justify-content-between">
<div className="flex-grow-1 text-truncate py-2">
@ -184,7 +184,7 @@ const SubscriptionModal = (props: Props) => {
</div>
<div
className={`d-flex align-items-center justify-content-center overflow-hidden p-1 ms-2 ms-md-0 rounded-circle border border-2 bg-white ${styles.imageWrapper} imageWrapper`}
className={`d-flex align-items-center justify-content-center overflow-hidden ms-2 ms-md-0 ${styles.imageWrapper}`}
>
<Image
alt={packageItem.displayName || packageItem.name}

View File

@ -1,11 +1,7 @@
.card {
box-shadow: 0px 0px 5px 0px var(--bs-light);
}
@media (hover: hover) {
.card:hover {
border-color: var(--color-black-50);
box-shadow: 0px 0px 5px 0px var(--color-black-75);
border-color: var(--color-black-25);
box-shadow: 0 0 0 2px var(--color-black-25);
}
}
@ -22,14 +18,11 @@
min-width: 60px;
width: 60px;
height: 60px;
border-color: var(--color-1-10) !important;
box-shadow: 0px 0px 5px 0px var(--color-1-20);
}
.image {
max-width: calc(100% - 8px);
max-height: calc(100% - 8px);
max-width: 100%;
max-height: 100%;
}
.link {

View File

@ -215,7 +215,7 @@ exports[`PackagesSection creates snapshot 1`] = `
class="d-flex flex-row align-items-center"
>
<div
class="d-flex align-items-center justify-content-center overflow-hidden p-1 rounded-circle border bg-white imageWrapper imageWrapper"
class="d-flex align-items-center justify-content-center overflow-hidden imageWrapper"
>
<img
alt="airflow"
@ -330,7 +330,7 @@ exports[`PackagesSection creates snapshot 1`] = `
class="d-flex flex-row align-items-center"
>
<div
class="d-flex align-items-center justify-content-center overflow-hidden p-1 rounded-circle border bg-white imageWrapper imageWrapper"
class="d-flex align-items-center justify-content-center overflow-hidden imageWrapper"
>
<img
alt="cerebro"
@ -445,7 +445,7 @@ exports[`PackagesSection creates snapshot 1`] = `
class="d-flex flex-row align-items-center"
>
<div
class="d-flex align-items-center justify-content-center overflow-hidden p-1 rounded-circle border bg-white imageWrapper imageWrapper"
class="d-flex align-items-center justify-content-center overflow-hidden imageWrapper"
>
<img
alt="elastic-stack"
@ -560,7 +560,7 @@ exports[`PackagesSection creates snapshot 1`] = `
class="d-flex flex-row align-items-center"
>
<div
class="d-flex align-items-center justify-content-center overflow-hidden p-1 rounded-circle border bg-white imageWrapper imageWrapper"
class="d-flex align-items-center justify-content-center overflow-hidden imageWrapper"
>
<img
alt="ibm-redis"
@ -675,7 +675,7 @@ exports[`PackagesSection creates snapshot 1`] = `
class="d-flex flex-row align-items-center"
>
<div
class="d-flex align-items-center justify-content-center overflow-hidden p-1 rounded-circle border bg-white imageWrapper imageWrapper"
class="d-flex align-items-center justify-content-center overflow-hidden imageWrapper"
>
<img
alt="SSH connections"
@ -790,7 +790,7 @@ exports[`PackagesSection creates snapshot 1`] = `
class="d-flex flex-row align-items-center"
>
<div
class="d-flex align-items-center justify-content-center overflow-hidden p-1 rounded-circle border bg-white imageWrapper imageWrapper"
class="d-flex align-items-center justify-content-center overflow-hidden imageWrapper"
>
<img
alt="Traefik"
@ -905,7 +905,7 @@ exports[`PackagesSection creates snapshot 1`] = `
class="d-flex flex-row align-items-center"
>
<div
class="d-flex align-items-center justify-content-center overflow-hidden p-1 rounded-circle border bg-white imageWrapper imageWrapper"
class="d-flex align-items-center justify-content-center overflow-hidden imageWrapper"
>
<img
alt="Trusted Registry Images"
@ -1020,7 +1020,7 @@ exports[`PackagesSection creates snapshot 1`] = `
class="d-flex flex-row align-items-center"
>
<div
class="d-flex align-items-center justify-content-center overflow-hidden p-1 rounded-circle border bg-white imageWrapper imageWrapper"
class="d-flex align-items-center justify-content-center overflow-hidden imageWrapper"
>
<img
alt="zookeeper"

View File

@ -203,7 +203,7 @@ const PackagesSection = (props: Props) => {
<td className="align-middle">
<div className="d-flex flex-row align-items-center">
<div
className={`d-flex align-items-center justify-content-center overflow-hidden p-1 rounded-circle border bg-white ${styles.imageWrapper} imageWrapper`}
className={`d-flex align-items-center justify-content-center overflow-hidden ${styles.imageWrapper}`}
>
<Image
alt={item.displayName || item.name}

View File

@ -1,7 +1,3 @@
.card {
box-shadow: 0px 0px 5px 0px var(--bs-light);
}
.badge {
font-size: 0.5rem;
}

View File

@ -23,13 +23,10 @@
background-color: var(--bs-white);
}
.imageWrapper {
.image {
min-width: 25px;
width: 25px;
height: 25px;
border-color: var(--color-1-10) !important;
box-shadow: 0px 0px 2px 0px var(--color-1-20);
}
.cellWrapper {
@ -54,6 +51,7 @@
.codeWrapper {
overflow-x: auto;
background-color: var(--color-black-5);
}
.variablesTable {

View File

@ -473,16 +473,12 @@ const WebhookForm = (props: Props) => {
</td>
<td className="align-middle">
<div className="d-flex flex-row align-items-center">
<div
className={`d-flex align-items-center justify-content-center overflow-hidden p-1 rounded-circle border border-2 bg-white ${styles.imageWrapper} imageWrapper`}
>
<Image
alt={item.displayName || item.name}
imageId={item.logoImageId}
className="mw-100 mh-100 fs-4"
kind={item.repository.kind}
/>
</div>
<Image
alt={item.displayName || item.name}
imageId={item.logoImageId}
className={`fs-4 ${styles.image}`}
kind={item.repository.kind}
/>
<div className={`ms-2 text-dark ${styles.cellWrapper}`}>
<div className="text-truncate">

View File

@ -442,17 +442,13 @@ exports[`WebhookForm creates snapshot 1`] = `
<div
class="d-flex flex-row align-items-center"
>
<div
class="d-flex align-items-center justify-content-center overflow-hidden p-1 rounded-circle border border-2 bg-white imageWrapper imageWrapper"
>
<img
alt="envoy"
aria-hidden="true"
class="mw-100 mh-100 fs-4"
src="/image/c5cfce82-9b0c-4a26-9a8d-c9d0fd5aa2cc"
srcset="/image/c5cfce82-9b0c-4a26-9a8d-c9d0fd5aa2cc@1x 1x, /image/c5cfce82-9b0c-4a26-9a8d-c9d0fd5aa2cc@2x 2x, /image/c5cfce82-9b0c-4a26-9a8d-c9d0fd5aa2cc@3x 3x, /image/c5cfce82-9b0c-4a26-9a8d-c9d0fd5aa2cc@4x 4x"
/>
</div>
<img
alt="envoy"
aria-hidden="true"
class="fs-4 image"
src="/image/c5cfce82-9b0c-4a26-9a8d-c9d0fd5aa2cc"
srcset="/image/c5cfce82-9b0c-4a26-9a8d-c9d0fd5aa2cc@1x 1x, /image/c5cfce82-9b0c-4a26-9a8d-c9d0fd5aa2cc@2x 2x, /image/c5cfce82-9b0c-4a26-9a8d-c9d0fd5aa2cc@3x 3x, /image/c5cfce82-9b0c-4a26-9a8d-c9d0fd5aa2cc@4x 4x"
/>
<div
class="ms-2 text-dark cellWrapper"
>

View File

@ -4,6 +4,10 @@
padding-top: 7rem !important;
}
.mainTitle {
font-weight: 200;
}
.search {
min-width: 250px;
max-width: 500px;
@ -32,6 +36,10 @@
width: 75px;
}
.legend {
font-weight: 300;
}
.legendIcon {
font-size: 70%;
line-height: 1rem;
@ -97,6 +105,10 @@
font-size: 85%;
width: 90px;
}
.banner {
width: 250px;
}
}
@media only screen and (min-width: 1400px) {

View File

@ -1,28 +0,0 @@
.card {
margin: 0 auto;
max-width: 750px;
box-shadow: 0px 0px 5px 0px var(--bs-light);
}
.body {
padding: 1.75rem !important;
}
@media only screen and (max-width: 767.98px) {
.body {
padding: 0.75rem;
}
}
@media only screen and (min-width: 768px) {
.card {
min-height: 198px;
}
}
@media (hover: hover) {
.card:hover {
border-color: var(--color-black-50);
box-shadow: 0px 0px 5px 0px var(--color-black-75);
}
}

View File

@ -1,133 +0,0 @@
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { BrowserRouter as Router } from 'react-router-dom';
import { Package } from '../../types';
import { prepareQueryString } from '../../utils/prepareQueryString';
import PackageCard from './PackageCard';
const getMockPackage = (fixtureId: string): Package => {
return require(`./__fixtures__/PackageCard/${fixtureId}.json`) as Package;
};
const mockHistoryPush = jest.fn();
jest.mock('react-router-dom', () => ({
...(jest.requireActual('react-router-dom') as {}),
useHistory: () => ({
push: mockHistoryPush,
}),
}));
describe('PackageCard', () => {
afterEach(() => {
jest.resetAllMocks();
});
it('renders correctly', () => {
const mockPackage = getMockPackage('1');
const { asFragment } = render(
<Router>
<PackageCard package={mockPackage} />
</Router>
);
expect(asFragment()).toMatchSnapshot();
});
describe('Image', () => {
it('renders package logo', () => {
const mockPackage = getMockPackage('2');
render(
<Router>
<PackageCard package={mockPackage} />
</Router>
);
const image = screen.getByAltText(`Logo ${mockPackage.displayName}`);
expect(image).toBeInTheDocument();
});
it('renders placeholder when imageId is null', () => {
const mockPackage = getMockPackage('3');
render(
<Router>
<PackageCard package={mockPackage} />
</Router>
);
const image = screen.getByAltText(`Logo ${mockPackage.displayName}`);
expect(image).toBeInTheDocument();
expect((image as HTMLImageElement).src).toBe('http://localhost/static/media/placeholder_pkg_helm.png');
});
});
describe('Title', () => {
it('renders display name', () => {
const mockPackage = getMockPackage('4');
render(
<Router>
<PackageCard package={mockPackage} />
</Router>
);
const title = screen.queryByText(mockPackage.displayName!);
expect(title).toBeInTheDocument();
});
it('renders name when display name is null', () => {
const mockPackage = getMockPackage('5');
render(
<Router>
<PackageCard package={mockPackage} />
</Router>
);
const title = screen.queryByText(mockPackage.name!);
expect(title).toBeInTheDocument();
});
});
describe('Repository button', () => {
it('renders repository link', async () => {
const mockPackage = getMockPackage('7');
render(
<Router>
<PackageCard package={mockPackage} />
</Router>
);
const buttons = screen.queryAllByTestId('repoLink');
expect(buttons).toHaveLength(2);
const icons = screen.queryAllByAltText('Icon');
expect(icons).toHaveLength(16);
expect(icons[0]).toBeInTheDocument();
expect((icons[0] as HTMLImageElement).src).toBe('http://localhost/static/media/helm-chart.svg');
await userEvent.click(buttons[0]!);
expect(mockHistoryPush).toHaveBeenCalledTimes(1);
expect(mockHistoryPush).toHaveBeenCalledWith({
pathname: '/packages/search',
search: prepareQueryString({
pageNumber: 1,
filters: {
repo: [mockPackage.repository.name],
},
}),
});
});
});
describe('Detail', () => {
it('opens detail page', async () => {
const mockPackage = getMockPackage('9');
render(
<Router>
<PackageCard package={mockPackage} />
</Router>
);
const link = screen.getByRole('link');
expect(link).toBeInTheDocument();
await userEvent.click(link);
expect(window.location.pathname).toBe('/packages/helm/stable/test');
});
});
});

View File

@ -1,33 +0,0 @@
import { Link } from 'react-router-dom';
import { Package } from '../../types';
import buildPackageURL from '../../utils/buildPackageURL';
import PackageInfo from '../common/PackageInfo';
import styles from './PackageCard.module.css';
interface Props {
package: Package;
className?: string;
}
const PackageCard = (props: Props) => (
<div
className={`col-12 col-xxl-6 col-xxxl-5 py-sm-3 py-2 px-0 px-xxl-3 position-relative ${props.className}`}
role="listitem"
>
<div className={`card cardWithHover h-100 ${styles.card}`}>
<Link
className="text-decoration-none text-reset h-100"
to={{
pathname: buildPackageURL(props.package.normalizedName, props.package.repository, props.package.version!),
}}
>
<div className={`card-body d-flex flex-column h-100 ${styles.body}`}>
<PackageInfo package={props.package} />
</div>
</Link>
</div>
</div>
);
export default PackageCard;

View File

@ -2,3 +2,14 @@
min-height: 500px;
background-color: var(--body-bg);
}
.card {
max-width: 750px !important;
margin: 0 auto;
}
@media only screen and (min-width: 768px) {
.card {
min-height: 172px;
}
}

View File

@ -6,7 +6,7 @@ import API from '../../api';
import { Package } from '../../types';
import Loading from '../common/Loading';
import NoData from '../common/NoData';
import PackageCard from './PackageCard';
import PackageCard from '../common/PackageCard';
import styles from './RandomPackages.module.css';
const RandomPackages = () => {
@ -45,7 +45,11 @@ const RandomPackages = () => {
<PackageCard
key={`rp_${item.packageId}`}
package={item}
className={classnames({ 'd-none d-xxl-block': index > 4 })}
className={styles.card}
cardWrapperClassName={classnames('col-12 col-xxl-6 col-xxxl-5', {
'd-none d-xxl-block': index > 4,
})}
noBadges
/>
);
})}

View File

@ -23,7 +23,7 @@ const SearchTip = () => {
<span className="fw-semibold me-1">Tip:</span>
{activeTip.content} Example:{' '}
<Link
className="fw-bold textLighter p-0"
className="fw-semibold textLighter p-0"
to={{
pathname: '/packages/search',
search: prepareQueryString({

View File

@ -1,755 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`PackageCard renders correctly 1`] = `
<DocumentFragment>
<div
class="col-12 col-xxl-6 col-xxxl-5 py-sm-3 py-2 px-0 px-xxl-3 position-relative undefined"
role="listitem"
>
<div
class="card cardWithHover h-100 card"
>
<a
class="text-decoration-none text-reset h-100"
href="/packages/helm/stable/test"
>
<div
class="card-body d-flex flex-column h-100 body"
>
<div
class="d-flex align-items-start justify-content-between mw-100"
>
<div
class="d-flex align-items-stretch flex-grow-1 h-100 truncateWrapper"
>
<div
class="d-flex align-items-center justify-content-center overflow-hidden rounded-circle p-1 p-md-2 border position-relative bg-white imageWrapper imageWrapper"
>
<img
alt="Logo Pretty name"
aria-hidden="true"
class="image"
src="/image/imageId"
srcset="/image/imageId@1x 1x, /image/imageId@2x 2x, /image/imageId@3x 3x, /image/imageId@4x 4x"
/>
</div>
<div
class="d-flex flex-column justify-content-between ms-3 my-1 my-md-0 flex-grow-1 truncateWrapper titleWrapper"
>
<div
class="text-truncate card-title mb-0"
>
<div
class="d-flex flex-row align-items-center justify-content-between"
>
<div
class="text-truncate title"
>
Pretty name
</div>
<div
class="d-none d-xxl-flex d-xxxl-none flex-column ms-2"
>
<div
class="align-self-start d-flex align-items-center text-uppercase ms-auto kind"
>
<div
class="d-none d-md-inline-block"
>
<span
class="visually-hidden"
>
Helm chart
</span>
<button
aria-hidden="true"
aria-label="Filter by Helm chart repository kind"
class="btn btn-link m-0 p-0"
data-testid="repoIconLabelLink"
tabindex="-1"
>
<span
class="badge bg-light text-dark rounded-pill border bg badge"
>
<div
class="d-flex flex-row align-items-center"
>
<div
aria-hidden="true"
class="position-relative icon undefined"
>
<img
alt="Icon"
class="mw-100 mh-100 iconLight"
src="/static/media/helm-chart.svg"
/>
<img
alt="Icon"
class="mw-100 mh-100 iconDark"
src="/static/media/helm-chart-light.svg"
/>
</div>
<div
class="ms-1"
>
Helm chart
</div>
</div>
</span>
</button>
</div>
<div
class="d-flex d-md-none fs-6"
>
<span
class="badge bg-light text-dark rounded-pill border bg badge"
>
<div
class="d-flex flex-row align-items-center"
>
<div
aria-hidden="true"
class="position-relative icon undefined"
>
<img
alt="Icon"
class="mw-100 mh-100 iconLight"
src="/static/media/helm-chart.svg"
/>
<img
alt="Icon"
class="mw-100 mh-100 iconDark"
src="/static/media/helm-chart-light.svg"
/>
</div>
<div
class="ms-1"
>
Helm chart
</div>
</div>
</span>
</div>
</div>
</div>
</div>
</div>
<div
class="d-block d-md-none"
>
<div
class="card-subtitle align-items-baseline subtitle"
>
<div
class="d-inline d-md-none text-truncate w-100"
>
<div
class="position-absolute"
>
<div
class="dropdown-menu dropdown-menu-left text-wrap dropdown"
role="complementary"
>
<div
class="content"
>
<div
class="d-flex flex-column"
>
<div
class="d-flex flex-row align-items-center"
>
<small
class="text-muted text-uppercase me-1"
>
Repo:
</small>
<img
alt="Icon"
class="me-1 w-auto repoIconMini iconLight"
src="/static/media/helm-chart.svg"
/>
<img
alt="Icon"
class="me-1 w-auto repoIconMini iconDark"
src="/static/media/helm-chart-light.svg"
/>
<div
class="text-reset text-truncate labelContent"
>
stable
</div>
</div>
<div
class="mt-2 d-flex flex-row align-items-baseline"
>
<small
class="text-muted text-uppercase me-1"
>
Url:
</small>
<div
class="text-reset text-break labelContent"
data-testid="repoUrl"
>
<div
class="d-flex flex-row flex-wrap undefined"
data-testid="attachedIconToTextWrapper"
style="line-height: 21px;"
>
<div
class="d-inline"
>
r
</div>
<div
class="d-inline"
>
e
</div>
<div
class="d-inline"
>
p
</div>
<div
class="d-inline"
>
o
</div>
<div
class="d-inline"
>
U
</div>
<div
class="d-inline"
>
r
</div>
<div
class="d-inline"
>
l
</div>
<div
class="d-inline-block"
>
<div
class="position-relative d-inline"
>
<button
aria-label="Copy repository url to clipboard"
class="btn btn-sm bg-transparent"
type="button"
>
<div
aria-hidden="true"
class="d-flex flex-row align-items-center"
>
<svg
fill="none"
height="1em"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<rect
height="13"
rx="2"
ry="2"
width="13"
x="9"
y="9"
/>
<path
d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"
/>
</svg>
</div>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div
class="d-flex flex-row text-truncate"
>
<div
class="d-flex flex-row align-items-baseline me-1 text-muted text-uppercase"
>
<small>
Repo:
</small>
</div>
<span
class="visually-hidden"
>
stable
</span>
<button
aria-expanded="false"
aria-hidden="true"
aria-label="Filter by repo stable"
class="d-flex flex-row p-0 border-0 text-dark text-truncate bg-transparent position-relative link"
data-testid="repoLink"
tabindex="-1"
>
<div
class="text-truncate"
>
stable
</div>
</button>
</div>
</div>
</div>
</div>
<div
class="d-none d-md-block card-subtitle align-items-baseline subtitle"
>
<div
class="d-flex flex-row align-items-baseline"
>
<span
class="text-muted text-uppercase me-1"
>
User:
</span>
<span
class="visually-hidden"
>
user
</span>
<button
aria-hidden="true"
aria-label="Filter by user"
class="p-0 border-0 text-truncate text-dark mw-100 bg-transparent link mx50"
data-testid="userLink"
tabindex="-1"
>
<div
class="text-truncate"
>
user
</div>
</button>
<div
class="mx50"
>
<div
class="d-flex flex-row align-items-baseline ms-3 truncateWrapper"
>
<div
class="position-absolute"
>
<div
class="dropdown-menu dropdown-menu-left text-wrap dropdown"
role="complementary"
>
<div
class="content"
>
<div
class="d-flex flex-column"
>
<div
class="d-flex flex-row align-items-center"
>
<small
class="text-muted text-uppercase me-1"
>
Repo:
</small>
<img
alt="Icon"
class="me-1 w-auto repoIconMini iconLight"
src="/static/media/helm-chart.svg"
/>
<img
alt="Icon"
class="me-1 w-auto repoIconMini iconDark"
src="/static/media/helm-chart-light.svg"
/>
<div
class="text-reset text-truncate labelContent"
>
stable
</div>
</div>
<div
class="mt-2 d-flex flex-row align-items-baseline"
>
<small
class="text-muted text-uppercase me-1"
>
Url:
</small>
<div
class="text-reset text-break labelContent"
data-testid="repoUrl"
>
<div
class="d-flex flex-row flex-wrap undefined"
data-testid="attachedIconToTextWrapper"
style="line-height: 21px;"
>
<div
class="d-inline"
>
r
</div>
<div
class="d-inline"
>
e
</div>
<div
class="d-inline"
>
p
</div>
<div
class="d-inline"
>
o
</div>
<div
class="d-inline"
>
U
</div>
<div
class="d-inline"
>
r
</div>
<div
class="d-inline"
>
l
</div>
<div
class="d-inline-block"
>
<div
class="position-relative d-inline"
>
<button
aria-label="Copy repository url to clipboard"
class="btn btn-sm bg-transparent"
type="button"
>
<div
aria-hidden="true"
class="d-flex flex-row align-items-center"
>
<svg
fill="none"
height="1em"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<rect
height="13"
rx="2"
ry="2"
width="13"
x="9"
y="9"
/>
<path
d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"
/>
</svg>
</div>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div
class="d-flex flex-row text-truncate"
>
<div
class="d-flex flex-row align-items-baseline me-1 text-muted text-uppercase"
>
<small>
Repo:
</small>
</div>
<span
class="visually-hidden"
>
stable
</span>
<button
aria-expanded="false"
aria-hidden="true"
aria-label="Filter by repo stable"
class="d-flex flex-row p-0 border-0 text-dark text-truncate bg-transparent position-relative link"
data-testid="repoLink"
tabindex="-1"
>
<div
class="text-truncate"
>
stable
</div>
</button>
</div>
</div>
</div>
</div>
</div>
<div
class="d-none d-md-block card-subtitle text-truncate align-items-baseline position-relative subtitle lastLine"
>
<div
class="d-flex flex-row align-items-baseline text-truncate"
>
<span
class="text-muted text-uppercase me-1"
>
Version:
</span>
-
<span
class="text-muted text-uppercase me-1 ms-3"
>
App Version:
</span>
1.0.0
</div>
</div>
</div>
<div
class="d-none d-md-flex d-xxl-none d-xxxl-flex flex-column align-items-end mb-auto ms-2"
>
<div
class="align-self-start d-flex align-items-center text-uppercase ms-auto kind"
>
<div
class="d-none d-md-inline-block"
>
<span
class="visually-hidden"
>
Helm chart
</span>
<button
aria-hidden="true"
aria-label="Filter by Helm chart repository kind"
class="btn btn-link m-0 p-0"
data-testid="repoIconLabelLink"
tabindex="-1"
>
<span
class="badge bg-light text-dark rounded-pill border bg badge"
>
<div
class="d-flex flex-row align-items-center"
>
<div
aria-hidden="true"
class="position-relative icon undefined"
>
<img
alt="Icon"
class="mw-100 mh-100 iconLight"
src="/static/media/helm-chart.svg"
/>
<img
alt="Icon"
class="mw-100 mh-100 iconDark"
src="/static/media/helm-chart-light.svg"
/>
</div>
<div
class="ms-1"
>
Helm chart
</div>
</div>
</span>
</button>
</div>
<div
class="d-flex d-md-none fs-6"
>
<span
class="badge bg-light text-dark rounded-pill border bg badge"
>
<div
class="d-flex flex-row align-items-center"
>
<div
aria-hidden="true"
class="position-relative icon undefined"
>
<img
alt="Icon"
class="mw-100 mh-100 iconLight"
src="/static/media/helm-chart.svg"
/>
<img
alt="Icon"
class="mw-100 mh-100 iconDark"
src="/static/media/helm-chart-light.svg"
/>
</div>
<div
class="ms-1"
>
Helm chart
</div>
</div>
</span>
</div>
</div>
<div
class="mt-1"
>
<small
class="text-muted text-nowrap date"
>
Updated Invalid date
</small>
</div>
</div>
</div>
</div>
<div
class="mb-0 mb-md-1 mt-3 overflow-hidden description text-truncate"
>
desc
</div>
<div
class="d-none d-xxl-block d-xxxl-none text-end mt-2"
>
<small
class="text-muted text-nowrap date"
>
Updated Invalid date
</small>
</div>
<div
class="d-flex d-md-none d-xxl-none flex-row flex-wrap justify-content-between align-items-center mt-auto pt-2 pt-md-0 mt-1 mt-md-0 mt-xxl-1 mt-xxxl-0"
>
<small
class="text-muted text-nowrap date"
>
Updated Invalid date
</small>
<span>
<div
class="align-self-start d-flex align-items-center text-uppercase ms-auto kind"
>
<div
class="d-none d-md-inline-block"
>
<span
class="visually-hidden"
>
Helm chart
</span>
<button
aria-hidden="true"
aria-label="Filter by Helm chart repository kind"
class="btn btn-link m-0 p-0"
data-testid="repoIconLabelLink"
tabindex="-1"
>
<span
class="badge bg-light text-dark rounded-pill border bg badge"
>
<div
class="d-flex flex-row align-items-center"
>
<div
aria-hidden="true"
class="position-relative icon undefined"
>
<img
alt="Icon"
class="mw-100 mh-100 iconLight"
src="/static/media/helm-chart.svg"
/>
<img
alt="Icon"
class="mw-100 mh-100 iconDark"
src="/static/media/helm-chart-light.svg"
/>
</div>
<div
class="ms-1"
>
Helm chart
</div>
</div>
</span>
</button>
</div>
<div
class="d-flex d-md-none fs-6"
>
<span
class="badge bg-light text-dark rounded-pill border bg badge"
>
<div
class="d-flex flex-row align-items-center"
>
<div
aria-hidden="true"
class="position-relative icon undefined"
>
<img
alt="Icon"
class="mw-100 mh-100 iconLight"
src="/static/media/helm-chart.svg"
/>
<img
alt="Icon"
class="mw-100 mh-100 iconDark"
src="/static/media/helm-chart-light.svg"
/>
</div>
<div
class="ms-1"
>
Helm chart
</div>
</div>
</span>
</div>
</div>
</span>
</div>
<div
class="d-flex flex-wrap justify-content-lg-end mt-0 mt-md-auto labelsWrapper"
/>
</div>
</a>
</div>
</div>
</DocumentFragment>
`;

File diff suppressed because it is too large Load Diff

View File

@ -36,7 +36,7 @@ exports[`SearchTip creates snapshot 1`] = `
</span>
to refine your search. Example:
<a
class="fw-bold textLighter p-0"
class="fw-semibold textLighter p-0"
href="/packages/search?ts_query_web=kafka+operator&sort=relevance&page=1"
>
kafka operator

View File

@ -10,7 +10,7 @@ exports[`Home index creates snapshot 1`] = `
>
<div
aria-label="Find, install and publisher Kubernetes packages"
class="display-4 text-center fw-light d-block d-xxl-flex justify-content-center noFocus mainTitle"
class="display-4 text-center d-block d-xxl-flex justify-content-center noFocus mainTitle"
id="content"
role="banner"
tabindex="-1"
@ -106,7 +106,7 @@ exports[`Home index creates snapshot 1`] = `
type="button"
/>
<div
class="position-absolute text-dark tipIcon bigTipIcon"
class="d-none d-sm-block position-absolute text-dark tipIcon bigTipIcon"
>
<button
aria-label="Open search tips modal"
@ -136,7 +136,7 @@ exports[`Home index creates snapshot 1`] = `
- or -
<a
aria-label="Browse all packages"
class="btn btn-link textLighter fw-bold py-0 pb-1 ps-1 allPkgBtn"
class="btn btn-link textLighter fw-semibold py-0 pb-1 ps-1 allPkgBtn"
href="/packages/search"
>
browse all packages
@ -148,7 +148,7 @@ exports[`Home index creates snapshot 1`] = `
Or you can also
<a
aria-label="Browse all packages"
class="btn btn-link textLighter fw-bold py-0 pb-1 ps-1 pe-0"
class="btn btn-link textLighter fw-semibold py-0 pb-1 ps-1 pe-0"
href="/packages/search"
>
browse all packages
@ -206,9 +206,11 @@ exports[`Home index creates snapshot 1`] = `
class="text-center h5 my-4 mt-md-5 legend"
>
Artifact Hub is an
<b>
<span
class="fw-semibold"
>
Open Source
</b>
</span>
project
</div>
<div
@ -308,7 +310,7 @@ exports[`Home index creates snapshot 1`] = `
Please see the
<a
aria-label="Open documentation"
class="link btn btn-link text-light fw-bold textLight p-0 align-baseline inlineLink"
class="link btn btn-link text-light fw-semibold textLight p-0 align-baseline inlineLink"
href="/docs/topics/repositories"
rel="noopener noreferrer"
role="button"
@ -604,6 +606,9 @@ exports[`Home index creates snapshot 1`] = `
<div
class="mx-0 mx-md-3 mx-lg-5 my-4 my-sm-5 d-flex flex-row align-items-stretch justify-content-around"
>
<div
class="col"
/>
<a
aria-label="Open Container Initiative site"
class="link col iconLink"
@ -682,6 +687,9 @@ exports[`Home index creates snapshot 1`] = `
</div>
</div>
</a>
<div
class="col"
/>
</div>
Discovering artifacts to use with CNCF projects can be difficult. If every CNCF project that needs to share artifacts creates its own Hub this creates a fair amount of repeat work for each project and a fractured experience for those trying to find the artifacts to consume. The Artifact Hub attempts to solve that by providing a single experience for consumers that any CNCF project can leverage.
</div>
@ -707,7 +715,7 @@ exports[`Home index creates snapshot 1`] = `
Artifact Hub is a
<a
aria-label="Open CNCF sandbox projects site"
class="link fw-bold text-dark"
class="link fw-semibold text-dark"
href="https://www.cncf.io/sandbox-projects/"
rel="noopener noreferrer"
role="button"

View File

@ -4,6 +4,7 @@ import { FaGithub, FaSlack, FaTwitter } from 'react-icons/fa';
import { Link, useHistory } from 'react-router-dom';
import API from '../../api';
import useBreakpointDetect from '../../hooks/useBreakpointDetect';
import { Banner as IBanner, RepositoryKind, Stats } from '../../types';
import alertDispatcher from '../../utils/alertDispatcher';
import bannerDispatcher from '../../utils/bannerDispatcher';
@ -34,6 +35,7 @@ interface Props {
}
const HomeView = (props: Props) => {
const point = useBreakpointDetect();
const history = useHistory();
const sampleQueries = getSampleQueries();
const [isLoadingStats, setIsLoadingStats] = useState(false);
@ -88,7 +90,7 @@ const HomeView = (props: Props) => {
<div
role="banner"
aria-label="Find, install and publisher Kubernetes packages"
className={`display-4 text-center fw-light d-block d-xxl-flex justify-content-center noFocus ${styles.mainTitle}`}
className={`display-4 text-center d-block d-xxl-flex justify-content-center noFocus ${styles.mainTitle}`}
id="content"
tabIndex={-1}
>
@ -111,7 +113,7 @@ const HomeView = (props: Props) => {
<div className="d-inline-block d-md-none text-center mt-3">
- or -
<Link
className={`btn btn-link textLighter fw-bold py-0 pb-1 ps-1 ${styles.allPkgBtn}`}
className={`btn btn-link textLighter fw-semibold py-0 pb-1 ps-1 ${styles.allPkgBtn}`}
to={{
pathname: '/packages/search',
}}
@ -124,7 +126,7 @@ const HomeView = (props: Props) => {
<div className="d-none d-md-inline-block text-center mt-5">
{sampleQueries.length > 0 ? <>You can also </> : <>Or you can also </>}
<Link
className="btn btn-link textLighter fw-bold py-0 pb-1 ps-1 pe-0"
className="btn btn-link textLighter fw-semibold py-0 pb-1 ps-1 pe-0"
to={{
pathname: '/packages/search',
}}
@ -142,7 +144,7 @@ const HomeView = (props: Props) => {
</div>
<div className="d-none d-md-flex flex-row align-items-end justify-content-center flex-wrap">
<SampleQueries lineBreakIn={3} className="bg-secondary border-light" />
<SampleQueries lineBreakIn={3} className="bg-secondary" />
</div>
</div>
@ -158,14 +160,14 @@ const HomeView = (props: Props) => {
wrapperClassName="d-inline-block position-relative mt-4 mt-md-5"
banner={banner}
removeBanner={() => setBanner(null)}
maxEqualRatio
maxEqualRatio={point !== 'xs'}
/>
)}
{!whiteLabel && (
<>
<div className={`text-center h5 my-4 mt-md-5 ${styles.legend}`}>
Artifact Hub is an <b>Open Source</b> project
Artifact Hub is an <span className="fw-semibold">Open Source</span> project
</div>
<div className="d-flex flex-row align-items-center justify-content-center flex-wrap">
@ -206,7 +208,7 @@ const HomeView = (props: Props) => {
<div className={`text-center mx-3 mt-md-4 mb-4 fw-light ${styles.repoGuideText}`}>
Please see the{' '}
<ExternalLink
className={`btn btn-link text-light fw-bold textLight p-0 align-baseline ${styles.inlineLink}`}
className={`btn btn-link text-light fw-semibold textLight p-0 align-baseline ${styles.inlineLink}`}
href="/docs/topics/repositories"
label="Open documentation"
>
@ -335,6 +337,7 @@ const HomeView = (props: Props) => {
</ExternalLink>
</div>
<div className="mx-0 mx-md-3 mx-lg-5 my-4 my-sm-5 d-flex flex-row align-items-stretch justify-content-around">
<div className="col" />
<ExternalLink
href="https://opencontainers.org"
className={`col ${styles.iconLink}`}
@ -371,6 +374,7 @@ const HomeView = (props: Props) => {
</div>
</div>
</ExternalLink>
<div className="col" />
</div>
Discovering artifacts to use with CNCF projects can be difficult. If every CNCF project that needs to
share artifacts creates its own Hub this creates a fair amount of repeat work for each project and a
@ -392,7 +396,7 @@ const HomeView = (props: Props) => {
Artifact Hub is a{' '}
<ExternalLink
href="https://www.cncf.io/sandbox-projects/"
className="fw-bold text-dark"
className="fw-semibold text-dark"
label="Open CNCF sandbox projects site"
>
Cloud Native Computing Foundation

View File

@ -29,7 +29,7 @@ const Footer = (props: Props) => {
className={`d-flex flex-row flex-wrap align-items-stretch justify-content-between ${styles.footerContent}`}
>
<div>
<div className="h6 fw-bold text-uppercase">Project</div>
<div className="h6 fw-semibold text-uppercase">Project</div>
<div className="d-flex flex-column text-start">
<ExternalLink
className={`mb-1 ${styles.link}`}
@ -58,7 +58,7 @@ const Footer = (props: Props) => {
</div>
<div>
<div className="h6 fw-bold text-uppercase">Community</div>
<div className="h6 fw-semibold text-uppercase">Community</div>
<div className="d-flex flex-column text-start">
<ExternalLink
className={`mb-1 ${styles.link}`}
@ -94,7 +94,7 @@ const Footer = (props: Props) => {
</div>
<div className={styles.fullMobileSection}>
<div className="h6 fw-bold text-uppercase">About</div>
<div className="h6 fw-semibold text-uppercase">About</div>
<div className={styles.copyrightContent}>
Artifact Hub is an <b className="d-inline-block">Open Source</b> project licensed under the{' '}
<ExternalLink

View File

@ -5,6 +5,8 @@
.iconWrapper {
width: 2rem;
height: 2rem;
border-width: 2px;
font-size: 1.75rem;
}
.profileImage {

View File

@ -59,7 +59,7 @@ const MobileSettings = (props: Props) => {
buttonIcon={
<div
className={classnames(
'rounded-circle d-flex align-items-center justify-content-center lh-1 fs-3 bg-white',
'rounded-circle d-flex align-items-center justify-content-center lh-1 bg-white',
styles.iconWrapper
)}
>

View File

@ -66,3 +66,10 @@
opacity: 0.5;
}
}
@media only screen and (max-width: 767.98px) {
.search {
max-width: 100%;
width: 100%;
}
}

View File

@ -45,12 +45,12 @@ const Navbar = (props: Props) => {
return (
<>
<nav
className={classnames('navbar navbar-top navbar-expand-lg navbar-dark border-top-0 p-3', styles.navbar, {
className={classnames('navbar navbar-top navbar-expand-lg navbar-dark border-top-0 p-2 p-sm-3', styles.navbar, {
[`bg-transparent w-100 position-absolute ${styles.homeNavbar}`]: props.fromHome,
})}
>
<div className="container-lg px-sm-4 px-lg-0">
<div className={`d-flex flex-row ${styles.mobileWrapper}`}>
<div className="container-lg px-0 px-sm-4 px-lg-0">
<div className={`d-flex flex-row px-1 ${styles.mobileWrapper}`}>
<Link data-testid="brandLink" className="navbar-brand d-flex align-items-center" to="/">
<div className="d-flex align-items-start">
<img className={`w-auto ${styles.logo}`} src={logo} alt={`Logo ${siteName}`} />
@ -67,7 +67,7 @@ const Navbar = (props: Props) => {
{isUndefined(props.fromHome) && (
<SearchBar
size="normal"
formClassName={`mx-2 me-md-auto my-3 my-md-0 flex-grow-1 pe-4 ${styles.search}`}
formClassName={`mx-2 me-md-auto my-3 my-md-0 flex-grow-1 pe-0 pe-sm-4 ${styles.search}`}
isSearching={props.isSearching}
tsQueryWeb={props.searchText}
openTips={openTips}

View File

@ -3,3 +3,7 @@
background-color: var(--color-2-500);
font-size: 0.875rem;
}
.navbar label {
font-size: 0.8rem;
}

View File

@ -7,7 +7,7 @@ interface Props {
const SubNavbar = (props: Props) => (
<nav className={`navbar navbar-expand-sm ${styles.navbar} ${props.className}`} role="navigation">
<div className="container-lg px-sm-4 px-lg-0 d-flex align-items-center justify-content-between flex-nowrap">
<div className="container-lg px-1 px-sm-4 px-lg-0 d-flex align-items-center justify-content-between flex-nowrap">
{props.children}
</div>
</nav>

View File

@ -17,7 +17,7 @@ exports[`Footer creates snapshot 1`] = `
>
<div>
<div
class="h6 fw-bold text-uppercase"
class="h6 fw-semibold text-uppercase"
>
Project
</div>
@ -56,7 +56,7 @@ exports[`Footer creates snapshot 1`] = `
</div>
<div>
<div
class="h6 fw-bold text-uppercase"
class="h6 fw-semibold text-uppercase"
>
Community
</div>
@ -156,7 +156,7 @@ exports[`Footer creates snapshot 1`] = `
class="fullMobileSection"
>
<div
class="h6 fw-bold text-uppercase"
class="h6 fw-semibold text-uppercase"
>
About
</div>

View File

@ -19,7 +19,7 @@ exports[`MobileSettings creates snapshot 1`] = `
class="d-flex align-items-center justify-content-center"
>
<div
class="rounded-circle d-flex align-items-center justify-content-center lh-1 fs-3 bg-white iconWrapper"
class="rounded-circle d-flex align-items-center justify-content-center lh-1 bg-white iconWrapper"
>
<svg
fill="currentColor"

View File

@ -3,13 +3,13 @@
exports[`Navbar creates snapshot 1`] = `
<DocumentFragment>
<nav
class="navbar navbar-top navbar-expand-lg navbar-dark border-top-0 p-3 navbar bg-transparent w-100 position-absolute homeNavbar"
class="navbar navbar-top navbar-expand-lg navbar-dark border-top-0 p-2 p-sm-3 navbar bg-transparent w-100 position-absolute homeNavbar"
>
<div
class="container-lg px-sm-4 px-lg-0"
class="container-lg px-0 px-sm-4 px-lg-0"
>
<div
class="d-flex flex-row mobileWrapper"
class="d-flex flex-row px-1 mobileWrapper"
>
<a
class="navbar-brand d-flex align-items-center"

View File

@ -7,7 +7,7 @@ exports[`SubNavbar creates snapshot 1`] = `
role="navigation"
>
<div
class="container-lg px-sm-4 px-lg-0 d-flex align-items-center justify-content-between flex-nowrap"
class="container-lg px-1 px-sm-4 px-lg-0 d-flex align-items-center justify-content-between flex-nowrap"
>
<div
data-testid="children"

View File

@ -1,7 +1,3 @@
.content {
background-color: var(--bs-light);
}
.icon {
font-size: 4rem;
}

Some files were not shown because too many files have changed in this diff Show More