UNPKG

@roadiehq/backstage-plugin-jira

Version:
204 lines (201 loc) 6.83 kB
import React, { useState, useEffect, useCallback } from 'react'; import { Typography, Card, Grid, Link, Avatar } from '@material-ui/core'; import 'xml-js'; import 'luxon'; import 'uuid'; import '@backstage/core-plugin-api'; import 'react-use'; import '../../../api/index.esm.js'; import { useUserInfo } from '../../../hooks/useUserInfo.esm.js'; import Skeleton from '@material-ui/lab/Skeleton'; import { DndProvider } from 'react-dnd'; import { HTML5Backend } from 'react-dnd-html5-backend'; import DraggableCard from '../../DraggableCard.esm.js'; import { makeStyles } from '@material-ui/core/styles'; const useStyles = makeStyles((theme) => ({ container: { overflowY: "auto", maxHeight: "100%" }, title: { fontWeight: Number(theme.typography.fontWeightBold), color: "darkgray" }, link: { color: theme.palette.text.primary, "&:hover": { color: "#539bf5", fill: "#539bf5" }, "&:first-child": { paddingRight: "4px" } }, secondaryText: { color: theme.palette.text.secondary } })); const JiraTicketSkeleton = () => { return /* @__PURE__ */ React.createElement( Skeleton, { variant: "rect", style: { fontSize: "5rem", borderRadius: "8px", margin: 3 } } ); }; const JiraTicketsSkeletonView = () => { return /* @__PURE__ */ React.createElement("div", null, Array.from({ length: 5 }).map(() => /* @__PURE__ */ React.createElement(JiraTicketSkeleton, null))); }; const JiraTicketCard = ({ user, ticket, index, moveCard }) => { const classes = useStyles(); return /* @__PURE__ */ React.createElement( DraggableCard, { key: ticket.key, id: ticket.key, index, moveCard }, /* @__PURE__ */ React.createElement(Card, { style: { marginBottom: "1em", padding: "1em" } }, /* @__PURE__ */ React.createElement(Grid, { container: true, spacing: 2 }, /* @__PURE__ */ React.createElement( Grid, { container: true, direction: "row", alignItems: "center", justifyContent: "space-between" }, /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Typography, { variant: "body2", className: classes.title }, /* @__PURE__ */ React.createElement( "img", { src: ticket?.issuetype?.iconUrl, alt: ticket?.issuetype?.name, title: ticket?.issuetype?.name, width: "15px", style: { marginRight: "5px", marginBottom: "-3px" } } ), ticket.parent ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement( Link, { href: `${user?.url}/browse/${ticket?.parent}`, target: "_blank", rel: "noopener noreferrer", underline: "none", className: `${classes.secondaryText} ${classes.link}` }, ticket.parent ), " / ", /* @__PURE__ */ React.createElement( Link, { href: `${user?.url}/browse/${ticket?.key}`, target: "_blank", rel: "noopener noreferrer", underline: "none", className: `${classes.secondaryText} ${classes.link}` }, ticket.key )) : /* @__PURE__ */ React.createElement( Link, { href: `${user?.url}/browse/${ticket?.key}`, target: "_blank", rel: "noopener noreferrer", underline: "none", className: `${classes.secondaryText} ${classes.link}` }, ticket.key ), /* @__PURE__ */ React.createElement( "span", { style: { display: "inline-flex", alignItems: "center", marginLeft: "5px" } }, /* @__PURE__ */ React.createElement( "img", { src: ticket?.priority?.iconUrl, alt: ticket?.priority?.name, title: ticket?.priority?.name, width: "15px", style: { marginRight: "5px" } } ), /* @__PURE__ */ React.createElement(Typography, { style: { fontSize: "1rem" } }, ticket?.priority?.name) ))), /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Typography, { variant: "body2", color: "textSecondary" }, /* @__PURE__ */ React.createElement( "img", { src: ticket?.status?.iconUrl, alt: ticket?.status?.name, title: ticket?.status?.name, width: "15px", style: { marginRight: "5px" } } ), ticket?.status?.name)) ), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, ticket.summary)), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(Grid, { container: true, direction: "row", alignItems: "center" }, ticket.assignee && /* @__PURE__ */ React.createElement( Avatar, { src: ticket.assignee.avatarUrl, style: { width: "30px", height: "30px" } } ), /* @__PURE__ */ React.createElement( Typography, { variant: "body2", style: { marginLeft: "8px" }, className: classes.secondaryText }, ticket.assignee ? ticket.assignee.displayName : "Unassigned" ))))) ); }; const JiraTicketsListView = ({ user, tickets }) => { const [cards, setCards] = useState(tickets || []); useEffect(() => { setCards(tickets || []); }, [tickets]); const moveCard = useCallback( (dragIndex, hoverIndex) => { const dragCard = cards[dragIndex]; const updatedCards = [...cards]; updatedCards.splice(dragIndex, 1); updatedCards.splice(hoverIndex, 0, dragCard); setCards(updatedCards); }, [cards] ); return /* @__PURE__ */ React.createElement(DndProvider, { backend: HTML5Backend }, cards.map((ticket, index) => /* @__PURE__ */ React.createElement( JiraTicketCard, { user, ticket, index, moveCard } ))); }; const Content = (props) => { const { userId } = props; const { user, loading, error, tickets } = useUserInfo(userId); if (loading) return /* @__PURE__ */ React.createElement(JiraTicketsSkeletonView, null); if (error) { return /* @__PURE__ */ React.createElement(Typography, null, "Error loading tickets: ", error.message); } if (!user) { return /* @__PURE__ */ React.createElement(Typography, null, "User not found"); } if (!tickets || tickets.length === 0) { return /* @__PURE__ */ React.createElement(Typography, null, "No tickets to show"); } return /* @__PURE__ */ React.createElement(JiraTicketsListView, { user, tickets }); }; export { Content }; //# sourceMappingURL=Content.esm.js.map