splitted up component to separate files
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
List,
|
||||
ListSubheader,
|
||||
ListItem,
|
||||
ListItemIcon,
|
||||
ListItemSecondaryAction,
|
||||
Tooltip,
|
||||
ListItemText,
|
||||
makeStyles,
|
||||
IconButton,
|
||||
} from '@material-ui/core';
|
||||
import UserIcon from '@material-ui/icons/Person';
|
||||
import EmailIcon from '@material-ui/icons/Email';
|
||||
import { StatusWarning } from '@backstage/core';
|
||||
import Pagerduty from './pd.svg';
|
||||
import { PagerDutyUserData } from './types';
|
||||
|
||||
const useStyles = makeStyles({
|
||||
denseListIcon: {
|
||||
marginRight: 0,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
svgButtonImage: {
|
||||
height: '1em',
|
||||
},
|
||||
});
|
||||
|
||||
type EscalationUserProps = {
|
||||
user: PagerDutyUserData;
|
||||
};
|
||||
|
||||
const EscalationUser = ({ user }: EscalationUserProps) => {
|
||||
const classes = useStyles();
|
||||
return (
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<UserIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={user.name} secondary={user.email} />
|
||||
<ListItemSecondaryAction>
|
||||
<Tooltip title="Send e-mail to user" placement="left">
|
||||
<IconButton href={`mailto:${user.email}`}>
|
||||
<EmailIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="View in PagerDuty" placement="left">
|
||||
<IconButton
|
||||
href={user.homepageUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<img
|
||||
src={Pagerduty}
|
||||
alt="View in PagerDuty"
|
||||
className={classes.svgButtonImage}
|
||||
/>
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</ListItemSecondaryAction>
|
||||
</ListItem>
|
||||
);
|
||||
};
|
||||
|
||||
const EscalationUsersEmptyState = () => {
|
||||
const classes = useStyles();
|
||||
return (
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<div className={classes.denseListIcon}>
|
||||
<StatusWarning />
|
||||
</div>
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Empty escalation policy" />
|
||||
</ListItem>
|
||||
);
|
||||
};
|
||||
|
||||
type EscalationPolicyProps = {
|
||||
escalation: PagerDutyUserData[];
|
||||
};
|
||||
|
||||
export const EscalationPolicy = ({ escalation }: EscalationPolicyProps) => (
|
||||
<List dense subheader={<ListSubheader>Escalation Policy</ListSubheader>}>
|
||||
{escalation.length ? (
|
||||
escalation.map((user, index) => (
|
||||
<EscalationUser key={user.id + index} user={user} />
|
||||
))
|
||||
) : (
|
||||
<EscalationUsersEmptyState />
|
||||
)}
|
||||
</List>
|
||||
);
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
List,
|
||||
ListItem,
|
||||
ListItemIcon,
|
||||
ListItemSecondaryAction,
|
||||
Tooltip,
|
||||
ListItemText,
|
||||
makeStyles,
|
||||
IconButton,
|
||||
ListSubheader,
|
||||
} from '@material-ui/core';
|
||||
import { StatusError, StatusWarning, StatusOK } from '@backstage/core';
|
||||
import Pagerduty from './pd.svg';
|
||||
import moment from 'moment';
|
||||
|
||||
const useStyles = makeStyles({
|
||||
denseListIcon: {
|
||||
marginRight: 0,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
svgButtonImage: {
|
||||
height: '1em',
|
||||
},
|
||||
});
|
||||
|
||||
const IncidentsEmptyState = () => {
|
||||
const classes = useStyles();
|
||||
return (
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<div className={classes.denseListIcon}>
|
||||
<StatusOK />
|
||||
</div>
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="No incidents" secondary="All clear!" />
|
||||
</ListItem>
|
||||
);
|
||||
};
|
||||
|
||||
type IncidentListProps = {
|
||||
incidents: any;
|
||||
};
|
||||
|
||||
const IncidentList = ({ incidents }: IncidentListProps) => {
|
||||
const classes = useStyles();
|
||||
return incidents.map((incident: any) => (
|
||||
<ListItem key={incident.id}>
|
||||
<ListItemIcon>
|
||||
<Tooltip title={incident.status} placement="top">
|
||||
<div className={classes.denseListIcon}>
|
||||
{incident.status === 'triggered' ? (
|
||||
<StatusError />
|
||||
) : (
|
||||
<StatusWarning />
|
||||
)}
|
||||
</div>
|
||||
</Tooltip>
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={incident.title}
|
||||
secondary={
|
||||
<span style={{ wordBreak: 'break-all', whiteSpace: 'normal' }}>
|
||||
Created {moment(incident.createdAt).fromNow()}, assigned to{' '}
|
||||
{(incident.assignees.length && incident.assignees[0].name) ||
|
||||
'nobody'}
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
<ListItemSecondaryAction>
|
||||
<Tooltip title="View in PagerDuty" placement="left">
|
||||
<IconButton
|
||||
href={incident.homepageUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<img
|
||||
src={Pagerduty}
|
||||
alt="View in PagerDuty"
|
||||
className={classes.svgButtonImage}
|
||||
/>
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</ListItemSecondaryAction>
|
||||
</ListItem>
|
||||
));
|
||||
};
|
||||
|
||||
type IncidentsProps = {
|
||||
incidents: Array<any>;
|
||||
};
|
||||
|
||||
export const Incidents = ({ incidents }: IncidentsProps) => (
|
||||
<List dense subheader={<ListSubheader>Incidents</ListSubheader>}>
|
||||
{incidents.length ? (
|
||||
<IncidentList incidents={incidents} />
|
||||
) : (
|
||||
<IncidentsEmptyState />
|
||||
)}
|
||||
</List>
|
||||
);
|
||||
@@ -14,237 +14,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import {
|
||||
InfoCard,
|
||||
StatusError,
|
||||
StatusWarning,
|
||||
StatusOK,
|
||||
} from '@backstage/core';
|
||||
import { InfoCard, MissingAnnotationEmptyState } from '@backstage/core';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import {
|
||||
List,
|
||||
ListSubheader,
|
||||
ListItem,
|
||||
ListItemIcon,
|
||||
ListItemSecondaryAction,
|
||||
Tooltip,
|
||||
ListItemText,
|
||||
makeStyles,
|
||||
IconButton,
|
||||
} from '@material-ui/core';
|
||||
import moment from 'moment';
|
||||
import Pagerduty from './pd.svg';
|
||||
import UserIcon from '@material-ui/icons/Person';
|
||||
import EmailIcon from '@material-ui/icons/Email';
|
||||
import { Grid, Button } from '@material-ui/core';
|
||||
import { Incidents } from './Incidents';
|
||||
import { EscalationPolicy } from './Escalation';
|
||||
import { PagerDutyData } from './types';
|
||||
|
||||
const useStyles = makeStyles({
|
||||
buttonContainer: {},
|
||||
denseListIcon: {
|
||||
marginRight: 0,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
svgButtonImage: {
|
||||
height: '1em',
|
||||
},
|
||||
});
|
||||
const PAGERDUTY_INTEGRATION_KEY = 'pagerduty.com/integration-key';
|
||||
|
||||
type IncidentListProps = {
|
||||
incidents: any;
|
||||
};
|
||||
|
||||
const IncidentList = ({ incidents }: IncidentListProps) => {
|
||||
const classes = useStyles();
|
||||
return incidents.map((incident: any) => (
|
||||
<ListItem key={incident.id}>
|
||||
<ListItemIcon>
|
||||
<Tooltip title={incident.status} placement="top">
|
||||
<div className={classes.denseListIcon}>
|
||||
{incident.status === 'triggered' ? (
|
||||
<StatusError />
|
||||
) : (
|
||||
<StatusWarning />
|
||||
)}
|
||||
</div>
|
||||
</Tooltip>
|
||||
</ListItemIcon>
|
||||
<ListItemText
|
||||
primary={incident.title}
|
||||
secondary={
|
||||
<span style={{ wordBreak: 'break-all', whiteSpace: 'normal' }}>
|
||||
Created {moment(incident.createdAt).fromNow()}, assigned to{' '}
|
||||
{(incident.assignees.length && incident.assignees[0].name) ||
|
||||
'nobody'}
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
<ListItemSecondaryAction>
|
||||
<Tooltip title="View in PagerDuty" placement="left">
|
||||
<IconButton
|
||||
href={incident.homepageUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<img
|
||||
src={Pagerduty}
|
||||
alt="View in PagerDuty"
|
||||
className={classes.svgButtonImage}
|
||||
/>
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</ListItemSecondaryAction>
|
||||
</ListItem>
|
||||
));
|
||||
};
|
||||
|
||||
const IncidentsEmptyState = () => {
|
||||
const classes = useStyles();
|
||||
return (
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<div className={classes.denseListIcon}>
|
||||
<StatusOK />
|
||||
</div>
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="No incidents" secondary="All clear!" />
|
||||
</ListItem>
|
||||
);
|
||||
};
|
||||
|
||||
type IncidentsProps = {
|
||||
incidents: Array<any>;
|
||||
};
|
||||
export const Incidents = ({ incidents }: IncidentsProps) => (
|
||||
<List dense subheader={<ListSubheader>Incidents</ListSubheader>}>
|
||||
{incidents.length ? (
|
||||
<IncidentList incidents={incidents} />
|
||||
) : (
|
||||
<IncidentsEmptyState />
|
||||
)}
|
||||
</List>
|
||||
);
|
||||
|
||||
type EscalationProps = {
|
||||
escalation: PagerDutyUserData[];
|
||||
};
|
||||
|
||||
const EscalationUsers = ({ escalation }: EscalationProps) => {
|
||||
const classes = useStyles();
|
||||
const escalations = escalation.map((user, index) => (
|
||||
<ListItem key={user.id + index}>
|
||||
<ListItemIcon>
|
||||
<UserIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={user.name} secondary={user.email} />
|
||||
<ListItemSecondaryAction>
|
||||
<Tooltip title="Send e-mail to user" placement="left">
|
||||
<IconButton href={`mailto:${user.email}`}>
|
||||
<EmailIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="View in PagerDuty" placement="left">
|
||||
<IconButton
|
||||
href={user.homepageUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<img
|
||||
src={Pagerduty}
|
||||
alt="View in PagerDuty"
|
||||
className={classes.svgButtonImage}
|
||||
/>
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</ListItemSecondaryAction>
|
||||
</ListItem>
|
||||
));
|
||||
return <div>{escalations}</div>;
|
||||
};
|
||||
|
||||
const EscalationUsersEmptyState = () => {
|
||||
const classes = useStyles();
|
||||
return (
|
||||
<ListItem>
|
||||
<ListItemIcon>
|
||||
<div className={classes.denseListIcon}>
|
||||
<StatusWarning />
|
||||
</div>
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Empty escalation policy" />
|
||||
</ListItem>
|
||||
);
|
||||
};
|
||||
|
||||
const EscalationPolicy = ({ escalation }: EscalationProps) => (
|
||||
<List dense subheader={<ListSubheader>Escalation Policy</ListSubheader>}>
|
||||
{escalation.length ? (
|
||||
<EscalationUsers escalation={escalation} />
|
||||
) : (
|
||||
<EscalationUsersEmptyState />
|
||||
)}
|
||||
</List>
|
||||
);
|
||||
|
||||
type CardBodyProps = {
|
||||
entity: Entity;
|
||||
data: PagerDutyData;
|
||||
};
|
||||
|
||||
const CardBody = ({ entity, data }: CardBodyProps) => {
|
||||
const { pagerDutyServices } = data;
|
||||
const classes = useStyles();
|
||||
|
||||
if (!pagerDutyServices.length) {
|
||||
return (
|
||||
<div>
|
||||
'The specified PagerDuty integration key does not match any PagerDuty
|
||||
service.'
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const { activeIncidents, escalationPolicy } = pagerDutyServices[0];
|
||||
|
||||
return (
|
||||
<>
|
||||
<Incidents key="1" incidents={activeIncidents} />
|
||||
<EscalationPolicy key="2" escalation={escalationPolicy} />
|
||||
<div key="3" className={classes.buttonContainer}>
|
||||
{/* <TriggerButton component={entity} /> */}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
type PagerDutyIncident = {
|
||||
id: string;
|
||||
title: string;
|
||||
status: string;
|
||||
createdAt: string;
|
||||
homepageUrl: string;
|
||||
assignees: Partial<PagerDutyUserData>[];
|
||||
};
|
||||
|
||||
type PagerDutyUserData = {
|
||||
email: string;
|
||||
name: string;
|
||||
homepageUrl: string;
|
||||
id: string;
|
||||
};
|
||||
|
||||
type PagerDutyServicesData = {
|
||||
activeIncidents: PagerDutyIncident[];
|
||||
escalationPolicy: PagerDutyUserData[];
|
||||
id: string;
|
||||
name: string;
|
||||
homepageUrl: string;
|
||||
};
|
||||
|
||||
type PagerDutyData = {
|
||||
pagerDutyServices: PagerDutyServicesData[];
|
||||
};
|
||||
export const isPluginApplicableToEntity = (entity: Entity) =>
|
||||
Boolean(entity.metadata.annotations?.[PAGERDUTY_INTEGRATION_KEY]);
|
||||
|
||||
type Props = {
|
||||
entity: Entity;
|
||||
@@ -284,11 +64,20 @@ export const PagerDutyServiceCard = ({ entity }: Props) => {
|
||||
],
|
||||
};
|
||||
|
||||
return (
|
||||
const { activeIncidents, escalationPolicy } = mockData.pagerDutyServices[0];
|
||||
|
||||
return isPluginApplicableToEntity(entity) ? (
|
||||
<MissingAnnotationEmptyState annotation={PAGERDUTY_INTEGRATION_KEY} />
|
||||
) : (
|
||||
<InfoCard title="PagerDuty">
|
||||
<CardBody entity={entity} data={mockData} />
|
||||
<Incidents incidents={activeIncidents} />
|
||||
<EscalationPolicy escalation={escalationPolicy} />
|
||||
<Grid container item xs={12} justify="flex-end">
|
||||
{/* <TriggerButton component={entity} /> */}
|
||||
<Button variant="contained" color="primary">
|
||||
Trigger Alarm
|
||||
</Button>
|
||||
</Grid>
|
||||
</InfoCard>
|
||||
);
|
||||
};
|
||||
|
||||
export const isPluginApplicableToEntity = (entity: Entity) => true;
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
export type PagerDutyIncident = {
|
||||
id: string;
|
||||
title: string;
|
||||
status: string;
|
||||
createdAt: string;
|
||||
homepageUrl: string;
|
||||
assignees: Partial<PagerDutyUserData>[];
|
||||
};
|
||||
|
||||
export type PagerDutyUserData = {
|
||||
email: string;
|
||||
name: string;
|
||||
homepageUrl: string;
|
||||
id: string;
|
||||
};
|
||||
|
||||
export type PagerDutyServicesData = {
|
||||
activeIncidents: PagerDutyIncident[];
|
||||
escalationPolicy: any; // PagerDutyUserData[];
|
||||
id: string;
|
||||
name: string;
|
||||
homepageUrl: string;
|
||||
};
|
||||
|
||||
export type PagerDutyData = {
|
||||
pagerDutyServices: PagerDutyServicesData[];
|
||||
};
|
||||
Reference in New Issue
Block a user