change UI bsed on UX
This commit is contained in:
@@ -29,8 +29,8 @@ import {
|
||||
import UserIcon from '@material-ui/icons/Person';
|
||||
import EmailIcon from '@material-ui/icons/Email';
|
||||
import { StatusWarning } from '@backstage/core';
|
||||
import Pagerduty from '../assets/pd.svg';
|
||||
import { Oncall, PagerDutyEscalationPolicy } from './types';
|
||||
import { Oncall } from './types';
|
||||
import PagerdutyIcon from './Pd';
|
||||
|
||||
const useStyles = makeStyles({
|
||||
denseListIcon: {
|
||||
@@ -45,7 +45,7 @@ const useStyles = makeStyles({
|
||||
},
|
||||
});
|
||||
|
||||
const EscalationUser = ({ user }: PagerDutyEscalationPolicy) => {
|
||||
const EscalationUser = ({ user }: Oncall) => {
|
||||
const classes = useStyles();
|
||||
return (
|
||||
<ListItem>
|
||||
@@ -56,7 +56,7 @@ const EscalationUser = ({ user }: PagerDutyEscalationPolicy) => {
|
||||
<ListItemSecondaryAction>
|
||||
<Tooltip title="Send e-mail to user" placement="left">
|
||||
<IconButton href={`mailto:${user.email}`}>
|
||||
<EmailIcon />
|
||||
<EmailIcon color="primary" />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="View in PagerDuty" placement="left">
|
||||
@@ -64,12 +64,9 @@ const EscalationUser = ({ user }: PagerDutyEscalationPolicy) => {
|
||||
href={user.html_url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
color="primary"
|
||||
>
|
||||
<img
|
||||
src={Pagerduty}
|
||||
alt="View in PagerDuty"
|
||||
className={classes.svgButtonImage}
|
||||
/>
|
||||
<PagerdutyIcon viewBox="0 0 100 100" />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</ListItemSecondaryAction>
|
||||
|
||||
@@ -25,11 +25,12 @@ import {
|
||||
makeStyles,
|
||||
IconButton,
|
||||
ListSubheader,
|
||||
Link,
|
||||
} from '@material-ui/core';
|
||||
import { StatusError, StatusWarning, StatusOK } from '@backstage/core';
|
||||
import Pagerduty from '../assets/pd.svg';
|
||||
import moment from 'moment';
|
||||
import { Incident } from '../components/types';
|
||||
import PagerdutyIcon from './Pd';
|
||||
|
||||
const useStyles = makeStyles({
|
||||
denseListIcon: {
|
||||
@@ -64,6 +65,7 @@ type IncidentListItemProps = {
|
||||
|
||||
const IncidentListItem = ({ incident }: IncidentListItemProps) => {
|
||||
const classes = useStyles();
|
||||
const user = incident.assignments[0].assignee;
|
||||
return (
|
||||
<ListItem key={incident.id}>
|
||||
<ListItemIcon>
|
||||
@@ -82,8 +84,9 @@ const IncidentListItem = ({ incident }: IncidentListItemProps) => {
|
||||
secondary={
|
||||
<span style={{ wordBreak: 'break-all', whiteSpace: 'normal' }}>
|
||||
Created {moment(incident.created_at).fromNow()}, assigned to{' '}
|
||||
{(incident?.assignments[0]?.assignee?.summary &&
|
||||
incident.assignments[0].assignee.summary) ||
|
||||
{(incident?.assignments[0]?.assignee?.summary && (
|
||||
<Link href={`mailto:${user.email}`}>{user.summary}</Link>
|
||||
)) ||
|
||||
'nobody'}
|
||||
</span>
|
||||
}
|
||||
@@ -91,15 +94,12 @@ const IncidentListItem = ({ incident }: IncidentListItemProps) => {
|
||||
<ListItemSecondaryAction>
|
||||
<Tooltip title="View in PagerDuty" placement="left">
|
||||
<IconButton
|
||||
href={incident.homepageUrl}
|
||||
href={user.html_url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
color="primary"
|
||||
>
|
||||
<img
|
||||
src={Pagerduty}
|
||||
alt="View in PagerDuty"
|
||||
className={classes.svgButtonImage}
|
||||
/>
|
||||
<PagerdutyIcon viewBox="0 0 100 100" />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</ListItemSecondaryAction>
|
||||
|
||||
@@ -14,15 +14,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { InfoCard, useApi } from '@backstage/core';
|
||||
import { useApi } from '@backstage/core';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { Grid, LinearProgress } from '@material-ui/core';
|
||||
import { LinearProgress } from '@material-ui/core';
|
||||
import { Incidents } from './Incidents';
|
||||
import { EscalationPolicy } from './Escalation';
|
||||
import { TriggerButton } from './TriggerButton';
|
||||
import { useAsync } from 'react-use';
|
||||
import { Alert } from '@material-ui/lab';
|
||||
import { pagerDutyApiRef } from '../api/pagerDutyClient';
|
||||
import { PagerdutyCard } from './PagerdutyCard';
|
||||
|
||||
export const PAGERDUTY_INTEGRATION_KEY = 'pagerduty.com/integration-key';
|
||||
|
||||
@@ -71,19 +72,26 @@ export const PagerDutyServiceCard = ({ entity }: Props) => {
|
||||
return <LinearProgress />;
|
||||
}
|
||||
|
||||
const link = {
|
||||
const pagerdutyLink = {
|
||||
title: 'View in PagerDuty',
|
||||
link: value!.homepageUrl,
|
||||
href: value!.homepageUrl,
|
||||
};
|
||||
|
||||
const triggerAlarm = {
|
||||
title: 'Trigger Alarm',
|
||||
action: <TriggerButton entity={entity} />,
|
||||
};
|
||||
|
||||
return (
|
||||
<InfoCard title="PagerDuty" deepLink={link}>
|
||||
<Incidents incidents={value!.incidents} />
|
||||
<EscalationPolicy escalation={value!.oncalls} />
|
||||
<Grid container item xs={12} justify="flex-end">
|
||||
<TriggerButton entity={entity} />
|
||||
</Grid>
|
||||
{/* todo show something when we dont have token */}
|
||||
</InfoCard>
|
||||
<PagerdutyCard
|
||||
title="Pagerduty"
|
||||
subheader={{ ViewPagerduty: pagerdutyLink, TriggerAlarm: triggerAlarm }}
|
||||
content={
|
||||
<>
|
||||
<Incidents incidents={value!.incidents} />
|
||||
<EscalationPolicy escalation={value!.oncalls} />
|
||||
</>
|
||||
}
|
||||
></PagerdutyCard>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
Card,
|
||||
CardHeader,
|
||||
CardContent,
|
||||
Divider,
|
||||
Link,
|
||||
makeStyles,
|
||||
} from '@material-ui/core';
|
||||
import LinkIcon from '@material-ui/icons/Link';
|
||||
import ReportProblemIcon from '@material-ui/icons/ReportProblem';
|
||||
import classnames from 'classnames';
|
||||
import Pagerduty from '../assets/pd.svg';
|
||||
import PagerdutyIcon from './Pd';
|
||||
|
||||
// TODO: create a general component to use it in pagerduty and aboutCard
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
links: {
|
||||
margin: theme.spacing(2, 0),
|
||||
display: 'grid',
|
||||
gridAutoFlow: 'column',
|
||||
gridAutoColumns: 'min-content',
|
||||
gridGap: theme.spacing(3),
|
||||
},
|
||||
link: {
|
||||
display: 'grid',
|
||||
justifyItems: 'center',
|
||||
gridGap: 4,
|
||||
textAlign: 'center',
|
||||
},
|
||||
label: {
|
||||
fontSize: '0.7rem',
|
||||
textTransform: 'uppercase',
|
||||
fontWeight: 600,
|
||||
letterSpacing: 1.2,
|
||||
},
|
||||
trigger: {
|
||||
color: theme.palette.secondary.main,
|
||||
},
|
||||
svgButtonImage: {
|
||||
height: '1.5em',
|
||||
color: theme.palette.primary.main,
|
||||
},
|
||||
}));
|
||||
|
||||
type SubHeaderProps = {
|
||||
ViewPagerduty: { title: string; href: string };
|
||||
TriggerAlarm: { title: string; action: React.ReactNode };
|
||||
};
|
||||
|
||||
type PagerdutyCardProps = {
|
||||
title: string;
|
||||
subheader: SubHeaderProps;
|
||||
content: React.ReactNode;
|
||||
};
|
||||
|
||||
type VerticalIconProps = {
|
||||
label: string;
|
||||
href?: string;
|
||||
action?: React.ReactNode;
|
||||
icon?: React.ReactNode;
|
||||
};
|
||||
|
||||
const VerticalIcon = ({
|
||||
label,
|
||||
href,
|
||||
icon = <LinkIcon />,
|
||||
action,
|
||||
}: VerticalIconProps) => {
|
||||
const classes = useStyles();
|
||||
if (action) {
|
||||
return (
|
||||
<>
|
||||
<Link className={classnames(classes.link, classes.trigger)} href={href}>
|
||||
{icon}
|
||||
{action}
|
||||
</Link>
|
||||
</>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Link className={classes.link} href={href}>
|
||||
{icon}
|
||||
<span className={classes.label}>{label}</span>
|
||||
</Link>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export const PagerdutyCard = ({
|
||||
title,
|
||||
subheader,
|
||||
content,
|
||||
}: PagerdutyCardProps) => {
|
||||
const classes = useStyles();
|
||||
const getSubheader = ({ ViewPagerduty, TriggerAlarm }: SubHeaderProps) => {
|
||||
return (
|
||||
<nav className={classes.links}>
|
||||
<VerticalIcon
|
||||
label={ViewPagerduty.title}
|
||||
href={ViewPagerduty.href}
|
||||
icon={
|
||||
// <LinkIcon />
|
||||
// <img
|
||||
// src={Pagerduty}
|
||||
// alt="View in PagerDuty"
|
||||
// className={classes.svgButtonImage}
|
||||
// />
|
||||
<PagerdutyIcon viewBox="0 0 100 100" />
|
||||
}
|
||||
></VerticalIcon>
|
||||
<VerticalIcon
|
||||
label={TriggerAlarm.title}
|
||||
icon={<ReportProblemIcon />}
|
||||
action={TriggerAlarm.action}
|
||||
></VerticalIcon>
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader
|
||||
title={title}
|
||||
subheader={getSubheader(subheader)}
|
||||
></CardHeader>
|
||||
<Divider />
|
||||
<CardContent>{content}</CardContent>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
// import React from 'react';
|
||||
// import SvgIcon, { SvgIconProps } from '@material-ui/core/SvgIcon';
|
||||
|
||||
// const SvgPd = (props: SvgIconProps) =>
|
||||
// React.createElement(
|
||||
// SvgIcon,
|
||||
// props,
|
||||
// <g fill="#7A7A7A" fillRule="nonzero">
|
||||
// <path d="M10.442 84.98H0V32.57c0-5.381 2.209-8.634 4.056-10.442 4.097-4.016 9.639-4.136 10.562-4.136h16.426c5.863 0 9.237 2.37 11.084 4.377 3.655 3.976 3.695 9.117 3.615 10.482v19.76c0 5.702-2.33 9.075-4.257 10.883-3.976 3.734-9.237 3.815-10.482 3.775H10.442v17.71zm20.963-28.193c.563 0 2.129-.16 2.972-.964.643-.602.964-1.687.964-3.253V32.289c0-.562-.12-2.048-.924-2.892-.763-.803-2.249-.963-3.373-.963H14.538c-4.096 0-4.096 3.092-4.096 4.136v24.217h20.963zM89.236.2h10.442v52.45c0 5.382-2.209 8.635-4.056 10.442-4.097 4.016-9.639 4.136-10.562 4.136H68.634c-5.863 0-9.237-2.369-11.084-4.377-3.655-3.976-3.695-9.116-3.615-10.482V32.65c0-5.702 2.33-9.076 4.257-10.883 3.976-3.735 9.237-3.815 10.482-3.775h20.562V.2zM68.273 28.435c-.563 0-2.129.16-2.972.963-.643.603-.964 1.687-.964 3.253v20.281c0 .563.12 2.049.924 2.892.763.803 2.249.964 3.373.964H85.14c4.137-.04 4.137-3.133 4.137-4.177V28.434H68.273z" />
|
||||
// </g>,
|
||||
// );
|
||||
|
||||
// export default SvgPd;
|
||||
|
||||
import React from 'react';
|
||||
import SvgIcon, { SvgIconProps } from '@material-ui/core/SvgIcon';
|
||||
|
||||
const SvgPd = (props: SvgIconProps) =>
|
||||
React.createElement(
|
||||
SvgIcon,
|
||||
props,
|
||||
<g fillRule="nonzero">
|
||||
<path d="M10.442 84.98H0V32.57c0-5.381 2.209-8.634 4.056-10.442 4.097-4.016 9.639-4.136 10.562-4.136h16.426c5.863 0 9.237 2.37 11.084 4.377 3.655 3.976 3.695 9.117 3.615 10.482v19.76c0 5.702-2.33 9.075-4.257 10.883-3.976 3.734-9.237 3.815-10.482 3.775H10.442v17.71zm20.963-28.193c.563 0 2.129-.16 2.972-.964.643-.602.964-1.687.964-3.253V32.289c0-.562-.12-2.048-.924-2.892-.763-.803-2.249-.963-3.373-.963H14.538c-4.096 0-4.096 3.092-4.096 4.136v24.217h20.963zM89.236.2h10.442v52.45c0 5.382-2.209 8.635-4.056 10.442-4.097 4.016-9.639 4.136-10.562 4.136H68.634c-5.863 0-9.237-2.369-11.084-4.377-3.655-3.976-3.695-9.116-3.615-10.482V32.65c0-5.702 2.33-9.076 4.257-10.883 3.976-3.735 9.237-3.815 10.482-3.775h20.562V.2zM68.273 28.435c-.563 0-2.129.16-2.972.963-.643.603-.964 1.687-.964 3.253v20.281c0 .563.12 2.049.924 2.892.763.803 2.249.964 3.373.964H85.14c4.137-.04 4.137-3.133 4.137-4.177V28.434H68.273z" />
|
||||
</g>,
|
||||
);
|
||||
|
||||
export default SvgPd;
|
||||
@@ -15,17 +15,34 @@
|
||||
*/
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { Button } from '@material-ui/core';
|
||||
import { Button, makeStyles } from '@material-ui/core';
|
||||
import { TriggerDialog } from './TriggerDialog';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { PAGERDUTY_INTEGRATION_KEY } from './PagerDutyServiceCard';
|
||||
|
||||
const useStyles = makeStyles({
|
||||
triggerAlarm: {
|
||||
paddingTop: 0,
|
||||
paddingBottom: 0,
|
||||
fontSize: '0.7rem',
|
||||
textTransform: 'uppercase',
|
||||
fontWeight: 600,
|
||||
letterSpacing: 1.2,
|
||||
lineHeight: 1.1,
|
||||
'&:hover, &:focus, &.focus': {
|
||||
backgroundColor: 'transparent',
|
||||
textDecoration: 'none',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
type Props = {
|
||||
entity: Entity;
|
||||
};
|
||||
|
||||
export const TriggerButton = ({ entity }: Props) => {
|
||||
const [showDialog, setShowDialog] = useState<boolean>(false);
|
||||
const classes = useStyles();
|
||||
|
||||
const handleDialog = () => {
|
||||
setShowDialog(!showDialog);
|
||||
@@ -34,12 +51,11 @@ export const TriggerButton = ({ entity }: Props) => {
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
size="small"
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
onClick={handleDialog}
|
||||
className={classes.triggerAlarm}
|
||||
>
|
||||
Trigger alarm
|
||||
Trigger Alarm
|
||||
</Button>
|
||||
{showDialog && (
|
||||
<TriggerDialog
|
||||
|
||||
@@ -103,6 +103,7 @@ export const TriggerDialog = ({ name, integrationKey, onClose }: Props) => {
|
||||
the issue and reach out to you if necessary.
|
||||
</p>
|
||||
<TextField
|
||||
inputProps={{ 'data-testid': 'trigger-input' }}
|
||||
id="description"
|
||||
multiline
|
||||
fullWidth
|
||||
@@ -114,6 +115,7 @@ export const TriggerDialog = ({ name, integrationKey, onClose }: Props) => {
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
data-testid="trigger-button"
|
||||
id="trigger"
|
||||
color="secondary"
|
||||
disabled={!description || loading}
|
||||
|
||||
@@ -32,7 +32,7 @@ export type Service = {
|
||||
name: string;
|
||||
html_url: string;
|
||||
integrationKey: string;
|
||||
escalation_policy: PagerDutyEscalationPolicy;
|
||||
escalation_policy: Oncall;
|
||||
};
|
||||
|
||||
export type ResponseService = {
|
||||
@@ -69,10 +69,6 @@ export type OncallsResponse = {
|
||||
oncalls: Oncall[];
|
||||
};
|
||||
|
||||
export type PagerDutyEscalationPolicy = {
|
||||
user: User;
|
||||
};
|
||||
|
||||
export type User = {
|
||||
id: string;
|
||||
summary: string;
|
||||
@@ -82,6 +78,5 @@ export type User = {
|
||||
};
|
||||
|
||||
export type Oncall = {
|
||||
escalation_policy: PagerDutyEscalationPolicy;
|
||||
user: User;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user