Skip to content

Commit

Permalink
feat: create crate detail page (#98)
Browse files Browse the repository at this point in the history
* chore: update libraries

* feat: create crate detail page
  • Loading branch information
Gumichocopengin8 authored Aug 14, 2023
1 parent 52e65f9 commit dd9f9b5
Show file tree
Hide file tree
Showing 9 changed files with 456 additions and 445 deletions.
1 change: 0 additions & 1 deletion api/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ async fn get_crate_recent_downloads(path: web::Path<String>) -> HttpResponse {
async fn fetch_crate(crate_name: &str) -> Result<crates_io_api::CrateResponse> {
// Retrieve download data.
let data = generate_async_client()?.get_crate(crate_name).await?;
print!("sdf {crate_name}");
let val = serde_json::to_value(data)?;
let full_crate: crates_io_api::CrateResponse = serde_json::from_value(val)?;
Ok(full_crate)
Expand Down
709 changes: 296 additions & 413 deletions web/package-lock.json

Large diffs are not rendered by default.

31 changes: 16 additions & 15 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,33 +15,34 @@
"dependencies": {
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@mui/icons-material": "^5.14.1",
"@mui/material": "^5.14.1",
"@mui/icons-material": "^5.14.3",
"@mui/material": "^5.14.4",
"axios": "^1.4.0",
"dayjs": "^1.11.9",
"echarts": "^5.4.3",
"next": "^13.2.4",
"pretty-bytes": "^6.1.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.45.2",
"recoil": "^0.7.7",
"wasm-pack": "^0.12.1"
"react-hook-form": "^7.45.4",
"recoil": "^0.7.7"
},
"devDependencies": {
"@playwright/test": "^1.36.1",
"@types/node": "^20.4.2",
"@types/react": "^18.2.15",
"@playwright/test": "^1.37.0",
"@types/node": "^20.5.0",
"@types/react": "^18.2.20",
"@typescript-eslint/eslint-plugin": "^5.59.11",
"@typescript-eslint/parser": "^5.59.11",
"eslint": "^8.45.0",
"eslint-config-next": "^13.4.10",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-react": "^7.32.2",
"eslint": "^8.47.0",
"eslint-config-next": "^13.4.13",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-react": "^7.33.1",
"eslint-plugin-react-hooks": "^4.6.0",
"husky": "^8.0.3",
"lint-staged": "^13.2.3",
"prettier": "^3.0.0",
"typescript": "^5.1.6"
"lint-staged": "^14.0.0",
"prettier": "^3.0.1",
"typescript": "^5.1.6",
"wasm-pack": "^0.12.1"
},
"husky": {
"hooks": {
Expand Down
45 changes: 29 additions & 16 deletions web/src/components/[crate_names]/CrateTableRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,10 @@ import { useState } from 'react';
import dayjs from 'dayjs';
import { useRouter } from 'next/router';
import { css } from '@emotion/react';
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
Collapse,
Box,
Typography,
IconButton,
Link,
} from '@mui/material';
import Link from 'next/link';
import { Table, TableBody, TableCell, TableHead, TableRow, Collapse, Box, Typography, IconButton } from '@mui/material';
import GitHubIcon from '@mui/icons-material/GitHub';
import LaunchIcon from '@mui/icons-material/Launch';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
import DescriptionIcon from '@mui/icons-material/Description';
Expand Down Expand Up @@ -61,7 +52,7 @@ const CrateTableRow = ({ crateData }: Props): JSX.Element => {
</TableCell>
<TableCell component="th" scope="row">
<Typography variant="subtitle1" component="h2">
<Link href={`https://crates.io/crates/${crateData.crate.name}`} rel="noreferrer">
<Link css={Anchor} href={`/details/${crateData.crate.name}`}>
{crateData.crate.name}
</Link>
</Typography>
Expand All @@ -72,7 +63,7 @@ const CrateTableRow = ({ crateData }: Props): JSX.Element => {
<TableCell align="right">{dateFormat(crateData.crate.created_at)}</TableCell>
<TableCell align="center">
{crateData.crate.documentation ? (
<Link href={crateData.crate.documentation} rel="noreferrer">
<Link css={Anchor} href={crateData.crate.documentation} target="_blank" rel="noreferrer">
<DescriptionIcon />
</Link>
) : (
Expand All @@ -81,16 +72,30 @@ const CrateTableRow = ({ crateData }: Props): JSX.Element => {
</TableCell>
<TableCell align="center">
{crateData.crate.homepage ? (
<Link href={crateData.crate.homepage} rel="noreferrer">
<Link css={Anchor} href={crateData.crate.homepage} target="_blank" rel="noreferrer">
<HomeIcon />
</Link>
) : (
'-'
)}
</TableCell>
<TableCell align="center">
{crateData.crate.homepage ? (
<Link
css={Anchor}
href={`https://crates.io/crates/${crateData.crate.name}`}
target="_blank"
rel="noreferrer"
>
<LaunchIcon />
</Link>
) : (
'-'
)}
</TableCell>
<TableCell align="center">
{crateData.crate.repository ? (
<Link color="inherit" href={crateData.crate.repository} rel="noreferrer">
<Link css={AnchorGitHub} color="inherit" href={crateData.crate.repository} target="_blank" rel="noreferrer">
<GitHubIcon />
</Link>
) : (
Expand Down Expand Up @@ -159,4 +164,12 @@ const RootTableRow = css`
}
`;

const Anchor = css`
color: #1976d2;
`;

const AnchorGitHub = css`
color: inherit;
`;

export default CrateTableRow;
61 changes: 61 additions & 0 deletions web/src/components/details/[crate_name]/CrateSizeChart.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import ReactECharts from 'components/echarts/ReactEChart';
import { Version } from 'interfaces/crate';
import { css } from '@emotion/react';
import prettyBytes from 'pretty-bytes';
import type { EChartsOption } from 'echarts';
import { Typography } from '@mui/material';
import { useMemo } from 'react';

interface Props {
versionList: Version[];
}

const CrateSizeChart = ({ versionList }: Props): JSX.Element => {
const option: EChartsOption = useMemo(() => {
return {
tooltip: {
trigger: 'axis',
axisPointer: { type: 'shadow' },
valueFormatter: (val) => prettyBytes(Number(val)),
},
xAxis: {
type: 'category',
data: versionList.map((version) => version.num),
},
yAxis: {
type: 'value',
axisLabel: {
formatter: (val) => prettyBytes(Number(val)),
},
},
series: [
{
data: versionList.map((version) => version?.crate_size ?? 0),
type: 'bar',
},
],
dataZoom: [
{ realtime: true, show: true, type: 'slider' },
{ realtime: true, show: true, type: 'inside', zoomLock: true },
],
};
}, [versionList]);

return (
<div>
<div css={SizeChart}>
<Typography variant="h6" component="h3" gutterBottom>
Crate Size Transition
</Typography>
<ReactECharts option={option} />
</div>
</div>
);
};

const SizeChart = css`
width: 100%;
height: 45vh;
`;

export default CrateSizeChart;
37 changes: 37 additions & 0 deletions web/src/components/shared/CrateDetailView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { useRouter } from 'next/router';
import { css } from '@emotion/react';
import { useRecoilValue } from 'recoil';
import { crateDataResultsState } from 'recoil/atoms';
import CrateSizeChart from 'components/details/[crate_name]/CrateSizeChart';
import { Typography } from '@mui/material';

const CrateDetailView = (): JSX.Element => {
const router = useRouter();
const { crate_name } = router.query;
const crateNameList = crate_name ? [crate_name.toString()] : [];
const crateDataResult = useRecoilValue(crateDataResultsState(crateNameList));

return (
<>
<div css={Wrapper}>
<div>
{crateDataResult.map((crate) => (
<div key={crate.crate.id}>
<Typography variant="h5" component="h2" gutterBottom>
{crate.crate.name}
</Typography>
<Typography variant="body1">{crate.crate.description}</Typography>
<CrateSizeChart versionList={[...crate.versions].reverse()} />
</div>
))}
</div>
</div>
</>
);
};

const Wrapper = css`
flex: 1;
`;

export default CrateDetailView;
1 change: 1 addition & 0 deletions web/src/components/shared/table/StatsTableHead.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const StatsTableHead = () => {
<TableCell align="right">Created At</TableCell>
<TableCell align="center">Doc</TableCell>
<TableCell align="center">Homepage</TableCell>
<TableCell align="center">Crates.io</TableCell>
<TableCell align="center">Repo</TableCell>
<TableCell />
</TableRow>
Expand Down
3 changes: 3 additions & 0 deletions web/src/components/skelton/table/TableSkeltonRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ const TableSkeltonRow = () => {
<TableCell>
<Skeleton height={32} />
</TableCell>
<TableCell>
<Skeleton height={32} />
</TableCell>
<TableCell>
<IconButton size="small" disabled>
<CloseIcon fontSize="small" />
Expand Down
13 changes: 13 additions & 0 deletions web/src/pages/details/[crate_name].tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';
import CrateDetailView from 'components/shared/CrateDetailView';
import Spinner from 'components/shared/Spinner';

const CrateDetailPage = (): JSX.Element => {
return (
<React.Suspense fallback={<Spinner />}>
<CrateDetailView />
</React.Suspense>
);
};

export default CrateDetailPage;

0 comments on commit dd9f9b5

Please sign in to comment.