diff --git a/plugins/pagerduty/src/components/About/AboutCard.tsx b/plugins/pagerduty/src/components/About/AboutCard.tsx
new file mode 100644
index 0000000000..7d5419908a
--- /dev/null
+++ b/plugins/pagerduty/src/components/About/AboutCard.tsx
@@ -0,0 +1,33 @@
+/*
+ * 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 { Card, CardContent, CardHeader, Divider } from '@material-ui/core';
+import { SubHeader } from './SubHeader';
+import { SubHeaderLink } from '../types';
+
+type Props = {
+ title: string;
+ links: SubHeaderLink[];
+ content: React.ReactNode;
+};
+
+export const AboutCard = ({ title, links, content }: Props) => (
+
+ } />
+
+ {content}
+
+);
diff --git a/plugins/pagerduty/src/components/About/SubHeader.tsx b/plugins/pagerduty/src/components/About/SubHeader.tsx
new file mode 100644
index 0000000000..5e4ea96fe0
--- /dev/null
+++ b/plugins/pagerduty/src/components/About/SubHeader.tsx
@@ -0,0 +1,50 @@
+/*
+ * 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 { VerticalIcon } from './VerticalIcon';
+import { SubHeaderLink } from '../types';
+import { makeStyles } from '@material-ui/core';
+
+const useStyles = makeStyles(theme => ({
+ links: {
+ margin: theme.spacing(2, 0),
+ display: 'grid',
+ gridAutoFlow: 'column',
+ gridAutoColumns: 'min-content',
+ gridGap: theme.spacing(3),
+ },
+}));
+
+type Props = {
+ links: SubHeaderLink[];
+};
+
+export const SubHeader = ({ links }: Props) => {
+ const classes = useStyles();
+ return (
+
+ );
+};
diff --git a/plugins/pagerduty/src/components/About/VerticalIcon.tsx b/plugins/pagerduty/src/components/About/VerticalIcon.tsx
new file mode 100644
index 0000000000..5463372ac0
--- /dev/null
+++ b/plugins/pagerduty/src/components/About/VerticalIcon.tsx
@@ -0,0 +1,85 @@
+/*
+ * 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 classnames from 'classnames';
+import { makeStyles, Link } from '@material-ui/core';
+import LinkIcon from '@material-ui/icons/Link';
+import { Link as RouterLink } from 'react-router-dom';
+
+export type VerticalIconProps = {
+ icon?: React.ReactNode;
+ href?: string;
+ title?: string;
+ label: string;
+ action?: React.ReactNode;
+};
+
+const useIconStyles = makeStyles(theme => ({
+ link: {
+ display: 'grid',
+ justifyItems: 'center',
+ gridGap: 4,
+ textAlign: 'center',
+ },
+ label: {
+ fontSize: '0.7rem',
+ textTransform: 'uppercase',
+ fontWeight: 600,
+ letterSpacing: 1.2,
+ },
+ linkStyle: {
+ color: theme.palette.secondary.main,
+ },
+}));
+
+export function VerticalIcon({
+ icon = ,
+ href = '#',
+ action,
+ ...props
+}: VerticalIconProps) {
+ const classes = useIconStyles();
+
+ if (action) {
+ return (
+
+ {icon}
+ {action}
+
+ );
+ }
+
+ // Absolute links should not be using RouterLink
+ if (href?.startsWith('//') || href?.includes('://')) {
+ return (
+
+ {icon}
+ {props.label}
+
+ );
+ }
+
+ return (
+
+ {icon}
+ {props.label}
+
+ );
+}
diff --git a/plugins/pagerduty/src/components/About/index.ts b/plugins/pagerduty/src/components/About/index.ts
new file mode 100644
index 0000000000..4e495daa54
--- /dev/null
+++ b/plugins/pagerduty/src/components/About/index.ts
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+export { AboutCard } from './AboutCard';
+// export { SubHeader } from './SubHeader';
+// export { VerticalIcon } from './VerticalIcon';
diff --git a/plugins/pagerduty/src/components/Incident/Incidents.tsx b/plugins/pagerduty/src/components/Incident/Incidents.tsx
index 4b229fb4bc..732a582cdb 100644
--- a/plugins/pagerduty/src/components/Incident/Incidents.tsx
+++ b/plugins/pagerduty/src/components/Incident/Incidents.tsx
@@ -25,16 +25,14 @@ import { Alert } from '@material-ui/lab';
type Props = {
serviceId: string;
- refreshIncidents: Boolean;
+ refreshIncidents: boolean;
};
export const Incidents = ({ serviceId, refreshIncidents }: Props) => {
const api = useApi(pagerDutyApiRef);
const [{ value: incidents, loading, error }, getIncidents] = useAsyncFn(
- async () => {
- return await api.getIncidentsByServiceId(serviceId);
- },
+ async () => await api.getIncidentsByServiceId(serviceId),
);
useEffect(() => {
diff --git a/plugins/pagerduty/src/components/PagerDutyCard.test.tsx b/plugins/pagerduty/src/components/PagerDutyCard.test.tsx
index 34ddb63f71..a6615aee82 100644
--- a/plugins/pagerduty/src/components/PagerDutyCard.test.tsx
+++ b/plugins/pagerduty/src/components/PagerDutyCard.test.tsx
@@ -85,11 +85,9 @@ describe('PageDutyCard', () => {
),
);
await waitFor(() => !queryByTestId('progress'));
- expect(getByText('View in PagerDuty')).toBeInTheDocument();
- expect(getByText('Trigger Alarm')).toBeInTheDocument();
- expect(
- getByText('Nice! No incidents are assigned to you!'),
- ).toBeInTheDocument();
+ expect(getByText('Service Directory')).toBeInTheDocument();
+ expect(getByText('Create Incident')).toBeInTheDocument();
+ expect(getByText('Nice! No incidents found!')).toBeInTheDocument();
expect(getByText('Empty escalation policy')).toBeInTheDocument();
});
@@ -141,8 +139,8 @@ describe('PageDutyCard', () => {
),
);
await waitFor(() => !queryByTestId('progress'));
- expect(getByText('View in PagerDuty')).toBeInTheDocument();
- expect(getByText('Trigger Alarm')).toBeInTheDocument();
+ expect(getByText('Service Directory')).toBeInTheDocument();
+ expect(getByText('Create Incident')).toBeInTheDocument();
const triggerButton = getByTestId('trigger-button');
await act(async () => {
fireEvent.click(triggerButton);
diff --git a/plugins/pagerduty/src/components/PagerDutyCard.tsx b/plugins/pagerduty/src/components/PagerDutyCard.tsx
index ac309e8a95..8fd20f37e8 100644
--- a/plugins/pagerduty/src/components/PagerDutyCard.tsx
+++ b/plugins/pagerduty/src/components/PagerDutyCard.tsx
@@ -13,36 +13,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import React, { useState } from 'react';
+import React, { useState, useCallback } from 'react';
import { useApi, Progress } from '@backstage/core';
import { Entity } from '@backstage/catalog-model';
-import {
- Button,
- Card,
- CardContent,
- CardHeader,
- Divider,
- makeStyles,
-} from '@material-ui/core';
+import { Button, makeStyles } from '@material-ui/core';
import { Incidents } from './Incident';
import { EscalationPolicy } from './Escalation';
import { useAsync } from 'react-use';
import { Alert } from '@material-ui/lab';
import { pagerDutyApiRef, UnauthorizedError } from '../api';
-import { IconLinkVertical } from '@backstage/plugin-catalog';
-import { PagerDutyIcon } from './PagerDutyIcon';
import AlarmAddIcon from '@material-ui/icons/AlarmAdd';
import { TriggerDialog } from './TriggerDialog';
-import { MissingTokenError } from './MissingTokenError';
+import { MissingTokenError } from './Errors/MissingTokenError';
+import WebIcon from '@material-ui/icons/Web';
+import { AboutCard } from './About/AboutCard';
-const useStyles = makeStyles(theme => ({
- links: {
- margin: theme.spacing(2, 0),
- display: 'grid',
- gridAutoFlow: 'column',
- gridAutoColumns: 'min-content',
- gridGap: theme.spacing(3),
- },
+const useStyles = makeStyles({
triggerAlarm: {
paddingTop: 0,
paddingBottom: 0,
@@ -56,7 +42,7 @@ const useStyles = makeStyles(theme => ({
textDecoration: 'none',
},
},
-}));
+});
export const PAGERDUTY_INTEGRATION_KEY = 'pagerduty.com/integration-key';
@@ -76,6 +62,14 @@ export const PagerDutyCard = ({ entity }: Props) => {
PAGERDUTY_INTEGRATION_KEY
];
+ const handleRefresh = useCallback(() => {
+ setRefreshIncidents(x => !x);
+ }, []);
+
+ const handleDialog = useCallback(() => {
+ setShowDialog(x => !x);
+ }, []);
+
const { value: service, loading, error } = useAsync(async () => {
const services = await api.getServiceByIntegrationKey(integrationKey);
@@ -87,10 +81,6 @@ export const PagerDutyCard = ({ entity }: Props) => {
};
});
- const handleDialog = () => {
- setShowDialog(!showDialog);
- };
-
if (error instanceof UnauthorizedError) {
return ;
}
@@ -107,13 +97,14 @@ export const PagerDutyCard = ({ entity }: Props) => {
return ;
}
- const pagerdutyLink = {
- title: 'View in PagerDuty',
+ const serviceLink = {
+ title: 'Service Directory',
href: service!.url,
+ icon: ,
};
- const triggerAlarm = {
- title: 'Trigger Alarm',
+ const triggerLink = {
+ title: 'Create Incident',
action: (
),
- };
-
- const onTriggerRefresh = () => {
- setRefreshIncidents(true);
+ icon: ,
};
return (
-
-
- }
- />
- }
- action={triggerAlarm.action}
- />
-
- }
- />
-
-
-
-
-
-
-
+
+
+
+
+ >
+ }
+ />
);
};
diff --git a/plugins/pagerduty/src/components/TriggerDialog/TriggerDialog.test.tsx b/plugins/pagerduty/src/components/TriggerDialog/TriggerDialog.test.tsx
index 7ef57d67b4..8073ab44b5 100644
--- a/plugins/pagerduty/src/components/TriggerDialog/TriggerDialog.test.tsx
+++ b/plugins/pagerduty/src/components/TriggerDialog/TriggerDialog.test.tsx
@@ -70,7 +70,7 @@ describe('TriggerDialog', () => {
handleDialog={() => {}}
name={entity.metadata.name}
integrationKey="abc123"
- onTriggerRefresh={() => {}}
+ onIncidentCreated={() => {}}
/>
,
),
diff --git a/plugins/pagerduty/src/components/TriggerDialog/TriggerDialog.tsx b/plugins/pagerduty/src/components/TriggerDialog/TriggerDialog.tsx
index 4717b8fece..4fa88a1b9a 100644
--- a/plugins/pagerduty/src/components/TriggerDialog/TriggerDialog.tsx
+++ b/plugins/pagerduty/src/components/TriggerDialog/TriggerDialog.tsx
@@ -35,7 +35,7 @@ type Props = {
integrationKey: string;
showDialog: boolean;
handleDialog: () => void;
- onTriggerRefresh: () => void;
+ onIncidentCreated: () => void;
};
export const TriggerDialog = ({
@@ -43,7 +43,7 @@ export const TriggerDialog = ({
integrationKey,
showDialog,
handleDialog,
- onTriggerRefresh,
+ onIncidentCreated: onIncidentCreated,
}: Props) => {
const alertApi = useApi(alertApiRef);
const identityApi = useApi(identityApiRef);
@@ -72,24 +72,20 @@ export const TriggerDialog = ({
alertApi.post({
message: `Alarm successfully triggered by ${userName}`,
});
- onTriggerRefresh();
+ onIncidentCreated();
handleDialog();
}
+ }, [value, alertApi, handleDialog, userName, onIncidentCreated]);
- if (error) {
- alertApi.post({
- message: `Failed to trigger alarm. ${error.message}`,
- severity: 'error',
- });
- }
- }, [value, error, alertApi, handleDialog, userName, onTriggerRefresh]);
-
- if (!showDialog) {
- return null;
+ if (error) {
+ alertApi.post({
+ message: `Failed to trigger alarm. ${error.message}`,
+ severity: 'error',
+ });
}
return (
-