Composability updates for Splunk On-Call plugin
Signed-off-by: Tim Hansen <timbonicus@gmail.com>
This commit is contained in:
@@ -25,27 +25,24 @@ cd packages/app
|
||||
yarn add @backstage/plugin-splunk-on-call
|
||||
```
|
||||
|
||||
Add it to the app in `plugins.ts`:
|
||||
|
||||
```ts
|
||||
export { plugin as SplunkOnCall } from '@backstage/plugin-splunk-on-call';
|
||||
```
|
||||
|
||||
Add it to the `EntityPage.tsx`:
|
||||
Add it to your `EntityPage`:
|
||||
|
||||
```ts
|
||||
// packages/app/src/components/catalog/EntityPage.tsx
|
||||
import {
|
||||
isPluginApplicableToEntity as isSplunkOnCallAvailable,
|
||||
SplunkOnCallCard,
|
||||
isSplunkOnCallAvailable,
|
||||
EntitySplunkOnCallCard,
|
||||
} from '@backstage/plugin-splunk-on-call';
|
||||
// ...
|
||||
{
|
||||
isSplunkOnCallAvailable(entity) && (
|
||||
<Grid item md={6}>
|
||||
<SplunkOnCallCard entity={entity} />
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
const overviewContent = (
|
||||
<Grid container spacing={3} alignItems="stretch">
|
||||
<EntitySwitch>
|
||||
<EntitySwitch.Case if={isSplunkOnCallAvailable}>
|
||||
<Grid item md={6}>
|
||||
<EntitySplunkOnCallCard />
|
||||
</Grid>
|
||||
</EntitySwitch.Case>
|
||||
</EntitySwitch>
|
||||
```
|
||||
|
||||
## Client configuration
|
||||
|
||||
+30
-16
@@ -14,10 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { render, waitFor, fireEvent, act } from '@testing-library/react';
|
||||
import { SplunkOnCallCard } from './SplunkOnCallCard';
|
||||
import { act, fireEvent, render, waitFor } from '@testing-library/react';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { wrapInTestApp } from '@backstage/test-utils';
|
||||
import {
|
||||
alertApiRef,
|
||||
ApiProvider,
|
||||
@@ -27,10 +25,12 @@ import {
|
||||
ConfigReader,
|
||||
createApiRef,
|
||||
} from '@backstage/core';
|
||||
import { EntityContext } from '@backstage/plugin-catalog-react';
|
||||
import { wrapInTestApp } from '@backstage/test-utils';
|
||||
import {
|
||||
splunkOnCallApiRef,
|
||||
UnauthorizedError,
|
||||
SplunkOnCallClient,
|
||||
UnauthorizedError,
|
||||
} from '../api';
|
||||
import {
|
||||
ESCALATION_POLICIES,
|
||||
@@ -39,6 +39,7 @@ import {
|
||||
MOCK_INCIDENT,
|
||||
MOCK_TEAM,
|
||||
} from '../api/mocks';
|
||||
import { EntitySplunkOnCallCard } from './EntitySplunkOnCallCard';
|
||||
|
||||
const mockSplunkOnCallApi: Partial<SplunkOnCallClient> = {
|
||||
getUsers: async () => [],
|
||||
@@ -65,15 +66,20 @@ const apis = ApiRegistry.from([
|
||||
}),
|
||||
],
|
||||
]);
|
||||
const entity: Entity = {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
name: 'splunkoncall-test',
|
||||
annotations: {
|
||||
'splunk.com/on-call-team': 'Example',
|
||||
|
||||
const mockEntityData = {
|
||||
loading: false,
|
||||
error: undefined,
|
||||
entity: {
|
||||
apiVersion: 'backstage.io/v1alpha1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
name: 'splunkoncall-test',
|
||||
annotations: {
|
||||
'splunk.com/on-call-team': 'Example',
|
||||
},
|
||||
},
|
||||
},
|
||||
} as Entity,
|
||||
};
|
||||
|
||||
describe('SplunkOnCallCard', () => {
|
||||
@@ -85,7 +91,9 @@ describe('SplunkOnCallCard', () => {
|
||||
const { getByText, queryByTestId } = render(
|
||||
wrapInTestApp(
|
||||
<ApiProvider apis={apis}>
|
||||
<SplunkOnCallCard entity={entity} />
|
||||
<EntityContext.Provider value={mockEntityData}>
|
||||
<EntitySplunkOnCallCard />
|
||||
</EntityContext.Provider>
|
||||
</ApiProvider>,
|
||||
),
|
||||
);
|
||||
@@ -106,7 +114,9 @@ describe('SplunkOnCallCard', () => {
|
||||
const { getByText, queryByTestId } = render(
|
||||
wrapInTestApp(
|
||||
<ApiProvider apis={apis}>
|
||||
<SplunkOnCallCard entity={entity} />
|
||||
<EntityContext.Provider value={mockEntityData}>
|
||||
<EntitySplunkOnCallCard />
|
||||
</EntityContext.Provider>
|
||||
</ApiProvider>,
|
||||
),
|
||||
);
|
||||
@@ -123,7 +133,9 @@ describe('SplunkOnCallCard', () => {
|
||||
const { getByText, queryByTestId } = render(
|
||||
wrapInTestApp(
|
||||
<ApiProvider apis={apis}>
|
||||
<SplunkOnCallCard entity={entity} />
|
||||
<EntityContext.Provider value={mockEntityData}>
|
||||
<EntitySplunkOnCallCard />
|
||||
</EntityContext.Provider>
|
||||
</ApiProvider>,
|
||||
),
|
||||
);
|
||||
@@ -144,7 +156,9 @@ describe('SplunkOnCallCard', () => {
|
||||
const { getByText, queryByTestId, getByRole } = render(
|
||||
wrapInTestApp(
|
||||
<ApiProvider apis={apis}>
|
||||
<SplunkOnCallCard entity={entity} />
|
||||
<EntityContext.Provider value={mockEntityData}>
|
||||
<EntitySplunkOnCallCard />
|
||||
</EntityContext.Provider>
|
||||
</ApiProvider>,
|
||||
),
|
||||
);
|
||||
+15
-17
@@ -13,33 +13,34 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React, { useState, useCallback } from 'react';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { useAsync } from 'react-use';
|
||||
import {
|
||||
useApi,
|
||||
Progress,
|
||||
HeaderIconLinkRow,
|
||||
MissingAnnotationEmptyState,
|
||||
configApiRef,
|
||||
EmptyState,
|
||||
HeaderIconLinkRow,
|
||||
IconLinkVerticalProps,
|
||||
MissingAnnotationEmptyState,
|
||||
Progress,
|
||||
useApi,
|
||||
} from '@backstage/core';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { useEntity } from '@backstage/plugin-catalog-react';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
Divider,
|
||||
CardContent,
|
||||
Typography,
|
||||
} from '@material-ui/core';
|
||||
import { Incidents } from './Incident';
|
||||
import { EscalationPolicy } from './Escalation';
|
||||
import AlarmAddIcon from '@material-ui/icons/AlarmAdd';
|
||||
import WebIcon from '@material-ui/icons/Web';
|
||||
import { useAsync } from 'react-use';
|
||||
import { Alert } from '@material-ui/lab';
|
||||
import { splunkOnCallApiRef, UnauthorizedError } from '../api';
|
||||
import AlarmAddIcon from '@material-ui/icons/AlarmAdd';
|
||||
import { TriggerDialog } from './TriggerDialog';
|
||||
import { MissingApiKeyOrApiIdError } from './Errors/MissingApiKeyOrApiIdError';
|
||||
import { EscalationPolicy } from './Escalation';
|
||||
import { Incidents } from './Incident';
|
||||
import { TriggerDialog } from './TriggerDialog';
|
||||
import { User } from './types';
|
||||
|
||||
export const SPLUNK_ON_CALL_TEAM = 'splunk.com/on-call-team';
|
||||
@@ -58,16 +59,13 @@ export const MissingEventsRestEndpoint = () => (
|
||||
</CardContent>
|
||||
);
|
||||
|
||||
export const isPluginApplicableToEntity = (entity: Entity) =>
|
||||
export const isSplunkOnCallAvailable = (entity: Entity) =>
|
||||
Boolean(entity.metadata.annotations?.[SPLUNK_ON_CALL_TEAM]);
|
||||
|
||||
type Props = {
|
||||
entity: Entity;
|
||||
};
|
||||
|
||||
export const SplunkOnCallCard = ({ entity }: Props) => {
|
||||
export const EntitySplunkOnCallCard = () => {
|
||||
const config = useApi(configApiRef);
|
||||
const api = useApi(splunkOnCallApiRef);
|
||||
const { entity } = useEntity();
|
||||
const [showDialog, setShowDialog] = useState<boolean>(false);
|
||||
const [refreshIncidents, setRefreshIncidents] = useState<boolean>(false);
|
||||
const team = entity.metadata.annotations![SPLUNK_ON_CALL_TEAM];
|
||||
@@ -23,8 +23,7 @@ import {
|
||||
Header,
|
||||
SupportButton,
|
||||
} from '@backstage/core';
|
||||
import { SplunkOnCallCard } from './SplunkOnCallCard';
|
||||
import { useEntity } from '@backstage/plugin-catalog-react';
|
||||
import { EntitySplunkOnCallCard } from './EntitySplunkOnCallCard';
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
overflowXScroll: {
|
||||
@@ -44,7 +43,6 @@ export const SplunkOnCallPage = ({
|
||||
pageTitle,
|
||||
}: SplunkOnCallPageProps): JSX.Element => {
|
||||
const classes = useStyles();
|
||||
const { entity } = useEntity();
|
||||
|
||||
return (
|
||||
<Page themeId="tool">
|
||||
@@ -57,7 +55,7 @@ export const SplunkOnCallPage = ({
|
||||
</ContentHeader>
|
||||
<Grid container spacing={3} direction="row">
|
||||
<Grid item xs={12} sm={6} md={4}>
|
||||
<SplunkOnCallCard entity={entity} />
|
||||
<EntitySplunkOnCallCard />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Content>
|
||||
|
||||
@@ -14,14 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
export {
|
||||
SplunkOnCallCard,
|
||||
splunkOnCallPlugin,
|
||||
splunkOnCallPlugin as plugin,
|
||||
SplunkOnCallPage,
|
||||
} from './plugin';
|
||||
export {
|
||||
isPluginApplicableToEntity,
|
||||
SplunkOnCallCard,
|
||||
} from './components/SplunkOnCallCard';
|
||||
export { isSplunkOnCallAvailable } from './components/EntitySplunkOnCallCard';
|
||||
export {
|
||||
SplunkOnCallClient,
|
||||
splunkOnCallApiRef,
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
discoveryApiRef,
|
||||
configApiRef,
|
||||
createRoutableExtension,
|
||||
createComponentExtension,
|
||||
} from '@backstage/core';
|
||||
import { splunkOnCallApiRef, SplunkOnCallClient } from './api';
|
||||
|
||||
@@ -49,3 +50,14 @@ export const SplunkOnCallPage = splunkOnCallPlugin.provide(
|
||||
mountPoint: rootRouteRef,
|
||||
}),
|
||||
);
|
||||
|
||||
export const SplunkOnCallCard = splunkOnCallPlugin.provide(
|
||||
createComponentExtension({
|
||||
component: {
|
||||
lazy: () =>
|
||||
import('./components/EntitySplunkOnCallCard').then(
|
||||
m => m.EntitySplunkOnCallCard,
|
||||
),
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user