@roadiehq/backstage-plugin-jira
Version:
284 lines (281 loc) • 11.4 kB
JavaScript
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
import { useState, useEffect } from 'react';
import { makeStyles, createStyles, Box, IconButton, Menu, MenuItem, Checkbox, Button, Grid, Typography, Divider, TableContainer, Table, TableHead, TableRow, TableCell, TableBody, TablePagination, Avatar } from '@material-ui/core';
import Alert from '@material-ui/lab/Alert';
import { InfoCard, Progress } from '@backstage/core-components';
import { useEntity } from '@backstage/plugin-catalog-react';
import 'xml-js';
import 'luxon';
import 'uuid';
import { useAnalytics } from '@backstage/core-plugin-api';
import 'react-use';
import '../../api/index.esm.js';
import { useProjectInfo } from '../../hooks/useProjectInfo.esm.js';
import { useProjectEntity } from '../../hooks/useProjectEntity.esm.js';
import { Status } from './components/Status.esm.js';
import { ActivityStream } from '../EntityJiraActivityStreamCard/ActivityStream.esm.js';
import { Selectors } from './components/Selectors.esm.js';
import { useEmptyIssueTypeFilter } from '../../hooks/useEmptyIssueTypeFilter.esm.js';
import MoreVertIcon from '@material-ui/icons/MoreVert';
import ArrowForwardIcon from '@material-ui/icons/ArrowForward';
const useStyles = makeStyles(
(theme) => createStyles({
infoCard: {
marginBottom: theme.spacing(3),
"& + .MuiAlert-root": {
marginTop: theme.spacing(3)
}
},
root: {
flexGrow: 1,
fontSize: "0.75rem",
"& > * + *": {
marginTop: theme.spacing(1)
}
},
ticketLink: {
color: theme.palette.link,
textDecoration: "none",
transition: "color 0.3s",
"&:hover": {
color: theme.palette.linkHover
}
}
})
);
const CardProjectDetails = ({
project,
component
}) => /* @__PURE__ */ jsxs(Box, { display: "inline-flex", alignItems: "center", children: [
/* @__PURE__ */ jsx(Avatar, { alt: "", src: project.iconUrl }),
/* @__PURE__ */ jsxs(Box, { ml: 1, children: [
project.name,
" | ",
project.type,
component ? /* @__PURE__ */ jsxs(Box, { children: [
"component: ",
component
] }) : null
] })
] });
const JiraOverviewCard = (props) => {
const { hideIssueFilter } = props;
const { entity } = useEntity();
const classes = useStyles();
const analytics = useAnalytics();
const { projectKey, component, tokenType, label } = useProjectEntity(entity);
const [statusesNames, setStatusesNames] = useState([]);
const {
project,
issues,
tickets,
ticketIds,
projectLoading,
projectError,
fetchProjectInfo
} = useProjectInfo(projectKey, component, label, statusesNames);
const {
issueTypes: displayIssues,
type,
changeType
} = useEmptyIssueTypeFilter(issues);
const [anchorEl, setAnchorEl] = useState(null);
const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(5);
useEffect(() => {
setPage(0);
}, [tickets]);
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
return /* @__PURE__ */ jsxs(
InfoCard,
{
className: classes.infoCard,
title: "Jira",
subheader: project && /* @__PURE__ */ jsxs(
Box,
{
display: "flex",
justifyContent: "space-between",
width: "100%",
alignItems: "center",
children: [
/* @__PURE__ */ jsxs(Box, { children: [
/* @__PURE__ */ jsx(CardProjectDetails, { project, component }),
/* @__PURE__ */ jsxs(Box, { display: "inline-flex", pl: 1, children: [
/* @__PURE__ */ jsx(
IconButton,
{
"aria-label": "more",
"aria-controls": "long-menu",
"aria-haspopup": "true",
onClick: handleClick,
children: /* @__PURE__ */ jsx(MoreVertIcon, {})
}
),
/* @__PURE__ */ jsx(
Menu,
{
id: "simple-menu",
anchorEl,
keepMounted: true,
open: Boolean(anchorEl),
onClose: handleClose,
children: /* @__PURE__ */ jsxs(MenuItem, { onClick: changeType, children: [
/* @__PURE__ */ jsx(Checkbox, { checked: type === "all" }),
/* @__PURE__ */ jsx(Fragment, { children: "Show empty issue types" })
] })
}
)
] })
] }),
/* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(
Button,
{
variant: "outlined",
color: "primary",
size: "medium",
endIcon: /* @__PURE__ */ jsx(ArrowForwardIcon, {}),
href: `${project?.url}/browse/${projectKey}`,
target: "_blank",
children: "Open in JIRA"
}
) })
]
}
),
children: [
projectLoading && !(project && issues) ? /* @__PURE__ */ jsx(Progress, {}) : null,
projectError ? /* @__PURE__ */ jsx(Alert, { severity: "error", className: classes.infoCard, children: projectError.message }) : null,
project && issues ? /* @__PURE__ */ jsxs("div", { className: classes.root, children: [
!hideIssueFilter && /* @__PURE__ */ jsx(
Selectors,
{
projectKey,
statusesNames,
setStatusesNames,
fetchProjectInfo
}
),
/* @__PURE__ */ jsx(Grid, { container: true, spacing: 3, children: displayIssues?.map((issueType) => /* @__PURE__ */ jsx(Grid, { item: true, xs: true, children: /* @__PURE__ */ jsxs(
Box,
{
width: 100,
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
children: [
/* @__PURE__ */ jsx(Status, { name: issueType.name, iconUrl: issueType.iconUrl }),
/* @__PURE__ */ jsx(Typography, { variant: "h4", children: issueType.total })
]
}
) }, issueType.name)) }),
/* @__PURE__ */ jsx(Divider, {}),
/* @__PURE__ */ jsxs(TableContainer, { children: [
/* @__PURE__ */ jsxs(Table, { className: classes.infoCard, "aria-label": "tickets-table", children: [
/* @__PURE__ */ jsx(TableHead, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
/* @__PURE__ */ jsx(TableCell, { children: "Key" }),
/* @__PURE__ */ jsx(TableCell, { align: "left", children: "Summary" }),
/* @__PURE__ */ jsx(TableCell, { align: "left", children: "Priority" }),
/* @__PURE__ */ jsx(TableCell, { align: "left", children: "Status" }),
/* @__PURE__ */ jsx(TableCell, { align: "left", children: "Created" }),
/* @__PURE__ */ jsx(TableCell, { align: "left", children: "Updated" }),
/* @__PURE__ */ jsx(TableCell, { align: "left", children: "Assignee" })
] }) }),
/* @__PURE__ */ jsx(TableBody, { children: tickets && tickets.length > 0 ? tickets.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map((ticket) => /* @__PURE__ */ jsxs(TableRow, { children: [
/* @__PURE__ */ jsx(TableCell, { component: "th", children: /* @__PURE__ */ jsx(
"a",
{
href: `${project?.url}/browse/${ticket?.key}`,
target: "_blank",
rel: "noopener noreferrer",
className: classes.ticketLink,
children: ticket?.key
}
) }),
/* @__PURE__ */ jsx(TableCell, { align: "left", children: ticket?.summary }),
/* @__PURE__ */ jsx(TableCell, { align: "left", children: /* @__PURE__ */ jsx(
"img",
{
src: ticket?.priority?.iconUrl,
alt: ticket?.priority?.name,
title: ticket?.priority?.name,
width: "20px"
}
) }),
/* @__PURE__ */ jsx(TableCell, { align: "left", children: ticket?.status }),
/* @__PURE__ */ jsx(TableCell, { align: "left", children: new Date(ticket?.created).toLocaleDateString() }),
/* @__PURE__ */ jsx(TableCell, { align: "left", children: new Date(ticket?.updated).toLocaleDateString() }),
/* @__PURE__ */ jsx(
TableCell,
{
align: "left",
style: { display: "flex", alignItems: "center" },
children: ticket?.assignee?.displayName ? /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(
"img",
{
src: ticket?.assignee?.avatarUrl,
alt: ticket?.assignee?.displayName,
title: ticket?.assignee?.displayName,
style: { marginRight: "10px" },
width: "30px"
}
),
ticket?.assignee?.displayName
] }) : /* @__PURE__ */ jsx("span", { children: "Not Assigned" })
}
)
] }, ticket?.key)) : /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: 7, align: "center", children: "No Jira tickets available." }) }) })
] }),
/* @__PURE__ */ jsx(
TablePagination,
{
rowsPerPageOptions: [5, 10, 20],
component: "div",
count: tickets?.length ?? 0,
rowsPerPage,
page,
onPageChange: (_event, newPage) => {
setPage(newPage);
analytics.captureEvent(
"paginate",
`page: ${newPage}, size: ${rowsPerPage}`
);
},
onRowsPerPageChange: (event) => {
setRowsPerPage(parseInt(event.target.value, 10));
setPage(0);
analytics.captureEvent(
"paginate",
`page: 0, size: ${parseInt(event.target.value, 10)}`
);
}
}
)
] }),
/* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(Typography, { variant: "subtitle1", children: "Activity Stream" }),
/* @__PURE__ */ jsx(
ActivityStream,
{
projectKey,
tokenType,
componentName: component,
label,
ticketIds
}
)
] })
] }) : null
]
}
);
};
export { JiraOverviewCard };
//# sourceMappingURL=JiraOverviewCard.esm.js.map