Skip to content

Commit

Permalink
Update repository page UI (#34)
Browse files Browse the repository at this point in the history
  • Loading branch information
m-mizutani authored Dec 7, 2021
1 parent 8959780 commit d0969b2
Show file tree
Hide file tree
Showing 10 changed files with 567 additions and 152 deletions.
140 changes: 140 additions & 0 deletions assets/components/pages/repository/label.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import React from "react";
import { Grid, Alert, Typography } from "@mui/material";
import Stack from "@mui/material/Stack";

import List from "@mui/material/List";
import ListItem from "@mui/material/ListItem";
import ListItemButton from "@mui/material/ListItemButton";
import ListItemIcon from "@mui/material/ListItemIcon";
import ListItemText from "@mui/material/ListItemText";
import Checkbox from "@mui/material/Checkbox";

import * as model from "@/components/model";
import * as ui from "@/components/ui";

export default RepoLabels;

function RepoLabels(props: { repo: model.repository }) {
type labelsStatus = {
isLoaded: boolean;
labels?: model.repoLabel[];
err?: any;
};

const [status, setStatus] = React.useState<labelsStatus>({
isLoaded: false,
});

const get = () => {
fetch(`/api/v1/repo-label`)
.then((res) => res.json())
.then(
(result) => {
console.log("labels:", { result });
if (result.error) {
setStatus({ isLoaded: true, err: result.error });
} else {
setStatus({
isLoaded: true,
labels: result.data,
});
}
},
(error) => {
console.log("got error:", { error });
setStatus({
isLoaded: true,
err: error.message,
});
}
);
};
React.useEffect(get, []);

if (!status.isLoaded) {
return <Alert severity="info">Loading...</Alert>;
} else if (status.err) {
return <Alert severity="error">{status.err}</Alert>;
}

return (
<List sx={{ width: "100%", maxWidth: 560, bgcolor: "background.paper" }}>
{status.labels.map((label) => {
return <RepoLabel repo={props.repo} label={label} key={label.name} />;
})}
</List>
);
}

function RepoLabel(props: { repo: model.repository; label: model.repoLabel }) {
const initChecked = props.repo.edges.labels
? props.repo.edges.labels.filter((label) => {
return label.id === props.label.id;
}).length > 0
: false;

const [status, setStatus] = React.useState<{
done: boolean;
err?: any;
}>({ done: false });
const [checked, setChecked] = React.useState<boolean>(initChecked);

const update = (value: boolean) => {
const method = value ? "POST" : "DELETE";
const url = `/api/v1/repo-label/${props.label.id}/assign/${props.repo.id}`;

fetch(url, { method })
.then((res) => res.json())
.then(
(result) => {
console.log({ result });
setChecked(value);
setStatus({ done: true });
},
(error) => {
console.log("error:", { error });
setStatus({ done: true, err: error });
}
);
};

return (
<ListItem
secondaryAction={
status.done ? (
status.err ? (
<Alert security="error">{status.err}</Alert>
) : (
<Alert security="success">Updated</Alert>
)
) : (
<></>
)
}
disablePadding>
<ListItemButton
onClick={() => {
setStatus({ done: false });
update(!checked);
}}
dense>
<ListItemIcon>
<Checkbox
edge="start"
checked={checked}
tabIndex={-1}
disableRipple
/>
</ListItemIcon>
<ListItemText
primary={
<Stack direction="row" spacing={2}>
<ui.RepoLabel label={props.label} />
<Typography paddingTop={1}>{props.label.description}</Typography>
</Stack>
}
/>
</ListItemButton>
</ListItem>
);
}
156 changes: 18 additions & 138 deletions assets/components/pages/repository/repository.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
import React from "react";
import { Grid, Alert, Typography } from "@mui/material";
import GitHubIcon from "@mui/icons-material/GitHub";
import Stack from "@mui/material/Stack";

import List from "@mui/material/List";
import ListItem from "@mui/material/ListItem";
import ListItemButton from "@mui/material/ListItemButton";
import ListItemIcon from "@mui/material/ListItemIcon";
import ListItemText from "@mui/material/ListItemText";
import Checkbox from "@mui/material/Checkbox";

import * as app from "@/components/app";
import * as model from "@/components/model";
import * as ui from "@/components/ui";

import Labels from "./label";
import Scans from "./scan";
import VulnStatuses from "./vulnStatus";

export default function Repository(props: { owner: string; repo: string }) {
type repoStatus = {
Expand Down Expand Up @@ -62,10 +57,20 @@ export default function Repository(props: { owner: string; repo: string }) {
}

return (
<Grid marginTop={5}>
<Typography variant="h5">Labels</Typography>
<RepoLabels repo={status.repository} />
</Grid>
<>
<Grid marginTop={5}>
<Typography variant="h5">Recent scan reports</Typography>
<Scans repo={status.repository} />
</Grid>
<Grid marginTop={5}>
<Typography variant="h5">Status</Typography>
<VulnStatuses repo={status.repository} />
</Grid>
<Grid marginTop={5}>
<Typography variant="h5">Labels</Typography>
<Labels repo={status.repository} />
</Grid>
</>
);
};

Expand All @@ -82,128 +87,3 @@ export default function Repository(props: { owner: string; repo: string }) {
</app.Main>
);
}

function RepoLabels(props: { repo: model.repository }) {
type labelsStatus = {
isLoaded: boolean;
labels?: model.repoLabel[];
err?: any;
};

const [status, setStatus] = React.useState<labelsStatus>({
isLoaded: false,
});

const get = () => {
fetch(`/api/v1/repo-label`)
.then((res) => res.json())
.then(
(result) => {
console.log("labels:", { result });
if (result.error) {
setStatus({ isLoaded: true, err: result.error });
} else {
setStatus({
isLoaded: true,
labels: result.data,
});
}
},
(error) => {
console.log("got error:", { error });
setStatus({
isLoaded: true,
err: error.message,
});
}
);
};
React.useEffect(get, []);

if (!status.isLoaded) {
return <Alert severity="info">Loading...</Alert>;
} else if (status.err) {
return <Alert severity="error">{status.err}</Alert>;
}

return (
<List sx={{ width: "100%", maxWidth: 560, bgcolor: "background.paper" }}>
{status.labels.map((label) => {
return <RepoLabel repo={props.repo} label={label} key={label.name} />;
})}
</List>
);
}

function RepoLabel(props: { repo: model.repository; label: model.repoLabel }) {
const initChecked = props.repo.edges.labels
? props.repo.edges.labels.filter((label) => {
return label.id === props.label.id;
}).length > 0
: false;

const [status, setStatus] = React.useState<{
done: boolean;
err?: any;
}>({ done: false });
const [checked, setChecked] = React.useState<boolean>(initChecked);

const update = (value: boolean) => {
const method = value ? "POST" : "DELETE";
const url = `/api/v1/repo-label/${props.label.id}/assign/${props.repo.id}`;

fetch(url, { method })
.then((res) => res.json())
.then(
(result) => {
console.log({ result });
setChecked(value);
setStatus({ done: true });
},
(error) => {
console.log("error:", { error });
setStatus({ done: true, err: error });
}
);
};

return (
<ListItem
secondaryAction={
status.done ? (
status.err ? (
<Alert security="error">{status.err}</Alert>
) : (
<Alert security="success">Updated</Alert>
)
) : (
<></>
)
}
disablePadding>
<ListItemButton
onClick={() => {
setStatus({ done: false });
update(!checked);
}}
dense>
<ListItemIcon>
<Checkbox
edge="start"
checked={checked}
tabIndex={-1}
disableRipple
/>
</ListItemIcon>
<ListItemText
primary={
<Stack direction="row" spacing={2}>
<ui.RepoLabel label={props.label} />
<Typography paddingTop={1}>{props.label.description}</Typography>
</Stack>
}
/>
</ListItemButton>
</ListItem>
);
}
Loading

0 comments on commit d0969b2

Please sign in to comment.