Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions workspaces/ilert/.changeset/silent-wasps-explain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@backstage-community/plugin-ilert': minor
---

Migrate plugin from mui to bui
7 changes: 2 additions & 5 deletions workspaces/ilert/plugins/ilert/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,8 @@
"@backstage/errors": "backstage:^",
"@backstage/frontend-plugin-api": "backstage:^",
"@backstage/plugin-catalog-react": "backstage:^",
"@date-io/luxon": "1.x",
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "4.0.0-alpha.61",
"@material-ui/pickers": "^3.3.10",
"@backstage/ui": "backstage:^",
"@remixicon/react": "^4.2.0",
"@types/react": "^16.13.1 || ^17.0.0 || ^18.0.0",
"humanize-duration": "^3.26.0",
"luxon": "^3.0.0",
Expand Down
4 changes: 2 additions & 2 deletions workspaces/ilert/plugins/ilert/report.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Entity } from '@backstage/catalog-model';
import { FetchApi } from '@backstage/core-plugin-api';
import { JSX as JSX_2 } from 'react/jsx-runtime';
import { RouteRef } from '@backstage/core-plugin-api';
import { SvgIconProps } from '@material-ui/core/SvgIcon';
import { SVGAttributes } from 'react';

// @public (undocumented)
export const ACCEPTED = 'ACCEPTED';
Expand Down Expand Up @@ -531,7 +531,7 @@ export class ILertClient implements ILertApi {
}

// @public (undocumented)
export const ILertIcon: (props: SvgIconProps) => JSX_2.Element;
export const ILertIcon: (props: SVGAttributes<SVGSVGElement>) => JSX_2.Element;

// @public (undocumented)
export const ILertPage: () => JSX_2.Element;
Expand Down
24 changes: 20 additions & 4 deletions workspaces/ilert/plugins/ilert/src/ILertIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,29 @@
* limitations under the License.
*/

