feat(splunk-on-call-plugin): filter on-call based on team
This commit is contained in:
@@ -26,20 +26,23 @@ import { User } from '../types';
|
||||
|
||||
type Props = {
|
||||
users: { [key: string]: User };
|
||||
team: string;
|
||||
};
|
||||
|
||||
export const EscalationPolicy = ({ users }: Props) => {
|
||||
export const EscalationPolicy = ({ users, team }: Props) => {
|
||||
const api = useApi(splunkOnCallApiRef);
|
||||
|
||||
const { value: userNames, loading, error } = useAsync(async () => {
|
||||
const oncalls = await api.getOnCallUsers();
|
||||
const users = oncalls.flatMap(oncall => {
|
||||
return oncall.oncallNow?.flatMap(oncallNow => {
|
||||
return oncallNow.users?.flatMap(user => {
|
||||
return user?.onCalluser?.username;
|
||||
const users = oncalls
|
||||
.filter(oncall => oncall.team?.name === team)
|
||||
.flatMap(oncall => {
|
||||
return oncall.oncallNow?.flatMap(oncallNow => {
|
||||
return oncallNow.users?.flatMap(user => {
|
||||
return user?.onCalluser?.username;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return users;
|
||||
});
|
||||
|
||||
@@ -225,7 +225,7 @@ export const IncidentListItem = ({ incident, onIncidentAction }: Props) => {
|
||||
resolveAction={handleResolveIncident}
|
||||
aknowledgeAction={handleAcknowledgeIncident}
|
||||
/>
|
||||
<Tooltip title="View in SplunkOnCall" placement="top">
|
||||
<Tooltip title="View in Splunk On-Call" placement="top">
|
||||
<IconButton
|
||||
href={incident.incidentLink}
|
||||
target="_blank"
|
||||
|
||||
@@ -50,20 +50,21 @@ const useStyles = makeStyles({
|
||||
},
|
||||
});
|
||||
|
||||
export const SPLUNK_ON_CALL_INTEGRATION_KEY = '';
|
||||
export const SPLUNK_ON_CALL_TEAM = 'splunk-on-call.com/team';
|
||||
|
||||
export const isPluginApplicableToEntity = (entity: Entity) =>
|
||||
Boolean(entity.metadata.annotations?.[SPLUNK_ON_CALL_INTEGRATION_KEY]);
|
||||
Boolean(entity.metadata.annotations?.[SPLUNK_ON_CALL_TEAM]);
|
||||
|
||||
type Props = {
|
||||
entity: Entity;
|
||||
};
|
||||
|
||||
export const SplunkOnCallCard = () => {
|
||||
export const SplunkOnCallCard = ({ entity }: Props) => {
|
||||
const classes = useStyles();
|
||||
const api = useApi(splunkOnCallApiRef);
|
||||
const [showDialog, setShowDialog] = useState<boolean>(false);
|
||||
const [refreshIncidents, setRefreshIncidents] = useState<boolean>(false);
|
||||
const team = entity.metadata.annotations![SPLUNK_ON_CALL_TEAM];
|
||||
|
||||
const handleRefresh = useCallback(() => {
|
||||
setRefreshIncidents(x => !x);
|
||||
@@ -127,7 +128,9 @@ export const SplunkOnCallCard = () => {
|
||||
<Divider />
|
||||
<CardContent>
|
||||
<Incidents refreshIncidents={refreshIncidents} />
|
||||
{users?.usersHashMap && <EscalationPolicy users={users.usersHashMap} />}
|
||||
{users?.usersHashMap && (
|
||||
<EscalationPolicy team={team} users={users.usersHashMap} />
|
||||
)}
|
||||
{users && (
|
||||
<TriggerDialog
|
||||
users={users?.userList}
|
||||
|
||||
@@ -34,6 +34,9 @@ import {
|
||||
FormControl,
|
||||
InputLabel,
|
||||
} from '@material-ui/core';
|
||||
import Card from '@material-ui/core/Card';
|
||||
import CardActions from '@material-ui/core/CardActions';
|
||||
import CardContent from '@material-ui/core/CardContent';
|
||||
import { useApi, alertApiRef, identityApiRef } from '@backstage/core';
|
||||
import { useAsync, useAsyncFn } from 'react-use';
|
||||
import { splunkOnCallApiRef } from '../../api';
|
||||
@@ -189,57 +192,75 @@ export const TriggerDialog = ({
|
||||
automatically be amended to the alarm so that the receiver can reach
|
||||
out to you if necessary.
|
||||
</Typography>
|
||||
<FormControl className={classes.formControl}>
|
||||
<InputLabel>Select users</InputLabel>
|
||||
<Select
|
||||
id="user-targets"
|
||||
multiple
|
||||
value={userTargets}
|
||||
onChange={handleUserTargets}
|
||||
input={<Input />}
|
||||
renderValue={selected => (
|
||||
<div className={classes.chips}>
|
||||
{(selected as string[]).map(value => (
|
||||
<Chip key={value} label={value} className={classes.chip} />
|
||||
<Card>
|
||||
<CardContent>
|
||||
<Typography color="textPrimary" gutterBottom>
|
||||
Select the targets
|
||||
</Typography>
|
||||
<FormControl className={classes.formControl}>
|
||||
<InputLabel>Select users</InputLabel>
|
||||
<Select
|
||||
id="user-targets"
|
||||
multiple
|
||||
value={userTargets}
|
||||
onChange={handleUserTargets}
|
||||
input={<Input />}
|
||||
renderValue={selected => (
|
||||
<div className={classes.chips}>
|
||||
{(selected as string[]).map(value => (
|
||||
<Chip
|
||||
key={value}
|
||||
label={value}
|
||||
className={classes.chip}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
MenuProps={MenuProps}
|
||||
>
|
||||
{users.map(user => (
|
||||
<MenuItem key={user.email} value={user.username}>
|
||||
{user.firstName} {user.lastName}
|
||||
</MenuItem>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
MenuProps={MenuProps}
|
||||
>
|
||||
{users.map(user => (
|
||||
<MenuItem key={user.email} value={user.username}>
|
||||
{user.firstName} {user.lastName}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
<FormControl className={classes.formControl}>
|
||||
<InputLabel>Select an escalation poilicy</InputLabel>
|
||||
<Select
|
||||
id="policy-targets"
|
||||
multiple
|
||||
value={policyTargets}
|
||||
onChange={handlePolicyTargets}
|
||||
input={<Input />}
|
||||
renderValue={selected => (
|
||||
<div className={classes.chips}>
|
||||
{(selected as string[]).map(value => (
|
||||
<Chip key={value} label={value} className={classes.chip} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
MenuProps={MenuProps}
|
||||
>
|
||||
{!error &&
|
||||
!loading &&
|
||||
policies &&
|
||||
policies.map(policy => (
|
||||
<MenuItem key={policy.policy.slug} value={policy.policy.slug}>
|
||||
{policy.policy.name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</Select>
|
||||
</FormControl>
|
||||
<FormControl className={classes.formControl}>
|
||||
<InputLabel>Select an escalation poilicy</InputLabel>
|
||||
<Select
|
||||
id="policy-targets"
|
||||
multiple
|
||||
value={policyTargets}
|
||||
onChange={handlePolicyTargets}
|
||||
input={<Input />}
|
||||
renderValue={selected => (
|
||||
<div className={classes.chips}>
|
||||
{(selected as string[]).map(value => (
|
||||
<Chip
|
||||
key={value}
|
||||
label={value}
|
||||
className={classes.chip}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
MenuProps={MenuProps}
|
||||
>
|
||||
{!error &&
|
||||
!loading &&
|
||||
policies &&
|
||||
policies.map(policy => (
|
||||
<MenuItem
|
||||
key={policy.policy.slug}
|
||||
value={policy.policy.slug}
|
||||
>
|
||||
{policy.policy.name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<FormControl className={classes.formControl}>
|
||||
<InputLabel>Acknowledge Behavior</InputLabel>
|
||||
<Select
|
||||
@@ -247,8 +268,14 @@ export const TriggerDialog = ({
|
||||
value={isMultiResponder}
|
||||
onChange={isMultiResponderChanged}
|
||||
>
|
||||
<MenuItem value="1">Stop paging</MenuItem>
|
||||
<MenuItem value="0">Continue paging</MenuItem>
|
||||
<MenuItem value="1">
|
||||
Stop paging after a single Acknowledge from an escalation policy
|
||||
or user
|
||||
</MenuItem>
|
||||
<MenuItem value="0">
|
||||
Continue paging until each escalation policy or user above has
|
||||
acknowledged
|
||||
</MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
<TextField
|
||||
@@ -259,7 +286,7 @@ export const TriggerDialog = ({
|
||||
fullWidth
|
||||
rows="4"
|
||||
margin="normal"
|
||||
label="Problem summary"
|
||||
label="Incident summary"
|
||||
variant="outlined"
|
||||
onChange={summaryChanged}
|
||||
/>
|
||||
@@ -271,7 +298,7 @@ export const TriggerDialog = ({
|
||||
fullWidth
|
||||
rows="2"
|
||||
margin="normal"
|
||||
label="Problem details"
|
||||
label="Incident body"
|
||||
variant="outlined"
|
||||
onChange={detailsChanged}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user