fennec-fe/src/commits/commit-list.tsx

109 lines
3.4 KiB
TypeScript
Raw Normal View History

2021-05-09 15:29:11 +08:00
import { useQuery } from '@apollo/client';
import { faPlayCircle, faVial } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { CircularProgress, Collapse, IconButton, LinearProgress, List, ListItem, ListItemIcon, ListItemSecondaryAction, ListItemText, makeStyles, useTheme } from '@material-ui/core';
import { Cancel, CheckCircle, CloudDownload, ShoppingCart, Timer } from '@material-ui/icons';
import { format } from 'date-fns';
import React, { FC, Fragment, ReactNode, useState } from 'react';
import { Commit, Pipeline, PipelineTask, TaskStatuses } from '../generated/graphql';
import { COMMITS } from './queries';
interface Props {
pipeline: Pipeline;
}
const useStyles = makeStyles((theme) => ({
root: {
flex: "1 1 100%",
},
nested: {
paddingLeft: theme.spacing(4),
},
}));
export const CommitList: FC<Props> = ({pipeline}) => {
const { data, loading } = useQuery<{ commits: Commit[] }>(COMMITS, {
variables: {
pipelineId: pipeline.id,
},
});
const classes = useStyles();
return (
<section className={classes.root}>
{(() => {
if (loading) {
return <LinearProgress color="secondary" />;
}
return <List>
{data?.commits.map(commit => (
<Item key={commit.hash} commit={commit} />
))}
</List>;
})()}
</section>
)
}
const Item: FC<{commit: Commit}> = ({commit}) => {
const [isOpen, setOpen] = useState(() => false);
const classes = useStyles();
return (
<Fragment>
<ListItem button onClick={() => setOpen(!isOpen)}>
<ListItemText
primary={commit.message}
secondary={format(commit.date, "yyyy-MM-dd HH:mm:ss")}
/>
<ListItemSecondaryAction>
<IconButton edge="end" aria-label="delete">
<ShoppingCart />
</IconButton>
<IconButton edge="end" aria-label="delete">
<CloudDownload />
</IconButton>
<IconButton edge="end" aria-label="delete">
<FontAwesomeIcon icon={faVial} />
</IconButton>
<IconButton edge="end" aria-label="delete">
<FontAwesomeIcon icon={faPlayCircle} />
</IconButton>
</ListItemSecondaryAction>
</ListItem>
<Collapse in={isOpen} timeout="auto" unmountOnExit>
<List component="div" disablePadding>
{
commit.tasks.map(task => (<TaskItem key={task.id} task={task} />))
}
</List>
</Collapse>
</Fragment>
);
}
const TaskItem: FC<{task: PipelineTask}> = ({task}) => {
const classes = useStyles();
const theme = useTheme();
const statusIcon: ReactNode = (() => {
switch (task.status) {
case TaskStatuses.Pending:
return <Timer style={{ color: theme.palette.info.main }} />;
case TaskStatuses.Success:
return <CheckCircle style={{ color: theme.palette.success.main }} />;
case TaskStatuses.Failed:
return <Cancel style={{ color: theme.palette.error.main }} />;
case TaskStatuses.Working:
return <CircularProgress style={{ color: theme.palette.secondary.main }} />;
}
}
)()
return (
<ListItem button className={classes.nested}>
<ListItemIcon>{statusIcon}</ListItemIcon>
<ListItemText primary={format(task.startedAt, "yyyy-MM-dd HH:mm:ss")} />
</ListItem>
);
};