Skip to content

Commit

Permalink
Group licenses detected in the same file (#126)
Browse files Browse the repository at this point in the history
Signed-off-by: Damian Stasik <[email protected]>
Co-authored-by: abstractionfactory <[email protected]>
  • Loading branch information
damianstasik and abstractionfactory authored Sep 4, 2024
1 parent eea8e73 commit 7b1da90
Show file tree
Hide file tree
Showing 9 changed files with 159 additions and 133 deletions.
12 changes: 10 additions & 2 deletions frontend/src/components/Icon/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,24 @@ interface IconProps {
viewBox?: string;
width?: number;
height?: number;
title?: string;
}

export function Icon({ path, className, width = 24, height = 24 }: IconProps) {
export function Icon({
title,
path,
className,
width = 24,
height = 24,
}: IconProps) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox={`0 0 ${width} ${height}`}
aria-hidden="true"
aria-hidden={title ? undefined : true}
className={className}
>
{title ? <title>{title}</title> : null}
<path fill="currentColor" d={path} />
</svg>
);
Expand Down
72 changes: 72 additions & 0 deletions frontend/src/components/LicenseSidebarBlock/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { SidebarBlock } from "../SidebarBlock";
import { Fragment, ReactNode } from "react";
import { definitions } from "@/api";
import { Icon } from "../Icon";
import { info } from "@/icons/info";

interface BlockProps {
license?: definitions["LicenseList"];
}

function LicenseSidebarBlockTitle() {
return (
<>
License
<Icon
title="License detection is best effort. Please see the linked license file for details."
path={info}
className="size-4 text-gray-700 hover:text-gray-900 dark:text-gray-300 dark:hover:text-gray-100"
/>
</>
);
}

export function LicenseSidebarBlock(props: BlockProps) {
let content: ReactNode;

if (props.license === undefined) {
content = <span className="flex h-em w-24 animate-pulse bg-gray-500/25" />;
} else if (props.license === null || props.license.length === 0) {
content = "None detected";
} else {
const sortedLicenses = [...props.license].sort(
(a, b) => b.confidence - a.confidence,
);

const groupedLicenses = Object.groupBy(
sortedLicenses,
(license) => license.link,
);

const licenses = Object.entries(groupedLicenses).map(([link, license]) => (
<li className="flex flex-col items-start gap-2" key={link}>
<a
href={link}
className="underline"
target="_blank"
rel="noreferrer noopener"
>
{license[0].file}
</a>
<span className="text-gray-800 dark:text-gray-300">
{license?.map((license, index, arr) => (
<Fragment key={license.spdx}>
{license.spdx}
{index < arr.length - 1 && ", "}
</Fragment>
))}
</span>
</li>
));

content = <ul className="flex flex-col gap-4">{licenses}</ul>;
}

return (
<SidebarBlock title={<LicenseSidebarBlockTitle />}>{content}</SidebarBlock>
);
}

export function LicenceSidebarBlockSkeleton() {
return <LicenseSidebarBlock />;
}
41 changes: 0 additions & 41 deletions frontend/src/components/MetadataSidebarBlock/index.tsx

This file was deleted.

77 changes: 0 additions & 77 deletions frontend/src/components/RepoMetadataSidebarBlock/index.tsx

This file was deleted.

38 changes: 38 additions & 0 deletions frontend/src/components/RepoSidebarBlock/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { SidebarBlock } from "../SidebarBlock";

function getLinkLabel(url: string) {
const match = url.match(/github\.com\/([^/]+)\/([^/]+)/);

if (!match) {
return null;
}

return `${match[1]}/${match[2]}`;
}

interface BlockProps {
link?: string | undefined;
}

export function RepoSidebarBlock(props: BlockProps) {
return (
<SidebarBlock title="Repository">
{props.link ? (
<a
href={props.link}
className="underline"
target="_blank"
rel="noreferrer noopener"
>
{getLinkLabel(props.link)}
</a>
) : (
<span className="flex h-em w-32 animate-pulse bg-gray-500/25" />
)}
</SidebarBlock>
);
}

export function RepoSidebarBlockSkeleton() {
return <RepoSidebarBlock />;
}
4 changes: 2 additions & 2 deletions frontend/src/components/SidebarBlock/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { ReactNode } from "react";

interface SidebarBlockProps {
title: string;
title: ReactNode;
children: ReactNode;
}

export function SidebarBlock({ title, children }: SidebarBlockProps) {
return (
<div className="px-4 py-4">
<h4 className="mb-4 font-sans text-xl font-semibold leading-none">
<h4 className="mb-4 flex items-center gap-2 font-sans text-xl font-semibold leading-none">
{title}
</h4>

Expand Down
23 changes: 18 additions & 5 deletions frontend/src/routes/Module/components/MetadataSidebarBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { getModuleVersionDataQuery } from "../query";
import { useModuleParams } from "../hooks/useModuleParams";

import {
RepoMetadataSidebarBlock,
RepoMetadataSidebarBlockSkeleton,
} from "@/components/RepoMetadataSidebarBlock";
RepoSidebarBlock,
RepoSidebarBlockSkeleton,
} from "@/components/RepoSidebarBlock";
import { LicenseSidebarBlock } from "@/components/LicenseSidebarBlock";

export function ModuleMetadataSidebarBlock() {
const { namespace, name, target, version } = useModuleParams();
Expand All @@ -14,7 +15,19 @@ export function ModuleMetadataSidebarBlock() {
getModuleVersionDataQuery(namespace, name, target, version),
);

return <RepoMetadataSidebarBlock license={data.licenses} link={data.link} />;
return (
<>
<LicenseSidebarBlock license={data.licenses} />
<RepoSidebarBlock link={data.link} />
</>
);
}

export { RepoMetadataSidebarBlockSkeleton as ModuleMetadataSidebarBlockSkeleton };
export function ModuleMetadataSidebarBlockSkeleton() {
return (
<>
<LicenseSidebarBlock />
<RepoSidebarBlockSkeleton />
</>
);
}
23 changes: 18 additions & 5 deletions frontend/src/routes/Provider/components/MetadataSidebarBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { getProviderVersionDataQuery } from "../query";
import { useProviderParams } from "../hooks/useProviderParams";

import {
RepoMetadataSidebarBlock,
RepoMetadataSidebarBlockSkeleton,
} from "@/components/RepoMetadataSidebarBlock";
RepoSidebarBlock,
RepoSidebarBlockSkeleton,
} from "@/components/RepoSidebarBlock";
import { LicenseSidebarBlock } from "@/components/LicenseSidebarBlock";

export function ProviderMetadataSidebarBlock() {
const { namespace, provider, version } = useProviderParams();
Expand All @@ -14,7 +15,19 @@ export function ProviderMetadataSidebarBlock() {
getProviderVersionDataQuery(namespace, provider, version),
);

return <RepoMetadataSidebarBlock license={data.license} link={data.link} />;
return (
<>
<LicenseSidebarBlock license={data.license} />
<RepoSidebarBlock link={data.link} />
</>
);
}

export { RepoMetadataSidebarBlockSkeleton as ProviderMetadataSidebarBlockSkeleton };
export function ProviderMetadataSidebarBlockSkeleton() {
return (
<>
<LicenseSidebarBlock />
<RepoSidebarBlockSkeleton />
</>
);
}
2 changes: 1 addition & 1 deletion frontend/tsconfig.app.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"lib": ["ESNext", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
"paths": {
Expand Down

0 comments on commit 7b1da90

Please sign in to comment.