From 3328ae8889b2e498ffb2188bb43373e27e7c17b9 Mon Sep 17 00:00:00 2001 From: Marko Simon Date: Fri, 23 Sep 2022 17:25:50 +0200 Subject: [PATCH 01/13] rename all incident entities to alert Signed-off-by: Marko Simon --- plugins/ilert/src/api/client.ts | 129 ++++++++---------- plugins/ilert/src/api/index.ts | 8 +- plugins/ilert/src/api/types.ts | 50 +++---- .../AlertActionsMenu.tsx} | 76 +++++------ .../AlertAssignModal.tsx} | 67 +++++---- .../IncidentLink.tsx => Alert/AlertLink.tsx} | 17 +-- .../AlertNewModal.tsx} | 52 +++---- .../AlertStatus.tsx} | 14 +- .../{IncidentsPage => Alert}/index.ts | 4 +- .../AlertsPage.tsx} | 52 +++---- .../AlertsTable.tsx} | 74 +++++----- .../StatusChip.tsx | 12 +- .../TableTitle.tsx | 34 ++--- .../{Incident => AlertsPage}/index.ts | 4 +- .../src/components/ILertCard/ILertCard.tsx | 50 +++---- .../ILertCard/ILertCardActionsHeader.tsx | 26 ++-- .../src/components/ILertPage/ILertPage.tsx | 20 +-- ...eIncidentActions.ts => useAlertActions.ts} | 31 ++--- plugins/ilert/src/hooks/useAlertSource.ts | 6 +- .../ilert/src/hooks/useAlertSourceOnCalls.ts | 6 +- .../hooks/{useIncidents.ts => useAlerts.ts} | 86 ++++++------ ...useAssignIncident.ts => useAssignAlert.ts} | 34 ++--- .../{useNewIncident.ts => useNewAlert.ts} | 8 +- plugins/ilert/src/types.ts | 44 +++--- 24 files changed, 430 insertions(+), 474 deletions(-) rename plugins/ilert/src/components/{Incident/IncidentActionsMenu.tsx => Alert/AlertActionsMenu.tsx} (73%) rename plugins/ilert/src/components/{Incident/IncidentAssignModal.tsx => Alert/AlertAssignModal.tsx} (76%) rename plugins/ilert/src/components/{Incident/IncidentLink.tsx => Alert/AlertLink.tsx} (80%) rename plugins/ilert/src/components/{Incident/IncidentNewModal.tsx => Alert/AlertNewModal.tsx} (92%) rename plugins/ilert/src/components/{Incident/IncidentStatus.tsx => Alert/AlertStatus.tsx} (79%) rename plugins/ilert/src/components/{IncidentsPage => Alert}/index.ts (90%) rename plugins/ilert/src/components/{IncidentsPage/IncidentsPage.tsx => AlertsPage/AlertsPage.tsx} (71%) rename plugins/ilert/src/components/{IncidentsPage/IncidentsTable.tsx => AlertsPage/AlertsTable.tsx} (80%) rename plugins/ilert/src/components/{IncidentsPage => AlertsPage}/StatusChip.tsx (82%) rename plugins/ilert/src/components/{IncidentsPage => AlertsPage}/TableTitle.tsx (76%) rename plugins/ilert/src/components/{Incident => AlertsPage}/index.ts (89%) rename plugins/ilert/src/hooks/{useIncidentActions.ts => useAlertActions.ts} (69%) rename plugins/ilert/src/hooks/{useIncidents.ts => useAlerts.ts} (57%) rename plugins/ilert/src/hooks/{useAssignIncident.ts => useAssignAlert.ts} (68%) rename plugins/ilert/src/hooks/{useNewIncident.ts => useNewAlert.ts} (95%) diff --git a/plugins/ilert/src/api/client.ts b/plugins/ilert/src/api/client.ts index 7ab9a6d08c..2fa6f38c6e 100644 --- a/plugins/ilert/src/api/client.ts +++ b/plugins/ilert/src/api/client.ts @@ -13,30 +13,30 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { AuthenticationError, ResponseError } from '@backstage/errors'; import { + ConfigApi, + createApiRef, + DiscoveryApi, +} from '@backstage/core-plugin-api'; +import { AuthenticationError, ResponseError } from '@backstage/errors'; +import { DateTime as dt } from 'luxon'; +import { + Alert, + AlertAction, + AlertResponder, AlertSource, EscalationPolicy, - Incident, - IncidentAction, - IncidentResponder, OnCall, Schedule, UptimeMonitor, User, } from '../types'; import { - ILertApi, - GetIncidentsOpts, - GetIncidentsCountOpts, EventRequest, + GetAlertsCountOpts, + GetAlertsOpts, + ILertApi, } from './types'; -import { DateTime as dt } from 'luxon'; -import { - ConfigApi, - createApiRef, - DiscoveryApi, -} from '@backstage/core-plugin-api'; /** @public */ export const ilertApiRef = createApiRef({ @@ -102,7 +102,7 @@ export class ILertClient implements ILertApi { return await response.json(); } - async fetchIncidents(opts?: GetIncidentsOpts): Promise { + async fetchAlerts(opts?: GetAlertsOpts): Promise { const init = { headers: JSON_HEADERS, }; @@ -126,15 +126,12 @@ export class ILertClient implements ILertApi { query.append('state', state); }); } - const response = await this.fetch( - `/api/v1/incidents?${query.toString()}`, - init, - ); + const response = await this.fetch(`/api/alerts?${query.toString()}`, init); return response; } - async fetchIncidentsCount(opts?: GetIncidentsCountOpts): Promise { + async fetchAlertsCount(opts?: GetAlertsCountOpts): Promise { const init = { headers: JSON_HEADERS, }; @@ -145,96 +142,85 @@ export class ILertClient implements ILertApi { }); } const response = await this.fetch( - `/api/v1/incidents/count?${query.toString()}`, + `/api/alerts/count?${query.toString()}`, init, ); return response && response.count ? response.count : 0; } - async fetchIncident(id: number): Promise { + async fetchAlert(id: number): Promise { const init = { headers: JSON_HEADERS, }; const response = await this.fetch( - `/api/v1/incidents/${encodeURIComponent(id)}`, + `/api/alerts/${encodeURIComponent(id)}`, init, ); return response; } - async fetchIncidentResponders( - incident: Incident, - ): Promise { + async fetchAlertResponders(alert: Alert): Promise { const init = { headers: JSON_HEADERS, }; const response = await this.fetch( - `/api/v1/incidents/${encodeURIComponent(incident.id)}/responders`, + `/api/alerts/${encodeURIComponent(alert.id)}/responders`, init, ); return response; } - async fetchIncidentActions(incident: Incident): Promise { + async fetchAlertActions(alert: Alert): Promise { const init = { headers: JSON_HEADERS, }; const response = await this.fetch( - `/api/v1/incidents/${encodeURIComponent(incident.id)}/actions`, + `/api/alerts/${encodeURIComponent(alert.id)}/actions`, init, ); return response; } - async acceptIncident( - incident: Incident, - userName: string, - ): Promise { + async acceptAlert(alert: Alert, userName: string): Promise { const init = { method: 'POST', headers: JSON_HEADERS, body: JSON.stringify({ - apiKey: incident.alertSource?.integrationKey || '', - incidentKey: incident.incidentKey, + apiKey: alert.alertSource?.integrationKey || '', + alertKey: alert.alertKey, summary: `from ${userName} via Backstage plugin`, eventType: 'ACCEPT', }), }; - await this.fetch('/api/v1/events', init); - return this.fetchIncident(incident.id); + await this.fetch('/api/events', init); + return this.fetchAlert(alert.id); } - async resolveIncident( - incident: Incident, - userName: string, - ): Promise { + async resolveAlert(alert: Alert, userName: string): Promise { const init = { method: 'POST', headers: JSON_HEADERS, body: JSON.stringify({ - apiKey: incident.alertSource?.integrationKey || '', - incidentKey: incident.incidentKey, + apiKey: alert.alertSource?.integrationKey || '', + alertKey: alert.alertKey, summary: `from ${userName} via Backstage plugin`, eventType: 'RESOLVE', }), }; - await this.fetch('/api/v1/events', init); - return this.fetchIncident(incident.id); + await this.fetch('/api/events', init); + return this.fetchAlert(alert.id); } - async assignIncident( - incident: Incident, - responder: IncidentResponder, - ): Promise { + async assignAlert(alert: Alert, responder: AlertResponder): Promise { const init = { method: 'PUT', headers: JSON_HEADERS, @@ -254,19 +240,14 @@ export class ILertClient implements ILertApi { } const response = await this.fetch( - `/api/v1/incidents/${encodeURIComponent( - incident.id, - )}/assign?${query.toString()}`, + `/api/alerts/${encodeURIComponent(alert.id)}/assign?${query.toString()}`, init, ); return response; } - async triggerIncidentAction( - incident: Incident, - action: IncidentAction, - ): Promise { + async triggerAlertAction(alert: Alert, action: AlertAction): Promise { const init = { method: 'POST', headers: JSON_HEADERS, @@ -279,12 +260,12 @@ export class ILertClient implements ILertApi { }; await this.fetch( - `/api/v1/incidents/${encodeURIComponent(incident.id)}/actions`, + `/api/alerts/${encodeURIComponent(alert.id)}/actions`, init, ); } - async createIncident(eventRequest: EventRequest): Promise { + async createAlert(eventRequest: EventRequest): Promise { const init = { method: 'POST', headers: JSON_HEADERS, @@ -305,7 +286,7 @@ export class ILertClient implements ILertApi { }), }; - const response = await this.fetch('/api/v1/events', init); + const response = await this.fetch('/api/events', init); return response; } @@ -314,7 +295,7 @@ export class ILertClient implements ILertApi { headers: JSON_HEADERS, }; - const response = await this.fetch('/api/v1/uptime-monitors', init); + const response = await this.fetch('/api/uptime-monitors', init); return response; } @@ -325,7 +306,7 @@ export class ILertClient implements ILertApi { }; const response: UptimeMonitor = await this.fetch( - `/api/v1/uptime-monitors/${encodeURIComponent(id)}`, + `/api/uptime-monitors/${encodeURIComponent(id)}`, init, ); @@ -342,7 +323,7 @@ export class ILertClient implements ILertApi { }; const response = await this.fetch( - `/api/v1/uptime-monitors/${encodeURIComponent(uptimeMonitor.id)}`, + `/api/uptime-monitors/${encodeURIComponent(uptimeMonitor.id)}`, init, ); @@ -359,7 +340,7 @@ export class ILertClient implements ILertApi { }; const response = await this.fetch( - `/api/v1/uptime-monitors/${encodeURIComponent(uptimeMonitor.id)}`, + `/api/uptime-monitors/${encodeURIComponent(uptimeMonitor.id)}`, init, ); @@ -371,7 +352,7 @@ export class ILertClient implements ILertApi { headers: JSON_HEADERS, }; - const response = await this.fetch('/api/v1/alert-sources', init); + const response = await this.fetch('/api/alert-sources', init); return response; } @@ -384,7 +365,7 @@ export class ILertClient implements ILertApi { }; const response = await this.fetch( - `/api/v1/alert-sources/${encodeURIComponent(idOrIntegrationKey)}`, + `/api/alert-sources/${encodeURIComponent(idOrIntegrationKey)}`, init, ); @@ -397,7 +378,7 @@ export class ILertClient implements ILertApi { }; const response = await this.fetch( - `/api/v1/on-calls?policies=${encodeURIComponent( + `/api/on-calls?policies=${encodeURIComponent( alertSource.escalationPolicy.id, )}&expand=user&expand=escalationPolicy&timezone=${dt.local().zoneName}`, init, @@ -414,7 +395,7 @@ export class ILertClient implements ILertApi { }; const response = await this.fetch( - `/api/v1/alert-sources/${encodeURIComponent(alertSource.id)}`, + `/api/alert-sources/${encodeURIComponent(alertSource.id)}`, init, ); @@ -429,7 +410,7 @@ export class ILertClient implements ILertApi { }; const response = await this.fetch( - `/api/v1/alert-sources/${encodeURIComponent(alertSource.id)}`, + `/api/alert-sources/${encodeURIComponent(alertSource.id)}`, init, ); @@ -453,7 +434,7 @@ export class ILertClient implements ILertApi { }), }; - const response = await this.fetch('/api/v1/maintenance-windows', init); + const response = await this.fetch('/api/maintenance-windows', init); return response; } @@ -463,7 +444,7 @@ export class ILertClient implements ILertApi { headers: JSON_HEADERS, }; - const response = await this.fetch('/api/v1/schedules', init); + const response = await this.fetch('/api/schedules', init); return response; } @@ -473,7 +454,7 @@ export class ILertClient implements ILertApi { headers: JSON_HEADERS, }; - const response = await this.fetch('/api/v1/users', init); + const response = await this.fetch('/api/users', init); return response; } @@ -491,17 +472,15 @@ export class ILertClient implements ILertApi { }; const response = await this.fetch( - `/api/v1/schedules/${encodeURIComponent(scheduleId)}/overrides`, + `/api/schedules/${encodeURIComponent(scheduleId)}/overrides`, init, ); return response; } - getIncidentDetailsURL(incident: Incident): string { - return `${this.baseUrl}/incident/view.jsf?id=${encodeURIComponent( - incident.id, - )}`; + getAlertDetailsURL(alert: Alert): string { + return `${this.baseUrl}/alert/view.jsf?id=${encodeURIComponent(alert.id)}`; } getAlertSourceDetailsURL(alertSource: AlertSource | null): string { diff --git a/plugins/ilert/src/api/index.ts b/plugins/ilert/src/api/index.ts index e1163090ec..b33a702a5c 100644 --- a/plugins/ilert/src/api/index.ts +++ b/plugins/ilert/src/api/index.ts @@ -14,11 +14,11 @@ * limitations under the License. */ -export { ILertClient, ilertApiRef } from './client'; +export { ilertApiRef, ILertClient } from './client'; export type { - ILertApi, EventRequest, - GetIncidentsCountOpts, - GetIncidentsOpts, + GetAlertsCountOpts, + GetAlertsOpts, + ILertApi, TableState, } from './types'; diff --git a/plugins/ilert/src/api/types.ts b/plugins/ilert/src/api/types.ts index 2e9ea30f2f..b7af3d845d 100644 --- a/plugins/ilert/src/api/types.ts +++ b/plugins/ilert/src/api/types.ts @@ -15,16 +15,16 @@ */ import { + Alert, + AlertAction, + AlertResponder, AlertSource, - Incident, - User, - IncidentStatus, - UptimeMonitor, + AlertStatus, EscalationPolicy, - Schedule, - IncidentResponder, - IncidentAction, OnCall, + Schedule, + UptimeMonitor, + User, } from '../types'; /** @public */ @@ -34,16 +34,16 @@ export type TableState = { }; /** @public */ -export type GetIncidentsOpts = { +export type GetAlertsOpts = { maxResults?: number; startIndex?: number; - states?: IncidentStatus[]; + states?: AlertStatus[]; alertSources?: number[]; }; /** @public */ -export type GetIncidentsCountOpts = { - states?: IncidentStatus[]; +export type GetAlertsCountOpts = { + states?: AlertStatus[]; }; /** @public */ @@ -57,22 +57,16 @@ export type EventRequest = { /** @public */ export interface ILertApi { - fetchIncidents(opts?: GetIncidentsOpts): Promise; - fetchIncidentsCount(opts?: GetIncidentsCountOpts): Promise; - fetchIncident(id: number): Promise; - fetchIncidentResponders(incident: Incident): Promise; - fetchIncidentActions(incident: Incident): Promise; - acceptIncident(incident: Incident, userName: string): Promise; - resolveIncident(incident: Incident, userName: string): Promise; - assignIncident( - incident: Incident, - responder: IncidentResponder, - ): Promise; - createIncident(eventRequest: EventRequest): Promise; - triggerIncidentAction( - incident: Incident, - action: IncidentAction, - ): Promise; + fetchAlerts(opts?: GetAlertsOpts): Promise; + fetchAlertsCount(opts?: GetAlertsCountOpts): Promise; + fetchAlert(id: number): Promise; + fetchAlertResponders(alert: Alert): Promise; + fetchAlertActions(alert: Alert): Promise; + acceptAlert(alert: Alert, userName: string): Promise; + resolveAlert(alert: Alert, userName: string): Promise; + assignAlert(alert: Alert, responder: AlertResponder): Promise; + createAlert(eventRequest: EventRequest): Promise; + triggerAlertAction(alert: Alert, action: AlertAction): Promise; fetchUptimeMonitors(): Promise; pauseUptimeMonitor(uptimeMonitor: UptimeMonitor): Promise; @@ -100,7 +94,7 @@ export interface ILertApi { end: string, ): Promise; - getIncidentDetailsURL(incident: Incident): string; + getAlertDetailsURL(alert: Alert): string; getAlertSourceDetailsURL(alertSource: AlertSource | null): string; getEscalationPolicyDetailsURL(escalationPolicy: EscalationPolicy): string; getUptimeMonitorDetailsURL(uptimeMonitor: UptimeMonitor): string; diff --git a/plugins/ilert/src/components/Incident/IncidentActionsMenu.tsx b/plugins/ilert/src/components/Alert/AlertActionsMenu.tsx similarity index 73% rename from plugins/ilert/src/components/Incident/IncidentActionsMenu.tsx rename to plugins/ilert/src/components/Alert/AlertActionsMenu.tsx index 909e4dc362..ff20e39b24 100644 --- a/plugins/ilert/src/components/Incident/IncidentActionsMenu.tsx +++ b/plugins/ilert/src/components/Alert/AlertActionsMenu.tsx @@ -13,42 +13,42 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; import { IconButton, Menu, MenuItem, Typography } from '@material-ui/core'; import MoreVertIcon from '@material-ui/icons/MoreVert'; +import React from 'react'; import { ilertApiRef } from '../../api'; -import { Incident, IncidentAction } from '../../types'; -import { IncidentAssignModal } from './IncidentAssignModal'; -import { useIncidentActions } from '../../hooks/useIncidentActions'; +import { useAlertActions } from '../../hooks/useAlertActions'; +import { Alert, AlertAction } from '../../types'; +import { AlertAssignModal } from './AlertAssignModal'; +import { DEFAULT_NAMESPACE, parseEntityRef } from '@backstage/catalog-model'; +import { Link, Progress } from '@backstage/core-components'; import { alertApiRef, - useApi, identityApiRef, + useApi, } from '@backstage/core-plugin-api'; -import { Progress, Link } from '@backstage/core-components'; -import { DEFAULT_NAMESPACE, parseEntityRef } from '@backstage/catalog-model'; -export const IncidentActionsMenu = ({ - incident, - onIncidentChanged, +export const AlertActionsMenu = ({ + alert, + onAlertChanged, setIsLoading, }: { - incident: Incident; - onIncidentChanged?: (incident: Incident) => void; + alert: Alert; + onAlertChanged?: (alert: Alert) => void; setIsLoading?: (isLoading: boolean) => void; }) => { const ilertApi = useApi(ilertApiRef); const alertApi = useApi(alertApiRef); const identityApi = useApi(identityApiRef); const [anchorEl, setAnchorEl] = React.useState(null); - const callback = onIncidentChanged || ((_: Incident): void => {}); + const callback = onAlertChanged || ((_: Alert): void => {}); const setProcessing = setIsLoading || ((_: boolean): void => {}); - const [isAssignIncidentModalOpened, setIsAssignIncidentModalOpened] = + const [isAssignAlertModalOpened, setIsAssignAlertModalOpened] = React.useState(false); - const [{ incidentActions, isLoading }] = useIncidentActions( - incident, + const [{ alertActions, isLoading }] = useAlertActions( + alert, Boolean(anchorEl), ); @@ -70,10 +70,10 @@ export const IncidentActionsMenu = ({ defaultKind: 'User', defaultNamespace: DEFAULT_NAMESPACE, }); - const newIncident = await ilertApi.acceptIncident(incident, userName); - alertApi.post({ message: 'Incident accepted.' }); + const newAlert = await ilertApi.acceptAlert(alert, userName); + alertApi.post({ message: 'Alert accepted.' }); - callback(newIncident); + callback(newAlert); setProcessing(false); } catch (err) { setProcessing(false); @@ -90,10 +90,10 @@ export const IncidentActionsMenu = ({ defaultKind: 'User', defaultNamespace: DEFAULT_NAMESPACE, }); - const newIncident = await ilertApi.resolveIncident(incident, userName); - alertApi.post({ message: 'Incident resolved.' }); + const newAlert = await ilertApi.resolveAlert(alert, userName); + alertApi.post({ message: 'Alert resolved.' }); - callback(newIncident); + callback(newAlert); setProcessing(false); } catch (err) { setProcessing(false); @@ -103,15 +103,15 @@ export const IncidentActionsMenu = ({ const handleAssign = () => { handleCloseMenu(); - setIsAssignIncidentModalOpened(true); + setIsAssignAlertModalOpened(true); }; - const handleTriggerAction = (action: IncidentAction) => async () => { + const handleTriggerAction = (action: AlertAction) => async () => { try { handleCloseMenu(); setProcessing(true); - await ilertApi.triggerIncidentAction(incident, action); - alertApi.post({ message: 'Incident action triggered.' }); + await ilertApi.triggerAlertAction(alert, action); + alertApi.post({ message: 'Alert action triggered.' }); setProcessing(false); } catch (err) { setProcessing(false); @@ -119,7 +119,7 @@ export const IncidentActionsMenu = ({ } }; - const actions: React.ReactNode[] = incidentActions.map(a => { + const actions: React.ReactNode[] = alertActions.map(a => { const successTrigger = a.history ? a.history.find(h => h.success) : undefined; @@ -152,7 +152,7 @@ export const IncidentActionsMenu = ({ - {incident.status === 'PENDING' ? ( + {alert.status === 'PENDING' ? ( Accept @@ -169,7 +169,7 @@ export const IncidentActionsMenu = ({ ) : null} - {incident.status !== 'RESOLVED' ? ( + {alert.status !== 'RESOLVED' ? ( Resolve @@ -177,7 +177,7 @@ export const IncidentActionsMenu = ({ ) : null} - {incident.status !== 'RESOLVED' ? ( + {alert.status !== 'RESOLVED' ? ( Assign @@ -195,17 +195,15 @@ export const IncidentActionsMenu = ({ - - View in iLert - + View in iLert - ); diff --git a/plugins/ilert/src/components/Incident/IncidentAssignModal.tsx b/plugins/ilert/src/components/Alert/AlertAssignModal.tsx similarity index 76% rename from plugins/ilert/src/components/Incident/IncidentAssignModal.tsx rename to plugins/ilert/src/components/Alert/AlertAssignModal.tsx index 5fd8a97df3..d1ecefafa1 100644 --- a/plugins/ilert/src/components/Incident/IncidentAssignModal.tsx +++ b/plugins/ilert/src/components/Alert/AlertAssignModal.tsx @@ -13,21 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; -import { makeStyles } from '@material-ui/core/styles'; -import Alert from '@material-ui/lab/Alert'; +import { alertApiRef, useApi } from '@backstage/core-plugin-api'; +import { Typography } from '@material-ui/core'; import Button from '@material-ui/core/Button'; -import TextField from '@material-ui/core/TextField'; import Dialog from '@material-ui/core/Dialog'; import DialogActions from '@material-ui/core/DialogActions'; import DialogContent from '@material-ui/core/DialogContent'; import DialogTitle from '@material-ui/core/DialogTitle'; +import { makeStyles } from '@material-ui/core/styles'; +import TextField from '@material-ui/core/TextField'; +import MUIAlert from '@material-ui/lab/Alert'; import Autocomplete from '@material-ui/lab/Autocomplete'; -import { useAssignIncident } from '../../hooks/useAssignIncident'; -import { Typography } from '@material-ui/core'; +import React from 'react'; import { ilertApiRef } from '../../api'; -import { Incident } from '../../types'; -import { alertApiRef, useApi } from '@backstage/core-plugin-api'; +import { useAssignAlert } from '../../hooks/useAssignAlert'; +import { Alert } from '../../types'; const useStyles = makeStyles(() => ({ container: { @@ -55,45 +55,42 @@ const useStyles = makeStyles(() => ({ }, })); -export const IncidentAssignModal = ({ - incident, +export const AlertAssignModal = ({ + alert, isModalOpened, setIsModalOpened, - onIncidentChanged, + onAlertChanged, }: { - incident: Incident | null; + alert: Alert | null; isModalOpened: boolean; setIsModalOpened: (open: boolean) => void; - onIncidentChanged?: (incident: Incident) => void; + onAlertChanged?: (alert: Alert) => void; }) => { const [ - { incidentRespondersList, incidentResponder, isLoading }, - { setIsLoading, setIncidentResponder, setIncidentRespondersList }, - ] = useAssignIncident(incident, isModalOpened); - const callback = onIncidentChanged || ((_: Incident): void => {}); + { alertRespondersList, alertResponder, isLoading }, + { setIsLoading, setAlertResponder, setAlertRespondersList }, + ] = useAssignAlert(alert, isModalOpened); + const callback = onAlertChanged || ((_: Alert): void => {}); const ilertApi = useApi(ilertApiRef); const alertApi = useApi(alertApiRef); const classes = useStyles(); const handleClose = () => { - setIncidentRespondersList([]); + setAlertRespondersList([]); setIsModalOpened(false); }; const handleAssign = () => { - if (!incident || !incidentResponder) { + if (!alert || !alertResponder) { return; } setIsLoading(true); - setIncidentRespondersList([]); + setAlertRespondersList([]); setTimeout(async () => { try { - const newIncident = await ilertApi.assignIncident( - incident, - incidentResponder, - ); - callback(newIncident); - alertApi.post({ message: 'Incident assigned.' }); + const newAlert = await ilertApi.assignAlert(alert, alertResponder); + callback(newAlert); + alertApi.post({ message: 'Alert assigned.' }); } catch (err) { alertApi.post({ message: err, severity: 'error' }); } @@ -102,33 +99,33 @@ export const IncidentAssignModal = ({ }, 250); }; - const canAssign = !!incidentResponder; + const canAssign = !!alertResponder; return ( - + Select responder to assign - + - This action will assign the incident to the selected responder. + This action will assign the alert to the selected responder. - + { - setIncidentResponder(newValue); + setAlertResponder(newValue); }} autoHighlight groupBy={option => { diff --git a/plugins/ilert/src/components/Incident/IncidentLink.tsx b/plugins/ilert/src/components/Alert/AlertLink.tsx similarity index 80% rename from plugins/ilert/src/components/Incident/IncidentLink.tsx rename to plugins/ilert/src/components/Alert/AlertLink.tsx index 381a656b72..8c526899aa 100644 --- a/plugins/ilert/src/components/Incident/IncidentLink.tsx +++ b/plugins/ilert/src/components/Alert/AlertLink.tsx @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; import { makeStyles } from '@material-ui/core/styles'; -import { Incident } from '../../types'; +import React from 'react'; import { ilertApiRef } from '../../api'; +import { Alert } from '../../types'; -import { useApi } from '@backstage/core-plugin-api'; import { Link } from '@backstage/core-components'; +import { useApi } from '@backstage/core-plugin-api'; const useStyles = makeStyles({ link: { @@ -27,20 +27,17 @@ const useStyles = makeStyles({ }, }); -export const IncidentLink = ({ incident }: { incident: Incident | null }) => { +export const AlertLink = ({ alert }: { alert: Alert | null }) => { const ilertApi = useApi(ilertApiRef); const classes = useStyles(); - if (!incident) { + if (!alert) { return null; } return ( - - #{incident.id} + + #{alert.id} ); }; diff --git a/plugins/ilert/src/components/Incident/IncidentNewModal.tsx b/plugins/ilert/src/components/Alert/AlertNewModal.tsx similarity index 92% rename from plugins/ilert/src/components/Incident/IncidentNewModal.tsx rename to plugins/ilert/src/components/Alert/AlertNewModal.tsx index 561047d45e..66928e07e3 100644 --- a/plugins/ilert/src/components/Incident/IncidentNewModal.tsx +++ b/plugins/ilert/src/components/Alert/AlertNewModal.tsx @@ -13,27 +13,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; import { DEFAULT_NAMESPACE, parseEntityRef } from '@backstage/catalog-model'; -import { makeStyles } from '@material-ui/core/styles'; -import Alert from '@material-ui/lab/Alert'; -import Button from '@material-ui/core/Button'; -import TextField from '@material-ui/core/TextField'; -import Dialog from '@material-ui/core/Dialog'; -import DialogActions from '@material-ui/core/DialogActions'; -import DialogContent from '@material-ui/core/DialogContent'; -import DialogTitle from '@material-ui/core/DialogTitle'; -import Autocomplete from '@material-ui/lab/Autocomplete'; -import { useNewIncident } from '../../hooks/useNewIncident'; -import { Typography } from '@material-ui/core'; -import useMediaQuery from '@material-ui/core/useMediaQuery'; -import { ilertApiRef } from '../../api'; -import { AlertSource } from '../../types'; import { alertApiRef, identityApiRef, useApi, } from '@backstage/core-plugin-api'; +import { Typography } from '@material-ui/core'; +import Button from '@material-ui/core/Button'; +import Dialog from '@material-ui/core/Dialog'; +import DialogActions from '@material-ui/core/DialogActions'; +import DialogContent from '@material-ui/core/DialogContent'; +import DialogTitle from '@material-ui/core/DialogTitle'; +import { makeStyles } from '@material-ui/core/styles'; +import TextField from '@material-ui/core/TextField'; +import useMediaQuery from '@material-ui/core/useMediaQuery'; +import Alert from '@material-ui/lab/Alert'; +import Autocomplete from '@material-ui/lab/Autocomplete'; +import React from 'react'; +import { ilertApiRef } from '../../api'; +import { useNewAlert } from '../../hooks/useNewAlert'; +import { AlertSource } from '../../types'; const useStyles = makeStyles(() => ({ container: { @@ -61,23 +61,23 @@ const useStyles = makeStyles(() => ({ }, })); -export const IncidentNewModal = ({ +export const AlertNewModal = ({ isModalOpened, setIsModalOpened, - refetchIncidents, + refetchAlerts, initialAlertSource, entityName, }: { isModalOpened: boolean; setIsModalOpened: (open: boolean) => void; - refetchIncidents: () => void; + refetchAlerts: () => void; initialAlertSource?: AlertSource | null; entityName?: string; }) => { const [ { alertSources, alertSource, summary, details, isLoading }, { setAlertSource, setSummary, setDetails, setIsLoading }, - ] = useNewIncident(isModalOpened, initialAlertSource); + ] = useNewAlert(isModalOpened, initialAlertSource); const ilertApi = useApi(ilertApiRef); const alertApi = useApi(alertApiRef); const identityApi = useApi(identityApiRef); @@ -107,15 +107,15 @@ export const IncidentNewModal = ({ defaultKind: 'User', defaultNamespace: DEFAULT_NAMESPACE, }); - await ilertApi.createIncident({ + await ilertApi.createAlert({ integrationKey, summary, details, userName, source, }); - alertApi.post({ message: 'Incident created.' }); - refetchIncidents(); + alertApi.post({ message: 'Alert created.' }); + refetchAlerts(); } catch (err) { alertApi.post({ message: err, severity: 'error' }); } @@ -129,16 +129,16 @@ export const IncidentNewModal = ({ - + {entityName ? (
- This action will trigger an incident for{' '} + This action will trigger an alert for{' '} "{entityName}".
) : ( - 'New incident' + 'New alert' )}
diff --git a/plugins/ilert/src/components/Incident/IncidentStatus.tsx b/plugins/ilert/src/components/Alert/AlertStatus.tsx similarity index 79% rename from plugins/ilert/src/components/Incident/IncidentStatus.tsx rename to plugins/ilert/src/components/Alert/AlertStatus.tsx index e6eb1525f7..9be81205dd 100644 --- a/plugins/ilert/src/components/Incident/IncidentStatus.tsx +++ b/plugins/ilert/src/components/Alert/AlertStatus.tsx @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; +import { StatusError, StatusOK } from '@backstage/core-components'; import { makeStyles } from '@material-ui/core/styles'; import Tooltip from '@material-ui/core/Tooltip'; -import { ACCEPTED, Incident, PENDING, RESOLVED } from '../../types'; -import { StatusError, StatusOK } from '@backstage/core-components'; +import React from 'react'; +import { ACCEPTED, Alert, PENDING, RESOLVED } from '../../types'; const useStyles = makeStyles({ denseListIcon: { @@ -29,19 +29,19 @@ const useStyles = makeStyles({ }, }); -export const incidentStatusLabels = { +export const alertStatusLabels = { [RESOLVED]: 'Resolved', [ACCEPTED]: 'Accepted', [PENDING]: 'Pending', } as Record; -export const IncidentStatus = ({ incident }: { incident: Incident }) => { +export const AlertStatus = ({ alert }: { alert: Alert }) => { const classes = useStyles(); return ( - +
- {incident.status === 'PENDING' ? : } + {alert.status === 'PENDING' ? : }
); diff --git a/plugins/ilert/src/components/IncidentsPage/index.ts b/plugins/ilert/src/components/Alert/index.ts similarity index 90% rename from plugins/ilert/src/components/IncidentsPage/index.ts rename to plugins/ilert/src/components/Alert/index.ts index a5ad4e65e6..a569777b21 100644 --- a/plugins/ilert/src/components/IncidentsPage/index.ts +++ b/plugins/ilert/src/components/Alert/index.ts @@ -13,5 +13,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export * from './IncidentsPage'; -export * from './IncidentsTable'; +export * from './AlertActionsMenu'; +export * from './AlertStatus'; diff --git a/plugins/ilert/src/components/IncidentsPage/IncidentsPage.tsx b/plugins/ilert/src/components/AlertsPage/AlertsPage.tsx similarity index 71% rename from plugins/ilert/src/components/IncidentsPage/IncidentsPage.tsx rename to plugins/ilert/src/components/AlertsPage/AlertsPage.tsx index 3dc0907777..c7df9101a5 100644 --- a/plugins/ilert/src/components/IncidentsPage/IncidentsPage.tsx +++ b/plugins/ilert/src/components/AlertsPage/AlertsPage.tsx @@ -13,37 +13,37 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; -import { AuthenticationError } from '@backstage/errors'; -import Button from '@material-ui/core/Button'; -import AddIcon from '@material-ui/icons/Add'; -import { IncidentsTable } from './IncidentsTable'; -import { MissingAuthorizationHeaderError } from '../Errors'; -import { useIncidents } from '../../hooks/useIncidents'; -import { IncidentNewModal } from '../Incident/IncidentNewModal'; import { Content, ContentHeader, - SupportButton, ResponseErrorPanel, + SupportButton, } from '@backstage/core-components'; +import { AuthenticationError } from '@backstage/errors'; +import Button from '@material-ui/core/Button'; +import AddIcon from '@material-ui/icons/Add'; +import React from 'react'; +import { useAlerts } from '../../hooks/useAlerts'; +import { AlertNewModal } from '../Alert/AlertNewModal'; +import { MissingAuthorizationHeaderError } from '../Errors'; +import { AlertsTable } from './AlertsTable'; -export const IncidentsPage = () => { +export const AlertsPage = () => { const [ - { tableState, states, incidents, incidentsCount, isLoading, error }, + { tableState, states, alerts, alertsCount, isLoading, error }, { - onIncidentStatesChange, + onAlertStatesChange, onChangePage, onChangeRowsPerPage, - onIncidentChanged, - refetchIncidents, + onAlertChanged, + refetchAlerts, setIsLoading, }, - ] = useIncidents(true); + ] = useAlerts(true); const [isModalOpened, setIsModalOpened] = React.useState(false); - const handleCreateNewIncidentClick = () => { + const handleCreateNewAlertClick = () => { setIsModalOpened(true); }; @@ -65,32 +65,32 @@ export const IncidentsPage = () => { return ( - + - This helps you to bring iLert into your developer portal. - ({ }, })); -export const IncidentsTable = ({ - incidents, - incidentsCount, +export const AlertsTable = ({ + alerts, + alertsCount, tableState, states, isLoading, - onIncidentChanged, + onAlertChanged, setIsLoading, - onIncidentStatesChange, + onAlertStatesChange, onChangePage, onChangeRowsPerPage, compact, }: { - incidents: Incident[]; - incidentsCount: number; + alerts: Alert[]; + alertsCount: number; tableState: TableState; - states: IncidentStatus[]; + states: AlertStatus[]; isLoading: boolean; - onIncidentChanged: (incident: Incident) => void; + onAlertChanged: (alert: Alert) => void; setIsLoading: (isLoading: boolean) => void; - onIncidentStatesChange: (states: IncidentStatus[]) => void; + onAlertStatesChange: (states: AlertStatus[]) => void; onChangePage: (page: number) => void; onChangeRowsPerPage: (pageSize: number) => void; compact?: boolean; @@ -92,14 +92,14 @@ export const IncidentsTable = ({ highlight: true, cellStyle: smColumnStyle, headerStyle: smColumnStyle, - render: rowData => , + render: rowData => , }; const summaryColumn: TableColumn = { title: 'Summary', field: 'summary', cellStyle: !compact ? xlColumnStyle : undefined, headerStyle: !compact ? xlColumnStyle : undefined, - render: rowData => {(rowData as Incident).summary}, + render: rowData => {(rowData as Alert).summary}, }; const sourceColumn: TableColumn = { title: 'Source', @@ -107,7 +107,7 @@ export const IncidentsTable = ({ cellStyle: mdColumnStyle, headerStyle: mdColumnStyle, render: rowData => ( - + ), }; const durationColumn: TableColumn = { @@ -118,10 +118,10 @@ export const IncidentsTable = ({ headerStyle: smColumnStyle, render: rowData => ( - {(rowData as Incident).status !== 'RESOLVED' + {(rowData as Alert).status !== 'RESOLVED' ? humanizeDuration( Interval.fromDateTimes( - dt.fromISO((rowData as Incident).reportTime), + dt.fromISO((rowData as Alert).reportTime), dt.now(), ) .toDuration() @@ -130,8 +130,8 @@ export const IncidentsTable = ({ ) : humanizeDuration( Interval.fromDateTimes( - dt.fromISO((rowData as Incident).reportTime), - dt.fromISO((rowData as Incident).resolvedOn), + dt.fromISO((rowData as Alert).reportTime), + dt.fromISO((rowData as Alert).resolvedOn), ) .toDuration() .valueOf(), @@ -147,7 +147,7 @@ export const IncidentsTable = ({ headerStyle: !compact ? mdColumnStyle : lgColumnStyle, render: rowData => ( - {ilertApi.getUserInitials((rowData as Incident).assignedTo)} + {ilertApi.getUserInitials((rowData as Alert).assignedTo)} ), }; @@ -158,7 +158,7 @@ export const IncidentsTable = ({ headerStyle: smColumnStyle, render: rowData => ( - {(rowData as Incident).priority === 'HIGH' ? 'High' : 'Low'} + {(rowData as Alert).priority === 'HIGH' ? 'High' : 'Low'} ), }; @@ -167,7 +167,7 @@ export const IncidentsTable = ({ field: 'status', cellStyle: xsColumnStyle, headerStyle: xsColumnStyle, - render: rowData => , + render: rowData => , }; const actionsColumn: TableColumn = { title: '', @@ -175,9 +175,9 @@ export const IncidentsTable = ({ cellStyle: xsColumnStyle, headerStyle: xsColumnStyle, render: rowData => ( - ), @@ -236,14 +236,14 @@ export const IncidentsTable = ({ }} emptyContent={ - No incidents right now + No alerts right now } title={ !compact ? ( ) : ( @@ -252,12 +252,12 @@ export const IncidentsTable = ({ ) } page={tableState.page} - totalCount={incidentsCount} + totalCount={alertsCount} onPageChange={onChangePage} onRowsPerPageChange={onChangeRowsPerPage} // localization={{ header: { actions: undefined } }} columns={columns} - data={incidents} + data={alerts} isLoading={isLoading} /> ); diff --git a/plugins/ilert/src/components/IncidentsPage/StatusChip.tsx b/plugins/ilert/src/components/AlertsPage/StatusChip.tsx similarity index 82% rename from plugins/ilert/src/components/IncidentsPage/StatusChip.tsx rename to plugins/ilert/src/components/AlertsPage/StatusChip.tsx index 98521234de..833e903b32 100644 --- a/plugins/ilert/src/components/IncidentsPage/StatusChip.tsx +++ b/plugins/ilert/src/components/AlertsPage/StatusChip.tsx @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; import { Chip, withStyles } from '@material-ui/core'; -import { Incident, PENDING, ACCEPTED, RESOLVED } from '../../types'; -import { incidentStatusLabels } from '../Incident/IncidentStatus'; +import React from 'react'; +import { ACCEPTED, Alert, PENDING, RESOLVED } from '../../types'; +import { alertStatusLabels } from '../Alert/AlertStatus'; const ResolvedChip = withStyles({ root: { @@ -41,10 +41,10 @@ const PendingChip = withStyles({ }, })(Chip); -export const StatusChip = ({ incident }: { incident: Incident }) => { - const label = `${incidentStatusLabels[incident.status]}`; +export const StatusChip = ({ alert }: { alert: Alert }) => { + const label = `${alertStatusLabels[alert.status]}`; - switch (incident.status) { + switch (alert.status) { case RESOLVED: return ; case ACCEPTED: diff --git a/plugins/ilert/src/components/IncidentsPage/TableTitle.tsx b/plugins/ilert/src/components/AlertsPage/TableTitle.tsx similarity index 76% rename from plugins/ilert/src/components/IncidentsPage/TableTitle.tsx rename to plugins/ilert/src/components/AlertsPage/TableTitle.tsx index 8b8fde87f7..c610e91d94 100644 --- a/plugins/ilert/src/components/IncidentsPage/TableTitle.tsx +++ b/plugins/ilert/src/components/AlertsPage/TableTitle.tsx @@ -13,16 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; -import { PENDING, ACCEPTED, RESOLVED, IncidentStatus } from '../../types'; -import { incidentStatusLabels } from '../Incident/IncidentStatus'; +import Checkbox from '@material-ui/core/Checkbox'; import FormControl from '@material-ui/core/FormControl'; import ListItemText from '@material-ui/core/ListItemText'; -import Select from '@material-ui/core/Select'; -import Typography from '@material-ui/core/Typography'; import MenuItem from '@material-ui/core/MenuItem'; -import Checkbox from '@material-ui/core/Checkbox'; +import Select from '@material-ui/core/Select'; import { makeStyles } from '@material-ui/core/styles'; +import Typography from '@material-ui/core/Typography'; +import React from 'react'; +import { ACCEPTED, AlertStatus, PENDING, RESOLVED } from '../../types'; +import { alertStatusLabels } from '../Alert/AlertStatus'; const ITEM_HEIGHT = 48; const ITEM_PADDING_TOP = 8; @@ -53,15 +53,15 @@ const useStyles = makeStyles({ }); export const TableTitle = ({ - incidentStates, - onIncidentStatesChange, + alertStates, + onAlertStatesChange, }: { - incidentStates: IncidentStatus[]; - onIncidentStatesChange: (states: IncidentStatus[]) => void; + alertStates: AlertStatus[]; + onAlertStatesChange: (states: AlertStatus[]) => void; }) => { const classes = useStyles(); - const handleIncidentStatusSelectChange = (event: any) => { - onIncidentStatesChange(event.target.value); + const handleAlertStatusSelectChange = (event: any) => { + onAlertStatesChange(event.target.value); }; return ( @@ -75,19 +75,19 @@ export const TableTitle = ({ size="small" > diff --git a/plugins/ilert/src/components/Incident/index.ts b/plugins/ilert/src/components/AlertsPage/index.ts similarity index 89% rename from plugins/ilert/src/components/Incident/index.ts rename to plugins/ilert/src/components/AlertsPage/index.ts index 5065cb1de9..c42d558dca 100644 --- a/plugins/ilert/src/components/Incident/index.ts +++ b/plugins/ilert/src/components/AlertsPage/index.ts @@ -13,5 +13,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export * from './IncidentActionsMenu'; -export * from './IncidentStatus'; +export * from './AlertsPage'; +export * from './AlertsTable'; diff --git a/plugins/ilert/src/components/ILertCard/ILertCard.tsx b/plugins/ilert/src/components/ILertCard/ILertCard.tsx index 6330189a01..d124751b2b 100644 --- a/plugins/ilert/src/components/ILertCard/ILertCard.tsx +++ b/plugins/ilert/src/components/ILertCard/ILertCard.tsx @@ -13,27 +13,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; import { Entity } from '@backstage/catalog-model'; +import { ResponseErrorPanel } from '@backstage/core-components'; import { AuthenticationError } from '@backstage/errors'; import Card from '@material-ui/core/Card'; import CardContent from '@material-ui/core/CardContent'; import CardHeader from '@material-ui/core/CardHeader'; import Divider from '@material-ui/core/Divider'; import { makeStyles } from '@material-ui/core/styles'; +import React from 'react'; import { ILERT_INTEGRATION_KEY_ANNOTATION } from '../../constants'; -import { MissingAuthorizationHeaderError } from '../Errors'; -import { useIncidents } from '../../hooks/useIncidents'; -import { IncidentsTable } from '../IncidentsPage'; -import { IncidentNewModal } from '../Incident/IncidentNewModal'; -import { ILertCardActionsHeader } from './ILertCardActionsHeader'; -import { useAlertSource } from '../../hooks/useAlertSource'; import { useILertEntity } from '../../hooks'; +import { useAlerts } from '../../hooks/useAlerts'; +import { useAlertSource } from '../../hooks/useAlertSource'; +import { AlertNewModal } from '../Alert/AlertNewModal'; +import { AlertsTable } from '../AlertsPage'; +import { MissingAuthorizationHeaderError } from '../Errors'; +import { ILertCardActionsHeader } from './ILertCardActionsHeader'; +import { ILertCardEmptyState } from './ILertCardEmptyState'; import { ILertCardHeaderStatus } from './ILertCardHeaderStatus'; import { ILertCardMaintenanceModal } from './ILertCardMaintenanceModal'; -import { ILertCardEmptyState } from './ILertCardEmptyState'; import { ILertCardOnCall } from './ILertCardOnCall'; -import { ResponseErrorPanel } from '@backstage/core-components'; /** @public */ export const isPluginApplicableToEntity = (entity: Entity) => @@ -60,18 +60,18 @@ export const ILertCard = () => { { setAlertSource, refetchAlertSource }, ] = useAlertSource(integrationKey); const [ - { tableState, states, incidents, incidentsCount, isLoading, error }, + { tableState, states, alerts, alertsCount, isLoading, error }, { - onIncidentStatesChange, + onAlertStatesChange, onChangePage, onChangeRowsPerPage, - onIncidentChanged, - refetchIncidents, + onAlertChanged, + refetchAlerts, setIsLoading, }, - ] = useIncidents(false, true, alertSource); + ] = useAlerts(false, true, alertSource); - const [isNewIncidentModalOpened, setIsNewIncidentModalOpened] = + const [isNewAlertModalOpened, setIsNewAlertModalOpened] = React.useState(false); const [isMaintenanceModalOpened, setIsMaintenanceModalOpened] = React.useState(false); @@ -97,7 +97,7 @@ export const ILertCard = () => { @@ -107,13 +107,13 @@ export const ILertCard = () => { - { /> - diff --git a/plugins/ilert/src/components/ILertCard/ILertCardActionsHeader.tsx b/plugins/ilert/src/components/ILertCard/ILertCardActionsHeader.tsx index 4e0b562369..49f2c789c4 100644 --- a/plugins/ilert/src/components/ILertCard/ILertCardActionsHeader.tsx +++ b/plugins/ilert/src/components/ILertCard/ILertCardActionsHeader.tsx @@ -13,20 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; -import Alert from '@material-ui/lab/Alert'; import Button from '@material-ui/core/Button'; import Dialog from '@material-ui/core/Dialog'; import DialogActions from '@material-ui/core/DialogActions'; import DialogContent from '@material-ui/core/DialogContent'; import DialogTitle from '@material-ui/core/DialogTitle'; +import Typography from '@material-ui/core/Typography'; import AlarmAddIcon from '@material-ui/icons/AlarmAdd'; import BuildIcon from '@material-ui/icons/Build'; import PauseIcon from '@material-ui/icons/Pause'; import PlayArrowIcon from '@material-ui/icons/PlayArrow'; import TimelineIcon from '@material-ui/icons/Timeline'; import WebIcon from '@material-ui/icons/Web'; -import Typography from '@material-ui/core/Typography'; +import Alert from '@material-ui/lab/Alert'; +import React from 'react'; import { ilertApiRef } from '../../api'; import { AlertSource, UptimeMonitor } from '../../types'; @@ -34,18 +34,18 @@ import { HeaderIconLinkRow, IconLinkVerticalProps, } from '@backstage/core-components'; -import { useApi, alertApiRef } from '@backstage/core-plugin-api'; +import { alertApiRef, useApi } from '@backstage/core-plugin-api'; export const ILertCardActionsHeader = ({ alertSource, setAlertSource, - setIsNewIncidentModalOpened, + setIsNewAlertModalOpened, setIsMaintenanceModalOpened, uptimeMonitor, }: { alertSource: AlertSource | null; setAlertSource: (alertSource: AlertSource) => void; - setIsNewIncidentModalOpened: (isOpen: boolean) => void; + setIsNewAlertModalOpened: (isOpen: boolean) => void; setIsMaintenanceModalOpened: (isOpen: boolean) => void; uptimeMonitor: UptimeMonitor | null; }) => { @@ -54,8 +54,8 @@ export const ILertCardActionsHeader = ({ const [isLoading, setIsLoading] = React.useState(false); const [isDisableModalOpened, setIsDisableModalOpened] = React.useState(false); - const handleCreateNewIncident = () => { - setIsNewIncidentModalOpened(true); + const handleCreateNewAlert = () => { + setIsNewAlertModalOpened(true); }; const handleEnableAlertSource = async () => { @@ -108,9 +108,9 @@ export const ILertCardActionsHeader = ({ icon: , }; - const createIncidentLink: IconLinkVerticalProps = { - label: 'Create Incident', - onClick: handleCreateNewIncident, + const createAlertLink: IconLinkVerticalProps = { + label: 'Create Alert', + onClick: handleCreateNewAlert, icon: , color: 'secondary', disabled: @@ -149,7 +149,7 @@ export const ILertCardActionsHeader = ({ const links: IconLinkVerticalProps[] = [ alertSourceLink, - createIncidentLink, + createAlertLink, alertSource && alertSource.active ? disableAlertSourceLink : enableAlertSourceLink, @@ -178,7 +178,7 @@ export const ILertCardActionsHeader = ({ Do you really want to disable this alert source? A disabled alert - source cannot create new incidents. + source cannot create new alerts.
diff --git a/plugins/ilert/src/components/ILertPage/ILertPage.tsx b/plugins/ilert/src/components/ILertPage/ILertPage.tsx index 89dae215e4..8dfed11690 100644 --- a/plugins/ilert/src/components/ILertPage/ILertPage.tsx +++ b/plugins/ilert/src/components/ILertPage/ILertPage.tsx @@ -13,24 +13,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; -import { IncidentsPage } from '../IncidentsPage'; -import { UptimeMonitorsPage } from '../UptimeMonitorsPage'; -import { OnCallSchedulesPage } from '../OnCallSchedulesPage'; import { - Page, - Header, - HeaderTabs, - HeaderLabel, Content, + Header, + HeaderLabel, + HeaderTabs, + Page, } from '@backstage/core-components'; +import React from 'react'; +import { AlertsPage } from '../AlertsPage'; +import { OnCallSchedulesPage } from '../OnCallSchedulesPage'; +import { UptimeMonitorsPage } from '../UptimeMonitorsPage'; /** @public */ export const ILertPage = () => { const [selectedTab, setSelectedTab] = React.useState(0); const tabs = [ { label: 'Who is on call?' }, - { label: 'Incidents' }, + { label: 'Alerts' }, { label: 'Uptime Monitors' }, ]; const renderTab = () => { @@ -38,7 +38,7 @@ export const ILertPage = () => { case 0: return ; case 1: - return ; + return ; case 2: return ; default: diff --git a/plugins/ilert/src/hooks/useIncidentActions.ts b/plugins/ilert/src/hooks/useAlertActions.ts similarity index 69% rename from plugins/ilert/src/hooks/useIncidentActions.ts rename to plugins/ilert/src/hooks/useAlertActions.ts index 75621f67c3..875a8099f3 100644 --- a/plugins/ilert/src/hooks/useIncidentActions.ts +++ b/plugins/ilert/src/hooks/useAlertActions.ts @@ -13,48 +13,45 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; -import { ilertApiRef } from '../api'; +import { errorApiRef, useApi } from '@backstage/core-plugin-api'; import { AuthenticationError } from '@backstage/errors'; +import React from 'react'; import useAsyncRetry from 'react-use/lib/useAsyncRetry'; -import { Incident, IncidentAction } from '../types'; -import { useApi, errorApiRef } from '@backstage/core-plugin-api'; +import { ilertApiRef } from '../api'; +import { Alert, AlertAction } from '../types'; -export const useIncidentActions = ( - incident: Incident | null, - open: boolean, -) => { +export const useAlertActions = (alert: Alert | null, open: boolean) => { const ilertApi = useApi(ilertApiRef); const errorApi = useApi(errorApiRef); - const [incidentActionsList, setIncidentActionsList] = React.useState< - IncidentAction[] - >([]); + const [alertActionsList, setAlertActionsList] = React.useState( + [], + ); const [isLoading, setIsLoading] = React.useState(false); const { error, retry } = useAsyncRetry(async () => { try { - if (!incident || !open) { + if (!alert || !open) { return; } - const data = await ilertApi.fetchIncidentActions(incident); - setIncidentActionsList(data); + const data = await ilertApi.fetchAlertActions(alert); + setAlertActionsList(data); } catch (e) { if (!(e instanceof AuthenticationError)) { errorApi.post(e); } throw e; } - }, [incident, open]); + }, [alert, open]); return [ { - incidentActions: incidentActionsList, + alertActions: alertActionsList, error, isLoading, }, { - setIncidentActionsList, + setAlertActionsList, setIsLoading, retry, }, diff --git a/plugins/ilert/src/hooks/useAlertSource.ts b/plugins/ilert/src/hooks/useAlertSource.ts index 279150a724..c80b3d59eb 100644 --- a/plugins/ilert/src/hooks/useAlertSource.ts +++ b/plugins/ilert/src/hooks/useAlertSource.ts @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; -import { ilertApiRef } from '../api'; +import { errorApiRef, useApi } from '@backstage/core-plugin-api'; import { AuthenticationError } from '@backstage/errors'; +import React from 'react'; import useAsyncRetry from 'react-use/lib/useAsyncRetry'; +import { ilertApiRef } from '../api'; import { AlertSource, UptimeMonitor } from '../types'; -import { useApi, errorApiRef } from '@backstage/core-plugin-api'; export const useAlertSource = (integrationKey: string) => { const ilertApi = useApi(ilertApiRef); diff --git a/plugins/ilert/src/hooks/useAlertSourceOnCalls.ts b/plugins/ilert/src/hooks/useAlertSourceOnCalls.ts index 5a804e37fd..2884e890db 100644 --- a/plugins/ilert/src/hooks/useAlertSourceOnCalls.ts +++ b/plugins/ilert/src/hooks/useAlertSourceOnCalls.ts @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; -import { ilertApiRef } from '../api'; +import { errorApiRef, useApi } from '@backstage/core-plugin-api'; import { AuthenticationError } from '@backstage/errors'; +import React from 'react'; import useAsyncRetry from 'react-use/lib/useAsyncRetry'; +import { ilertApiRef } from '../api'; import { AlertSource, OnCall } from '../types'; -import { useApi, errorApiRef } from '@backstage/core-plugin-api'; export const useAlertSourceOnCalls = (alertSource?: AlertSource | null) => { const ilertApi = useApi(ilertApiRef); diff --git a/plugins/ilert/src/hooks/useIncidents.ts b/plugins/ilert/src/hooks/useAlerts.ts similarity index 57% rename from plugins/ilert/src/hooks/useIncidents.ts rename to plugins/ilert/src/hooks/useAlerts.ts index 45f28937c5..8acabe0086 100644 --- a/plugins/ilert/src/hooks/useIncidents.ts +++ b/plugins/ilert/src/hooks/useAlerts.ts @@ -13,20 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; -import { GetIncidentsOpts, ilertApiRef, TableState } from '../api'; +import { errorApiRef, useApi } from '@backstage/core-plugin-api'; import { AuthenticationError } from '@backstage/errors'; +import React from 'react'; import useAsyncRetry from 'react-use/lib/useAsyncRetry'; -import { - ACCEPTED, - PENDING, - Incident, - IncidentStatus, - AlertSource, -} from '../types'; -import { useApi, errorApiRef } from '@backstage/core-plugin-api'; +import { GetAlertsOpts, ilertApiRef, TableState } from '../api'; +import { ACCEPTED, Alert, AlertSource, AlertStatus, PENDING } from '../types'; -export const useIncidents = ( +export const useAlerts = ( paging: boolean, singleSource?: boolean, alertSource?: AlertSource | null, @@ -38,21 +32,21 @@ export const useIncidents = ( page: 0, pageSize: 10, }); - const [states, setStates] = React.useState([ + const [states, setStates] = React.useState([ ACCEPTED, PENDING, ]); - const [incidentsList, setIncidentsList] = React.useState([]); - const [incidentsCount, setIncidentsCount] = React.useState(0); + const [alertsList, setAlertsList] = React.useState([]); + const [alertsCount, setAlertsCount] = React.useState(0); const [isLoading, setIsLoading] = React.useState(false); - const fetchIncidentsCall = async () => { + const fetchAlertsCall = async () => { try { if (singleSource && !alertSource) { return; } setIsLoading(true); - const opts: GetIncidentsOpts = { + const opts: GetAlertsOpts = { states, alertSources: alertSource ? [alertSource.id] : [], }; @@ -60,8 +54,8 @@ export const useIncidents = ( opts.maxResults = tableState.pageSize; opts.startIndex = tableState.page * tableState.pageSize; } - const data = await ilertApi.fetchIncidents(opts); - setIncidentsList(data || []); + const data = await ilertApi.fetchAlerts(opts); + setAlertsList(data || []); setIsLoading(false); } catch (e) { if (!(e instanceof AuthenticationError)) { @@ -72,10 +66,10 @@ export const useIncidents = ( } }; - const fetchIncidentsCountCall = async () => { + const fetchAlertsCountCall = async () => { try { - const count = await ilertApi.fetchIncidentsCount({ states }); - setIncidentsCount(count || 0); + const count = await ilertApi.fetchAlertsCount({ states }); + setAlertsCount(count || 0); } catch (e) { if (!(e instanceof AuthenticationError)) { errorApi.post(e); @@ -83,44 +77,44 @@ export const useIncidents = ( throw e; } }; - const fetchIncidents = useAsyncRetry(fetchIncidentsCall, [ + const fetchAlerts = useAsyncRetry(fetchAlertsCall, [ tableState, states, singleSource, alertSource, ]); - const refetchIncidents = () => { + const refetchAlerts = () => { setTableState({ ...tableState, page: 0 }); - Promise.all([fetchIncidentsCall(), fetchIncidentsCountCall()]); + Promise.all([fetchAlertsCall(), fetchAlertsCountCall()]); }; - const fetchIncidentsCount = useAsyncRetry(fetchIncidentsCountCall, [states]); + const fetchAlertsCount = useAsyncRetry(fetchAlertsCountCall, [states]); - const error = fetchIncidents.error || fetchIncidentsCount.error; + const error = fetchAlerts.error || fetchAlertsCount.error; const retry = () => { - fetchIncidents.retry(); - fetchIncidentsCount.retry(); + fetchAlerts.retry(); + fetchAlertsCount.retry(); }; - const onIncidentChanged = (newIncident: Incident) => { - let shouldRefetchIncidents = false; - setIncidentsList( - incidentsList.reduce((acc: Incident[], incident: Incident) => { - if (newIncident.id === incident.id) { - if (states.includes(newIncident.status)) { - acc.push(newIncident); + const onAlertChanged = (newAlert: Alert) => { + let shouldRefetchAlerts = false; + setAlertsList( + alertsList.reduce((acc: Alert[], alert: Alert) => { + if (newAlert.id === alert.id) { + if (states.includes(newAlert.status)) { + acc.push(newAlert); } else { - shouldRefetchIncidents = true; + shouldRefetchAlerts = true; } return acc; } - acc.push(incident); + acc.push(alert); return acc; }, []), ); - if (shouldRefetchIncidents) { - refetchIncidents(); + if (shouldRefetchAlerts) { + refetchAlerts(); } }; @@ -130,7 +124,7 @@ export const useIncidents = ( const onChangeRowsPerPage = (p: number) => { setTableState({ ...tableState, pageSize: p }); }; - const onIncidentStatesChange = (s: IncidentStatus[]) => { + const onAlertStatesChange = (s: AlertStatus[]) => { setStates(s); }; @@ -138,22 +132,22 @@ export const useIncidents = ( { tableState, states, - incidents: incidentsList, - incidentsCount, + alerts: alertsList, + alertsCount, error, isLoading, }, { setTableState, setStates, - setIncidentsList, + setAlertsList, setIsLoading, retry, - onIncidentChanged, - refetchIncidents, + onAlertChanged, + refetchAlerts, onChangePage, onChangeRowsPerPage, - onIncidentStatesChange, + onAlertStatesChange, }, ] as const; }; diff --git a/plugins/ilert/src/hooks/useAssignIncident.ts b/plugins/ilert/src/hooks/useAssignAlert.ts similarity index 68% rename from plugins/ilert/src/hooks/useAssignIncident.ts rename to plugins/ilert/src/hooks/useAssignAlert.ts index b760f31e9c..f81eae724f 100644 --- a/plugins/ilert/src/hooks/useAssignIncident.ts +++ b/plugins/ilert/src/hooks/useAssignAlert.ts @@ -13,30 +13,30 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; -import { ilertApiRef } from '../api'; +import { errorApiRef, useApi } from '@backstage/core-plugin-api'; import { AuthenticationError } from '@backstage/errors'; +import React from 'react'; import useAsyncRetry from 'react-use/lib/useAsyncRetry'; -import { Incident, IncidentResponder } from '../types'; -import { useApi, errorApiRef } from '@backstage/core-plugin-api'; +import { ilertApiRef } from '../api'; +import { Alert, AlertResponder } from '../types'; -export const useAssignIncident = (incident: Incident | null, open: boolean) => { +export const useAssignAlert = (alert: Alert | null, open: boolean) => { const ilertApi = useApi(ilertApiRef); const errorApi = useApi(errorApiRef); - const [incidentRespondersList, setIncidentRespondersList] = React.useState< - IncidentResponder[] + const [alertRespondersList, setAlertRespondersList] = React.useState< + AlertResponder[] >([]); - const [incidentResponder, setIncidentResponder] = - React.useState(null); + const [alertResponder, setAlertResponder] = + React.useState(null); const [isLoading, setIsLoading] = React.useState(false); const { error, retry } = useAsyncRetry(async () => { try { - if (!incident || !open) { + if (!alert || !open) { return; } - const data = await ilertApi.fetchIncidentResponders(incident); + const data = await ilertApi.fetchAlertResponders(alert); if (data && Array.isArray(data)) { const groups = [ 'SUGGESTED', @@ -45,7 +45,7 @@ export const useAssignIncident = (incident: Incident | null, open: boolean) => { 'ON_CALL_SCHEDULE', ]; data.sort((a, b) => groups.indexOf(a.group) - groups.indexOf(b.group)); - setIncidentRespondersList(data); + setAlertRespondersList(data); } } catch (e) { if (!(e instanceof AuthenticationError)) { @@ -53,18 +53,18 @@ export const useAssignIncident = (incident: Incident | null, open: boolean) => { } throw e; } - }, [incident, open]); + }, [alert, open]); return [ { - incidentRespondersList, - incidentResponder, + alertRespondersList, + alertResponder, error, isLoading, }, { - setIncidentRespondersList, - setIncidentResponder, + setAlertRespondersList, + setAlertResponder, setIsLoading, retry, }, diff --git a/plugins/ilert/src/hooks/useNewIncident.ts b/plugins/ilert/src/hooks/useNewAlert.ts similarity index 95% rename from plugins/ilert/src/hooks/useNewIncident.ts rename to plugins/ilert/src/hooks/useNewAlert.ts index f2bb3a8cd3..a560c1b035 100644 --- a/plugins/ilert/src/hooks/useNewIncident.ts +++ b/plugins/ilert/src/hooks/useNewAlert.ts @@ -13,14 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; -import { ilertApiRef } from '../api'; +import { errorApiRef, useApi } from '@backstage/core-plugin-api'; import { AuthenticationError } from '@backstage/errors'; +import React from 'react'; import useAsyncRetry from 'react-use/lib/useAsyncRetry'; +import { ilertApiRef } from '../api'; import { AlertSource } from '../types'; -import { useApi, errorApiRef } from '@backstage/core-plugin-api'; -export const useNewIncident = ( +export const useNewAlert = ( open: boolean, initialAlertSource?: AlertSource | null, ) => { diff --git a/plugins/ilert/src/types.ts b/plugins/ilert/src/types.ts index 3d1531329a..3e5ecf94c4 100644 --- a/plugins/ilert/src/types.ts +++ b/plugins/ilert/src/types.ts @@ -15,15 +15,15 @@ */ /** @public */ -export interface Incident { +export interface Alert { id: number; summary: string; details: string; reportTime: string; resolvedOn: string; - status: IncidentStatus; - priority: IncidentPriority; - incidentKey: string; + status: AlertStatus; + priority: AlertPriority; + alertKey: string; alertSource: AlertSource | null; assignedTo: User | null; logEntries: LogEntry[]; @@ -42,10 +42,10 @@ export const ACCEPTED = 'ACCEPTED'; export const RESOLVED = 'RESOLVED'; /** @public */ -export type IncidentStatus = typeof PENDING | typeof ACCEPTED | typeof RESOLVED; +export type AlertStatus = typeof PENDING | typeof ACCEPTED | typeof RESOLVED; /** @public */ -export type IncidentPriority = 'HIGH' | 'LOW'; +export type AlertPriority = 'HIGH' | 'LOW'; /** @public */ export interface Link { @@ -76,7 +76,7 @@ export interface LogEntry { timestamp: string; logEntryType: string; text: string; - incidentId?: number; + alertId?: number; iconName?: string; iconClass?: string; filterTypes?: string[]; @@ -125,8 +125,8 @@ export interface AlertSource { iconUrl?: string; lightIconUrl?: string; darkIconUrl?: string; - incidentCreation?: AlertSourceIncidentCreation; - incidentPriorityRule?: AlertSourceIncidentPriorityRule; + alertCreation?: AlertSourceAlertCreation; + alertPriorityRule?: AlertSourceAlertPriorityRule; emailFiltered?: boolean; emailResolveFiltered?: boolean; active?: boolean; @@ -209,16 +209,16 @@ export type AlertSourceIntegrationType = | 'CORTEXXSOAR' | string; /** @public */ -export type AlertSourceIncidentCreation = - | 'ONE_INCIDENT_PER_EMAIL' - | 'ONE_INCIDENT_PER_EMAIL_SUBJECT' - | 'ONE_PENDING_INCIDENT_ALLOWED' - | 'ONE_OPEN_INCIDENT_ALLOWED' +export type AlertSourceAlertCreation = + | 'ONE_ALERT_PER_EMAIL' + | 'ONE_ALERT_PER_EMAIL_SUBJECT' + | 'ONE_PENDING_ALERT_ALLOWED' + | 'ONE_OPEN_ALERT_ALLOWED' | 'OPEN_RESOLVE_ON_EXTRACTION'; /** @public */ export type AlertSourceFilterOperator = 'AND' | 'OR'; /** @public */ -export type AlertSourceIncidentPriorityRule = +export type AlertSourceAlertPriorityRule = | 'HIGH' | 'LOW' | 'HIGH_DURING_SUPPORT_HOURS' @@ -251,7 +251,7 @@ export interface AlertSourceSupportDay { /** @public */ export interface AlertSourceSupportHours { timezone: AlertSourceTimeZone; - autoRaiseIncidents: boolean; + autoRaiseAlerts: boolean; supportDays: { MONDAY: AlertSourceSupportDay; TUESDAY: AlertSourceSupportDay; @@ -324,7 +324,7 @@ export interface UptimeMonitor { checkParams: UptimeMonitorCheckParams; intervalSec: number; timeoutMs: number; - createIncidentAfterFailedChecks: number; + createAlertAfterFailedChecks: number; paused: boolean; embedUrl: string; shareUrl: string; @@ -342,7 +342,7 @@ export interface UptimeMonitorCheckParams { } /** @public */ -export interface IncidentResponder { +export interface AlertResponder { group: 'SUGGESTED' | 'USER' | 'ESCALATION_POLICY' | 'ON_CALL_SCHEDULE'; id: number; name: string; @@ -350,19 +350,19 @@ export interface IncidentResponder { } /** @public */ -export interface IncidentAction { +export interface AlertAction { name: string; type: string; webhookId: string; extensionId?: string; - history?: IncidentActionHistory[]; + history?: AlertActionHistory[]; } /** @public */ -export interface IncidentActionHistory { +export interface AlertActionHistory { id: string; webhookId: string; - incidentId: number; + alertId: number; actor: User; success: boolean; } From f41d2d69a6ae886a0ff19c51f0b878bace42a3e3 Mon Sep 17 00:00:00 2001 From: Marko Simon Date: Thu, 29 Sep 2022 12:30:33 +0200 Subject: [PATCH 02/13] remove username from user display Signed-off-by: Marko Simon --- plugins/ilert/src/api/client.ts | 2 +- .../components/OnCallSchedulesPage/OnCallShiftItem.tsx | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/ilert/src/api/client.ts b/plugins/ilert/src/api/client.ts index 2fa6f38c6e..9b8a9f636e 100644 --- a/plugins/ilert/src/api/client.ts +++ b/plugins/ilert/src/api/client.ts @@ -521,7 +521,7 @@ export class ILertClient implements ILertApi { if (!user.firstName && !user.lastName) { return user.username; } - return `${user.firstName} ${user.lastName} (${user.username})`; + return `${user.firstName} ${user.lastName}`; } private async apiUrl() { diff --git a/plugins/ilert/src/components/OnCallSchedulesPage/OnCallShiftItem.tsx b/plugins/ilert/src/components/OnCallSchedulesPage/OnCallShiftItem.tsx index e0fa82fe85..f9c28430d8 100644 --- a/plugins/ilert/src/components/OnCallSchedulesPage/OnCallShiftItem.tsx +++ b/plugins/ilert/src/components/OnCallSchedulesPage/OnCallShiftItem.tsx @@ -13,14 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; import Button from '@material-ui/core/Button'; import Grid from '@material-ui/core/Grid'; +import { makeStyles } from '@material-ui/core/styles'; import Typography from '@material-ui/core/Typography'; import RepeatIcon from '@material-ui/icons/Repeat'; -import { Shift } from '../../types'; import { DateTime as dt } from 'luxon'; -import { makeStyles } from '@material-ui/core/styles'; +import React from 'react'; +import { Shift } from '../../types'; import { ShiftOverrideModal } from '../Shift/ShiftOverrideModal'; const useStyles = makeStyles({ @@ -71,7 +71,7 @@ export const OnCallShiftItem = ({ {shift && shift.user ? ( - {`${shift.user.firstName} ${shift.user.lastName} (${shift.user.username})`} + {`${shift.user.firstName} ${shift.user.lastName}`} ) : null} From bfd8e9282dc439cf405cc76b4abad48b5660dcf7 Mon Sep 17 00:00:00 2001 From: Marko Simon Date: Mon, 3 Oct 2022 13:26:30 +0200 Subject: [PATCH 03/13] add services Signed-off-by: Marko Simon --- plugins/ilert/src/api/client.ts | 50 ++++- plugins/ilert/src/api/index.ts | 3 +- plugins/ilert/src/api/types.ts | 16 ++ .../src/components/AlertsPage/AlertsTable.tsx | 21 ++- .../src/components/ILertPage/ILertPage.tsx | 4 + .../components/Service/ServiceActionsMenu.tsx | 68 +++++++ .../src/components/Service/ServiceLink.tsx | 43 +++++ .../components/Service/ServiceNewModal.tsx | 136 ++++++++++++++ .../src/components/Service/ServiceStatus.tsx | 57 ++++++ plugins/ilert/src/components/Service/index.ts | 17 ++ .../components/ServicesPage/ServicesPage.tsx | 90 +++++++++ .../components/ServicesPage/ServicesTable.tsx | 172 ++++++++++++++++++ .../components/ServicesPage/StatusChip.tsx | 82 +++++++++ .../components/ServicesPage/TableTitle.tsx | 97 ++++++++++ .../src/components/ServicesPage/index.ts | 17 ++ plugins/ilert/src/hooks/useNewService.ts | 32 ++++ plugins/ilert/src/hooks/useServices.ts | 91 +++++++++ plugins/ilert/src/types.ts | 46 +++++ 18 files changed, 1031 insertions(+), 11 deletions(-) create mode 100644 plugins/ilert/src/components/Service/ServiceActionsMenu.tsx create mode 100644 plugins/ilert/src/components/Service/ServiceLink.tsx create mode 100644 plugins/ilert/src/components/Service/ServiceNewModal.tsx create mode 100644 plugins/ilert/src/components/Service/ServiceStatus.tsx create mode 100644 plugins/ilert/src/components/Service/index.ts create mode 100644 plugins/ilert/src/components/ServicesPage/ServicesPage.tsx create mode 100644 plugins/ilert/src/components/ServicesPage/ServicesTable.tsx create mode 100644 plugins/ilert/src/components/ServicesPage/StatusChip.tsx create mode 100644 plugins/ilert/src/components/ServicesPage/TableTitle.tsx create mode 100644 plugins/ilert/src/components/ServicesPage/index.ts create mode 100644 plugins/ilert/src/hooks/useNewService.ts create mode 100644 plugins/ilert/src/hooks/useServices.ts diff --git a/plugins/ilert/src/api/client.ts b/plugins/ilert/src/api/client.ts index 9b8a9f636e..4269ef583d 100644 --- a/plugins/ilert/src/api/client.ts +++ b/plugins/ilert/src/api/client.ts @@ -28,6 +28,7 @@ import { EscalationPolicy, OnCall, Schedule, + Service, UptimeMonitor, User, } from '../types'; @@ -35,7 +36,9 @@ import { EventRequest, GetAlertsCountOpts, GetAlertsOpts, + GetServicesOpts, ILertApi, + ServiceRequest, } from './types'; /** @public */ @@ -127,7 +130,6 @@ export class ILertClient implements ILertApi { }); } const response = await this.fetch(`/api/alerts?${query.toString()}`, init); - return response; } @@ -444,7 +446,10 @@ export class ILertClient implements ILertApi { headers: JSON_HEADERS, }; - const response = await this.fetch('/api/schedules', init); + const response = await this.fetch( + '/api/schedules?include=currentShift&include=nextShift', + init, + ); return response; } @@ -479,6 +484,41 @@ export class ILertClient implements ILertApi { return response; } + async fetchServices(opts?: GetServicesOpts): Promise { + const init = { + headers: JSON_HEADERS, + }; + const query = new URLSearchParams(); + if (opts?.maxResults !== undefined) { + query.append('max-results', String(opts.maxResults)); + } + if (opts?.startIndex !== undefined) { + query.append('start-index', String(opts.startIndex)); + } + + query.append('include', 'uptime'); + + const response = await this.fetch( + `/api/services?${query.toString()}`, + init, + ); + return response; + } + + async createService(serviceRequest: ServiceRequest): Promise { + const init = { + method: 'POST', + headers: JSON_HEADERS, + body: JSON.stringify({ + // apiKey: eventRequest.integrationKey, + name: serviceRequest.name, + }), + }; + + const response = await this.fetch('/api/services', init); + return response; + } + getAlertDetailsURL(alert: Alert): string { return `${this.baseUrl}/alert/view.jsf?id=${encodeURIComponent(alert.id)}`; } @@ -510,6 +550,12 @@ export class ILertClient implements ILertApi { )}`; } + getServiceDetailsURL(service: Service): string { + return `${this.baseUrl}/service/view.jsf?id=${encodeURIComponent( + service.id, + )}`; + } + getUserPhoneNumber(user: User | null) { return user?.mobile?.number || user?.landline?.number || ''; } diff --git a/plugins/ilert/src/api/index.ts b/plugins/ilert/src/api/index.ts index b33a702a5c..f0688e0f63 100644 --- a/plugins/ilert/src/api/index.ts +++ b/plugins/ilert/src/api/index.ts @@ -16,9 +16,10 @@ export { ilertApiRef, ILertClient } from './client'; export type { - EventRequest, + AlertEventRequest as EventRequest, GetAlertsCountOpts, GetAlertsOpts, + GetServicesOpts, ILertApi, TableState, } from './types'; diff --git a/plugins/ilert/src/api/types.ts b/plugins/ilert/src/api/types.ts index b7af3d845d..39eb373ae2 100644 --- a/plugins/ilert/src/api/types.ts +++ b/plugins/ilert/src/api/types.ts @@ -23,6 +23,7 @@ import { EscalationPolicy, OnCall, Schedule, + Service, UptimeMonitor, User, } from '../types'; @@ -46,6 +47,12 @@ export type GetAlertsCountOpts = { states?: AlertStatus[]; }; +/** @public */ +export type GetServicesOpts = { + maxResults?: number; + startIndex?: number; +}; + /** @public */ export type EventRequest = { integrationKey: string; @@ -55,6 +62,11 @@ export type EventRequest = { source: string; }; +/** @public */ +export type ServiceRequest = { + name: string; +}; + /** @public */ export interface ILertApi { fetchAlerts(opts?: GetAlertsOpts): Promise; @@ -94,11 +106,15 @@ export interface ILertApi { end: string, ): Promise; + fetchServices(opts?: GetServicesOpts): Promise; + createService(eventRequest: ServiceRequest): Promise; + getAlertDetailsURL(alert: Alert): string; getAlertSourceDetailsURL(alertSource: AlertSource | null): string; getEscalationPolicyDetailsURL(escalationPolicy: EscalationPolicy): string; getUptimeMonitorDetailsURL(uptimeMonitor: UptimeMonitor): string; getScheduleDetailsURL(schedule: Schedule): string; + getServiceDetailsURL(service: Service): string; getUserPhoneNumber(user: User | null): string; getUserInitials(user: User | null): string; } diff --git a/plugins/ilert/src/components/AlertsPage/AlertsTable.tsx b/plugins/ilert/src/components/AlertsPage/AlertsTable.tsx index cb3a6b886a..38ef4f07b1 100644 --- a/plugins/ilert/src/components/AlertsPage/AlertsTable.tsx +++ b/plugins/ilert/src/components/AlertsPage/AlertsTable.tsx @@ -140,14 +140,19 @@ export const AlertsTable = ({ ), }; - const assignedToColumn: TableColumn = { - title: 'Assigned to', - field: 'assignedTo', + const respondersColumn: TableColumn = { + title: 'Responders', + field: 'responders', cellStyle: !compact ? mdColumnStyle : lgColumnStyle, headerStyle: !compact ? mdColumnStyle : lgColumnStyle, render: rowData => ( - - {ilertApi.getUserInitials((rowData as Alert).assignedTo)} + + {(rowData as Alert).responders.map((value, i, arr) => { + return ( + ilertApi.getUserInitials(value.user) + + (arr.length - 1 !== i ? ', ' : '') + ); + })} ), }; @@ -187,7 +192,7 @@ export const AlertsTable = ({ ? [ summaryColumn, durationColumn, - assignedToColumn, + respondersColumn, statusColumn, actionsColumn, ] @@ -196,7 +201,7 @@ export const AlertsTable = ({ summaryColumn, sourceColumn, durationColumn, - assignedToColumn, + respondersColumn, priorityColumn, statusColumn, actionsColumn, @@ -247,7 +252,7 @@ export const AlertsTable = ({ /> ) : ( - INCIDENTS + ALERTS ) } diff --git a/plugins/ilert/src/components/ILertPage/ILertPage.tsx b/plugins/ilert/src/components/ILertPage/ILertPage.tsx index 8dfed11690..cc7527c316 100644 --- a/plugins/ilert/src/components/ILertPage/ILertPage.tsx +++ b/plugins/ilert/src/components/ILertPage/ILertPage.tsx @@ -23,6 +23,7 @@ import { import React from 'react'; import { AlertsPage } from '../AlertsPage'; import { OnCallSchedulesPage } from '../OnCallSchedulesPage'; +import { ServicesPage } from '../ServicesPage'; import { UptimeMonitorsPage } from '../UptimeMonitorsPage'; /** @public */ @@ -32,6 +33,7 @@ export const ILertPage = () => { { label: 'Who is on call?' }, { label: 'Alerts' }, { label: 'Uptime Monitors' }, + { label: 'Services' }, ]; const renderTab = () => { switch (selectedTab) { @@ -41,6 +43,8 @@ export const ILertPage = () => { return ; case 2: return ; + case 3: + return ; default: return null; } diff --git a/plugins/ilert/src/components/Service/ServiceActionsMenu.tsx b/plugins/ilert/src/components/Service/ServiceActionsMenu.tsx new file mode 100644 index 0000000000..096cc391ee --- /dev/null +++ b/plugins/ilert/src/components/Service/ServiceActionsMenu.tsx @@ -0,0 +1,68 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { IconButton, Menu, MenuItem, Typography } from '@material-ui/core'; +import MoreVertIcon from '@material-ui/icons/MoreVert'; +import React from 'react'; +import { ilertApiRef } from '../../api'; +import { Service } from '../../types'; + +import { Link } from '@backstage/core-components'; +import { useApi } from '@backstage/core-plugin-api'; + +export const ServiceActionsMenu = ({ service }: { service: Service }) => { + const ilertApi = useApi(ilertApiRef); + const [anchorEl, setAnchorEl] = React.useState(null); + + const handleClick = (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget); + }; + + const handleCloseMenu = () => { + setAnchorEl(null); + }; + + return ( + <> + + + + + + + + View in iLert + + + + + + ); +}; diff --git a/plugins/ilert/src/components/Service/ServiceLink.tsx b/plugins/ilert/src/components/Service/ServiceLink.tsx new file mode 100644 index 0000000000..f8b1e88531 --- /dev/null +++ b/plugins/ilert/src/components/Service/ServiceLink.tsx @@ -0,0 +1,43 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { makeStyles } from '@material-ui/core/styles'; +import React from 'react'; +import { ilertApiRef } from '../../api'; +import { Service } from '../../types'; + +import { Link } from '@backstage/core-components'; +import { useApi } from '@backstage/core-plugin-api'; + +const useStyles = makeStyles({ + link: { + lineHeight: '22px', + }, +}); + +export const ServiceLink = ({ service }: { service: Service | null }) => { + const ilertApi = useApi(ilertApiRef); + const classes = useStyles(); + + if (!service) { + return null; + } + + return ( + + #{service.id} + + ); +}; diff --git a/plugins/ilert/src/components/Service/ServiceNewModal.tsx b/plugins/ilert/src/components/Service/ServiceNewModal.tsx new file mode 100644 index 0000000000..64823eaf46 --- /dev/null +++ b/plugins/ilert/src/components/Service/ServiceNewModal.tsx @@ -0,0 +1,136 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { alertApiRef, useApi } from '@backstage/core-plugin-api'; +import Button from '@material-ui/core/Button'; +import Dialog from '@material-ui/core/Dialog'; +import DialogActions from '@material-ui/core/DialogActions'; +import DialogContent from '@material-ui/core/DialogContent'; +import DialogTitle from '@material-ui/core/DialogTitle'; +import { makeStyles } from '@material-ui/core/styles'; +import TextField from '@material-ui/core/TextField'; +import React from 'react'; +import { ilertApiRef } from '../../api'; +import { useNewService } from '../../hooks/useNewService'; + +const useStyles = makeStyles(() => ({ + container: { + display: 'flex', + flexWrap: 'wrap', + }, + formControl: { + minWidth: 120, + width: '100%', + }, + option: { + fontSize: 15, + '& > span': { + marginRight: 10, + fontSize: 18, + }, + }, + optionWrapper: { + display: 'flex', + width: '100%', + }, + sourceImage: { + height: 22, + paddingRight: 4, + }, +})); + +export const ServiceNewModal = ({ + isModalOpened, + setIsModalOpened, + refetchServices, +}: { + isModalOpened: boolean; + setIsModalOpened: (open: boolean) => void; + refetchServices: () => void; +}) => { + const [{ name, isLoading }, { setName, setIsLoading }] = useNewService(); + const ilertApi = useApi(ilertApiRef); + const alertApi = useApi(alertApiRef); + const classes = useStyles(); + + const handleClose = () => { + setIsModalOpened(false); + }; + + const handleCreate = () => { + setIsLoading(true); + setTimeout(async () => { + try { + await ilertApi.createService({ + name, + }); + alertApi.post({ message: 'Service created.' }); + refetchServices(); + } catch (err) { + alertApi.post({ message: err, severity: 'error' }); + } + setIsModalOpened(false); + }, 250); + }; + + const canCreate = !!name; + + return ( + + 'New alert' + + {/* + + Please describe the problem you want to report. Be as descriptive as + possible. Your signed in user and a reference to the current page + will automatically be amended to the alarm so that the receiver can + reach out to you if necessary. + + */} + { + setName(event.target.value); + }} + /> + + + + + + + ); +}; diff --git a/plugins/ilert/src/components/Service/ServiceStatus.tsx b/plugins/ilert/src/components/Service/ServiceStatus.tsx new file mode 100644 index 0000000000..05923058aa --- /dev/null +++ b/plugins/ilert/src/components/Service/ServiceStatus.tsx @@ -0,0 +1,57 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { StatusError, StatusOK } from '@backstage/core-components'; +import { makeStyles } from '@material-ui/core/styles'; +import Tooltip from '@material-ui/core/Tooltip'; +import React from 'react'; +import { + DEGRADED, + MAJOR_OUTAGE, + OPERATIONAL, + PARTIAL_OUTAGE, + Service, + UNDER_MAINTENANCE, +} from '../../types'; + +const useStyles = makeStyles({ + denseListIcon: { + marginRight: 0, + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + }, +}); + +export const serviceStatusLabels = { + [OPERATIONAL]: 'Operational', + [UNDER_MAINTENANCE]: 'Under maintenance', + [DEGRADED]: 'Degraded', + [PARTIAL_OUTAGE]: 'Partial outage', + [MAJOR_OUTAGE]: 'Major outage', +} as Record; + +export const ServiceStatus = ({ service }: { service: Service }) => { + const classes = useStyles(); + + return ( + +
+ {service.status === 'OPERATIONAL' ? : } +
+
+ ); +}; diff --git a/plugins/ilert/src/components/Service/index.ts b/plugins/ilert/src/components/Service/index.ts new file mode 100644 index 0000000000..5227f44573 --- /dev/null +++ b/plugins/ilert/src/components/Service/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 * from './ServiceActionsMenu'; +export * from './ServiceStatus'; diff --git a/plugins/ilert/src/components/ServicesPage/ServicesPage.tsx b/plugins/ilert/src/components/ServicesPage/ServicesPage.tsx new file mode 100644 index 0000000000..73b2d92f3c --- /dev/null +++ b/plugins/ilert/src/components/ServicesPage/ServicesPage.tsx @@ -0,0 +1,90 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { + Content, + ContentHeader, + ResponseErrorPanel, + SupportButton, +} from '@backstage/core-components'; +import { AuthenticationError } from '@backstage/errors'; +import Button from '@material-ui/core/Button'; +import AddIcon from '@material-ui/icons/Add'; +import React from 'react'; +import { useServices } from '../../hooks/useServices'; +import { MissingAuthorizationHeaderError } from '../Errors'; +import { ServiceNewModal } from '../Service/ServiceNewModal'; +import { ServicesTable } from './ServicesTable'; + +export const ServicesPage = () => { + const [ + { tableState, services, isLoading, error }, + { onChangePage, onChangeRowsPerPage, refetchServices, setIsLoading }, + ] = useServices(true); + + const [isModalOpened, setIsModalOpened] = React.useState(false); + + const handleCreateNewServiceClick = () => { + setIsModalOpened(true); + }; + + if (error) { + if (error instanceof AuthenticationError) { + return ( + + + + ); + } + + return ( + + + + ); + } + + return ( + + + + + + This helps you to bring iLert into your developer portal. + + + + + ); +}; diff --git a/plugins/ilert/src/components/ServicesPage/ServicesTable.tsx b/plugins/ilert/src/components/ServicesPage/ServicesTable.tsx new file mode 100644 index 0000000000..bfb20acd71 --- /dev/null +++ b/plugins/ilert/src/components/ServicesPage/ServicesTable.tsx @@ -0,0 +1,172 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { makeStyles } from '@material-ui/core/styles'; +import Typography from '@material-ui/core/Typography'; +import React from 'react'; +import { ilertApiRef, TableState } from '../../api'; +import { Service } from '../../types'; +import { StatusChip } from './StatusChip'; + +import { Table, TableColumn } from '@backstage/core-components'; +import { useApi } from '@backstage/core-plugin-api'; +import { ServiceActionsMenu } from '../Service/ServiceActionsMenu'; +import { ServiceLink } from '../Service/ServiceLink'; + +const useStyles = makeStyles(theme => ({ + empty: { + padding: theme.spacing(2), + display: 'flex', + justifyContent: 'center', + }, +})); + +export const ServicesTable = ({ + services, + tableState, + isLoading, + onChangePage, + onChangeRowsPerPage, + compact, +}: { + services: Service[]; + tableState: TableState; + isLoading: boolean; + setIsLoading: (isLoading: boolean) => void; + onChangePage: (page: number) => void; + onChangeRowsPerPage: (pageSize: number) => void; + compact?: boolean; +}) => { + const ilertApi = useApi(ilertApiRef); + const classes = useStyles(); + + const xsColumnStyle = { + width: '5%', + maxWidth: '5%', + }; + const smColumnStyle = { + width: '10%', + maxWidth: '10%', + }; + const mdColumnStyle = { + width: '15%', + maxWidth: '15%', + }; + const lgColumnStyle = { + width: '20%', + maxWidth: '20%', + }; + const xlColumnStyle = { + width: '30%', + maxWidth: '30%', + }; + + const idColumn: TableColumn = { + title: 'ID', + field: 'id', + highlight: true, + cellStyle: smColumnStyle, + headerStyle: smColumnStyle, + render: rowData => , + }; + const nameColumn: TableColumn = { + title: 'Name', + field: 'name', + cellStyle: !compact ? xlColumnStyle : undefined, + headerStyle: !compact ? xlColumnStyle : undefined, + render: rowData => {(rowData as Service).name}, + }; + const statusColumn: TableColumn = { + title: 'Status', + field: 'status', + cellStyle: xsColumnStyle, + headerStyle: xsColumnStyle, + render: rowData => , + }; + const uptimeColumn: TableColumn = { + title: 'Uptime in the last 90 days', + field: 'uptimePercentage', + cellStyle: smColumnStyle, + headerStyle: smColumnStyle, + render: rowData => ( + + {(rowData as Service).uptime.uptimePercentage.p90} + + ), + }; + const actionsColumn: TableColumn = { + title: '', + field: '', + cellStyle: xsColumnStyle, + headerStyle: xsColumnStyle, + render: rowData => , + }; + + const columns: TableColumn[] = compact + ? [nameColumn, statusColumn, uptimeColumn, actionsColumn] + : [idColumn, nameColumn, statusColumn, uptimeColumn, actionsColumn]; + let tableStyle: React.CSSProperties = {}; + if (compact) { + tableStyle = { + width: '100%', + maxWidth: '100%', + minWidth: '0', + height: 'calc(100% - 10px)', + boxShadow: 'none !important', + borderRadius: 'none !important', + }; + } else { + tableStyle = { + width: '100%', + maxWidth: '100%', + }; + } + + return ( + + No services + + } + title={ + + SERVICES + + } + page={tableState.page} + onPageChange={onChangePage} + onRowsPerPageChange={onChangeRowsPerPage} + // localization={{ header: { actions: undefined } }} + columns={columns} + data={services} + isLoading={isLoading} + /> + ); +}; diff --git a/plugins/ilert/src/components/ServicesPage/StatusChip.tsx b/plugins/ilert/src/components/ServicesPage/StatusChip.tsx new file mode 100644 index 0000000000..5eb31b8a94 --- /dev/null +++ b/plugins/ilert/src/components/ServicesPage/StatusChip.tsx @@ -0,0 +1,82 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { Chip, withStyles } from '@material-ui/core'; +import React from 'react'; +import { + DEGRADED, + MAJOR_OUTAGE, + OPERATIONAL, + PARTIAL_OUTAGE, + Service, + UNDER_MAINTENANCE, +} from '../../types'; +import { serviceStatusLabels } from '../Service/ServiceStatus'; + +const OperationalChip = withStyles({ + root: { + backgroundColor: '#4caf50', + color: 'white', + margin: 0, + }, +})(Chip); + +const UnderMaintenanceChip = withStyles({ + root: { + backgroundColor: '#ffb74d', + color: 'white', + margin: 0, + }, +})(Chip); +const DegradedChip = withStyles({ + root: { + backgroundColor: '#d32f2f', + color: 'white', + margin: 0, + }, +})(Chip); +const PartialOutageChip = withStyles({ + root: { + backgroundColor: '#d4a5bb', + color: 'white', + margin: 0, + }, +})(Chip); +const MajorOutageChip = withStyles({ + root: { + backgroundColor: '#28c548', + color: 'white', + margin: 0, + }, +})(Chip); + +export const StatusChip = ({ service }: { service: Service }) => { + const label = `${serviceStatusLabels[service.status]}`; + + switch (service.status) { + case OPERATIONAL: + return ; + case UNDER_MAINTENANCE: + return ; + case DEGRADED: + return ; + case PARTIAL_OUTAGE: + return ; + case MAJOR_OUTAGE: + return ; + default: + return ; + } +}; diff --git a/plugins/ilert/src/components/ServicesPage/TableTitle.tsx b/plugins/ilert/src/components/ServicesPage/TableTitle.tsx new file mode 100644 index 0000000000..c610e91d94 --- /dev/null +++ b/plugins/ilert/src/components/ServicesPage/TableTitle.tsx @@ -0,0 +1,97 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 Checkbox from '@material-ui/core/Checkbox'; +import FormControl from '@material-ui/core/FormControl'; +import ListItemText from '@material-ui/core/ListItemText'; +import MenuItem from '@material-ui/core/MenuItem'; +import Select from '@material-ui/core/Select'; +import { makeStyles } from '@material-ui/core/styles'; +import Typography from '@material-ui/core/Typography'; +import React from 'react'; +import { ACCEPTED, AlertStatus, PENDING, RESOLVED } from '../../types'; +import { alertStatusLabels } from '../Alert/AlertStatus'; + +const ITEM_HEIGHT = 48; +const ITEM_PADDING_TOP = 8; +const MenuProps = { + PaperProps: { + style: { + maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP, + width: 250, + }, + }, +}; + +const useStyles = makeStyles({ + root: { + display: 'flex', + }, + label: { + marginTop: 8, + marginRight: 4, + }, + formControl: { + minWidth: 120, + maxWidth: 300, + }, + grow: { + flexGrow: 1, + }, +}); + +export const TableTitle = ({ + alertStates, + onAlertStatesChange, +}: { + alertStates: AlertStatus[]; + onAlertStatesChange: (states: AlertStatus[]) => void; +}) => { + const classes = useStyles(); + const handleAlertStatusSelectChange = (event: any) => { + onAlertStatesChange(event.target.value); + }; + + return ( +
+ + Status: + + + + +
+ ); +}; diff --git a/plugins/ilert/src/components/ServicesPage/index.ts b/plugins/ilert/src/components/ServicesPage/index.ts new file mode 100644 index 0000000000..6c4eef8100 --- /dev/null +++ b/plugins/ilert/src/components/ServicesPage/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 * from './ServicesPage'; +export * from './ServicesTable'; diff --git a/plugins/ilert/src/hooks/useNewService.ts b/plugins/ilert/src/hooks/useNewService.ts new file mode 100644 index 0000000000..7d50d29a39 --- /dev/null +++ b/plugins/ilert/src/hooks/useNewService.ts @@ -0,0 +1,32 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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'; + +export const useNewService = () => { + const [name, setName] = React.useState(''); + const [isLoading, setIsLoading] = React.useState(false); + + return [ + { + name, + isLoading, + }, + { + setName, + setIsLoading, + }, + ] as const; +}; diff --git a/plugins/ilert/src/hooks/useServices.ts b/plugins/ilert/src/hooks/useServices.ts new file mode 100644 index 0000000000..b6ea120f80 --- /dev/null +++ b/plugins/ilert/src/hooks/useServices.ts @@ -0,0 +1,91 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { errorApiRef, useApi } from '@backstage/core-plugin-api'; +import { AuthenticationError } from '@backstage/errors'; +import React from 'react'; +import useAsyncRetry from 'react-use/lib/useAsyncRetry'; +import { GetServicesOpts, ilertApiRef, TableState } from '../api'; +import { Service } from '../types'; + +export const useServices = (paging: boolean) => { + const ilertApi = useApi(ilertApiRef); + const errorApi = useApi(errorApiRef); + + const [tableState, setTableState] = React.useState({ + page: 0, + pageSize: 10, + }); + + const [servicesList, setServicesList] = React.useState([]); + const [isLoading, setIsLoading] = React.useState(false); + + const fetchServicesCall = async () => { + try { + setIsLoading(true); + const opts: GetServicesOpts = {}; + if (paging) { + opts.maxResults = tableState.pageSize; + opts.startIndex = tableState.page * tableState.pageSize; + } + const data = await ilertApi.fetchServices(opts); + setServicesList(data || []); + setIsLoading(false); + } catch (e) { + if (!(e instanceof AuthenticationError)) { + errorApi.post(e); + } + setIsLoading(false); + throw e; + } + }; + + const fetchServices = useAsyncRetry(fetchServicesCall, [tableState]); + + const refetchServices = () => { + setTableState({ ...tableState, page: 0 }); + Promise.all([fetchServicesCall()]); + }; + + const error = fetchServices.error; + const retry = () => { + fetchServices.retry(); + }; + + const onChangePage = (page: number) => { + setTableState({ ...tableState, page }); + }; + const onChangeRowsPerPage = (p: number) => { + setTableState({ ...tableState, pageSize: p }); + }; + + return [ + { + tableState, + services: servicesList, + isLoading, + error, + }, + { + setTableState, + setServicesList, + setIsLoading, + retry, + refetchServices, + onChangePage, + onChangeRowsPerPage, + }, + ] as const; +}; diff --git a/plugins/ilert/src/types.ts b/plugins/ilert/src/types.ts index 3e5ecf94c4..ebe5c1b39d 100644 --- a/plugins/ilert/src/types.ts +++ b/plugins/ilert/src/types.ts @@ -26,6 +26,7 @@ export interface Alert { alertKey: string; alertSource: AlertSource | null; assignedTo: User | null; + responders: Responder[]; logEntries: LogEntry[]; links: Link[]; images: Image[]; @@ -99,6 +100,13 @@ export interface User { department: string; } +/** @public */ +export interface Responder { + acceptedAt?: string; + status: string; + user: User; +} + /** @public */ export type UserRole = | 'USER' @@ -223,6 +231,26 @@ export type AlertSourceAlertPriorityRule = | 'LOW' | 'HIGH_DURING_SUPPORT_HOURS' | 'LOW_DURING_SUPPORT_HOURS'; + +/** @public */ +export const OPERATIONAL = 'OPERATIONAL'; +/** @public */ +export const UNDER_MAINTENANCE = 'UNDER_MAINTENANCE'; +/** @public */ +export const DEGRADED = 'DEGRADED'; +/** @public */ +export const PARTIAL_OUTAGE = 'PARTIAL_OUTAGE'; +/** @public */ +export const MAJOR_OUTAGE = 'MAJOR_OUTAGE'; + +/** @public */ +export type ServiceStatus = + | typeof OPERATIONAL + | typeof UNDER_MAINTENANCE + | typeof DEGRADED + | typeof PARTIAL_OUTAGE + | typeof MAJOR_OUTAGE; + /** @public */ export interface AlertSourceEmailPredicate { field: 'EMAIL_FROM' | 'EMAIL_SUBJECT' | 'EMAIL_BODY'; @@ -376,3 +404,21 @@ export interface OnCall { end: string; escalationLevel: number; } + +/** @public */ +export interface Service { + id: number; + name: string; + status: ServiceStatus; + uptime: Uptime; +} + +/** @public */ +export interface Uptime { + uptimePercentage: UptimePercentage; +} + +/** @public */ +export interface UptimePercentage { + p90: number; +} From 3ce7fb36d488b6263b65173cbf31634bb6e95ea5 Mon Sep 17 00:00:00 2001 From: Marko Simon Date: Mon, 3 Oct 2022 13:34:05 +0200 Subject: [PATCH 04/13] remove create service Signed-off-by: Marko Simon --- .../components/Service/ServiceNewModal.tsx | 136 ------------------ .../components/ServicesPage/ServicesPage.tsx | 25 +--- .../components/ServicesPage/ServicesTable.tsx | 36 +++-- 3 files changed, 18 insertions(+), 179 deletions(-) delete mode 100644 plugins/ilert/src/components/Service/ServiceNewModal.tsx diff --git a/plugins/ilert/src/components/Service/ServiceNewModal.tsx b/plugins/ilert/src/components/Service/ServiceNewModal.tsx deleted file mode 100644 index 64823eaf46..0000000000 --- a/plugins/ilert/src/components/Service/ServiceNewModal.tsx +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * 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 { alertApiRef, useApi } from '@backstage/core-plugin-api'; -import Button from '@material-ui/core/Button'; -import Dialog from '@material-ui/core/Dialog'; -import DialogActions from '@material-ui/core/DialogActions'; -import DialogContent from '@material-ui/core/DialogContent'; -import DialogTitle from '@material-ui/core/DialogTitle'; -import { makeStyles } from '@material-ui/core/styles'; -import TextField from '@material-ui/core/TextField'; -import React from 'react'; -import { ilertApiRef } from '../../api'; -import { useNewService } from '../../hooks/useNewService'; - -const useStyles = makeStyles(() => ({ - container: { - display: 'flex', - flexWrap: 'wrap', - }, - formControl: { - minWidth: 120, - width: '100%', - }, - option: { - fontSize: 15, - '& > span': { - marginRight: 10, - fontSize: 18, - }, - }, - optionWrapper: { - display: 'flex', - width: '100%', - }, - sourceImage: { - height: 22, - paddingRight: 4, - }, -})); - -export const ServiceNewModal = ({ - isModalOpened, - setIsModalOpened, - refetchServices, -}: { - isModalOpened: boolean; - setIsModalOpened: (open: boolean) => void; - refetchServices: () => void; -}) => { - const [{ name, isLoading }, { setName, setIsLoading }] = useNewService(); - const ilertApi = useApi(ilertApiRef); - const alertApi = useApi(alertApiRef); - const classes = useStyles(); - - const handleClose = () => { - setIsModalOpened(false); - }; - - const handleCreate = () => { - setIsLoading(true); - setTimeout(async () => { - try { - await ilertApi.createService({ - name, - }); - alertApi.post({ message: 'Service created.' }); - refetchServices(); - } catch (err) { - alertApi.post({ message: err, severity: 'error' }); - } - setIsModalOpened(false); - }, 250); - }; - - const canCreate = !!name; - - return ( - - 'New alert' - - {/* - - Please describe the problem you want to report. Be as descriptive as - possible. Your signed in user and a reference to the current page - will automatically be amended to the alarm so that the receiver can - reach out to you if necessary. - - */} - { - setName(event.target.value); - }} - /> - - - - - - - ); -}; diff --git a/plugins/ilert/src/components/ServicesPage/ServicesPage.tsx b/plugins/ilert/src/components/ServicesPage/ServicesPage.tsx index 73b2d92f3c..e3afd4cc1a 100644 --- a/plugins/ilert/src/components/ServicesPage/ServicesPage.tsx +++ b/plugins/ilert/src/components/ServicesPage/ServicesPage.tsx @@ -20,26 +20,17 @@ import { SupportButton, } from '@backstage/core-components'; import { AuthenticationError } from '@backstage/errors'; -import Button from '@material-ui/core/Button'; -import AddIcon from '@material-ui/icons/Add'; import React from 'react'; import { useServices } from '../../hooks/useServices'; import { MissingAuthorizationHeaderError } from '../Errors'; -import { ServiceNewModal } from '../Service/ServiceNewModal'; import { ServicesTable } from './ServicesTable'; export const ServicesPage = () => { const [ { tableState, services, isLoading, error }, - { onChangePage, onChangeRowsPerPage, refetchServices, setIsLoading }, + { onChangePage, onChangeRowsPerPage, setIsLoading }, ] = useServices(true); - const [isModalOpened, setIsModalOpened] = React.useState(false); - - const handleCreateNewServiceClick = () => { - setIsModalOpened(true); - }; - if (error) { if (error instanceof AuthenticationError) { return ( @@ -59,20 +50,6 @@ export const ServicesPage = () => { return ( - - This helps you to bring iLert into your developer portal. diff --git a/plugins/ilert/src/components/ServicesPage/ServicesTable.tsx b/plugins/ilert/src/components/ServicesPage/ServicesTable.tsx index bfb20acd71..4ed1d581ae 100644 --- a/plugins/ilert/src/components/ServicesPage/ServicesTable.tsx +++ b/plugins/ilert/src/components/ServicesPage/ServicesTable.tsx @@ -16,12 +16,11 @@ import { makeStyles } from '@material-ui/core/styles'; import Typography from '@material-ui/core/Typography'; import React from 'react'; -import { ilertApiRef, TableState } from '../../api'; +import { TableState } from '../../api'; import { Service } from '../../types'; import { StatusChip } from './StatusChip'; import { Table, TableColumn } from '@backstage/core-components'; -import { useApi } from '@backstage/core-plugin-api'; import { ServiceActionsMenu } from '../Service/ServiceActionsMenu'; import { ServiceLink } from '../Service/ServiceLink'; @@ -49,25 +48,24 @@ export const ServicesTable = ({ onChangeRowsPerPage: (pageSize: number) => void; compact?: boolean; }) => { - const ilertApi = useApi(ilertApiRef); const classes = useStyles(); - const xsColumnStyle = { - width: '5%', - maxWidth: '5%', - }; + // const xsColumnStyle = { + // width: '5%', + // maxWidth: '5%', + // }; const smColumnStyle = { width: '10%', maxWidth: '10%', }; - const mdColumnStyle = { - width: '15%', - maxWidth: '15%', - }; - const lgColumnStyle = { - width: '20%', - maxWidth: '20%', - }; + // const mdColumnStyle = { + // width: '15%', + // maxWidth: '15%', + // }; + // const lgColumnStyle = { + // width: '20%', + // maxWidth: '20%', + // }; const xlColumnStyle = { width: '30%', maxWidth: '30%', @@ -91,8 +89,8 @@ export const ServicesTable = ({ const statusColumn: TableColumn = { title: 'Status', field: 'status', - cellStyle: xsColumnStyle, - headerStyle: xsColumnStyle, + cellStyle: smColumnStyle, + headerStyle: smColumnStyle, render: rowData => , }; const uptimeColumn: TableColumn = { @@ -109,8 +107,8 @@ export const ServicesTable = ({ const actionsColumn: TableColumn = { title: '', field: '', - cellStyle: xsColumnStyle, - headerStyle: xsColumnStyle, + cellStyle: smColumnStyle, + headerStyle: smColumnStyle, render: rowData => , }; From 21d83eb2cc24b7595f7b561cba20fa963d2eca8c Mon Sep 17 00:00:00 2001 From: Marko Simon Date: Tue, 4 Oct 2022 11:42:39 +0200 Subject: [PATCH 05/13] add status pages Signed-off-by: Marko Simon --- plugins/ilert/src/api/client.ts | 33 ++++ plugins/ilert/src/api/index.ts | 3 +- plugins/ilert/src/api/types.ts | 11 ++ .../src/components/ILertPage/ILertPage.tsx | 4 + .../components/ServicesPage/StatusChip.tsx | 10 +- .../components/ServicesPage/TableTitle.tsx | 97 --------- .../StatusPage/StatusPageActionsMenu.tsx | 79 ++++++++ .../components/StatusPage/StatusPageLink.tsx | 50 +++++ .../StatusPage/StatusPageStatus.tsx | 61 ++++++ .../components/StatusPage/StatusPageURL.tsx | 49 +++++ .../StatusPage/StatusPageVisibility.tsx | 51 +++++ .../StatusPage/index.ts} | 19 +- .../components/StatusPagePage/StatusChip.tsx | 82 ++++++++ .../StatusPagePage/StatusPagesPage.tsx | 67 +++++++ .../StatusPagePage/StatusPagesTable.tsx | 184 ++++++++++++++++++ .../StatusPagePage/VisibilityChip.tsx | 48 +++++ .../src/components/StatusPagePage/index.ts | 17 ++ plugins/ilert/src/hooks/useStatusPages.ts | 93 +++++++++ plugins/ilert/src/types.ts | 18 ++ 19 files changed, 856 insertions(+), 120 deletions(-) delete mode 100644 plugins/ilert/src/components/ServicesPage/TableTitle.tsx create mode 100644 plugins/ilert/src/components/StatusPage/StatusPageActionsMenu.tsx create mode 100644 plugins/ilert/src/components/StatusPage/StatusPageLink.tsx create mode 100644 plugins/ilert/src/components/StatusPage/StatusPageStatus.tsx create mode 100644 plugins/ilert/src/components/StatusPage/StatusPageURL.tsx create mode 100644 plugins/ilert/src/components/StatusPage/StatusPageVisibility.tsx rename plugins/ilert/src/{hooks/useNewService.ts => components/StatusPage/index.ts} (67%) create mode 100644 plugins/ilert/src/components/StatusPagePage/StatusChip.tsx create mode 100644 plugins/ilert/src/components/StatusPagePage/StatusPagesPage.tsx create mode 100644 plugins/ilert/src/components/StatusPagePage/StatusPagesTable.tsx create mode 100644 plugins/ilert/src/components/StatusPagePage/VisibilityChip.tsx create mode 100644 plugins/ilert/src/components/StatusPagePage/index.ts create mode 100644 plugins/ilert/src/hooks/useStatusPages.ts diff --git a/plugins/ilert/src/api/client.ts b/plugins/ilert/src/api/client.ts index 4269ef583d..69b0a171f9 100644 --- a/plugins/ilert/src/api/client.ts +++ b/plugins/ilert/src/api/client.ts @@ -29,6 +29,7 @@ import { OnCall, Schedule, Service, + StatusPage, UptimeMonitor, User, } from '../types'; @@ -37,6 +38,7 @@ import { GetAlertsCountOpts, GetAlertsOpts, GetServicesOpts, + GetStatusPagesOpts, ILertApi, ServiceRequest, } from './types'; @@ -519,6 +521,27 @@ export class ILertClient implements ILertApi { return response; } + async fetchStatusPages(opts?: GetStatusPagesOpts): Promise { + const init = { + headers: JSON_HEADERS, + }; + const query = new URLSearchParams(); + if (opts?.maxResults !== undefined) { + query.append('max-results', String(opts.maxResults)); + } + if (opts?.startIndex !== undefined) { + query.append('start-index', String(opts.startIndex)); + } + + query.append('include', 'subscribed'); + + const response = await this.fetch( + `/api/status-pages?${query.toString()}`, + init, + ); + return response; + } + getAlertDetailsURL(alert: Alert): string { return `${this.baseUrl}/alert/view.jsf?id=${encodeURIComponent(alert.id)}`; } @@ -556,6 +579,16 @@ export class ILertClient implements ILertApi { )}`; } + getStatusPageDetailsURL(statusPage: StatusPage): string { + return `${this.baseUrl}/status-page/view.jsf?id=${encodeURIComponent( + statusPage.id, + )}`; + } + + getStatusPageURL(statusPage: StatusPage): string { + return statusPage.domain ? statusPage.domain : statusPage.subdomain; + } + getUserPhoneNumber(user: User | null) { return user?.mobile?.number || user?.landline?.number || ''; } diff --git a/plugins/ilert/src/api/index.ts b/plugins/ilert/src/api/index.ts index f0688e0f63..30120225a4 100644 --- a/plugins/ilert/src/api/index.ts +++ b/plugins/ilert/src/api/index.ts @@ -16,10 +16,11 @@ export { ilertApiRef, ILertClient } from './client'; export type { - AlertEventRequest as EventRequest, + EventRequest as EventRequest, GetAlertsCountOpts, GetAlertsOpts, GetServicesOpts, + GetStatusPagesOpts, ILertApi, TableState, } from './types'; diff --git a/plugins/ilert/src/api/types.ts b/plugins/ilert/src/api/types.ts index 39eb373ae2..4e6e56dfd5 100644 --- a/plugins/ilert/src/api/types.ts +++ b/plugins/ilert/src/api/types.ts @@ -24,6 +24,7 @@ import { OnCall, Schedule, Service, + StatusPage, UptimeMonitor, User, } from '../types'; @@ -53,6 +54,12 @@ export type GetServicesOpts = { startIndex?: number; }; +/** @public */ +export type GetStatusPagesOpts = { + maxResults?: number; + startIndex?: number; +}; + /** @public */ export type EventRequest = { integrationKey: string; @@ -109,12 +116,16 @@ export interface ILertApi { fetchServices(opts?: GetServicesOpts): Promise; createService(eventRequest: ServiceRequest): Promise; + fetchStatusPages(opts?: GetStatusPagesOpts): Promise; + getAlertDetailsURL(alert: Alert): string; getAlertSourceDetailsURL(alertSource: AlertSource | null): string; getEscalationPolicyDetailsURL(escalationPolicy: EscalationPolicy): string; getUptimeMonitorDetailsURL(uptimeMonitor: UptimeMonitor): string; getScheduleDetailsURL(schedule: Schedule): string; getServiceDetailsURL(service: Service): string; + getStatusPageDetailsURL(statusPage: StatusPage): string; + getStatusPageURL(statusPage: StatusPage): string; getUserPhoneNumber(user: User | null): string; getUserInitials(user: User | null): string; } diff --git a/plugins/ilert/src/components/ILertPage/ILertPage.tsx b/plugins/ilert/src/components/ILertPage/ILertPage.tsx index cc7527c316..45bd219d62 100644 --- a/plugins/ilert/src/components/ILertPage/ILertPage.tsx +++ b/plugins/ilert/src/components/ILertPage/ILertPage.tsx @@ -24,6 +24,7 @@ import React from 'react'; import { AlertsPage } from '../AlertsPage'; import { OnCallSchedulesPage } from '../OnCallSchedulesPage'; import { ServicesPage } from '../ServicesPage'; +import { StatusPagesPage } from '../StatusPagePage'; import { UptimeMonitorsPage } from '../UptimeMonitorsPage'; /** @public */ @@ -34,6 +35,7 @@ export const ILertPage = () => { { label: 'Alerts' }, { label: 'Uptime Monitors' }, { label: 'Services' }, + { label: 'Status pages' }, ]; const renderTab = () => { switch (selectedTab) { @@ -45,6 +47,8 @@ export const ILertPage = () => { return ; case 3: return ; + case 4: + return ; default: return null; } diff --git a/plugins/ilert/src/components/ServicesPage/StatusChip.tsx b/plugins/ilert/src/components/ServicesPage/StatusChip.tsx index 5eb31b8a94..f23c64450b 100644 --- a/plugins/ilert/src/components/ServicesPage/StatusChip.tsx +++ b/plugins/ilert/src/components/ServicesPage/StatusChip.tsx @@ -27,7 +27,7 @@ import { serviceStatusLabels } from '../Service/ServiceStatus'; const OperationalChip = withStyles({ root: { - backgroundColor: '#4caf50', + backgroundColor: '#388E3D', color: 'white', margin: 0, }, @@ -35,28 +35,28 @@ const OperationalChip = withStyles({ const UnderMaintenanceChip = withStyles({ root: { - backgroundColor: '#ffb74d', + backgroundColor: '#616161', color: 'white', margin: 0, }, })(Chip); const DegradedChip = withStyles({ root: { - backgroundColor: '#d32f2f', + backgroundColor: '#FBC02D', color: 'white', margin: 0, }, })(Chip); const PartialOutageChip = withStyles({ root: { - backgroundColor: '#d4a5bb', + backgroundColor: '#F57C02', color: 'white', margin: 0, }, })(Chip); const MajorOutageChip = withStyles({ root: { - backgroundColor: '#28c548', + backgroundColor: '#D22F2E', color: 'white', margin: 0, }, diff --git a/plugins/ilert/src/components/ServicesPage/TableTitle.tsx b/plugins/ilert/src/components/ServicesPage/TableTitle.tsx deleted file mode 100644 index c610e91d94..0000000000 --- a/plugins/ilert/src/components/ServicesPage/TableTitle.tsx +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * 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 Checkbox from '@material-ui/core/Checkbox'; -import FormControl from '@material-ui/core/FormControl'; -import ListItemText from '@material-ui/core/ListItemText'; -import MenuItem from '@material-ui/core/MenuItem'; -import Select from '@material-ui/core/Select'; -import { makeStyles } from '@material-ui/core/styles'; -import Typography from '@material-ui/core/Typography'; -import React from 'react'; -import { ACCEPTED, AlertStatus, PENDING, RESOLVED } from '../../types'; -import { alertStatusLabels } from '../Alert/AlertStatus'; - -const ITEM_HEIGHT = 48; -const ITEM_PADDING_TOP = 8; -const MenuProps = { - PaperProps: { - style: { - maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP, - width: 250, - }, - }, -}; - -const useStyles = makeStyles({ - root: { - display: 'flex', - }, - label: { - marginTop: 8, - marginRight: 4, - }, - formControl: { - minWidth: 120, - maxWidth: 300, - }, - grow: { - flexGrow: 1, - }, -}); - -export const TableTitle = ({ - alertStates, - onAlertStatesChange, -}: { - alertStates: AlertStatus[]; - onAlertStatesChange: (states: AlertStatus[]) => void; -}) => { - const classes = useStyles(); - const handleAlertStatusSelectChange = (event: any) => { - onAlertStatesChange(event.target.value); - }; - - return ( -
- - Status: - - - - -
- ); -}; diff --git a/plugins/ilert/src/components/StatusPage/StatusPageActionsMenu.tsx b/plugins/ilert/src/components/StatusPage/StatusPageActionsMenu.tsx new file mode 100644 index 0000000000..8fe94eb2e1 --- /dev/null +++ b/plugins/ilert/src/components/StatusPage/StatusPageActionsMenu.tsx @@ -0,0 +1,79 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { IconButton, Menu, MenuItem, Typography } from '@material-ui/core'; +import MoreVertIcon from '@material-ui/icons/MoreVert'; +import React from 'react'; +import { ilertApiRef } from '../../api'; +import { StatusPage } from '../../types'; + +import { Link } from '@backstage/core-components'; +import { useApi } from '@backstage/core-plugin-api'; + +export const StatusPageActionsMenu = ({ + statusPage, +}: { + statusPage: StatusPage; +}) => { + const ilertApi = useApi(ilertApiRef); + const [anchorEl, setAnchorEl] = React.useState(null); + + const handleClick = (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget); + }; + + const handleCloseMenu = () => { + setAnchorEl(null); + }; + + return ( + <> + + + + + + + + View in iLert + + + + + + + View status page + + + + + + ); +}; diff --git a/plugins/ilert/src/components/StatusPage/StatusPageLink.tsx b/plugins/ilert/src/components/StatusPage/StatusPageLink.tsx new file mode 100644 index 0000000000..60daddf9df --- /dev/null +++ b/plugins/ilert/src/components/StatusPage/StatusPageLink.tsx @@ -0,0 +1,50 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { makeStyles } from '@material-ui/core/styles'; +import React from 'react'; +import { ilertApiRef } from '../../api'; +import { StatusPage } from '../../types'; + +import { Link } from '@backstage/core-components'; +import { useApi } from '@backstage/core-plugin-api'; + +const useStyles = makeStyles({ + link: { + lineHeight: '22px', + }, +}); + +export const StatusPageLink = ({ + statusPage, +}: { + statusPage: StatusPage | null; +}) => { + const ilertApi = useApi(ilertApiRef); + const classes = useStyles(); + + if (!statusPage) { + return null; + } + + return ( + + #{statusPage.id} + + ); +}; diff --git a/plugins/ilert/src/components/StatusPage/StatusPageStatus.tsx b/plugins/ilert/src/components/StatusPage/StatusPageStatus.tsx new file mode 100644 index 0000000000..b40db5d8f3 --- /dev/null +++ b/plugins/ilert/src/components/StatusPage/StatusPageStatus.tsx @@ -0,0 +1,61 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { StatusError, StatusOK } from '@backstage/core-components'; +import { makeStyles } from '@material-ui/core/styles'; +import Tooltip from '@material-ui/core/Tooltip'; +import React from 'react'; +import { + DEGRADED, + MAJOR_OUTAGE, + OPERATIONAL, + PARTIAL_OUTAGE, + StatusPage, + UNDER_MAINTENANCE, +} from '../../types'; + +const useStyles = makeStyles({ + denseListIcon: { + marginRight: 0, + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + }, +}); + +export const statusPageStatusLabels = { + [OPERATIONAL]: 'Operational', + [UNDER_MAINTENANCE]: 'Under maintenance', + [DEGRADED]: 'Degraded', + [PARTIAL_OUTAGE]: 'Partial outage', + [MAJOR_OUTAGE]: 'Major outage', +} as Record; + +export const StatusPageStatus = ({ + statusPage, +}: { + statusPage: StatusPage; +}) => { + const classes = useStyles(); + + return ( + +
+ {statusPage.status === 'OPERATIONAL' ? : } +
+
+ ); +}; diff --git a/plugins/ilert/src/components/StatusPage/StatusPageURL.tsx b/plugins/ilert/src/components/StatusPage/StatusPageURL.tsx new file mode 100644 index 0000000000..b94903333a --- /dev/null +++ b/plugins/ilert/src/components/StatusPage/StatusPageURL.tsx @@ -0,0 +1,49 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { makeStyles } from '@material-ui/core/styles'; +import React from 'react'; +import { ilertApiRef } from '../../api'; +import { StatusPage } from '../../types'; + +import { Link } from '@backstage/core-components'; +import { useApi } from '@backstage/core-plugin-api'; + +const useStyles = makeStyles({ + link: { + lineHeight: '22px', + }, +}); + +export const StatusPageURL = ({ + statusPage, +}: { + statusPage: StatusPage | null; +}) => { + const ilertApi = useApi(ilertApiRef); + const classes = useStyles(); + + if (!statusPage) { + return null; + } + + const url = ilertApi.getStatusPageURL(statusPage); + + return ( + + {url} + + ); +}; diff --git a/plugins/ilert/src/components/StatusPage/StatusPageVisibility.tsx b/plugins/ilert/src/components/StatusPage/StatusPageVisibility.tsx new file mode 100644 index 0000000000..7c8f63dd35 --- /dev/null +++ b/plugins/ilert/src/components/StatusPage/StatusPageVisibility.tsx @@ -0,0 +1,51 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { StatusError, StatusOK } from '@backstage/core-components'; +import { makeStyles } from '@material-ui/core/styles'; +import Tooltip from '@material-ui/core/Tooltip'; +import React from 'react'; +import { PRIVATE, PUBLIC, StatusPage } from '../../types'; + +const useStyles = makeStyles({ + denseListIcon: { + marginRight: 0, + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + }, +}); + +export const statusPageVisibilityLabels = { + [PUBLIC]: 'Public', + [PRIVATE]: 'Private', +} as Record; + +export const StatusPageVisibility = ({ + statusPage, +}: { + statusPage: StatusPage; +}) => { + const classes = useStyles(); + + return ( + +
+ {statusPage.visibility === 'PUBLIC' ? : } +
+
+ ); +}; diff --git a/plugins/ilert/src/hooks/useNewService.ts b/plugins/ilert/src/components/StatusPage/index.ts similarity index 67% rename from plugins/ilert/src/hooks/useNewService.ts rename to plugins/ilert/src/components/StatusPage/index.ts index 7d50d29a39..93ea9deaba 100644 --- a/plugins/ilert/src/hooks/useNewService.ts +++ b/plugins/ilert/src/components/StatusPage/index.ts @@ -13,20 +13,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; - -export const useNewService = () => { - const [name, setName] = React.useState(''); - const [isLoading, setIsLoading] = React.useState(false); - - return [ - { - name, - isLoading, - }, - { - setName, - setIsLoading, - }, - ] as const; -}; +export * from './StatusPageActionsMenu'; +export * from './StatusPageStatus'; diff --git a/plugins/ilert/src/components/StatusPagePage/StatusChip.tsx b/plugins/ilert/src/components/StatusPagePage/StatusChip.tsx new file mode 100644 index 0000000000..50a64de212 --- /dev/null +++ b/plugins/ilert/src/components/StatusPagePage/StatusChip.tsx @@ -0,0 +1,82 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { Chip, withStyles } from '@material-ui/core'; +import React from 'react'; +import { + DEGRADED, + MAJOR_OUTAGE, + OPERATIONAL, + PARTIAL_OUTAGE, + StatusPage, + UNDER_MAINTENANCE, +} from '../../types'; +import { statusPageStatusLabels } from '../StatusPage/StatusPageStatus'; + +const OperationalChip = withStyles({ + root: { + backgroundColor: '#388E3D', + color: 'white', + margin: 0, + }, +})(Chip); + +const UnderMaintenanceChip = withStyles({ + root: { + backgroundColor: '#616161', + color: 'white', + margin: 0, + }, +})(Chip); +const DegradedChip = withStyles({ + root: { + backgroundColor: '#FBC02D', + color: 'white', + margin: 0, + }, +})(Chip); +const PartialOutageChip = withStyles({ + root: { + backgroundColor: '#F57C02', + color: 'white', + margin: 0, + }, +})(Chip); +const MajorOutageChip = withStyles({ + root: { + backgroundColor: '#D22F2E', + color: 'white', + margin: 0, + }, +})(Chip); + +export const StatusChip = ({ statusPage }: { statusPage: StatusPage }) => { + const label = `${statusPageStatusLabels[statusPage.status]}`; + + switch (statusPage.status) { + case OPERATIONAL: + return ; + case UNDER_MAINTENANCE: + return ; + case DEGRADED: + return ; + case PARTIAL_OUTAGE: + return ; + case MAJOR_OUTAGE: + return ; + default: + return ; + } +}; diff --git a/plugins/ilert/src/components/StatusPagePage/StatusPagesPage.tsx b/plugins/ilert/src/components/StatusPagePage/StatusPagesPage.tsx new file mode 100644 index 0000000000..6e4290c7c9 --- /dev/null +++ b/plugins/ilert/src/components/StatusPagePage/StatusPagesPage.tsx @@ -0,0 +1,67 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { + Content, + ContentHeader, + ResponseErrorPanel, + SupportButton, +} from '@backstage/core-components'; +import { AuthenticationError } from '@backstage/errors'; +import React from 'react'; +import { useStatusPages } from '../../hooks/useStatusPages'; +import { MissingAuthorizationHeaderError } from '../Errors'; +import { StatusPagesTable } from './StatusPagesTable'; + +export const StatusPagesPage = () => { + const [ + { tableState, statusPages, isLoading, error }, + { onChangePage, onChangeRowsPerPage, setIsLoading }, + ] = useStatusPages(true); + + if (error) { + if (error instanceof AuthenticationError) { + return ( + + + + ); + } + + return ( + + + + ); + } + + return ( + + + + This helps you to bring iLert into your developer portal. + + + + + ); +}; diff --git a/plugins/ilert/src/components/StatusPagePage/StatusPagesTable.tsx b/plugins/ilert/src/components/StatusPagePage/StatusPagesTable.tsx new file mode 100644 index 0000000000..8b013fdb35 --- /dev/null +++ b/plugins/ilert/src/components/StatusPagePage/StatusPagesTable.tsx @@ -0,0 +1,184 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { makeStyles } from '@material-ui/core/styles'; +import Typography from '@material-ui/core/Typography'; +import React from 'react'; +import { TableState } from '../../api'; +import { StatusPage } from '../../types'; +import { VisibilityChip } from './VisibilityChip'; + +import { Table, TableColumn } from '@backstage/core-components'; +import { StatusPageActionsMenu } from '../StatusPage/StatusPageActionsMenu'; +import { StatusPageLink } from '../StatusPage/StatusPageLink'; +import { StatusPageURL } from '../StatusPage/StatusPageURL'; +import { StatusChip } from './StatusChip'; + +const useStyles = makeStyles(theme => ({ + empty: { + padding: theme.spacing(2), + display: 'flex', + justifyContent: 'center', + }, +})); + +export const StatusPagesTable = ({ + statusPages, + tableState, + isLoading, + onChangePage, + onChangeRowsPerPage, + compact, +}: { + statusPages: StatusPage[]; + tableState: TableState; + isLoading: boolean; + setIsLoading: (isLoading: boolean) => void; + onChangePage: (page: number) => void; + onChangeRowsPerPage: (pageSize: number) => void; + compact?: boolean; +}) => { + const classes = useStyles(); + + // const xsColumnStyle = { + // width: '5%', + // maxWidth: '5%', + // }; + const smColumnStyle = { + width: '10%', + maxWidth: '10%', + }; + // const mdColumnStyle = { + // width: '15%', + // maxWidth: '15%', + // }; + // const lgColumnStyle = { + // width: '20%', + // maxWidth: '20%', + // }; + const xlColumnStyle = { + width: '30%', + maxWidth: '30%', + }; + + const idColumn: TableColumn = { + title: 'ID', + field: 'id', + highlight: true, + cellStyle: smColumnStyle, + headerStyle: smColumnStyle, + render: rowData => , + }; + const nameColumn: TableColumn = { + title: 'Name', + field: 'name', + cellStyle: !compact ? xlColumnStyle : undefined, + headerStyle: !compact ? xlColumnStyle : undefined, + render: rowData => {(rowData as StatusPage).name}, + }; + const urlColumn: TableColumn = { + title: 'URL', + field: 'url', + cellStyle: smColumnStyle, + headerStyle: smColumnStyle, + render: rowData => , + }; + const visibilityColumn: TableColumn = { + title: 'Visibility', + field: 'visibility', + cellStyle: smColumnStyle, + headerStyle: smColumnStyle, + render: rowData => , + }; + const statusColumn: TableColumn = { + title: 'Status', + field: 'status', + cellStyle: smColumnStyle, + headerStyle: smColumnStyle, + render: rowData => , + }; + const actionsColumn: TableColumn = { + title: '', + field: '', + cellStyle: smColumnStyle, + headerStyle: smColumnStyle, + render: rowData => ( + + ), + }; + + const columns: TableColumn[] = compact + ? [nameColumn, statusColumn, urlColumn, actionsColumn] + : [ + idColumn, + nameColumn, + statusColumn, + urlColumn, + visibilityColumn, + actionsColumn, + ]; + let tableStyle: React.CSSProperties = {}; + if (compact) { + tableStyle = { + width: '100%', + maxWidth: '100%', + minWidth: '0', + height: 'calc(100% - 10px)', + boxShadow: 'none !important', + borderRadius: 'none !important', + }; + } else { + tableStyle = { + width: '100%', + maxWidth: '100%', + }; + } + + return ( +
+ No status pages + + } + title={ + + STATUS PAGES + + } + page={tableState.page} + onPageChange={onChangePage} + onRowsPerPageChange={onChangeRowsPerPage} + // localization={{ header: { actions: undefined } }} + columns={columns} + data={statusPages} + isLoading={isLoading} + /> + ); +}; diff --git a/plugins/ilert/src/components/StatusPagePage/VisibilityChip.tsx b/plugins/ilert/src/components/StatusPagePage/VisibilityChip.tsx new file mode 100644 index 0000000000..fb72819216 --- /dev/null +++ b/plugins/ilert/src/components/StatusPagePage/VisibilityChip.tsx @@ -0,0 +1,48 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { Chip, withStyles } from '@material-ui/core'; +import React from 'react'; +import { PRIVATE, PUBLIC, StatusPage } from '../../types'; +import { statusPageVisibilityLabels } from '../StatusPage/StatusPageVisibility'; + +const PrivateChip = withStyles({ + root: { + backgroundColor: '#4caf50', + color: 'white', + margin: 0, + }, +})(Chip); + +const PublicChip = withStyles({ + root: { + backgroundColor: '#ffb74d', + color: 'white', + margin: 0, + }, +})(Chip); + +export const VisibilityChip = ({ statusPage }: { statusPage: StatusPage }) => { + const label = `${statusPageVisibilityLabels[statusPage.visibility]}`; + + switch (statusPage.visibility) { + case PRIVATE: + return ; + case PUBLIC: + return ; + default: + return ; + } +}; diff --git a/plugins/ilert/src/components/StatusPagePage/index.ts b/plugins/ilert/src/components/StatusPagePage/index.ts new file mode 100644 index 0000000000..8bc923ffe1 --- /dev/null +++ b/plugins/ilert/src/components/StatusPagePage/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 * from './StatusPagesPage'; +export * from './StatusPagesTable'; diff --git a/plugins/ilert/src/hooks/useStatusPages.ts b/plugins/ilert/src/hooks/useStatusPages.ts new file mode 100644 index 0000000000..740e0f515f --- /dev/null +++ b/plugins/ilert/src/hooks/useStatusPages.ts @@ -0,0 +1,93 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { errorApiRef, useApi } from '@backstage/core-plugin-api'; +import { AuthenticationError } from '@backstage/errors'; +import React from 'react'; +import useAsyncRetry from 'react-use/lib/useAsyncRetry'; +import { GetStatusPagesOpts, ilertApiRef, TableState } from '../api'; +import { StatusPage } from '../types'; + +export const useStatusPages = (paging: boolean) => { + const ilertApi = useApi(ilertApiRef); + const errorApi = useApi(errorApiRef); + + const [tableState, setTableState] = React.useState({ + page: 0, + pageSize: 10, + }); + + const [statusPagesList, setStatusPagesList] = React.useState( + [], + ); + const [isLoading, setIsLoading] = React.useState(false); + + const fetchStatusPagesCall = async () => { + try { + setIsLoading(true); + const opts: GetStatusPagesOpts = {}; + if (paging) { + opts.maxResults = tableState.pageSize; + opts.startIndex = tableState.page * tableState.pageSize; + } + const data = await ilertApi.fetchStatusPages(opts); + setStatusPagesList(data || []); + setIsLoading(false); + } catch (e) { + if (!(e instanceof AuthenticationError)) { + errorApi.post(e); + } + setIsLoading(false); + throw e; + } + }; + + const fetchStatusPages = useAsyncRetry(fetchStatusPagesCall, [tableState]); + + const refetchStatusPages = () => { + setTableState({ ...tableState, page: 0 }); + Promise.all([fetchStatusPagesCall()]); + }; + + const error = fetchStatusPages.error; + const retry = () => { + fetchStatusPages.retry(); + }; + + const onChangePage = (page: number) => { + setTableState({ ...tableState, page }); + }; + const onChangeRowsPerPage = (p: number) => { + setTableState({ ...tableState, pageSize: p }); + }; + + return [ + { + tableState, + statusPages: statusPagesList, + isLoading, + error, + }, + { + setTableState, + setStatusPagesList, + setIsLoading, + retry, + refetchStatusPages, + onChangePage, + onChangeRowsPerPage, + }, + ] as const; +}; diff --git a/plugins/ilert/src/types.ts b/plugins/ilert/src/types.ts index ebe5c1b39d..28b8b7ca8a 100644 --- a/plugins/ilert/src/types.ts +++ b/plugins/ilert/src/types.ts @@ -251,6 +251,14 @@ export type ServiceStatus = | typeof PARTIAL_OUTAGE | typeof MAJOR_OUTAGE; +/** @public */ +export const PRIVATE = 'PRIVATE'; +/** @public */ +export const PUBLIC = 'PUBLIC'; + +/** @public */ +export type StatusPageVisibility = typeof PRIVATE | typeof PUBLIC; + /** @public */ export interface AlertSourceEmailPredicate { field: 'EMAIL_FROM' | 'EMAIL_SUBJECT' | 'EMAIL_BODY'; @@ -422,3 +430,13 @@ export interface Uptime { export interface UptimePercentage { p90: number; } + +/** @public */ +export interface StatusPage { + id: number; + name: string; + domain: string; + subdomain: string; + visibility: StatusPageVisibility; + status: ServiceStatus; +} From 56793b0db3ca4ead067a0fced26e372a486366a3 Mon Sep 17 00:00:00 2001 From: Marko Simon Date: Wed, 12 Oct 2022 16:02:25 +0200 Subject: [PATCH 06/13] fix tab order Signed-off-by: Marko Simon --- plugins/ilert/src/components/ILertPage/ILertPage.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/ilert/src/components/ILertPage/ILertPage.tsx b/plugins/ilert/src/components/ILertPage/ILertPage.tsx index 45bd219d62..51512f6d39 100644 --- a/plugins/ilert/src/components/ILertPage/ILertPage.tsx +++ b/plugins/ilert/src/components/ILertPage/ILertPage.tsx @@ -33,9 +33,9 @@ export const ILertPage = () => { const tabs = [ { label: 'Who is on call?' }, { label: 'Alerts' }, - { label: 'Uptime Monitors' }, { label: 'Services' }, { label: 'Status pages' }, + { label: 'Uptime Monitors' }, ]; const renderTab = () => { switch (selectedTab) { @@ -44,11 +44,11 @@ export const ILertPage = () => { case 1: return ; case 2: - return ; - case 3: return ; - case 4: + case 3: return ; + case 4: + return ; default: return null; } From 0697af30da75218b82244af8909308cf777ba943 Mon Sep 17 00:00:00 2001 From: Marko Simon Date: Wed, 12 Oct 2022 16:59:33 +0200 Subject: [PATCH 07/13] add changeset Signed-off-by: Marko Simon --- .changeset/popular-mails-wave.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/popular-mails-wave.md diff --git a/.changeset/popular-mails-wave.md b/.changeset/popular-mails-wave.md new file mode 100644 index 0000000000..23517f0608 --- /dev/null +++ b/.changeset/popular-mails-wave.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-ilert': minor +--- + +Added support for multiple responders in alert list, added new tab with list to support iLert resource 'service', added new tab with list to support iLert resource 'status page' From 646426303efad4de265a73ca1363bfff204e5650 Mon Sep 17 00:00:00 2001 From: Marko Simon Date: Tue, 18 Oct 2022 16:38:37 +0200 Subject: [PATCH 08/13] update api-report.md Signed-off-by: Marko Simon --- plugins/ilert/api-report.md | 420 +++++++++++++++++++++++------------- 1 file changed, 265 insertions(+), 155 deletions(-) diff --git a/plugins/ilert/api-report.md b/plugins/ilert/api-report.md index 96576a8358..86ea698921 100644 --- a/plugins/ilert/api-report.md +++ b/plugins/ilert/api-report.md @@ -16,11 +16,96 @@ import { RouteRef } from '@backstage/core-plugin-api'; // @public (undocumented) export const ACCEPTED = 'ACCEPTED'; +// @public (undocumented) +export interface Alert { + // (undocumented) + alertKey: string; + // (undocumented) + alertSource: AlertSource | null; + // (undocumented) + assignedTo: User | null; + // (undocumented) + commentPublishToSubscribers: boolean; + // (undocumented) + commentText: string; + // (undocumented) + details: string; + // (undocumented) + id: number; + // (undocumented) + images: Image_2[]; + // (undocumented) + links: Link[]; + // (undocumented) + logEntries: LogEntry[]; + // (undocumented) + priority: AlertPriority; + // (undocumented) + reportTime: string; + // (undocumented) + resolvedOn: string; + // (undocumented) + responders: Responder[]; + // (undocumented) + status: AlertStatus; + // (undocumented) + subscribers: Subscriber[]; + // (undocumented) + summary: string; +} + +// @public (undocumented) +export interface AlertAction { + // (undocumented) + extensionId?: string; + // (undocumented) + history?: AlertActionHistory[]; + // (undocumented) + name: string; + // (undocumented) + type: string; + // (undocumented) + webhookId: string; +} + +// @public (undocumented) +export interface AlertActionHistory { + // (undocumented) + actor: User; + // (undocumented) + alertId: number; + // (undocumented) + id: string; + // (undocumented) + success: boolean; + // (undocumented) + webhookId: string; +} + +// @public (undocumented) +export type AlertPriority = 'HIGH' | 'LOW'; + +// @public (undocumented) +export interface AlertResponder { + // (undocumented) + disabled: boolean; + // (undocumented) + group: 'SUGGESTED' | 'USER' | 'ESCALATION_POLICY' | 'ON_CALL_SCHEDULE'; + // (undocumented) + id: number; + // (undocumented) + name: string; +} + // @public (undocumented) export interface AlertSource { // (undocumented) active?: boolean; // (undocumented) + alertCreation?: AlertSourceAlertCreation; + // (undocumented) + alertPriorityRule?: AlertSourceAlertPriorityRule; + // (undocumented) autoResolutionTimeout?: string; // (undocumented) autotaskMetadata?: AlertSourceAutotaskMetadata; @@ -45,10 +130,6 @@ export interface AlertSource { // (undocumented) id: number; // (undocumented) - incidentCreation?: AlertSourceIncidentCreation; - // (undocumented) - incidentPriorityRule?: AlertSourceIncidentPriorityRule; - // (undocumented) integrationKey?: string; // (undocumented) integrationType: AlertSourceIntegrationType; @@ -66,6 +147,21 @@ export interface AlertSource { teams: TeamShort[]; } +// @public (undocumented) +export type AlertSourceAlertCreation = + | 'ONE_ALERT_PER_EMAIL' + | 'ONE_ALERT_PER_EMAIL_SUBJECT' + | 'ONE_PENDING_ALERT_ALLOWED' + | 'ONE_OPEN_ALERT_ALLOWED' + | 'OPEN_RESOLVE_ON_EXTRACTION'; + +// @public (undocumented) +export type AlertSourceAlertPriorityRule = + | 'HIGH' + | 'LOW' + | 'HIGH_DURING_SUPPORT_HOURS' + | 'LOW_DURING_SUPPORT_HOURS'; + // @public (undocumented) export interface AlertSourceAutotaskMetadata { // (undocumented) @@ -109,21 +205,6 @@ export interface AlertSourceHeartbeat { summary: string; } -// @public (undocumented) -export type AlertSourceIncidentCreation = - | 'ONE_INCIDENT_PER_EMAIL' - | 'ONE_INCIDENT_PER_EMAIL_SUBJECT' - | 'ONE_PENDING_INCIDENT_ALLOWED' - | 'ONE_OPEN_INCIDENT_ALLOWED' - | 'OPEN_RESOLVE_ON_EXTRACTION'; - -// @public (undocumented) -export type AlertSourceIncidentPriorityRule = - | 'HIGH' - | 'LOW' - | 'HIGH_DURING_SUPPORT_HOURS' - | 'LOW_DURING_SUPPORT_HOURS'; - // @public (undocumented) export type AlertSourceIntegrationType = | 'NAGIOS' @@ -192,7 +273,7 @@ export interface AlertSourceSupportDay { // @public (undocumented) export interface AlertSourceSupportHours { // (undocumented) - autoRaiseIncidents: boolean; + autoRaiseAlerts: boolean; // (undocumented) supportDays: { MONDAY: AlertSourceSupportDay; @@ -214,6 +295,12 @@ export type AlertSourceTimeZone = | 'America/Los_Angeles' | 'Asia/Istanbul'; +// @public (undocumented) +export type AlertStatus = typeof PENDING | typeof ACCEPTED | typeof RESOLVED; + +// @public (undocumented) +export const DEGRADED = 'DEGRADED'; + // @public (undocumented) export const EntityILertCard: () => JSX.Element; @@ -255,71 +342,94 @@ export type EventRequest = { }; // @public (undocumented) -export type GetIncidentsCountOpts = { - states?: IncidentStatus[]; +export type GetAlertsCountOpts = { + states?: AlertStatus[]; }; // @public (undocumented) -export type GetIncidentsOpts = { +export type GetAlertsOpts = { maxResults?: number; startIndex?: number; - states?: IncidentStatus[]; + states?: AlertStatus[]; alertSources?: number[]; }; +// @public (undocumented) +export type GetServicesOpts = { + maxResults?: number; + startIndex?: number; +}; + +// @public (undocumented) +export type GetStatusPagesOpts = { + maxResults?: number; + startIndex?: number; +}; + // @public (undocumented) export interface ILertApi { // (undocumented) - acceptIncident(incident: Incident, userName: string): Promise; + acceptAlert(alert: Alert, userName: string): Promise; // (undocumented) addImmediateMaintenance( alertSourceId: number, minutes: number, ): Promise; // (undocumented) - assignIncident( - incident: Incident, - responder: IncidentResponder, - ): Promise; + assignAlert(alert: Alert, responder: AlertResponder): Promise; // (undocumented) - createIncident(eventRequest: EventRequest): Promise; + createAlert(eventRequest: EventRequest): Promise; + // Warning: (ae-forgotten-export) The symbol "ServiceRequest" needs to be exported by the entry point index.d.ts + // + // (undocumented) + createService(eventRequest: ServiceRequest): Promise; // (undocumented) disableAlertSource(alertSource: AlertSource): Promise; // (undocumented) enableAlertSource(alertSource: AlertSource): Promise; // (undocumented) + fetchAlert(id: number): Promise; + // (undocumented) + fetchAlertActions(alert: Alert): Promise; + // (undocumented) + fetchAlertResponders(alert: Alert): Promise; + // (undocumented) + fetchAlerts(opts?: GetAlertsOpts): Promise; + // (undocumented) + fetchAlertsCount(opts?: GetAlertsCountOpts): Promise; + // (undocumented) fetchAlertSource(idOrIntegrationKey: number | string): Promise; // (undocumented) fetchAlertSourceOnCalls(alertSource: AlertSource): Promise; // (undocumented) fetchAlertSources(): Promise; // (undocumented) - fetchIncident(id: number): Promise; - // (undocumented) - fetchIncidentActions(incident: Incident): Promise; - // (undocumented) - fetchIncidentResponders(incident: Incident): Promise; - // (undocumented) - fetchIncidents(opts?: GetIncidentsOpts): Promise; - // (undocumented) - fetchIncidentsCount(opts?: GetIncidentsCountOpts): Promise; - // (undocumented) fetchOnCallSchedules(): Promise; // (undocumented) + fetchServices(opts?: GetServicesOpts): Promise; + // (undocumented) + fetchStatusPages(opts?: GetStatusPagesOpts): Promise; + // (undocumented) fetchUptimeMonitor(id: number): Promise; // (undocumented) fetchUptimeMonitors(): Promise; // (undocumented) fetchUsers(): Promise; // (undocumented) + getAlertDetailsURL(alert: Alert): string; + // (undocumented) getAlertSourceDetailsURL(alertSource: AlertSource | null): string; // (undocumented) getEscalationPolicyDetailsURL(escalationPolicy: EscalationPolicy): string; // (undocumented) - getIncidentDetailsURL(incident: Incident): string; - // (undocumented) getScheduleDetailsURL(schedule: Schedule): string; // (undocumented) + getServiceDetailsURL(service: Service): string; + // (undocumented) + getStatusPageDetailsURL(statusPage: StatusPage): string; + // (undocumented) + getStatusPageURL(statusPage: StatusPage): string; + // (undocumented) getUptimeMonitorDetailsURL(uptimeMonitor: UptimeMonitor): string; // (undocumented) getUserInitials(user: User | null): string; @@ -335,14 +445,11 @@ export interface ILertApi { // (undocumented) pauseUptimeMonitor(uptimeMonitor: UptimeMonitor): Promise; // (undocumented) - resolveIncident(incident: Incident, userName: string): Promise; + resolveAlert(alert: Alert, userName: string): Promise; // (undocumented) resumeUptimeMonitor(uptimeMonitor: UptimeMonitor): Promise; // (undocumented) - triggerIncidentAction( - incident: Incident, - action: IncidentAction, - ): Promise; + triggerAlertAction(alert: Alert, action: AlertAction): Promise; } // @public (undocumented) @@ -359,42 +466,45 @@ export class ILertClient implements ILertApi { proxyPath: string; }); // (undocumented) - acceptIncident(incident: Incident, userName: string): Promise; + acceptAlert(alert: Alert, userName: string): Promise; // (undocumented) addImmediateMaintenance( alertSourceId: number, minutes: number, ): Promise; // (undocumented) - assignIncident( - incident: Incident, - responder: IncidentResponder, - ): Promise; + assignAlert(alert: Alert, responder: AlertResponder): Promise; // (undocumented) - createIncident(eventRequest: EventRequest): Promise; + createAlert(eventRequest: EventRequest): Promise; + // (undocumented) + createService(serviceRequest: ServiceRequest): Promise; // (undocumented) disableAlertSource(alertSource: AlertSource): Promise; // (undocumented) enableAlertSource(alertSource: AlertSource): Promise; // (undocumented) + fetchAlert(id: number): Promise; + // (undocumented) + fetchAlertActions(alert: Alert): Promise; + // (undocumented) + fetchAlertResponders(alert: Alert): Promise; + // (undocumented) + fetchAlerts(opts?: GetAlertsOpts): Promise; + // (undocumented) + fetchAlertsCount(opts?: GetAlertsCountOpts): Promise; + // (undocumented) fetchAlertSource(idOrIntegrationKey: number | string): Promise; // (undocumented) fetchAlertSourceOnCalls(alertSource: AlertSource): Promise; // (undocumented) fetchAlertSources(): Promise; // (undocumented) - fetchIncident(id: number): Promise; - // (undocumented) - fetchIncidentActions(incident: Incident): Promise; - // (undocumented) - fetchIncidentResponders(incident: Incident): Promise; - // (undocumented) - fetchIncidents(opts?: GetIncidentsOpts): Promise; - // (undocumented) - fetchIncidentsCount(opts?: GetIncidentsCountOpts): Promise; - // (undocumented) fetchOnCallSchedules(): Promise; // (undocumented) + fetchServices(opts?: GetServicesOpts): Promise; + // (undocumented) + fetchStatusPages(opts?: GetStatusPagesOpts): Promise; + // (undocumented) fetchUptimeMonitor(id: number): Promise; // (undocumented) fetchUptimeMonitors(): Promise; @@ -406,14 +516,20 @@ export class ILertClient implements ILertApi { discoveryApi: DiscoveryApi, ): ILertClient; // (undocumented) + getAlertDetailsURL(alert: Alert): string; + // (undocumented) getAlertSourceDetailsURL(alertSource: AlertSource | null): string; // (undocumented) getEscalationPolicyDetailsURL(escalationPolicy: EscalationPolicy): string; // (undocumented) - getIncidentDetailsURL(incident: Incident): string; - // (undocumented) getScheduleDetailsURL(schedule: Schedule): string; // (undocumented) + getServiceDetailsURL(service: Service): string; + // (undocumented) + getStatusPageDetailsURL(statusPage: StatusPage): string; + // (undocumented) + getStatusPageURL(statusPage: StatusPage): string; + // (undocumented) getUptimeMonitorDetailsURL(uptimeMonitor: UptimeMonitor): string; // (undocumented) getUserInitials(user: User | null): string; @@ -429,14 +545,11 @@ export class ILertClient implements ILertApi { // (undocumented) pauseUptimeMonitor(uptimeMonitor: UptimeMonitor): Promise; // (undocumented) - resolveIncident(incident: Incident, userName: string): Promise; + resolveAlert(alert: Alert, userName: string): Promise; // (undocumented) resumeUptimeMonitor(uptimeMonitor: UptimeMonitor): Promise; // (undocumented) - triggerIncidentAction( - incident: Incident, - action: IncidentAction, - ): Promise; + triggerAlertAction(alert: Alert, action: AlertAction): Promise; } // @public (undocumented) @@ -470,88 +583,6 @@ interface Image_2 { } export { Image_2 as Image }; -// @public (undocumented) -export interface Incident { - // (undocumented) - alertSource: AlertSource | null; - // (undocumented) - assignedTo: User | null; - // (undocumented) - commentPublishToSubscribers: boolean; - // (undocumented) - commentText: string; - // (undocumented) - details: string; - // (undocumented) - id: number; - // (undocumented) - images: Image_2[]; - // (undocumented) - incidentKey: string; - // (undocumented) - links: Link[]; - // (undocumented) - logEntries: LogEntry[]; - // (undocumented) - priority: IncidentPriority; - // (undocumented) - reportTime: string; - // (undocumented) - resolvedOn: string; - // (undocumented) - status: IncidentStatus; - // (undocumented) - subscribers: Subscriber[]; - // (undocumented) - summary: string; -} - -// @public (undocumented) -export interface IncidentAction { - // (undocumented) - extensionId?: string; - // (undocumented) - history?: IncidentActionHistory[]; - // (undocumented) - name: string; - // (undocumented) - type: string; - // (undocumented) - webhookId: string; -} - -// @public (undocumented) -export interface IncidentActionHistory { - // (undocumented) - actor: User; - // (undocumented) - id: string; - // (undocumented) - incidentId: number; - // (undocumented) - success: boolean; - // (undocumented) - webhookId: string; -} - -// @public (undocumented) -export type IncidentPriority = 'HIGH' | 'LOW'; - -// @public (undocumented) -export interface IncidentResponder { - // (undocumented) - disabled: boolean; - // (undocumented) - group: 'SUGGESTED' | 'USER' | 'ESCALATION_POLICY' | 'ON_CALL_SCHEDULE'; - // (undocumented) - id: number; - // (undocumented) - name: string; -} - -// @public (undocumented) -export type IncidentStatus = typeof PENDING | typeof ACCEPTED | typeof RESOLVED; - // @public (undocumented) const isPluginApplicableToEntity: (entity: Entity) => boolean; export { isPluginApplicableToEntity as isILertAvailable }; @@ -570,6 +601,8 @@ export interface Link { // @public (undocumented) export interface LogEntry { + // (undocumented) + alertId?: number; // (undocumented) filterTypes?: string[]; // (undocumented) @@ -579,8 +612,6 @@ export interface LogEntry { // (undocumented) id: number; // (undocumented) - incidentId?: number; - // (undocumented) logEntryType: string; // (undocumented) text: string; @@ -588,6 +619,9 @@ export interface LogEntry { timestamp: string; } +// @public (undocumented) +export const MAJOR_OUTAGE = 'MAJOR_OUTAGE'; + // @public (undocumented) export interface OnCall { // (undocumented) @@ -604,6 +638,12 @@ export interface OnCall { user: User; } +// @public (undocumented) +export const OPERATIONAL = 'OPERATIONAL'; + +// @public (undocumented) +export const PARTIAL_OUTAGE = 'PARTIAL_OUTAGE'; + // @public (undocumented) export const PENDING = 'PENDING'; @@ -615,9 +655,25 @@ export interface Phone { regionCode: string; } +// @public (undocumented) +export const PRIVATE = 'PRIVATE'; + +// @public (undocumented) +export const PUBLIC = 'PUBLIC'; + // @public (undocumented) export const RESOLVED = 'RESOLVED'; +// @public (undocumented) +export interface Responder { + // (undocumented) + acceptedAt?: string; + // (undocumented) + status: string; + // (undocumented) + user: User; +} + // @public (undocumented) export const Router: () => JSX.Element; @@ -643,6 +699,26 @@ export interface Schedule { timezone: string; } +// @public (undocumented) +export interface Service { + // (undocumented) + id: number; + // (undocumented) + name: string; + // (undocumented) + status: ServiceStatus; + // (undocumented) + uptime: Uptime; +} + +// @public (undocumented) +export type ServiceStatus = + | typeof OPERATIONAL + | typeof UNDER_MAINTENANCE + | typeof DEGRADED + | typeof PARTIAL_OUTAGE + | typeof MAJOR_OUTAGE; + // @public (undocumented) export interface Shift { // (undocumented) @@ -653,6 +729,25 @@ export interface Shift { user: User; } +// @public (undocumented) +export interface StatusPage { + // (undocumented) + domain: string; + // (undocumented) + id: number; + // (undocumented) + name: string; + // (undocumented) + status: ServiceStatus; + // (undocumented) + subdomain: string; + // (undocumented) + visibility: StatusPageVisibility; +} + +// @public (undocumented) +export type StatusPageVisibility = typeof PRIVATE | typeof PUBLIC; + // @public (undocumented) export interface Subscriber { // (undocumented) @@ -688,6 +783,15 @@ export interface TeamShort { name: string; } +// @public (undocumented) +export const UNDER_MAINTENANCE = 'UNDER_MAINTENANCE'; + +// @public (undocumented) +export interface Uptime { + // (undocumented) + uptimePercentage: UptimePercentage; +} + // @public (undocumented) export interface UptimeMonitor { // (undocumented) @@ -695,7 +799,7 @@ export interface UptimeMonitor { // (undocumented) checkType: 'http' | 'tcp' | 'udp' | 'ping'; // (undocumented) - createIncidentAfterFailedChecks: number; + createAlertAfterFailedChecks: number; // (undocumented) embedUrl: string; // (undocumented) @@ -732,6 +836,12 @@ export interface UptimeMonitorCheckParams { url?: string; } +// @public (undocumented) +export interface UptimePercentage { + // (undocumented) + p90: number; +} + // @public (undocumented) export interface User { // (undocumented) From ebe4489a3730514be2214a1522e59b13161f2ed8 Mon Sep 17 00:00:00 2001 From: Marko Simon Date: Tue, 18 Oct 2022 17:30:30 +0200 Subject: [PATCH 09/13] refactoring, fix api-reports.md Signed-off-by: Marko Simon --- plugins/ilert/api-report.md | 9 ++++++--- plugins/ilert/src/api/index.ts | 1 + plugins/ilert/src/api/types.ts | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/plugins/ilert/api-report.md b/plugins/ilert/api-report.md index 86ea698921..c1de4f796b 100644 --- a/plugins/ilert/api-report.md +++ b/plugins/ilert/api-report.md @@ -379,10 +379,8 @@ export interface ILertApi { assignAlert(alert: Alert, responder: AlertResponder): Promise; // (undocumented) createAlert(eventRequest: EventRequest): Promise; - // Warning: (ae-forgotten-export) The symbol "ServiceRequest" needs to be exported by the entry point index.d.ts - // // (undocumented) - createService(eventRequest: ServiceRequest): Promise; + createService(serviceRequest: ServiceRequest): Promise; // (undocumented) disableAlertSource(alertSource: AlertSource): Promise; // (undocumented) @@ -711,6 +709,11 @@ export interface Service { uptime: Uptime; } +// @public (undocumented) +export type ServiceRequest = { + name: string; +}; + // @public (undocumented) export type ServiceStatus = | typeof OPERATIONAL diff --git a/plugins/ilert/src/api/index.ts b/plugins/ilert/src/api/index.ts index 30120225a4..15d2981c20 100644 --- a/plugins/ilert/src/api/index.ts +++ b/plugins/ilert/src/api/index.ts @@ -22,5 +22,6 @@ export type { GetServicesOpts, GetStatusPagesOpts, ILertApi, + ServiceRequest as ServiceRequest, TableState, } from './types'; diff --git a/plugins/ilert/src/api/types.ts b/plugins/ilert/src/api/types.ts index 4e6e56dfd5..6d38d48023 100644 --- a/plugins/ilert/src/api/types.ts +++ b/plugins/ilert/src/api/types.ts @@ -114,7 +114,7 @@ export interface ILertApi { ): Promise; fetchServices(opts?: GetServicesOpts): Promise; - createService(eventRequest: ServiceRequest): Promise; + createService(serviceRequest: ServiceRequest): Promise; fetchStatusPages(opts?: GetStatusPagesOpts): Promise; From 0b89ebf6adab805d72a55244be44f13f340381dd Mon Sep 17 00:00:00 2001 From: Marko Simon Date: Thu, 20 Oct 2022 15:53:44 +0200 Subject: [PATCH 10/13] refactor code remove unnecessary code/components remove unnecessary styling Signed-off-by: Marko Simon --- plugins/ilert/api-report.md | 9 --- plugins/ilert/src/api/client.ts | 15 ----- plugins/ilert/src/api/index.ts | 1 - plugins/ilert/src/api/types.ts | 6 -- .../ilert/src/components/Alert/AlertLink.tsx | 14 +---- .../src/components/Alert/AlertStatus.tsx | 48 -------------- plugins/ilert/src/components/Alert/index.ts | 1 - .../src/components/AlertsPage/AlertsPage.tsx | 3 +- .../src/components/AlertsPage/AlertsTable.tsx | 63 ++++++------------- .../src/components/AlertsPage/StatusChip.tsx | 7 ++- .../src/components/AlertsPage/TableTitle.tsx | 2 +- .../OnCallSchedulesPage/OnCallShiftItem.tsx | 5 +- .../src/components/Service/ServiceLink.tsx | 14 +---- .../src/components/Service/ServiceStatus.tsx | 57 ----------------- plugins/ilert/src/components/Service/index.ts | 1 - .../components/ServicesPage/ServicesPage.tsx | 3 +- .../components/ServicesPage/ServicesTable.tsx | 55 ++++------------ .../components/ServicesPage/StatusChip.tsx | 9 ++- .../components/StatusPage/StatusPageLink.tsx | 13 +--- .../StatusPage/StatusPageStatus.tsx | 61 ------------------ .../components/StatusPage/StatusPageURL.tsx | 14 +---- .../StatusPage/StatusPageVisibility.tsx | 51 --------------- .../ilert/src/components/StatusPage/index.ts | 1 - .../components/StatusPagePage/StatusChip.tsx | 9 ++- .../StatusPagePage/StatusPagesPage.tsx | 3 +- .../StatusPagePage/StatusPagesTable.tsx | 58 ++++------------- .../StatusPagePage/VisibilityChip.tsx | 6 +- 27 files changed, 83 insertions(+), 446 deletions(-) delete mode 100644 plugins/ilert/src/components/Alert/AlertStatus.tsx delete mode 100644 plugins/ilert/src/components/Service/ServiceStatus.tsx delete mode 100644 plugins/ilert/src/components/StatusPage/StatusPageStatus.tsx delete mode 100644 plugins/ilert/src/components/StatusPage/StatusPageVisibility.tsx diff --git a/plugins/ilert/api-report.md b/plugins/ilert/api-report.md index c1de4f796b..51e2020dee 100644 --- a/plugins/ilert/api-report.md +++ b/plugins/ilert/api-report.md @@ -380,8 +380,6 @@ export interface ILertApi { // (undocumented) createAlert(eventRequest: EventRequest): Promise; // (undocumented) - createService(serviceRequest: ServiceRequest): Promise; - // (undocumented) disableAlertSource(alertSource: AlertSource): Promise; // (undocumented) enableAlertSource(alertSource: AlertSource): Promise; @@ -475,8 +473,6 @@ export class ILertClient implements ILertApi { // (undocumented) createAlert(eventRequest: EventRequest): Promise; // (undocumented) - createService(serviceRequest: ServiceRequest): Promise; - // (undocumented) disableAlertSource(alertSource: AlertSource): Promise; // (undocumented) enableAlertSource(alertSource: AlertSource): Promise; @@ -709,11 +705,6 @@ export interface Service { uptime: Uptime; } -// @public (undocumented) -export type ServiceRequest = { - name: string; -}; - // @public (undocumented) export type ServiceStatus = | typeof OPERATIONAL diff --git a/plugins/ilert/src/api/client.ts b/plugins/ilert/src/api/client.ts index 69b0a171f9..bc438786c7 100644 --- a/plugins/ilert/src/api/client.ts +++ b/plugins/ilert/src/api/client.ts @@ -40,7 +40,6 @@ import { GetServicesOpts, GetStatusPagesOpts, ILertApi, - ServiceRequest, } from './types'; /** @public */ @@ -507,20 +506,6 @@ export class ILertClient implements ILertApi { return response; } - async createService(serviceRequest: ServiceRequest): Promise { - const init = { - method: 'POST', - headers: JSON_HEADERS, - body: JSON.stringify({ - // apiKey: eventRequest.integrationKey, - name: serviceRequest.name, - }), - }; - - const response = await this.fetch('/api/services', init); - return response; - } - async fetchStatusPages(opts?: GetStatusPagesOpts): Promise { const init = { headers: JSON_HEADERS, diff --git a/plugins/ilert/src/api/index.ts b/plugins/ilert/src/api/index.ts index 15d2981c20..30120225a4 100644 --- a/plugins/ilert/src/api/index.ts +++ b/plugins/ilert/src/api/index.ts @@ -22,6 +22,5 @@ export type { GetServicesOpts, GetStatusPagesOpts, ILertApi, - ServiceRequest as ServiceRequest, TableState, } from './types'; diff --git a/plugins/ilert/src/api/types.ts b/plugins/ilert/src/api/types.ts index 6d38d48023..6cbea48c5d 100644 --- a/plugins/ilert/src/api/types.ts +++ b/plugins/ilert/src/api/types.ts @@ -69,11 +69,6 @@ export type EventRequest = { source: string; }; -/** @public */ -export type ServiceRequest = { - name: string; -}; - /** @public */ export interface ILertApi { fetchAlerts(opts?: GetAlertsOpts): Promise; @@ -114,7 +109,6 @@ export interface ILertApi { ): Promise; fetchServices(opts?: GetServicesOpts): Promise; - createService(serviceRequest: ServiceRequest): Promise; fetchStatusPages(opts?: GetStatusPagesOpts): Promise; diff --git a/plugins/ilert/src/components/Alert/AlertLink.tsx b/plugins/ilert/src/components/Alert/AlertLink.tsx index 8c526899aa..4382d6608b 100644 --- a/plugins/ilert/src/components/Alert/AlertLink.tsx +++ b/plugins/ilert/src/components/Alert/AlertLink.tsx @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { makeStyles } from '@material-ui/core/styles'; import React from 'react'; import { ilertApiRef } from '../../api'; import { Alert } from '../../types'; @@ -21,23 +20,12 @@ import { Alert } from '../../types'; import { Link } from '@backstage/core-components'; import { useApi } from '@backstage/core-plugin-api'; -const useStyles = makeStyles({ - link: { - lineHeight: '22px', - }, -}); - export const AlertLink = ({ alert }: { alert: Alert | null }) => { const ilertApi = useApi(ilertApiRef); - const classes = useStyles(); if (!alert) { return null; } - return ( - - #{alert.id} - - ); + return #{alert.id}; }; diff --git a/plugins/ilert/src/components/Alert/AlertStatus.tsx b/plugins/ilert/src/components/Alert/AlertStatus.tsx deleted file mode 100644 index 9be81205dd..0000000000 --- a/plugins/ilert/src/components/Alert/AlertStatus.tsx +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * 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 { StatusError, StatusOK } from '@backstage/core-components'; -import { makeStyles } from '@material-ui/core/styles'; -import Tooltip from '@material-ui/core/Tooltip'; -import React from 'react'; -import { ACCEPTED, Alert, PENDING, RESOLVED } from '../../types'; - -const useStyles = makeStyles({ - denseListIcon: { - marginRight: 0, - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - justifyContent: 'center', - }, -}); - -export const alertStatusLabels = { - [RESOLVED]: 'Resolved', - [ACCEPTED]: 'Accepted', - [PENDING]: 'Pending', -} as Record; - -export const AlertStatus = ({ alert }: { alert: Alert }) => { - const classes = useStyles(); - - return ( - -
- {alert.status === 'PENDING' ? : } -
-
- ); -}; diff --git a/plugins/ilert/src/components/Alert/index.ts b/plugins/ilert/src/components/Alert/index.ts index a569777b21..265fa23f81 100644 --- a/plugins/ilert/src/components/Alert/index.ts +++ b/plugins/ilert/src/components/Alert/index.ts @@ -14,4 +14,3 @@ * limitations under the License. */ export * from './AlertActionsMenu'; -export * from './AlertStatus'; diff --git a/plugins/ilert/src/components/AlertsPage/AlertsPage.tsx b/plugins/ilert/src/components/AlertsPage/AlertsPage.tsx index c7df9101a5..053b5a4267 100644 --- a/plugins/ilert/src/components/AlertsPage/AlertsPage.tsx +++ b/plugins/ilert/src/components/AlertsPage/AlertsPage.tsx @@ -19,7 +19,6 @@ import { ResponseErrorPanel, SupportButton, } from '@backstage/core-components'; -import { AuthenticationError } from '@backstage/errors'; import Button from '@material-ui/core/Button'; import AddIcon from '@material-ui/icons/Add'; import React from 'react'; @@ -48,7 +47,7 @@ export const AlertsPage = () => { }; if (error) { - if (error instanceof AuthenticationError) { + if (error.name === 'AuthenticationError') { return ( diff --git a/plugins/ilert/src/components/AlertsPage/AlertsTable.tsx b/plugins/ilert/src/components/AlertsPage/AlertsTable.tsx index 38ef4f07b1..12f1566276 100644 --- a/plugins/ilert/src/components/AlertsPage/AlertsTable.tsx +++ b/plugins/ilert/src/components/AlertsPage/AlertsTable.tsx @@ -86,31 +86,29 @@ export const AlertsTable = ({ maxWidth: '30%', }; - const idColumn: TableColumn = { + const idColumn: TableColumn = { title: 'ID', field: 'id', highlight: true, cellStyle: smColumnStyle, headerStyle: smColumnStyle, - render: rowData => , + render: rowData => , }; - const summaryColumn: TableColumn = { + const summaryColumn: TableColumn = { title: 'Summary', field: 'summary', cellStyle: !compact ? xlColumnStyle : undefined, headerStyle: !compact ? xlColumnStyle : undefined, - render: rowData => {(rowData as Alert).summary}, + render: rowData => {rowData.summary}, }; - const sourceColumn: TableColumn = { + const sourceColumn: TableColumn = { title: 'Source', field: 'source', cellStyle: mdColumnStyle, headerStyle: mdColumnStyle, - render: rowData => ( - - ), + render: rowData => , }; - const durationColumn: TableColumn = { + const durationColumn: TableColumn = { title: 'Duration', field: 'reportTime', type: 'datetime', @@ -118,20 +116,17 @@ export const AlertsTable = ({ headerStyle: smColumnStyle, render: rowData => ( - {(rowData as Alert).status !== 'RESOLVED' + {rowData.status !== 'RESOLVED' ? humanizeDuration( - Interval.fromDateTimes( - dt.fromISO((rowData as Alert).reportTime), - dt.now(), - ) + Interval.fromDateTimes(dt.fromISO(rowData.reportTime), dt.now()) .toDuration() .valueOf(), { units: ['h', 'm', 's'], largest: 2, round: true }, ) : humanizeDuration( Interval.fromDateTimes( - dt.fromISO((rowData as Alert).reportTime), - dt.fromISO((rowData as Alert).resolvedOn), + dt.fromISO(rowData.reportTime), + dt.fromISO(rowData.resolvedOn), ) .toDuration() .valueOf(), @@ -140,14 +135,14 @@ export const AlertsTable = ({ ), }; - const respondersColumn: TableColumn = { + const respondersColumn: TableColumn = { title: 'Responders', field: 'responders', cellStyle: !compact ? mdColumnStyle : lgColumnStyle, headerStyle: !compact ? mdColumnStyle : lgColumnStyle, render: rowData => ( - {(rowData as Alert).responders.map((value, i, arr) => { + {rowData.responders.map((value, i, arr) => { return ( ilertApi.getUserInitials(value.user) + (arr.length - 1 !== i ? ', ' : '') @@ -156,39 +151,39 @@ export const AlertsTable = ({ ), }; - const priorityColumn: TableColumn = { + const priorityColumn: TableColumn = { title: 'Priority', field: 'priority', cellStyle: smColumnStyle, headerStyle: smColumnStyle, render: rowData => ( - {(rowData as Alert).priority === 'HIGH' ? 'High' : 'Low'} + {rowData.priority === 'HIGH' ? 'High' : 'Low'} ), }; - const statusColumn: TableColumn = { + const statusColumn: TableColumn = { title: 'Status', field: 'status', cellStyle: xsColumnStyle, headerStyle: xsColumnStyle, - render: rowData => , + render: rowData => , }; - const actionsColumn: TableColumn = { + const actionsColumn: TableColumn = { title: '', field: '', cellStyle: xsColumnStyle, headerStyle: xsColumnStyle, render: rowData => ( ), }; - const columns: TableColumn[] = compact + const columns: TableColumn[] = compact ? [ summaryColumn, durationColumn, @@ -206,26 +201,9 @@ export const AlertsTable = ({ statusColumn, actionsColumn, ]; - let tableStyle: React.CSSProperties = {}; - if (compact) { - tableStyle = { - width: '100%', - maxWidth: '100%', - minWidth: '0', - height: 'calc(100% - 10px)', - boxShadow: 'none !important', - borderRadius: 'none !important', - }; - } else { - tableStyle = { - width: '100%', - maxWidth: '100%', - }; - } return (
; + export const StatusChip = ({ alert }: { alert: Alert }) => { const label = `${alertStatusLabels[alert.status]}`; diff --git a/plugins/ilert/src/components/AlertsPage/TableTitle.tsx b/plugins/ilert/src/components/AlertsPage/TableTitle.tsx index c610e91d94..9aab95c6f3 100644 --- a/plugins/ilert/src/components/AlertsPage/TableTitle.tsx +++ b/plugins/ilert/src/components/AlertsPage/TableTitle.tsx @@ -22,7 +22,7 @@ import { makeStyles } from '@material-ui/core/styles'; import Typography from '@material-ui/core/Typography'; import React from 'react'; import { ACCEPTED, AlertStatus, PENDING, RESOLVED } from '../../types'; -import { alertStatusLabels } from '../Alert/AlertStatus'; +import { alertStatusLabels } from './StatusChip'; const ITEM_HEIGHT = 48; const ITEM_PADDING_TOP = 8; diff --git a/plugins/ilert/src/components/OnCallSchedulesPage/OnCallShiftItem.tsx b/plugins/ilert/src/components/OnCallSchedulesPage/OnCallShiftItem.tsx index f9c28430d8..8ef5a990ec 100644 --- a/plugins/ilert/src/components/OnCallSchedulesPage/OnCallShiftItem.tsx +++ b/plugins/ilert/src/components/OnCallSchedulesPage/OnCallShiftItem.tsx @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { useApi } from '@backstage/core-plugin-api'; import Button from '@material-ui/core/Button'; import Grid from '@material-ui/core/Grid'; import { makeStyles } from '@material-ui/core/styles'; @@ -20,6 +21,7 @@ import Typography from '@material-ui/core/Typography'; import RepeatIcon from '@material-ui/icons/Repeat'; import { DateTime as dt } from 'luxon'; import React from 'react'; +import { ilertApiRef } from '../../api'; import { Shift } from '../../types'; import { ShiftOverrideModal } from '../Shift/ShiftOverrideModal'; @@ -48,6 +50,7 @@ export const OnCallShiftItem = ({ refetchOnCallSchedules: () => void; }) => { const classes = useStyles(); + const ilertApi = useApi(ilertApiRef); const [isModalOpened, setIsModalOpened] = React.useState(false); const handleOverride = () => { @@ -71,7 +74,7 @@ export const OnCallShiftItem = ({ {shift && shift.user ? ( - {`${shift.user.firstName} ${shift.user.lastName}`} + {ilertApi.getUserInitials(shift.user)} ) : null} diff --git a/plugins/ilert/src/components/Service/ServiceLink.tsx b/plugins/ilert/src/components/Service/ServiceLink.tsx index f8b1e88531..8e7868a2d2 100644 --- a/plugins/ilert/src/components/Service/ServiceLink.tsx +++ b/plugins/ilert/src/components/Service/ServiceLink.tsx @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { makeStyles } from '@material-ui/core/styles'; import React from 'react'; import { ilertApiRef } from '../../api'; import { Service } from '../../types'; @@ -21,23 +20,12 @@ import { Service } from '../../types'; import { Link } from '@backstage/core-components'; import { useApi } from '@backstage/core-plugin-api'; -const useStyles = makeStyles({ - link: { - lineHeight: '22px', - }, -}); - export const ServiceLink = ({ service }: { service: Service | null }) => { const ilertApi = useApi(ilertApiRef); - const classes = useStyles(); if (!service) { return null; } - return ( - - #{service.id} - - ); + return #{service.id}; }; diff --git a/plugins/ilert/src/components/Service/ServiceStatus.tsx b/plugins/ilert/src/components/Service/ServiceStatus.tsx deleted file mode 100644 index 05923058aa..0000000000 --- a/plugins/ilert/src/components/Service/ServiceStatus.tsx +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * 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 { StatusError, StatusOK } from '@backstage/core-components'; -import { makeStyles } from '@material-ui/core/styles'; -import Tooltip from '@material-ui/core/Tooltip'; -import React from 'react'; -import { - DEGRADED, - MAJOR_OUTAGE, - OPERATIONAL, - PARTIAL_OUTAGE, - Service, - UNDER_MAINTENANCE, -} from '../../types'; - -const useStyles = makeStyles({ - denseListIcon: { - marginRight: 0, - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - justifyContent: 'center', - }, -}); - -export const serviceStatusLabels = { - [OPERATIONAL]: 'Operational', - [UNDER_MAINTENANCE]: 'Under maintenance', - [DEGRADED]: 'Degraded', - [PARTIAL_OUTAGE]: 'Partial outage', - [MAJOR_OUTAGE]: 'Major outage', -} as Record; - -export const ServiceStatus = ({ service }: { service: Service }) => { - const classes = useStyles(); - - return ( - -
- {service.status === 'OPERATIONAL' ? : } -
-
- ); -}; diff --git a/plugins/ilert/src/components/Service/index.ts b/plugins/ilert/src/components/Service/index.ts index 5227f44573..11b2148046 100644 --- a/plugins/ilert/src/components/Service/index.ts +++ b/plugins/ilert/src/components/Service/index.ts @@ -14,4 +14,3 @@ * limitations under the License. */ export * from './ServiceActionsMenu'; -export * from './ServiceStatus'; diff --git a/plugins/ilert/src/components/ServicesPage/ServicesPage.tsx b/plugins/ilert/src/components/ServicesPage/ServicesPage.tsx index e3afd4cc1a..0e012b07a2 100644 --- a/plugins/ilert/src/components/ServicesPage/ServicesPage.tsx +++ b/plugins/ilert/src/components/ServicesPage/ServicesPage.tsx @@ -19,7 +19,6 @@ import { ResponseErrorPanel, SupportButton, } from '@backstage/core-components'; -import { AuthenticationError } from '@backstage/errors'; import React from 'react'; import { useServices } from '../../hooks/useServices'; import { MissingAuthorizationHeaderError } from '../Errors'; @@ -32,7 +31,7 @@ export const ServicesPage = () => { ] = useServices(true); if (error) { - if (error instanceof AuthenticationError) { + if (error.name === 'AuthenticationError') { return ( diff --git a/plugins/ilert/src/components/ServicesPage/ServicesTable.tsx b/plugins/ilert/src/components/ServicesPage/ServicesTable.tsx index 4ed1d581ae..30a83e4cec 100644 --- a/plugins/ilert/src/components/ServicesPage/ServicesTable.tsx +++ b/plugins/ilert/src/components/ServicesPage/ServicesTable.tsx @@ -50,91 +50,59 @@ export const ServicesTable = ({ }) => { const classes = useStyles(); - // const xsColumnStyle = { - // width: '5%', - // maxWidth: '5%', - // }; const smColumnStyle = { width: '10%', maxWidth: '10%', }; - // const mdColumnStyle = { - // width: '15%', - // maxWidth: '15%', - // }; - // const lgColumnStyle = { - // width: '20%', - // maxWidth: '20%', - // }; const xlColumnStyle = { width: '30%', maxWidth: '30%', }; - - const idColumn: TableColumn = { + const idColumn: TableColumn = { title: 'ID', field: 'id', highlight: true, cellStyle: smColumnStyle, headerStyle: smColumnStyle, - render: rowData => , + render: rowData => , }; - const nameColumn: TableColumn = { + const nameColumn: TableColumn = { title: 'Name', field: 'name', cellStyle: !compact ? xlColumnStyle : undefined, headerStyle: !compact ? xlColumnStyle : undefined, - render: rowData => {(rowData as Service).name}, + render: rowData => {rowData.name}, }; - const statusColumn: TableColumn = { + const statusColumn: TableColumn = { title: 'Status', field: 'status', cellStyle: smColumnStyle, headerStyle: smColumnStyle, - render: rowData => , + render: rowData => , }; - const uptimeColumn: TableColumn = { + const uptimeColumn: TableColumn = { title: 'Uptime in the last 90 days', field: 'uptimePercentage', cellStyle: smColumnStyle, headerStyle: smColumnStyle, render: rowData => ( - - {(rowData as Service).uptime.uptimePercentage.p90} - + {rowData.uptime.uptimePercentage.p90} ), }; - const actionsColumn: TableColumn = { + const actionsColumn: TableColumn = { title: '', field: '', cellStyle: smColumnStyle, headerStyle: smColumnStyle, - render: rowData => , + render: rowData => , }; - const columns: TableColumn[] = compact + const columns: TableColumn[] = compact ? [nameColumn, statusColumn, uptimeColumn, actionsColumn] : [idColumn, nameColumn, statusColumn, uptimeColumn, actionsColumn]; - let tableStyle: React.CSSProperties = {}; - if (compact) { - tableStyle = { - width: '100%', - maxWidth: '100%', - minWidth: '0', - height: 'calc(100% - 10px)', - boxShadow: 'none !important', - borderRadius: 'none !important', - }; - } else { - tableStyle = { - width: '100%', - maxWidth: '100%', - }; - } return (
; + export const StatusChip = ({ service }: { service: Service }) => { const label = `${serviceStatusLabels[service.status]}`; diff --git a/plugins/ilert/src/components/StatusPage/StatusPageLink.tsx b/plugins/ilert/src/components/StatusPage/StatusPageLink.tsx index 60daddf9df..edc6922e0d 100644 --- a/plugins/ilert/src/components/StatusPage/StatusPageLink.tsx +++ b/plugins/ilert/src/components/StatusPage/StatusPageLink.tsx @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { makeStyles } from '@material-ui/core/styles'; import React from 'react'; import { ilertApiRef } from '../../api'; import { StatusPage } from '../../types'; @@ -21,29 +20,19 @@ import { StatusPage } from '../../types'; import { Link } from '@backstage/core-components'; import { useApi } from '@backstage/core-plugin-api'; -const useStyles = makeStyles({ - link: { - lineHeight: '22px', - }, -}); - export const StatusPageLink = ({ statusPage, }: { statusPage: StatusPage | null; }) => { const ilertApi = useApi(ilertApiRef); - const classes = useStyles(); if (!statusPage) { return null; } return ( - + #{statusPage.id} ); diff --git a/plugins/ilert/src/components/StatusPage/StatusPageStatus.tsx b/plugins/ilert/src/components/StatusPage/StatusPageStatus.tsx deleted file mode 100644 index b40db5d8f3..0000000000 --- a/plugins/ilert/src/components/StatusPage/StatusPageStatus.tsx +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * 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 { StatusError, StatusOK } from '@backstage/core-components'; -import { makeStyles } from '@material-ui/core/styles'; -import Tooltip from '@material-ui/core/Tooltip'; -import React from 'react'; -import { - DEGRADED, - MAJOR_OUTAGE, - OPERATIONAL, - PARTIAL_OUTAGE, - StatusPage, - UNDER_MAINTENANCE, -} from '../../types'; - -const useStyles = makeStyles({ - denseListIcon: { - marginRight: 0, - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - justifyContent: 'center', - }, -}); - -export const statusPageStatusLabels = { - [OPERATIONAL]: 'Operational', - [UNDER_MAINTENANCE]: 'Under maintenance', - [DEGRADED]: 'Degraded', - [PARTIAL_OUTAGE]: 'Partial outage', - [MAJOR_OUTAGE]: 'Major outage', -} as Record; - -export const StatusPageStatus = ({ - statusPage, -}: { - statusPage: StatusPage; -}) => { - const classes = useStyles(); - - return ( - -
- {statusPage.status === 'OPERATIONAL' ? : } -
-
- ); -}; diff --git a/plugins/ilert/src/components/StatusPage/StatusPageURL.tsx b/plugins/ilert/src/components/StatusPage/StatusPageURL.tsx index b94903333a..1aaf209770 100644 --- a/plugins/ilert/src/components/StatusPage/StatusPageURL.tsx +++ b/plugins/ilert/src/components/StatusPage/StatusPageURL.tsx @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { makeStyles } from '@material-ui/core/styles'; import React from 'react'; import { ilertApiRef } from '../../api'; import { StatusPage } from '../../types'; @@ -21,19 +20,12 @@ import { StatusPage } from '../../types'; import { Link } from '@backstage/core-components'; import { useApi } from '@backstage/core-plugin-api'; -const useStyles = makeStyles({ - link: { - lineHeight: '22px', - }, -}); - export const StatusPageURL = ({ statusPage, }: { statusPage: StatusPage | null; }) => { const ilertApi = useApi(ilertApiRef); - const classes = useStyles(); if (!statusPage) { return null; @@ -41,9 +33,5 @@ export const StatusPageURL = ({ const url = ilertApi.getStatusPageURL(statusPage); - return ( - - {url} - - ); + return {url}; }; diff --git a/plugins/ilert/src/components/StatusPage/StatusPageVisibility.tsx b/plugins/ilert/src/components/StatusPage/StatusPageVisibility.tsx deleted file mode 100644 index 7c8f63dd35..0000000000 --- a/plugins/ilert/src/components/StatusPage/StatusPageVisibility.tsx +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * 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 { StatusError, StatusOK } from '@backstage/core-components'; -import { makeStyles } from '@material-ui/core/styles'; -import Tooltip from '@material-ui/core/Tooltip'; -import React from 'react'; -import { PRIVATE, PUBLIC, StatusPage } from '../../types'; - -const useStyles = makeStyles({ - denseListIcon: { - marginRight: 0, - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - justifyContent: 'center', - }, -}); - -export const statusPageVisibilityLabels = { - [PUBLIC]: 'Public', - [PRIVATE]: 'Private', -} as Record; - -export const StatusPageVisibility = ({ - statusPage, -}: { - statusPage: StatusPage; -}) => { - const classes = useStyles(); - - return ( - -
- {statusPage.visibility === 'PUBLIC' ? : } -
-
- ); -}; diff --git a/plugins/ilert/src/components/StatusPage/index.ts b/plugins/ilert/src/components/StatusPage/index.ts index 93ea9deaba..d805811d90 100644 --- a/plugins/ilert/src/components/StatusPage/index.ts +++ b/plugins/ilert/src/components/StatusPage/index.ts @@ -14,4 +14,3 @@ * limitations under the License. */ export * from './StatusPageActionsMenu'; -export * from './StatusPageStatus'; diff --git a/plugins/ilert/src/components/StatusPagePage/StatusChip.tsx b/plugins/ilert/src/components/StatusPagePage/StatusChip.tsx index 50a64de212..5cd785c4cd 100644 --- a/plugins/ilert/src/components/StatusPagePage/StatusChip.tsx +++ b/plugins/ilert/src/components/StatusPagePage/StatusChip.tsx @@ -23,7 +23,6 @@ import { StatusPage, UNDER_MAINTENANCE, } from '../../types'; -import { statusPageStatusLabels } from '../StatusPage/StatusPageStatus'; const OperationalChip = withStyles({ root: { @@ -62,6 +61,14 @@ const MajorOutageChip = withStyles({ }, })(Chip); +const statusPageStatusLabels = { + [OPERATIONAL]: 'Operational', + [UNDER_MAINTENANCE]: 'Under maintenance', + [DEGRADED]: 'Degraded', + [PARTIAL_OUTAGE]: 'Partial outage', + [MAJOR_OUTAGE]: 'Major outage', +} as Record; + export const StatusChip = ({ statusPage }: { statusPage: StatusPage }) => { const label = `${statusPageStatusLabels[statusPage.status]}`; diff --git a/plugins/ilert/src/components/StatusPagePage/StatusPagesPage.tsx b/plugins/ilert/src/components/StatusPagePage/StatusPagesPage.tsx index 6e4290c7c9..9d709c5e73 100644 --- a/plugins/ilert/src/components/StatusPagePage/StatusPagesPage.tsx +++ b/plugins/ilert/src/components/StatusPagePage/StatusPagesPage.tsx @@ -19,7 +19,6 @@ import { ResponseErrorPanel, SupportButton, } from '@backstage/core-components'; -import { AuthenticationError } from '@backstage/errors'; import React from 'react'; import { useStatusPages } from '../../hooks/useStatusPages'; import { MissingAuthorizationHeaderError } from '../Errors'; @@ -32,7 +31,7 @@ export const StatusPagesPage = () => { ] = useStatusPages(true); if (error) { - if (error instanceof AuthenticationError) { + if (error.name === 'AuthenticationError') { return ( diff --git a/plugins/ilert/src/components/StatusPagePage/StatusPagesTable.tsx b/plugins/ilert/src/components/StatusPagePage/StatusPagesTable.tsx index 8b013fdb35..8e965b42de 100644 --- a/plugins/ilert/src/components/StatusPagePage/StatusPagesTable.tsx +++ b/plugins/ilert/src/components/StatusPagePage/StatusPagesTable.tsx @@ -52,74 +52,60 @@ export const StatusPagesTable = ({ }) => { const classes = useStyles(); - // const xsColumnStyle = { - // width: '5%', - // maxWidth: '5%', - // }; const smColumnStyle = { width: '10%', maxWidth: '10%', }; - // const mdColumnStyle = { - // width: '15%', - // maxWidth: '15%', - // }; - // const lgColumnStyle = { - // width: '20%', - // maxWidth: '20%', - // }; const xlColumnStyle = { width: '30%', maxWidth: '30%', }; - const idColumn: TableColumn = { + const idColumn: TableColumn = { title: 'ID', field: 'id', highlight: true, cellStyle: smColumnStyle, headerStyle: smColumnStyle, - render: rowData => , + render: rowData => , }; - const nameColumn: TableColumn = { + const nameColumn: TableColumn = { title: 'Name', field: 'name', cellStyle: !compact ? xlColumnStyle : undefined, headerStyle: !compact ? xlColumnStyle : undefined, - render: rowData => {(rowData as StatusPage).name}, + render: rowData => {rowData.name}, }; - const urlColumn: TableColumn = { + const urlColumn: TableColumn = { title: 'URL', field: 'url', cellStyle: smColumnStyle, headerStyle: smColumnStyle, - render: rowData => , + render: rowData => , }; - const visibilityColumn: TableColumn = { + const visibilityColumn: TableColumn = { title: 'Visibility', field: 'visibility', cellStyle: smColumnStyle, headerStyle: smColumnStyle, - render: rowData => , + render: rowData => , }; - const statusColumn: TableColumn = { + const statusColumn: TableColumn = { title: 'Status', field: 'status', cellStyle: smColumnStyle, headerStyle: smColumnStyle, - render: rowData => , + render: rowData => , }; - const actionsColumn: TableColumn = { + const actionsColumn: TableColumn = { title: '', field: '', cellStyle: smColumnStyle, headerStyle: smColumnStyle, - render: rowData => ( - - ), + render: rowData => , }; - const columns: TableColumn[] = compact + const columns: TableColumn[] = compact ? [nameColumn, statusColumn, urlColumn, actionsColumn] : [ idColumn, @@ -129,26 +115,9 @@ export const StatusPagesTable = ({ visibilityColumn, actionsColumn, ]; - let tableStyle: React.CSSProperties = {}; - if (compact) { - tableStyle = { - width: '100%', - maxWidth: '100%', - minWidth: '0', - height: 'calc(100% - 10px)', - boxShadow: 'none !important', - borderRadius: 'none !important', - }; - } else { - tableStyle = { - width: '100%', - maxWidth: '100%', - }; - } return (
; + export const VisibilityChip = ({ statusPage }: { statusPage: StatusPage }) => { const label = `${statusPageVisibilityLabels[statusPage.visibility]}`; From b2adf21bda0afe08fba534bb86e9b19d0b4169be Mon Sep 17 00:00:00 2001 From: Marko Simon Date: Thu, 20 Oct 2022 16:07:13 +0200 Subject: [PATCH 11/13] remove uptime monitors Signed-off-by: Marko Simon --- plugins/ilert/src/api/client.ts | 64 ------- plugins/ilert/src/api/types.ts | 9 +- .../src/components/ILertPage/ILertPage.tsx | 4 - .../UptimeMonitorActionsMenu.tsx | 137 -------------- .../UptimeMonitor/UptimeMonitorLink.tsx | 50 ----- .../src/components/UptimeMonitor/index.ts | 16 -- .../UptimeMonitorsPage/StatusChip.tsx | 73 -------- .../UptimeMonitorCheckType.tsx | 42 ----- .../UptimeMonitorsPage/UptimeMonitorsPage.tsx | 67 ------- .../UptimeMonitorsTable.tsx | 176 ------------------ .../components/UptimeMonitorsPage/index.ts | 17 -- plugins/ilert/src/hooks/useUptimeMonitors.ts | 87 --------- plugins/ilert/src/types.ts | 26 --- 13 files changed, 1 insertion(+), 767 deletions(-) delete mode 100644 plugins/ilert/src/components/UptimeMonitor/UptimeMonitorActionsMenu.tsx delete mode 100644 plugins/ilert/src/components/UptimeMonitor/UptimeMonitorLink.tsx delete mode 100644 plugins/ilert/src/components/UptimeMonitor/index.ts delete mode 100644 plugins/ilert/src/components/UptimeMonitorsPage/StatusChip.tsx delete mode 100644 plugins/ilert/src/components/UptimeMonitorsPage/UptimeMonitorCheckType.tsx delete mode 100644 plugins/ilert/src/components/UptimeMonitorsPage/UptimeMonitorsPage.tsx delete mode 100644 plugins/ilert/src/components/UptimeMonitorsPage/UptimeMonitorsTable.tsx delete mode 100644 plugins/ilert/src/components/UptimeMonitorsPage/index.ts delete mode 100644 plugins/ilert/src/hooks/useUptimeMonitors.ts diff --git a/plugins/ilert/src/api/client.ts b/plugins/ilert/src/api/client.ts index bc438786c7..9eb60c8c6a 100644 --- a/plugins/ilert/src/api/client.ts +++ b/plugins/ilert/src/api/client.ts @@ -30,7 +30,6 @@ import { Schedule, Service, StatusPage, - UptimeMonitor, User, } from '../types'; import { @@ -293,63 +292,6 @@ export class ILertClient implements ILertApi { return response; } - async fetchUptimeMonitors(): Promise { - const init = { - headers: JSON_HEADERS, - }; - - const response = await this.fetch('/api/uptime-monitors', init); - - return response; - } - - async fetchUptimeMonitor(id: number): Promise { - const init = { - headers: JSON_HEADERS, - }; - - const response: UptimeMonitor = await this.fetch( - `/api/uptime-monitors/${encodeURIComponent(id)}`, - init, - ); - - return response; - } - - async pauseUptimeMonitor( - uptimeMonitor: UptimeMonitor, - ): Promise { - const init = { - method: 'PUT', - headers: JSON_HEADERS, - body: JSON.stringify({ ...uptimeMonitor, paused: true }), - }; - - const response = await this.fetch( - `/api/uptime-monitors/${encodeURIComponent(uptimeMonitor.id)}`, - init, - ); - - return response; - } - - async resumeUptimeMonitor( - uptimeMonitor: UptimeMonitor, - ): Promise { - const init = { - method: 'PUT', - headers: JSON_HEADERS, - body: JSON.stringify({ ...uptimeMonitor, paused: false }), - }; - - const response = await this.fetch( - `/api/uptime-monitors/${encodeURIComponent(uptimeMonitor.id)}`, - init, - ); - - return response; - } - async fetchAlertSources(): Promise { const init = { headers: JSON_HEADERS, @@ -546,12 +488,6 @@ export class ILertClient implements ILertApi { )}`; } - getUptimeMonitorDetailsURL(uptimeMonitor: UptimeMonitor): string { - return `${this.baseUrl}/uptime/view.jsf?id=${encodeURIComponent( - uptimeMonitor.id, - )}`; - } - getScheduleDetailsURL(schedule: Schedule): string { return `${this.baseUrl}/schedule/view.jsf?id=${encodeURIComponent( schedule.id, diff --git a/plugins/ilert/src/api/types.ts b/plugins/ilert/src/api/types.ts index 6cbea48c5d..28a7cea7c0 100644 --- a/plugins/ilert/src/api/types.ts +++ b/plugins/ilert/src/api/types.ts @@ -25,8 +25,7 @@ import { Schedule, Service, StatusPage, - UptimeMonitor, - User, + User } from '../types'; /** @public */ @@ -82,11 +81,6 @@ export interface ILertApi { createAlert(eventRequest: EventRequest): Promise; triggerAlertAction(alert: Alert, action: AlertAction): Promise; - fetchUptimeMonitors(): Promise; - pauseUptimeMonitor(uptimeMonitor: UptimeMonitor): Promise; - resumeUptimeMonitor(uptimeMonitor: UptimeMonitor): Promise; - fetchUptimeMonitor(id: number): Promise; - fetchAlertSources(): Promise; fetchAlertSource(idOrIntegrationKey: number | string): Promise; fetchAlertSourceOnCalls(alertSource: AlertSource): Promise; @@ -115,7 +109,6 @@ export interface ILertApi { getAlertDetailsURL(alert: Alert): string; getAlertSourceDetailsURL(alertSource: AlertSource | null): string; getEscalationPolicyDetailsURL(escalationPolicy: EscalationPolicy): string; - getUptimeMonitorDetailsURL(uptimeMonitor: UptimeMonitor): string; getScheduleDetailsURL(schedule: Schedule): string; getServiceDetailsURL(service: Service): string; getStatusPageDetailsURL(statusPage: StatusPage): string; diff --git a/plugins/ilert/src/components/ILertPage/ILertPage.tsx b/plugins/ilert/src/components/ILertPage/ILertPage.tsx index 51512f6d39..5b95677ce8 100644 --- a/plugins/ilert/src/components/ILertPage/ILertPage.tsx +++ b/plugins/ilert/src/components/ILertPage/ILertPage.tsx @@ -25,7 +25,6 @@ import { AlertsPage } from '../AlertsPage'; import { OnCallSchedulesPage } from '../OnCallSchedulesPage'; import { ServicesPage } from '../ServicesPage'; import { StatusPagesPage } from '../StatusPagePage'; -import { UptimeMonitorsPage } from '../UptimeMonitorsPage'; /** @public */ export const ILertPage = () => { @@ -35,7 +34,6 @@ export const ILertPage = () => { { label: 'Alerts' }, { label: 'Services' }, { label: 'Status pages' }, - { label: 'Uptime Monitors' }, ]; const renderTab = () => { switch (selectedTab) { @@ -47,8 +45,6 @@ export const ILertPage = () => { return ; case 3: return ; - case 4: - return ; default: return null; } diff --git a/plugins/ilert/src/components/UptimeMonitor/UptimeMonitorActionsMenu.tsx b/plugins/ilert/src/components/UptimeMonitor/UptimeMonitorActionsMenu.tsx deleted file mode 100644 index 2d25f8e50e..0000000000 --- a/plugins/ilert/src/components/UptimeMonitor/UptimeMonitorActionsMenu.tsx +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * 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 { IconButton, Menu, MenuItem, Typography } from '@material-ui/core'; -import MoreVertIcon from '@material-ui/icons/MoreVert'; - -import { ilertApiRef } from '../../api'; -import { UptimeMonitor } from '../../types'; - -import { alertApiRef, useApi } from '@backstage/core-plugin-api'; -import { Link } from '@backstage/core-components'; - -export const UptimeMonitorActionsMenu = ({ - uptimeMonitor, - onUptimeMonitorChanged, -}: { - uptimeMonitor: UptimeMonitor; - onUptimeMonitorChanged?: (uptimeMonitor: UptimeMonitor) => void; -}) => { - const ilertApi = useApi(ilertApiRef); - const alertApi = useApi(alertApiRef); - const [anchorEl, setAnchorEl] = React.useState(null); - const callback = onUptimeMonitorChanged || ((_: UptimeMonitor): void => {}); - - const handleClick = (event: React.MouseEvent) => { - setAnchorEl(event.currentTarget); - }; - - const handleCloseMenu = () => { - setAnchorEl(null); - }; - - const handlePause = async (): Promise => { - try { - const newUptimeMonitor = await ilertApi.pauseUptimeMonitor(uptimeMonitor); - handleCloseMenu(); - alertApi.post({ message: 'Uptime monitor paused.' }); - - callback(newUptimeMonitor); - } catch (err) { - alertApi.post({ message: err, severity: 'error' }); - } - }; - - const handleResume = async (): Promise => { - try { - const newUptimeMonitor = await ilertApi.resumeUptimeMonitor( - uptimeMonitor, - ); - handleCloseMenu(); - alertApi.post({ message: 'Uptime monitor resumed.' }); - - callback(newUptimeMonitor); - } catch (err) { - alertApi.post({ message: err, severity: 'error' }); - } - }; - - const handleOpenReport = async (): Promise => { - try { - const um = await ilertApi.fetchUptimeMonitor(uptimeMonitor.id); - handleCloseMenu(); - window.open(um.shareUrl, '_blank'); - } catch (err) { - alertApi.post({ message: err, severity: 'error' }); - } - }; - - return ( - <> - - - - - {uptimeMonitor.paused ? ( - - - Resume - - - ) : null} - - {!uptimeMonitor.paused ? ( - - - Pause - - - ) : null} - - - - - View Report - - - - - - - - View in iLert - - - - - - ); -}; diff --git a/plugins/ilert/src/components/UptimeMonitor/UptimeMonitorLink.tsx b/plugins/ilert/src/components/UptimeMonitor/UptimeMonitorLink.tsx deleted file mode 100644 index c70a8a40f0..0000000000 --- a/plugins/ilert/src/components/UptimeMonitor/UptimeMonitorLink.tsx +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * 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 { makeStyles } from '@material-ui/core/styles'; -import { UptimeMonitor } from '../../types'; -import { ilertApiRef } from '../../api'; - -import { useApi } from '@backstage/core-plugin-api'; -import { Link } from '@backstage/core-components'; - -const useStyles = makeStyles({ - link: { - lineHeight: '22px', - }, -}); - -export const UptimeMonitorLink = ({ - uptimeMonitor, -}: { - uptimeMonitor: UptimeMonitor | null; -}) => { - const ilertApi = useApi(ilertApiRef); - const classes = useStyles(); - - if (!uptimeMonitor) { - return null; - } - - return ( - - #{uptimeMonitor.id} - - ); -}; diff --git a/plugins/ilert/src/components/UptimeMonitor/index.ts b/plugins/ilert/src/components/UptimeMonitor/index.ts deleted file mode 100644 index a4aa2fb88c..0000000000 --- a/plugins/ilert/src/components/UptimeMonitor/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * 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 * from './UptimeMonitorActionsMenu'; diff --git a/plugins/ilert/src/components/UptimeMonitorsPage/StatusChip.tsx b/plugins/ilert/src/components/UptimeMonitorsPage/StatusChip.tsx deleted file mode 100644 index 39f3ef250b..0000000000 --- a/plugins/ilert/src/components/UptimeMonitorsPage/StatusChip.tsx +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * 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 Chip from '@material-ui/core/Chip'; -import { withStyles } from '@material-ui/core/styles'; -import { UptimeMonitor } from '../../types'; - -const UpChip = withStyles({ - root: { - backgroundColor: '#4caf50', - color: 'white', - margin: 0, - }, -})(Chip); - -const DownChip = withStyles({ - root: { - backgroundColor: '#d32f2f', - color: 'white', - margin: 0, - }, -})(Chip); - -const UnknownChip = withStyles({ - root: { - backgroundColor: '#92949c', - color: 'white', - margin: 0, - }, -})(Chip); - -export const uptimeMonitorStatusLabels = { - ['up']: 'Up', - ['down']: 'Down', - ['unknown']: 'Unknown', -} as Record; - -export const StatusChip = ({ - uptimeMonitor, -}: { - uptimeMonitor: UptimeMonitor; -}) => { - let label = `${uptimeMonitorStatusLabels[uptimeMonitor.status]}`; - - if (uptimeMonitor.paused) { - label = 'Paused'; - return ; - } - - switch (uptimeMonitor.status) { - case 'up': - return ; - case 'down': - return ; - case 'unknown': - return ; - default: - return ; - } -}; diff --git a/plugins/ilert/src/components/UptimeMonitorsPage/UptimeMonitorCheckType.tsx b/plugins/ilert/src/components/UptimeMonitorsPage/UptimeMonitorCheckType.tsx deleted file mode 100644 index a39901836f..0000000000 --- a/plugins/ilert/src/components/UptimeMonitorsPage/UptimeMonitorCheckType.tsx +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * 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 { UptimeMonitor } from '../../types'; -import Typography from '@material-ui/core/Typography'; - -export const UptimeMonitorCheckType = ({ - uptimeMonitor, -}: { - uptimeMonitor: UptimeMonitor; -}) => { - switch (uptimeMonitor.region) { - case 'EU': - return ( - {`${uptimeMonitor.checkType.toUpperCase()} πŸ‡©πŸ‡ͺ`} - ); - default: - return ( - {`${uptimeMonitor.checkType.toUpperCase()} πŸ‡ΊπŸ‡Έ`} - ); - } -}; diff --git a/plugins/ilert/src/components/UptimeMonitorsPage/UptimeMonitorsPage.tsx b/plugins/ilert/src/components/UptimeMonitorsPage/UptimeMonitorsPage.tsx deleted file mode 100644 index 33612d492b..0000000000 --- a/plugins/ilert/src/components/UptimeMonitorsPage/UptimeMonitorsPage.tsx +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * 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 { AuthenticationError } from '@backstage/errors'; -import { UptimeMonitorsTable } from './UptimeMonitorsTable'; -import { MissingAuthorizationHeaderError } from '../Errors'; -import { useUptimeMonitors } from '../../hooks/useUptimeMonitors'; -import { - Content, - ContentHeader, - SupportButton, - ResponseErrorPanel, -} from '@backstage/core-components'; - -export const UptimeMonitorsPage = () => { - const [ - { tableState, uptimeMonitors, isLoading, error }, - { onChangePage, onChangeRowsPerPage, onUptimeMonitorChanged }, - ] = useUptimeMonitors(); - - if (error) { - if (error instanceof AuthenticationError) { - return ( - - - - ); - } - - return ( - - - - ); - } - - return ( - - - - This helps you to bring iLert into your developer portal. - - - - - ); -}; diff --git a/plugins/ilert/src/components/UptimeMonitorsPage/UptimeMonitorsTable.tsx b/plugins/ilert/src/components/UptimeMonitorsPage/UptimeMonitorsTable.tsx deleted file mode 100644 index 3099018e91..0000000000 --- a/plugins/ilert/src/components/UptimeMonitorsPage/UptimeMonitorsTable.tsx +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * 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 { makeStyles } from '@material-ui/core/styles'; -import { TableState } from '../../api'; -import { UptimeMonitor } from '../../types'; -import { StatusChip } from './StatusChip'; -import Typography from '@material-ui/core/Typography'; -import { DateTime as dt, Interval } from 'luxon'; -import humanizeDuration from 'humanize-duration'; -import { EscalationPolicyLink } from '../EscalationPolicy/EscalationPolicyLink'; -import { UptimeMonitorCheckType } from './UptimeMonitorCheckType'; -import { UptimeMonitorActionsMenu } from '../UptimeMonitor/UptimeMonitorActionsMenu'; -import { UptimeMonitorLink } from '../UptimeMonitor/UptimeMonitorLink'; -import { Table, TableColumn } from '@backstage/core-components'; - -const useStyles = makeStyles(theme => ({ - empty: { - padding: theme.spacing(2), - display: 'flex', - justifyContent: 'center', - }, -})); - -export const UptimeMonitorsTable = ({ - uptimeMonitors, - tableState, - isLoading, - onChangePage, - onChangeRowsPerPage, - onUptimeMonitorChanged, -}: { - uptimeMonitors: UptimeMonitor[]; - tableState: TableState; - isLoading: boolean; - onChangePage: (page: number) => void; - onChangeRowsPerPage: (pageSize: number) => void; - onUptimeMonitorChanged: (uptimeMonitor: UptimeMonitor) => void; -}) => { - const classes = useStyles(); - - const smColumnStyle = { - width: '5%', - maxWidth: '5%', - }; - const mdColumnStyle = { - width: '10%', - maxWidth: '10%', - }; - const lgColumnStyle = { - width: '15%', - maxWidth: '15%', - }; - - const columns: TableColumn[] = [ - { - title: 'ID', - field: 'id', - highlight: true, - cellStyle: mdColumnStyle, - headerStyle: mdColumnStyle, - render: rowData => ( - - ), - }, - { - title: 'Name', - field: 'name', - render: rowData => ( - {(rowData as UptimeMonitor).name} - ), - }, - { - title: 'Check Type', - field: 'checkType', - cellStyle: lgColumnStyle, - headerStyle: lgColumnStyle, - render: rowData => ( - - ), - }, - { - title: 'Last state change', - field: 'lastStatusChange', - type: 'datetime', - cellStyle: mdColumnStyle, - headerStyle: mdColumnStyle, - render: rowData => ( - - {humanizeDuration( - Interval.fromDateTimes( - dt.fromISO((rowData as UptimeMonitor).lastStatusChange), - dt.now(), - ) - .toDuration() - .valueOf(), - { units: ['h', 'm', 's'], largest: 2, round: true }, - )} - - ), - }, - { - title: 'Escalation policy', - field: 'assignedTo', - cellStyle: lgColumnStyle, - headerStyle: lgColumnStyle, - render: rowData => ( - - ), - }, - { - title: 'Status', - field: 'status', - cellStyle: smColumnStyle, - headerStyle: smColumnStyle, - render: rowData => ( - - ), - }, - { - title: '', - field: '', - cellStyle: smColumnStyle, - headerStyle: smColumnStyle, - render: rowData => ( - - ), - }, - ]; - - return ( -
- No uptime monitor - - } - page={tableState.page} - onPageChange={onChangePage} - onRowsPerPageChange={onChangeRowsPerPage} - localization={{ header: { actions: undefined } }} - isLoading={isLoading} - columns={columns} - data={uptimeMonitors} - /> - ); -}; diff --git a/plugins/ilert/src/components/UptimeMonitorsPage/index.ts b/plugins/ilert/src/components/UptimeMonitorsPage/index.ts deleted file mode 100644 index 865783b5e6..0000000000 --- a/plugins/ilert/src/components/UptimeMonitorsPage/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * 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 * from './UptimeMonitorsPage'; -export * from './UptimeMonitorsTable'; diff --git a/plugins/ilert/src/hooks/useUptimeMonitors.ts b/plugins/ilert/src/hooks/useUptimeMonitors.ts deleted file mode 100644 index c71d5f02af..0000000000 --- a/plugins/ilert/src/hooks/useUptimeMonitors.ts +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * 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 { ilertApiRef, TableState } from '../api'; -import { AuthenticationError } from '@backstage/errors'; -import useAsyncRetry from 'react-use/lib/useAsyncRetry'; -import { UptimeMonitor } from '../types'; -import { useApi, errorApiRef } from '@backstage/core-plugin-api'; - -export const useUptimeMonitors = () => { - const ilertApi = useApi(ilertApiRef); - const errorApi = useApi(errorApiRef); - - const [tableState, setTableState] = React.useState({ - page: 0, - pageSize: 10, - }); - const [uptimeMonitorsList, setUptimeMonitorsList] = React.useState< - UptimeMonitor[] - >([]); - const [isLoading, setIsLoading] = React.useState(false); - - const { error, retry } = useAsyncRetry(async () => { - try { - setIsLoading(true); - const data = await ilertApi.fetchUptimeMonitors(); - setUptimeMonitorsList(data || []); - setIsLoading(false); - } catch (e) { - setIsLoading(false); - if (!(e instanceof AuthenticationError)) { - errorApi.post(e); - } - throw e; - } - }, [tableState]); - - const onUptimeMonitorChanged = (newUptimeMonitor: UptimeMonitor) => { - setUptimeMonitorsList( - uptimeMonitorsList.map((uptimeMonitor: UptimeMonitor): UptimeMonitor => { - if (newUptimeMonitor.id === uptimeMonitor.id) { - return newUptimeMonitor; - } - - return uptimeMonitor; - }), - ); - }; - - const onChangePage = (page: number) => { - setTableState({ ...tableState, page }); - }; - const onChangeRowsPerPage = (pageSize: number) => { - setTableState({ ...tableState, pageSize }); - }; - - return [ - { - tableState, - uptimeMonitors: uptimeMonitorsList, - error, - isLoading, - }, - { - setTableState, - setUptimeMonitorsList, - retry, - onUptimeMonitorChanged, - onChangePage, - onChangeRowsPerPage, - setIsLoading, - }, - ] as const; -}; diff --git a/plugins/ilert/src/types.ts b/plugins/ilert/src/types.ts index 28b8b7ca8a..e55abb67a5 100644 --- a/plugins/ilert/src/types.ts +++ b/plugins/ilert/src/types.ts @@ -351,32 +351,6 @@ export interface Shift { end: string; } -/** @public */ -export interface UptimeMonitor { - id: number; - name: string; - region: 'EU' | 'US'; - checkType: 'http' | 'tcp' | 'udp' | 'ping'; - checkParams: UptimeMonitorCheckParams; - intervalSec: number; - timeoutMs: number; - createAlertAfterFailedChecks: number; - paused: boolean; - embedUrl: string; - shareUrl: string; - status: string; - lastStatusChange: string; - escalationPolicy: EscalationPolicy; - teams: TeamShort[]; -} - -/** @public */ -export interface UptimeMonitorCheckParams { - host?: string; - port?: number; - url?: string; -} - /** @public */ export interface AlertResponder { group: 'SUGGESTED' | 'USER' | 'ESCALATION_POLICY' | 'ON_CALL_SCHEDULE'; From dc1214e8aabc4f47df3ce407f564f8ada168f844 Mon Sep 17 00:00:00 2001 From: Marko Simon Date: Thu, 20 Oct 2022 16:28:20 +0200 Subject: [PATCH 12/13] fix last commit, update api-reports Signed-off-by: Marko Simon --- plugins/ilert/api-report.md | 64 ------------------- .../src/components/ILertCard/ILertCard.tsx | 7 +- .../ILertCard/ILertCardActionsHeader.tsx | 16 +---- plugins/ilert/src/hooks/useAlertSource.ts | 37 ++--------- 4 files changed, 7 insertions(+), 117 deletions(-) diff --git a/plugins/ilert/api-report.md b/plugins/ilert/api-report.md index 51e2020dee..6cc0c12a8f 100644 --- a/plugins/ilert/api-report.md +++ b/plugins/ilert/api-report.md @@ -406,10 +406,6 @@ export interface ILertApi { // (undocumented) fetchStatusPages(opts?: GetStatusPagesOpts): Promise; // (undocumented) - fetchUptimeMonitor(id: number): Promise; - // (undocumented) - fetchUptimeMonitors(): Promise; - // (undocumented) fetchUsers(): Promise; // (undocumented) getAlertDetailsURL(alert: Alert): string; @@ -426,8 +422,6 @@ export interface ILertApi { // (undocumented) getStatusPageURL(statusPage: StatusPage): string; // (undocumented) - getUptimeMonitorDetailsURL(uptimeMonitor: UptimeMonitor): string; - // (undocumented) getUserInitials(user: User | null): string; // (undocumented) getUserPhoneNumber(user: User | null): string; @@ -439,12 +433,8 @@ export interface ILertApi { end: string, ): Promise; // (undocumented) - pauseUptimeMonitor(uptimeMonitor: UptimeMonitor): Promise; - // (undocumented) resolveAlert(alert: Alert, userName: string): Promise; // (undocumented) - resumeUptimeMonitor(uptimeMonitor: UptimeMonitor): Promise; - // (undocumented) triggerAlertAction(alert: Alert, action: AlertAction): Promise; } @@ -499,10 +489,6 @@ export class ILertClient implements ILertApi { // (undocumented) fetchStatusPages(opts?: GetStatusPagesOpts): Promise; // (undocumented) - fetchUptimeMonitor(id: number): Promise; - // (undocumented) - fetchUptimeMonitors(): Promise; - // (undocumented) fetchUsers(): Promise; // (undocumented) static fromConfig( @@ -524,8 +510,6 @@ export class ILertClient implements ILertApi { // (undocumented) getStatusPageURL(statusPage: StatusPage): string; // (undocumented) - getUptimeMonitorDetailsURL(uptimeMonitor: UptimeMonitor): string; - // (undocumented) getUserInitials(user: User | null): string; // (undocumented) getUserPhoneNumber(user: User | null): string; @@ -537,12 +521,8 @@ export class ILertClient implements ILertApi { end: string, ): Promise; // (undocumented) - pauseUptimeMonitor(uptimeMonitor: UptimeMonitor): Promise; - // (undocumented) resolveAlert(alert: Alert, userName: string): Promise; // (undocumented) - resumeUptimeMonitor(uptimeMonitor: UptimeMonitor): Promise; - // (undocumented) triggerAlertAction(alert: Alert, action: AlertAction): Promise; } @@ -786,50 +766,6 @@ export interface Uptime { uptimePercentage: UptimePercentage; } -// @public (undocumented) -export interface UptimeMonitor { - // (undocumented) - checkParams: UptimeMonitorCheckParams; - // (undocumented) - checkType: 'http' | 'tcp' | 'udp' | 'ping'; - // (undocumented) - createAlertAfterFailedChecks: number; - // (undocumented) - embedUrl: string; - // (undocumented) - escalationPolicy: EscalationPolicy; - // (undocumented) - id: number; - // (undocumented) - intervalSec: number; - // (undocumented) - lastStatusChange: string; - // (undocumented) - name: string; - // (undocumented) - paused: boolean; - // (undocumented) - region: 'EU' | 'US'; - // (undocumented) - shareUrl: string; - // (undocumented) - status: string; - // (undocumented) - teams: TeamShort[]; - // (undocumented) - timeoutMs: number; -} - -// @public (undocumented) -export interface UptimeMonitorCheckParams { - // (undocumented) - host?: string; - // (undocumented) - port?: number; - // (undocumented) - url?: string; -} - // @public (undocumented) export interface UptimePercentage { // (undocumented) diff --git a/plugins/ilert/src/components/ILertCard/ILertCard.tsx b/plugins/ilert/src/components/ILertCard/ILertCard.tsx index d124751b2b..204c32369c 100644 --- a/plugins/ilert/src/components/ILertCard/ILertCard.tsx +++ b/plugins/ilert/src/components/ILertCard/ILertCard.tsx @@ -55,10 +55,8 @@ const useStyles = makeStyles({ export const ILertCard = () => { const classes = useStyles(); const { integrationKey, name } = useILertEntity(); - const [ - { alertSource, uptimeMonitor }, - { setAlertSource, refetchAlertSource }, - ] = useAlertSource(integrationKey); + const [{ alertSource }, { setAlertSource, refetchAlertSource }] = + useAlertSource(integrationKey); const [ { tableState, states, alerts, alertsCount, isLoading, error }, { @@ -99,7 +97,6 @@ export const ILertCard = () => { setAlertSource={setAlertSource} setIsNewAlertModalOpened={setIsNewAlertModalOpened} setIsMaintenanceModalOpened={setIsMaintenanceModalOpened} - uptimeMonitor={uptimeMonitor} /> } action={} diff --git a/plugins/ilert/src/components/ILertCard/ILertCardActionsHeader.tsx b/plugins/ilert/src/components/ILertCard/ILertCardActionsHeader.tsx index 49f2c789c4..85118b29b9 100644 --- a/plugins/ilert/src/components/ILertCard/ILertCardActionsHeader.tsx +++ b/plugins/ilert/src/components/ILertCard/ILertCardActionsHeader.tsx @@ -23,12 +23,11 @@ import AlarmAddIcon from '@material-ui/icons/AlarmAdd'; import BuildIcon from '@material-ui/icons/Build'; import PauseIcon from '@material-ui/icons/Pause'; import PlayArrowIcon from '@material-ui/icons/PlayArrow'; -import TimelineIcon from '@material-ui/icons/Timeline'; import WebIcon from '@material-ui/icons/Web'; import Alert from '@material-ui/lab/Alert'; import React from 'react'; import { ilertApiRef } from '../../api'; -import { AlertSource, UptimeMonitor } from '../../types'; +import { AlertSource } from '../../types'; import { HeaderIconLinkRow, @@ -41,13 +40,11 @@ export const ILertCardActionsHeader = ({ setAlertSource, setIsNewAlertModalOpened, setIsMaintenanceModalOpened, - uptimeMonitor, }: { alertSource: AlertSource | null; setAlertSource: (alertSource: AlertSource) => void; setIsNewAlertModalOpened: (isOpen: boolean) => void; setIsMaintenanceModalOpened: (isOpen: boolean) => void; - uptimeMonitor: UptimeMonitor | null; }) => { const ilertApi = useApi(ilertApiRef); const alertApi = useApi(alertApiRef); @@ -140,13 +137,6 @@ export const ILertCardActionsHeader = ({ disabled: !alertSource || isLoading, }; - const uptimeMonitorReportLink: IconLinkVerticalProps = { - label: 'Uptime Report', - href: uptimeMonitor ? uptimeMonitor.shareUrl : '', - icon: , - disabled: !alertSource || !uptimeMonitor || isLoading, - }; - const links: IconLinkVerticalProps[] = [ alertSourceLink, createAlertLink, @@ -155,10 +145,6 @@ export const ILertCardActionsHeader = ({ : enableAlertSourceLink, ]; - if (alertSource && alertSource.integrationType === 'MONITOR') { - links.push(uptimeMonitorReportLink); - } - if (alertSource && alertSource.status !== 'IN_MAINTENANCE') { links.push(maintenanceAlertSourceLink); } diff --git a/plugins/ilert/src/hooks/useAlertSource.ts b/plugins/ilert/src/hooks/useAlertSource.ts index c80b3d59eb..9048ee3031 100644 --- a/plugins/ilert/src/hooks/useAlertSource.ts +++ b/plugins/ilert/src/hooks/useAlertSource.ts @@ -18,7 +18,7 @@ import { AuthenticationError } from '@backstage/errors'; import React from 'react'; import useAsyncRetry from 'react-use/lib/useAsyncRetry'; import { ilertApiRef } from '../api'; -import { AlertSource, UptimeMonitor } from '../types'; +import { AlertSource } from '../types'; export const useAlertSource = (integrationKey: string) => { const ilertApi = useApi(ilertApiRef); @@ -28,10 +28,6 @@ export const useAlertSource = (integrationKey: string) => { null, ); const [isAlertSourceLoading, setIsAlertSourceLoading] = React.useState(false); - const [uptimeMonitor, setUptimeMonitor] = - React.useState(null); - const [isUptimeMonitorLoading, setIsUptimeMonitorLoading] = - React.useState(false); const fetchAlertSourceCall = async () => { try { @@ -56,38 +52,13 @@ export const useAlertSource = (integrationKey: string) => { [integrationKey], ); - const fetchUptimeMonitorCall = async () => { - try { - if (!alertSource || alertSource.integrationType !== 'MONITOR') { - return; - } - setIsUptimeMonitorLoading(true); - const data = await ilertApi.fetchUptimeMonitor(alertSource.id); - setUptimeMonitor(data || null); - setIsUptimeMonitorLoading(false); - } catch (e) { - setIsUptimeMonitorLoading(false); - if (!(e instanceof AuthenticationError)) { - errorApi.post(e); - } - throw e; - } - }; - - const { error: uptimeMonitorError, retry: uptimeMonitorRetry } = - useAsyncRetry(fetchUptimeMonitorCall, [alertSource]); - - const retry = () => { - alertSourceRetry(); - uptimeMonitorRetry(); - }; + const retry = () => alertSourceRetry(); return [ { alertSource, - uptimeMonitor, - error: alertSourceError || uptimeMonitorError, - isLoading: isAlertSourceLoading || isUptimeMonitorLoading, + error: alertSourceError, + isLoading: isAlertSourceLoading, }, { retry, From bb4bdd0d156ceac2757bacf69c545056164fb2e0 Mon Sep 17 00:00:00 2001 From: Marko Simon Date: Thu, 20 Oct 2022 16:40:04 +0200 Subject: [PATCH 13/13] fix for prettier Signed-off-by: Marko Simon --- plugins/ilert/src/api/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/ilert/src/api/types.ts b/plugins/ilert/src/api/types.ts index 28a7cea7c0..959d7975ac 100644 --- a/plugins/ilert/src/api/types.ts +++ b/plugins/ilert/src/api/types.ts @@ -25,7 +25,7 @@ import { Schedule, Service, StatusPage, - User + User, } from '../types'; /** @public */