import SvgIcon, { SvgIconProps } from '@material-ui/core/SvgIcon';
/*
* Copyright 2022 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 { SVGAttributes } from 'react';

/**
* @public
*/
export const ILertIcon = (props: SvgIconProps) => (
<SvgIcon {...props}>
export const ILertIcon = (props: SVGAttributes<SVGSVGElement>) => (
<svg viewBox="0 0 24 24" {...props}>
<g>
<path
stroke="none"
Expand Down Expand Up @@ -65,5 +81,5 @@ export const ILertIcon = (props: SvgIconProps) => (
d="M 10.355469 5.945312 C 10.355469 8.613281 11.957031 11.019531 14.417969 12.050781 L 14.417969 9.917969 C 15.972656 10.925781 17.972656 10.925781 19.527344 9.917969 L 19.527344 12.050781 C 20.847656 11.496094 21.953125 10.53125 22.679688 9.300781 L 22.679688 4.105469 C 22.679688 1.847656 20.832031 0 18.574219 0 L 14.066406 0 C 11.796875 1.113281 10.355469 3.417969 10.355469 5.945312 Z M 16.972656 2.5625 C 18.84375 2.5625 20.355469 4.078125 20.355469 5.945312 C 20.355469 7.8125 18.84375 9.328125 16.972656 9.328125 C 15.105469 9.328125 13.589844 7.8125 13.589844 5.945312 C 13.59375 4.078125 15.105469 2.566406 16.972656 2.5625 Z M 16.972656 2.5625"
/>
</g>
</SvgIcon>
</svg>
);
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import IconButton from '@material-ui/core/IconButton';
import Menu from '@material-ui/core/Menu';
import MenuItem from '@material-ui/core/MenuItem';
import Typography from '@material-ui/core/Typography';
import MoreVertIcon from '@material-ui/icons/MoreVert';
import type { MouseEvent, ReactNode } from 'react';
import { ButtonIcon, MenuTrigger, Menu, MenuItem, Text } from '@backstage/ui';
import { RiMore2Line } from '@remixicon/react';
import { useState } from 'react';
import { ilertApiRef } from '../../api';
import { useAlertActions } from '../../hooks/useAlertActions';
Expand All @@ -42,28 +38,15 @@ export const AlertActionsMenu = ({
const ilertApi = useApi(ilertApiRef);
const alertApi = useApi(toastApiRef);
const identityApi = useApi(identityApiRef);
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const callback = onAlertChanged || ((_: Alert): void => {});
const setProcessing = setIsLoading || ((_: boolean): void => {});
const [isAssignAlertModalOpened, setIsAssignAlertModalOpened] =
useState(false);

const [{ alertActions, isLoading }] = useAlertActions(
alert,
Boolean(anchorEl),
);

const handleClick = (event: MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget);
};

const handleCloseMenu = () => {
setAnchorEl(null);
};
const [{ alertActions, isLoading }] = useAlertActions(alert, true);

const handleAccept = async (): Promise<void> => {
try {
handleCloseMenu();
setProcessing(true);

const { userEntityRef } = await identityApi.getBackstageIdentity();
Expand All @@ -84,7 +67,6 @@ export const AlertActionsMenu = ({

const handleResolve = async (): Promise<void> => {
try {
handleCloseMenu();
setProcessing(true);
const { userEntityRef } = await identityApi.getBackstageIdentity();
const { name: userName } = parseEntityRef(userEntityRef, {
Expand All @@ -103,13 +85,11 @@ export const AlertActionsMenu = ({
};

const handleAssign = () => {
handleCloseMenu();
setIsAssignAlertModalOpened(true);
};

const handleTriggerAction = (action: AlertAction) => async () => {
try {
handleCloseMenu();
setProcessing(true);
await ilertApi.triggerAlertAction(alert, action);
alertApi.post({ title: 'Alert action triggered.' });
Expand All @@ -120,86 +100,67 @@ export const AlertActionsMenu = ({
}
};

const actions: ReactNode[] = alertActions.map(a => {
const successTrigger = a.history
? a.history.find(h => h.success)
: undefined;
const triggeredBy =
successTrigger && successTrigger.actor
? `${successTrigger.actor.firstName} ${successTrigger.actor.lastName}`
: '';
return (
<MenuItem
key={a.webhookId}
onClick={handleTriggerAction(a)}
disabled={!!successTrigger}
>
<Typography variant="inherit" noWrap>
{triggeredBy ? `${a.name} (by ${triggeredBy})` : a.name}
</Typography>
</MenuItem>
);
});

return (
<>
<IconButton
aria-label="more"
aria-controls="long-menu"
aria-haspopup="true"
onClick={handleClick}
size="small"
>
<MoreVertIcon />
</IconButton>
<Menu
id={`alert-actions-menu-${alert.id}`}
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleCloseMenu}
PaperProps={{
style: { maxHeight: 48 * 5.5 },
}}
>
{alert.status === 'PENDING' ? (
<MenuItem key="ack" onClick={handleAccept}>
<Typography variant="inherit" noWrap>
Accept
</Typography>
<MenuTrigger>
<ButtonIcon
aria-label="more"
variant="secondary"
icon={<RiMore2Line size={16} />}
/>
<Menu>
{alert.status === 'PENDING' ? (
<MenuItem key="ack" onAction={handleAccept}>
<Text>Accept</Text>
</MenuItem>
) : null}

{alert.status !== 'RESOLVED' ? (
<MenuItem key="close" onAction={handleResolve}>
<Text>Resolve</Text>
</MenuItem>
) : null}

{alert.status !== 'RESOLVED' ? (
<MenuItem key="assign" onAction={handleAssign}>
<Text>Assign</Text>
</MenuItem>
) : null}

{isLoading ? (
<MenuItem key="loading">
<Progress style={{ width: '100%' }} />
</MenuItem>
) : (
alertActions.map(a => {
const successTrigger = a.history
? a.history.find(h => h.success)
: undefined;
const triggeredBy =
successTrigger && successTrigger.actor
? `${successTrigger.actor.firstName} ${successTrigger.actor.lastName}`
: '';
return (
<MenuItem
key={a.webhookId}
onAction={handleTriggerAction(a)}
isDisabled={!!successTrigger}
>
<Text>
{triggeredBy ? `${a.name} (by ${triggeredBy})` : a.name}
</Text>
</MenuItem>
);
})
)}

<MenuItem key="details">
<Text>
<Link to={ilertApi.getAlertDetailsURL(alert)}>View in ilert</Link>
</Text>
</MenuItem>
) : null}

{alert.status !== 'RESOLVED' ? (
<MenuItem key="close" onClick={handleResolve}>
<Typography variant="inherit" noWrap>
Resolve
</Typography>
</MenuItem>
) : null}

{alert.status !== 'RESOLVED' ? (
<MenuItem key="assign" onClick={handleAssign}>
<Typography variant="inherit" noWrap>
Assign
</Typography>
</MenuItem>
) : null}

{isLoading ? (
<MenuItem key="loading">
<Progress style={{ width: '100%' }} />
</MenuItem>
) : (
actions
)}

<MenuItem key="details" onClick={handleCloseMenu}>
<Typography variant="inherit" noWrap>
<Link to={ilertApi.getAlertDetailsURL(alert)}>View in ilert</Link>
</Typography>
</MenuItem>
</Menu>
</Menu>
</MenuTrigger>
<AlertAssignModal
alert={alert}
setIsModalOpened={setIsAssignAlertModalOpened}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* 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.
*/
@layer components {
.alertInfo {
background-color: var(--bui-bg-surface-2);
border-left: 4px solid #2196f3;
padding: var(--bui-space-3);
margin-bottom: var(--bui-space-3);
border-radius: var(--bui-radius-2);
}

.selectWrapper {
margin-bottom: var(--bui-space-3);
margin-top: var(--bui-space-3);
}

.label {
display: block;
margin-bottom: var(--bui-space-2);
color: var(--bui-fg-primary);
font-weight: 500;
font-size: 14px;
}

.select {
width: 100%;
padding: var(--bui-space-2) var(--bui-space-3);
border: 1px solid var(--bui-border-primary);
border-radius: var(--bui-radius-2);
background-color: var(--bui-bg-surface-1);
color: var(--bui-fg-primary);
font-size: 14px;
font-family: inherit;
cursor: pointer;
}

.select:hover {
border-color: var(--bui-border-secondary);
}

.select:focus {
outline: none;
border-color: #2196f3;
box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1);
}

.select:disabled {
background-color: var(--bui-bg-surface-2);
cursor: not-allowed;
opacity: 0.6;
}
}
Loading
Loading