@backstage-community/plugin-splunk-on-call 0.19.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/README.md +15 -1
- package/config.d.ts +3 -0
- package/dist/alpha/apis.esm.js +4 -3
- package/dist/alpha/apis.esm.js.map +1 -1
- package/dist/alpha.d.ts +33 -15
- package/dist/api/client.esm.js +24 -5
- package/dist/api/client.esm.js.map +1 -1
- package/dist/components/Incident/IncidentListItem.esm.js +14 -13
- package/dist/components/Incident/IncidentListItem.esm.js.map +1 -1
- package/dist/components/TriggerDialog/TriggerDialog.esm.js +9 -8
- package/dist/components/TriggerDialog/TriggerDialog.esm.js.map +1 -1
- package/dist/index.d.ts +28 -24
- package/dist/index.esm.js +1 -1
- package/dist/plugin.esm.js +7 -3
- package/dist/plugin.esm.js.map +1 -1
- package/package.json +11 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @backstage-community/plugin-splunk-on-call
|
|
2
2
|
|
|
3
|
+
## 0.21.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 333f1ce: Backstage version bump to v1.49.2
|
|
8
|
+
|
|
9
|
+
## 0.20.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- bb7860e: Backstage version bump to v1.48.2
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- 4dfd773: Use Backstage Frontend Fetch API
|
|
18
|
+
|
|
3
19
|
## 0.19.0
|
|
4
20
|
|
|
5
21
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -72,6 +72,20 @@ splunkOnCall:
|
|
|
72
72
|
eventsRestEndpoint: <SPLUNK_ON_CALL_REST_ENDPOINT>
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
+
You can also point `eventsRestEndpoint` at the Backstage proxy by using a relative path. This keeps the REST endpoint off the frontend and allows the proxy to enforce auth policies:
|
|
76
|
+
|
|
77
|
+
```yaml
|
|
78
|
+
splunkOnCall:
|
|
79
|
+
eventsRestEndpoint: /splunk-on-call-events
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
```yaml
|
|
83
|
+
proxy:
|
|
84
|
+
'/splunk-on-call-events':
|
|
85
|
+
target: https://alert.victorops.com/integrations/generic/20131114/alert
|
|
86
|
+
allowedMethods: ['POST']
|
|
87
|
+
```
|
|
88
|
+
|
|
75
89
|
In order to make the API calls, you need to provide a new proxy config which will redirect to the Splunk On-Call API endpoint and add authentication information in the headers:
|
|
76
90
|
|
|
77
91
|
```yaml
|
|
@@ -87,7 +101,7 @@ proxy:
|
|
|
87
101
|
|
|
88
102
|
In addition, to make certain API calls (trigger-resolve-acknowledge an incident) you need to add the `PATCH` method to the backend `cors` methods list: `[GET, POST, PUT, DELETE, PATCH]`.
|
|
89
103
|
|
|
90
|
-
**
|
|
104
|
+
**NOTE**: The Splunk On-Call frontend uses Backstage's authenticated fetch, so you can keep the `/splunk-on-call` proxy endpoint protected by your backend auth policy. If you only want read-only access, you can also restrict the proxy to `GET` using the following configuration:
|
|
91
105
|
|
|
92
106
|
```yaml
|
|
93
107
|
proxy:
|
package/config.d.ts
CHANGED
|
@@ -19,6 +19,9 @@ export interface Config {
|
|
|
19
19
|
*/
|
|
20
20
|
splunkOnCall?: {
|
|
21
21
|
/**
|
|
22
|
+
* Base REST endpoint used for incident actions. Can be an absolute URL or
|
|
23
|
+
* a proxy path (for example, `/splunk-on-call-events`).
|
|
24
|
+
*
|
|
22
25
|
* @visibility frontend
|
|
23
26
|
*/
|
|
24
27
|
eventsRestEndpoint?: string;
|
package/dist/alpha/apis.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ApiBlueprint, discoveryApiRef, configApiRef } from '@backstage/frontend-plugin-api';
|
|
1
|
+
import { ApiBlueprint, discoveryApiRef, configApiRef, fetchApiRef } from '@backstage/frontend-plugin-api';
|
|
2
2
|
import { splunkOnCallApiRef, SplunkOnCallClient } from '../api/client.esm.js';
|
|
3
3
|
|
|
4
4
|
const splunkOnCallApi = ApiBlueprint.make({
|
|
@@ -7,9 +7,10 @@ const splunkOnCallApi = ApiBlueprint.make({
|
|
|
7
7
|
api: splunkOnCallApiRef,
|
|
8
8
|
deps: {
|
|
9
9
|
discoveryApi: discoveryApiRef,
|
|
10
|
-
configApi: configApiRef
|
|
10
|
+
configApi: configApiRef,
|
|
11
|
+
fetchApi: fetchApiRef
|
|
11
12
|
},
|
|
12
|
-
factory: ({ configApi, discoveryApi }) => SplunkOnCallClient.fromConfig(configApi, discoveryApi)
|
|
13
|
+
factory: ({ configApi, discoveryApi, fetchApi }) => SplunkOnCallClient.fromConfig(configApi, discoveryApi, fetchApi)
|
|
13
14
|
})
|
|
14
15
|
});
|
|
15
16
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apis.esm.js","sources":["../../src/alpha/apis.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n ApiBlueprint,\n configApiRef,\n discoveryApiRef,\n} from '@backstage/frontend-plugin-api';\nimport { SplunkOnCallClient, splunkOnCallApiRef } from '../api';\n\n/**\n * @alpha\n */\nexport const splunkOnCallApi = ApiBlueprint.make({\n name: 'splunk-on-call',\n params: defineParams =>\n defineParams({\n api: splunkOnCallApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n configApi: configApiRef,\n },\n factory: ({ configApi, discoveryApi }) =>\n SplunkOnCallClient.fromConfig(configApi, discoveryApi),\n }),\n});\n"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"apis.esm.js","sources":["../../src/alpha/apis.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n ApiBlueprint,\n configApiRef,\n discoveryApiRef,\n fetchApiRef,\n} from '@backstage/frontend-plugin-api';\nimport { SplunkOnCallClient, splunkOnCallApiRef } from '../api';\n\n/**\n * @alpha\n */\nexport const splunkOnCallApi = ApiBlueprint.make({\n name: 'splunk-on-call',\n params: defineParams =>\n defineParams({\n api: splunkOnCallApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n configApi: configApiRef,\n fetchApi: fetchApiRef,\n },\n factory: ({ configApi, discoveryApi, fetchApi }) =>\n SplunkOnCallClient.fromConfig(configApi, discoveryApi, fetchApi),\n }),\n});\n"],"names":[],"mappings":";;;AA0Ba,MAAA,eAAA,GAAkB,aAAa,IAAK,CAAA;AAAA,EAC/C,IAAM,EAAA,gBAAA;AAAA,EACN,MAAA,EAAQ,kBACN,YAAa,CAAA;AAAA,IACX,GAAK,EAAA,kBAAA;AAAA,IACL,IAAM,EAAA;AAAA,MACJ,YAAc,EAAA,eAAA;AAAA,MACd,SAAW,EAAA,YAAA;AAAA,MACX,QAAU,EAAA;AAAA,KACZ;AAAA,IACA,OAAA,EAAS,CAAC,EAAE,SAAW,EAAA,YAAA,EAAc,QAAS,EAAA,KAC5C,kBAAmB,CAAA,UAAA,CAAW,SAAW,EAAA,YAAA,EAAc,QAAQ;AAAA,GAClE;AACL,CAAC;;;;"}
|
package/dist/alpha.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import * as _backstage_plugin_catalog_react_alpha from '@backstage/plugin-catalog-react/alpha';
|
|
2
2
|
import * as _backstage_catalog_model from '@backstage/catalog-model';
|
|
3
3
|
import * as react from 'react';
|
|
4
|
-
import * as
|
|
4
|
+
import * as _backstage_filter_predicates from '@backstage/filter-predicates';
|
|
5
5
|
import * as _backstage_frontend_plugin_api from '@backstage/frontend-plugin-api';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -17,20 +17,18 @@ declare const _default: _backstage_frontend_plugin_api.OverridableFrontendPlugin
|
|
|
17
17
|
configInput: {};
|
|
18
18
|
output: _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.AnyApiFactory, "core.api.factory", {}>;
|
|
19
19
|
inputs: {};
|
|
20
|
-
params: <TApi, TImpl extends TApi, TDeps extends {
|
|
21
|
-
[x: string]: unknown;
|
|
22
|
-
}>(params: _backstage_frontend_plugin_api.ApiFactory<TApi, TImpl, TDeps>) => _backstage_frontend_plugin_api.ExtensionBlueprintParams<_backstage_frontend_plugin_api.AnyApiFactory>;
|
|
20
|
+
params: <TApi, TImpl extends TApi, TDeps extends { [name in string]: unknown; }>(params: _backstage_frontend_plugin_api.ApiFactory<TApi, TImpl, TDeps>) => _backstage_frontend_plugin_api.ExtensionBlueprintParams<_backstage_frontend_plugin_api.AnyApiFactory>;
|
|
23
21
|
}>;
|
|
24
22
|
"entity-card:splunk-on-call/splunk-on-call": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
|
|
25
23
|
kind: "entity-card";
|
|
26
24
|
name: "splunk-on-call";
|
|
27
25
|
config: {
|
|
28
|
-
filter:
|
|
29
|
-
type: "content" | "
|
|
26
|
+
filter: _backstage_filter_predicates.FilterPredicate | undefined;
|
|
27
|
+
type: "content" | "info" | undefined;
|
|
30
28
|
};
|
|
31
29
|
configInput: {
|
|
32
|
-
filter?:
|
|
33
|
-
type?: "content" | "
|
|
30
|
+
filter?: _backstage_filter_predicates.FilterPredicate | undefined;
|
|
31
|
+
type?: "content" | "info" | undefined;
|
|
34
32
|
};
|
|
35
33
|
output: _backstage_frontend_plugin_api.ExtensionDataRef<react.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
|
|
36
34
|
optional: true;
|
|
@@ -42,8 +40,8 @@ declare const _default: _backstage_frontend_plugin_api.OverridableFrontendPlugin
|
|
|
42
40
|
inputs: {};
|
|
43
41
|
params: {
|
|
44
42
|
loader: () => Promise<JSX.Element>;
|
|
45
|
-
filter?:
|
|
46
|
-
type?: _backstage_plugin_catalog_react_alpha.EntityCardType
|
|
43
|
+
filter?: string | _backstage_filter_predicates.FilterPredicate | ((entity: _backstage_catalog_model.Entity) => boolean);
|
|
44
|
+
type?: _backstage_plugin_catalog_react_alpha.EntityCardType;
|
|
47
45
|
};
|
|
48
46
|
}>;
|
|
49
47
|
"page:splunk-on-call": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
|
|
@@ -51,19 +49,39 @@ declare const _default: _backstage_frontend_plugin_api.OverridableFrontendPlugin
|
|
|
51
49
|
name: undefined;
|
|
52
50
|
config: {
|
|
53
51
|
path: string | undefined;
|
|
52
|
+
title: string | undefined;
|
|
54
53
|
};
|
|
55
54
|
configInput: {
|
|
55
|
+
title?: string | undefined;
|
|
56
56
|
path?: string | undefined;
|
|
57
57
|
};
|
|
58
58
|
output: _backstage_frontend_plugin_api.ExtensionDataRef<react.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<string, "core.routing.path", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.RouteRef<_backstage_frontend_plugin_api.AnyRouteRefParams>, "core.routing.ref", {
|
|
59
59
|
optional: true;
|
|
60
|
+
}> | _backstage_frontend_plugin_api.ExtensionDataRef<string, "core.title", {
|
|
61
|
+
optional: true;
|
|
62
|
+
}> | _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.IconElement, "core.icon", {
|
|
63
|
+
optional: true;
|
|
60
64
|
}>;
|
|
61
|
-
inputs: {
|
|
65
|
+
inputs: {
|
|
66
|
+
pages: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.ConfigurableExtensionDataRef<react.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "core.routing.path", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<_backstage_frontend_plugin_api.RouteRef<_backstage_frontend_plugin_api.AnyRouteRefParams>, "core.routing.ref", {
|
|
67
|
+
optional: true;
|
|
68
|
+
}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "core.title", {
|
|
69
|
+
optional: true;
|
|
70
|
+
}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<_backstage_frontend_plugin_api.IconElement, "core.icon", {
|
|
71
|
+
optional: true;
|
|
72
|
+
}>, {
|
|
73
|
+
singleton: false;
|
|
74
|
+
optional: false;
|
|
75
|
+
internal: false;
|
|
76
|
+
}>;
|
|
77
|
+
};
|
|
62
78
|
params: {
|
|
63
|
-
defaultPath?: [Error: "Use the 'path' param instead"] | undefined;
|
|
64
79
|
path: string;
|
|
65
|
-
|
|
66
|
-
|
|
80
|
+
title?: string;
|
|
81
|
+
icon?: _backstage_frontend_plugin_api.IconElement;
|
|
82
|
+
loader?: () => Promise<react.JSX.Element>;
|
|
83
|
+
routeRef?: _backstage_frontend_plugin_api.RouteRef;
|
|
84
|
+
noHeader?: boolean;
|
|
67
85
|
};
|
|
68
86
|
}>;
|
|
69
87
|
}>;
|
package/dist/api/client.esm.js
CHANGED
|
@@ -2,6 +2,8 @@ import { createApiRef } from '@backstage/core-plugin-api';
|
|
|
2
2
|
|
|
3
3
|
class UnauthorizedError extends Error {
|
|
4
4
|
}
|
|
5
|
+
class MissingEventsRestEndpointError extends Error {
|
|
6
|
+
}
|
|
5
7
|
const splunkOnCallApiRef = createApiRef({
|
|
6
8
|
id: "plugin.splunk-on-call.api"
|
|
7
9
|
});
|
|
@@ -9,11 +11,12 @@ class SplunkOnCallClient {
|
|
|
9
11
|
constructor(config) {
|
|
10
12
|
this.config = config;
|
|
11
13
|
}
|
|
12
|
-
static fromConfig(configApi, discoveryApi) {
|
|
14
|
+
static fromConfig(configApi, discoveryApi, fetchApi) {
|
|
13
15
|
const eventsRestEndpoint = configApi.getOptionalString("splunkOnCall.eventsRestEndpoint") || null;
|
|
14
16
|
return new SplunkOnCallClient({
|
|
15
17
|
eventsRestEndpoint,
|
|
16
|
-
discoveryApi
|
|
18
|
+
discoveryApi,
|
|
19
|
+
fetchApi
|
|
17
20
|
});
|
|
18
21
|
}
|
|
19
22
|
async getIncidents() {
|
|
@@ -82,7 +85,13 @@ class SplunkOnCallClient {
|
|
|
82
85
|
},
|
|
83
86
|
body
|
|
84
87
|
};
|
|
85
|
-
const
|
|
88
|
+
const eventsRestEndpoint = await this.getEventsRestEndpoint();
|
|
89
|
+
if (!eventsRestEndpoint) {
|
|
90
|
+
throw new MissingEventsRestEndpointError(
|
|
91
|
+
"Splunk On-Call REST endpoint is not configured."
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
const url = `${eventsRestEndpoint}/${routingKey}`;
|
|
86
95
|
return this.request(url, request);
|
|
87
96
|
}
|
|
88
97
|
async findByUrl(url) {
|
|
@@ -96,7 +105,7 @@ class SplunkOnCallClient {
|
|
|
96
105
|
return response.json();
|
|
97
106
|
}
|
|
98
107
|
async request(url, options) {
|
|
99
|
-
const response = await fetch(url, options);
|
|
108
|
+
const response = await this.config.fetchApi.fetch(url, options);
|
|
100
109
|
if (response.status === 403) {
|
|
101
110
|
throw new UnauthorizedError();
|
|
102
111
|
}
|
|
@@ -108,7 +117,17 @@ class SplunkOnCallClient {
|
|
|
108
117
|
}
|
|
109
118
|
return response;
|
|
110
119
|
}
|
|
120
|
+
async getEventsRestEndpoint() {
|
|
121
|
+
if (!this.config.eventsRestEndpoint) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
if (this.config.eventsRestEndpoint.startsWith("/")) {
|
|
125
|
+
const proxyBase = await this.config.discoveryApi.getBaseUrl("proxy");
|
|
126
|
+
return `${proxyBase}${this.config.eventsRestEndpoint}`;
|
|
127
|
+
}
|
|
128
|
+
return this.config.eventsRestEndpoint;
|
|
129
|
+
}
|
|
111
130
|
}
|
|
112
131
|
|
|
113
|
-
export { SplunkOnCallClient, UnauthorizedError, splunkOnCallApiRef };
|
|
132
|
+
export { MissingEventsRestEndpointError, SplunkOnCallClient, UnauthorizedError, splunkOnCallApiRef };
|
|
114
133
|
//# sourceMappingURL=client.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.esm.js","sources":["../../src/api/client.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Incident,\n OnCall,\n User,\n EscalationPolicyInfo,\n RoutingKey,\n Team,\n} from '../components/types';\nimport {\n SplunkOnCallApi,\n TriggerAlarmRequest,\n IncidentsResponse,\n OnCallsResponse,\n ClientApiConfig,\n RequestOptions,\n ListUserResponse,\n EscalationPolicyResponse,\n ListRoutingKeyResponse,\n} from './types';\nimport {\n
|
|
1
|
+
{"version":3,"file":"client.esm.js","sources":["../../src/api/client.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Incident,\n OnCall,\n User,\n EscalationPolicyInfo,\n RoutingKey,\n Team,\n} from '../components/types';\nimport {\n SplunkOnCallApi,\n TriggerAlarmRequest,\n IncidentsResponse,\n OnCallsResponse,\n ClientApiConfig,\n RequestOptions,\n ListUserResponse,\n EscalationPolicyResponse,\n ListRoutingKeyResponse,\n} from './types';\nimport {\n ConfigApi,\n DiscoveryApi,\n FetchApi,\n createApiRef,\n} from '@backstage/core-plugin-api';\n\n/** @public */\nexport class UnauthorizedError extends Error {}\n\n/** @public */\nexport class MissingEventsRestEndpointError extends Error {}\n\n/** @public */\nexport const splunkOnCallApiRef = createApiRef<SplunkOnCallApi>({\n id: 'plugin.splunk-on-call.api',\n});\n\n/** @public */\nexport class SplunkOnCallClient implements SplunkOnCallApi {\n static fromConfig(\n configApi: ConfigApi,\n discoveryApi: DiscoveryApi,\n fetchApi: FetchApi,\n ) {\n const eventsRestEndpoint: string | null =\n configApi.getOptionalString('splunkOnCall.eventsRestEndpoint') || null;\n return new SplunkOnCallClient({\n eventsRestEndpoint,\n discoveryApi,\n fetchApi,\n });\n }\n constructor(private readonly config: ClientApiConfig) {}\n\n async getIncidents(): Promise<Incident[]> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'proxy',\n )}/splunk-on-call/v1/incidents`;\n\n const { incidents } = await this.findByUrl<IncidentsResponse>(url);\n\n return incidents;\n }\n\n async getOnCallUsers(): Promise<OnCall[]> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'proxy',\n )}/splunk-on-call/v1/oncall/current`;\n const { teamsOnCall } = await this.findByUrl<OnCallsResponse>(url);\n\n return teamsOnCall;\n }\n\n async getTeams(): Promise<Team[]> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'proxy',\n )}/splunk-on-call/v1/team`;\n const teams = await this.findByUrl<Team[]>(url);\n\n return teams;\n }\n\n async getRoutingKeys(): Promise<RoutingKey[]> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'proxy',\n )}/splunk-on-call/v1/org/routing-keys`;\n const { routingKeys } = await this.findByUrl<ListRoutingKeyResponse>(url);\n\n return routingKeys;\n }\n\n async getUsers(): Promise<User[]> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'proxy',\n )}/splunk-on-call/v2/user`;\n const { users } = await this.findByUrl<ListUserResponse>(url);\n\n return users;\n }\n\n async getEscalationPolicies(): Promise<EscalationPolicyInfo[]> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'proxy',\n )}/splunk-on-call/v1/policies`;\n const { policies } = await this.findByUrl<EscalationPolicyResponse>(url);\n\n return policies;\n }\n\n async incidentAction(options: TriggerAlarmRequest): Promise<Response> {\n const {\n routingKey,\n incidentType,\n incidentId,\n incidentDisplayName,\n incidentMessage,\n incidentStartTime,\n } = options;\n\n const body = JSON.stringify({\n message_type: incidentType,\n ...(incidentId ? { entity_id: incidentId } : {}),\n ...(incidentDisplayName\n ? { entity_display_name: incidentDisplayName }\n : {}),\n ...(incidentMessage ? { state_message: incidentMessage } : {}),\n ...(incidentStartTime ? { state_start_time: incidentStartTime } : {}),\n });\n\n const request = {\n method: 'POST',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n body,\n };\n\n const eventsRestEndpoint = await this.getEventsRestEndpoint();\n if (!eventsRestEndpoint) {\n throw new MissingEventsRestEndpointError(\n 'Splunk On-Call REST endpoint is not configured.',\n );\n }\n const url = `${eventsRestEndpoint}/${routingKey}`;\n\n return this.request(url, request);\n }\n\n private async findByUrl<T>(url: string): Promise<T> {\n const options = {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n const response = await this.request(url, options);\n\n return response.json();\n }\n\n private async request(\n url: string,\n options: RequestOptions,\n ): Promise<Response> {\n const response = await this.config.fetchApi.fetch(url, options);\n if (response.status === 403) {\n throw new UnauthorizedError();\n }\n if (!response.ok) {\n const payload = await response.json();\n const errors = payload.errors.map((error: string) => error).join(' ');\n const message = `Request failed with ${response.status}, ${errors}`;\n throw new Error(message);\n }\n return response;\n }\n\n private async getEventsRestEndpoint(): Promise<string | null> {\n if (!this.config.eventsRestEndpoint) {\n return null;\n }\n\n if (this.config.eventsRestEndpoint.startsWith('/')) {\n const proxyBase = await this.config.discoveryApi.getBaseUrl('proxy');\n return `${proxyBase}${this.config.eventsRestEndpoint}`;\n }\n\n return this.config.eventsRestEndpoint;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -15,7 +15,8 @@ import OpenInBrowserIcon from '@material-ui/icons/OpenInBrowser';
|
|
|
15
15
|
import { splunkOnCallApiRef } from '../../api/client.esm.js';
|
|
16
16
|
import useAsyncFn from 'react-use/esm/useAsyncFn';
|
|
17
17
|
import { StatusOK, StatusWarning, StatusError } from '@backstage/core-components';
|
|
18
|
-
import { useApi
|
|
18
|
+
import { useApi } from '@backstage/core-plugin-api';
|
|
19
|
+
import { toastApiRef } from '@backstage/frontend-plugin-api';
|
|
19
20
|
|
|
20
21
|
const useStyles = makeStyles({
|
|
21
22
|
denseListIcon: {
|
|
@@ -93,7 +94,7 @@ const IncidentListItem = ({
|
|
|
93
94
|
const classes = useStyles();
|
|
94
95
|
const duration = (/* @__PURE__ */ new Date()).getTime() - new Date(incident.startTime).getTime();
|
|
95
96
|
const createdAt = DateTime.local().minus(Duration.fromMillis(duration)).toRelative({ locale: "en" });
|
|
96
|
-
const
|
|
97
|
+
const toastApi = useApi(toastApiRef);
|
|
97
98
|
const api = useApi(splunkOnCallApiRef);
|
|
98
99
|
const hasBeenManuallyTriggered = incident.monitorName?.includes("vouser-");
|
|
99
100
|
const source = () => {
|
|
@@ -124,29 +125,29 @@ const IncidentListItem = ({
|
|
|
124
125
|
);
|
|
125
126
|
useEffect(() => {
|
|
126
127
|
if (acknowledgeValue) {
|
|
127
|
-
|
|
128
|
-
|
|
128
|
+
toastApi.post({
|
|
129
|
+
title: `Incident successfully acknowledged`
|
|
129
130
|
});
|
|
130
131
|
}
|
|
131
132
|
if (resolveValue) {
|
|
132
|
-
|
|
133
|
-
|
|
133
|
+
toastApi.post({
|
|
134
|
+
title: `Incident successfully resolved`
|
|
134
135
|
});
|
|
135
136
|
}
|
|
136
137
|
if (resolveValue || acknowledgeValue) {
|
|
137
138
|
onIncidentAction();
|
|
138
139
|
}
|
|
139
|
-
}, [acknowledgeValue, resolveValue,
|
|
140
|
+
}, [acknowledgeValue, resolveValue, toastApi, onIncidentAction]);
|
|
140
141
|
if (acknowledgeError) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
142
|
+
toastApi.post({
|
|
143
|
+
title: `Failed to acknowledge incident. ${acknowledgeError.message}`,
|
|
144
|
+
status: "danger"
|
|
144
145
|
});
|
|
145
146
|
}
|
|
146
147
|
if (resolveError) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
148
|
+
toastApi.post({
|
|
149
|
+
title: `Failed to resolve incident. ${resolveError.message}`,
|
|
150
|
+
status: "danger"
|
|
150
151
|
});
|
|
151
152
|
}
|
|
152
153
|
return /* @__PURE__ */ jsxs(ListItem, { dense: true, children: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IncidentListItem.esm.js","sources":["../../../src/components/Incident/IncidentListItem.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useEffect } from 'react';\nimport ListItem from '@material-ui/core/ListItem';\nimport ListItemIcon from '@material-ui/core/ListItemIcon';\nimport ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport IconButton from '@material-ui/core/IconButton';\nimport Typography from '@material-ui/core/Typography';\nimport { makeStyles } from '@material-ui/core/styles';\nimport DoneIcon from '@material-ui/icons/Done';\nimport DoneAllIcon from '@material-ui/icons/DoneAll';\nimport { DateTime, Duration } from 'luxon';\nimport { Incident, IncidentPhase } from '../types';\nimport OpenInBrowserIcon from '@material-ui/icons/OpenInBrowser';\nimport { splunkOnCallApiRef } from '../../api/client';\nimport useAsyncFn from 'react-use/esm/useAsyncFn';\nimport { TriggerAlarmRequest } from '../../api/types';\n\nimport {\n StatusError,\n StatusWarning,\n StatusOK,\n} from '@backstage/core-components';\nimport { useApi, alertApiRef } from '@backstage/core-plugin-api';\n\nconst useStyles = makeStyles({\n denseListIcon: {\n marginRight: 0,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n },\n listItemPrimary: {\n fontWeight: 'bold',\n },\n listItemIcon: {\n minWidth: '1em',\n },\n secondaryAction: {\n paddingRight: 48,\n },\n});\n\ntype Props = {\n team: string;\n incident: Incident;\n onIncidentAction: () => void;\n readOnly: boolean;\n};\n\nconst IncidentPhaseStatus = ({\n currentPhase,\n}: {\n currentPhase: IncidentPhase;\n}) => {\n switch (currentPhase) {\n case 'UNACKED':\n return <StatusError />;\n case 'ACKED':\n return <StatusWarning />;\n default:\n return <StatusOK />;\n }\n};\n\nconst incidentPhaseTooltip = (currentPhase: IncidentPhase) => {\n switch (currentPhase) {\n case 'UNACKED':\n return 'Triggered';\n case 'ACKED':\n return 'Acknowledged';\n default:\n return 'Resolved';\n }\n};\n\nconst IncidentAction = ({\n currentPhase,\n incidentId,\n resolveAction,\n acknowledgeAction,\n}: {\n currentPhase: string;\n incidentId: string;\n resolveAction: (args: TriggerAlarmRequest) => void;\n acknowledgeAction: (args: TriggerAlarmRequest) => void;\n}) => {\n switch (currentPhase) {\n case 'UNACKED':\n return (\n <Tooltip title=\"Acknowledge\" placement=\"top\">\n <IconButton\n onClick={() =>\n acknowledgeAction({ incidentId, incidentType: 'ACKNOWLEDGEMENT' })\n }\n >\n <DoneIcon />\n </IconButton>\n </Tooltip>\n );\n case 'ACKED':\n return (\n <Tooltip title=\"Resolve\" placement=\"top\">\n <IconButton\n onClick={() =>\n resolveAction({ incidentId, incidentType: 'RECOVERY' })\n }\n >\n <DoneAllIcon />\n </IconButton>\n </Tooltip>\n );\n default:\n return <></>;\n }\n};\n\nexport const IncidentListItem = ({\n incident,\n readOnly,\n onIncidentAction,\n team,\n}: Props) => {\n const classes = useStyles();\n const duration =\n new Date().getTime() - new Date(incident.startTime!).getTime();\n const createdAt = DateTime.local()\n .minus(Duration.fromMillis(duration))\n .toRelative({ locale: 'en' });\n const alertApi = useApi(alertApiRef);\n const api = useApi(splunkOnCallApiRef);\n\n const hasBeenManuallyTriggered = incident.monitorName?.includes('vouser-');\n\n const source = () => {\n if (hasBeenManuallyTriggered) {\n return incident.monitorName?.replace('vouser-', '');\n }\n if (incident.monitorType === 'API') {\n return '{ REST }';\n }\n\n return incident.monitorName;\n };\n\n const [{ value: resolveValue, error: resolveError }, handleResolveIncident] =\n useAsyncFn(\n async ({ incidentId, incidentType }: TriggerAlarmRequest) =>\n await api.incidentAction({\n routingKey: team,\n incidentType,\n incidentId,\n }),\n );\n\n const [\n { value: acknowledgeValue, error: acknowledgeError },\n handleAcknowledgeIncident,\n ] = useAsyncFn(\n async ({ incidentId, incidentType }: TriggerAlarmRequest) =>\n await api.incidentAction({\n routingKey: team,\n incidentType,\n incidentId,\n }),\n );\n\n useEffect(() => {\n if (acknowledgeValue) {\n alertApi.post({\n message: `Incident successfully acknowledged`,\n });\n }\n\n if (resolveValue) {\n alertApi.post({\n message: `Incident successfully resolved`,\n });\n }\n if (resolveValue || acknowledgeValue) {\n onIncidentAction();\n }\n }, [acknowledgeValue, resolveValue, alertApi, onIncidentAction]);\n\n if (acknowledgeError) {\n alertApi.post({\n message: `Failed to acknowledge incident. ${acknowledgeError.message}`,\n severity: 'error',\n });\n }\n\n if (resolveError) {\n alertApi.post({\n message: `Failed to resolve incident. ${resolveError.message}`,\n severity: 'error',\n });\n }\n\n return (\n <ListItem dense key={incident.entityId}>\n <ListItemIcon className={classes.listItemIcon}>\n <Tooltip\n title={incidentPhaseTooltip(incident.currentPhase)}\n placement=\"top\"\n >\n <div className={classes.denseListIcon}>\n <IncidentPhaseStatus currentPhase={incident.currentPhase} />\n </div>\n </Tooltip>\n </ListItemIcon>\n <ListItemText\n primary={incident.entityDisplayName}\n primaryTypographyProps={{\n variant: 'body1',\n className: classes.listItemPrimary,\n }}\n secondary={\n <Typography noWrap variant=\"body2\" color=\"textSecondary\">\n #{incident.incidentNumber} - Created {createdAt}{' '}\n {source() && `by ${source()}`}\n </Typography>\n }\n />\n\n {incident.incidentLink && incident.incidentNumber && (\n <ListItemSecondaryAction>\n {!readOnly && (\n <IncidentAction\n currentPhase={incident.currentPhase || ''}\n incidentId={incident.entityId}\n resolveAction={handleResolveIncident}\n acknowledgeAction={handleAcknowledgeIncident}\n />\n )}\n <Tooltip title=\"View in Splunk On-Call\" placement=\"top\">\n <IconButton\n href={incident.incidentLink}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n color=\"primary\"\n >\n <OpenInBrowserIcon />\n </IconButton>\n </Tooltip>\n </ListItemSecondaryAction>\n )}\n </ListItem>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"IncidentListItem.esm.js","sources":["../../../src/components/Incident/IncidentListItem.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useEffect } from 'react';\nimport ListItem from '@material-ui/core/ListItem';\nimport ListItemIcon from '@material-ui/core/ListItemIcon';\nimport ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport IconButton from '@material-ui/core/IconButton';\nimport Typography from '@material-ui/core/Typography';\nimport { makeStyles } from '@material-ui/core/styles';\nimport DoneIcon from '@material-ui/icons/Done';\nimport DoneAllIcon from '@material-ui/icons/DoneAll';\nimport { DateTime, Duration } from 'luxon';\nimport { Incident, IncidentPhase } from '../types';\nimport OpenInBrowserIcon from '@material-ui/icons/OpenInBrowser';\nimport { splunkOnCallApiRef } from '../../api/client';\nimport useAsyncFn from 'react-use/esm/useAsyncFn';\nimport { TriggerAlarmRequest } from '../../api/types';\n\nimport {\n StatusError,\n StatusWarning,\n StatusOK,\n} from '@backstage/core-components';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { toastApiRef } from '@backstage/frontend-plugin-api';\n\nconst useStyles = makeStyles({\n denseListIcon: {\n marginRight: 0,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n },\n listItemPrimary: {\n fontWeight: 'bold',\n },\n listItemIcon: {\n minWidth: '1em',\n },\n secondaryAction: {\n paddingRight: 48,\n },\n});\n\ntype Props = {\n team: string;\n incident: Incident;\n onIncidentAction: () => void;\n readOnly: boolean;\n};\n\nconst IncidentPhaseStatus = ({\n currentPhase,\n}: {\n currentPhase: IncidentPhase;\n}) => {\n switch (currentPhase) {\n case 'UNACKED':\n return <StatusError />;\n case 'ACKED':\n return <StatusWarning />;\n default:\n return <StatusOK />;\n }\n};\n\nconst incidentPhaseTooltip = (currentPhase: IncidentPhase) => {\n switch (currentPhase) {\n case 'UNACKED':\n return 'Triggered';\n case 'ACKED':\n return 'Acknowledged';\n default:\n return 'Resolved';\n }\n};\n\nconst IncidentAction = ({\n currentPhase,\n incidentId,\n resolveAction,\n acknowledgeAction,\n}: {\n currentPhase: string;\n incidentId: string;\n resolveAction: (args: TriggerAlarmRequest) => void;\n acknowledgeAction: (args: TriggerAlarmRequest) => void;\n}) => {\n switch (currentPhase) {\n case 'UNACKED':\n return (\n <Tooltip title=\"Acknowledge\" placement=\"top\">\n <IconButton\n onClick={() =>\n acknowledgeAction({ incidentId, incidentType: 'ACKNOWLEDGEMENT' })\n }\n >\n <DoneIcon />\n </IconButton>\n </Tooltip>\n );\n case 'ACKED':\n return (\n <Tooltip title=\"Resolve\" placement=\"top\">\n <IconButton\n onClick={() =>\n resolveAction({ incidentId, incidentType: 'RECOVERY' })\n }\n >\n <DoneAllIcon />\n </IconButton>\n </Tooltip>\n );\n default:\n return <></>;\n }\n};\n\nexport const IncidentListItem = ({\n incident,\n readOnly,\n onIncidentAction,\n team,\n}: Props) => {\n const classes = useStyles();\n const duration =\n new Date().getTime() - new Date(incident.startTime!).getTime();\n const createdAt = DateTime.local()\n .minus(Duration.fromMillis(duration))\n .toRelative({ locale: 'en' });\n const toastApi = useApi(toastApiRef);\n const api = useApi(splunkOnCallApiRef);\n\n const hasBeenManuallyTriggered = incident.monitorName?.includes('vouser-');\n\n const source = () => {\n if (hasBeenManuallyTriggered) {\n return incident.monitorName?.replace('vouser-', '');\n }\n if (incident.monitorType === 'API') {\n return '{ REST }';\n }\n\n return incident.monitorName;\n };\n\n const [{ value: resolveValue, error: resolveError }, handleResolveIncident] =\n useAsyncFn(\n async ({ incidentId, incidentType }: TriggerAlarmRequest) =>\n await api.incidentAction({\n routingKey: team,\n incidentType,\n incidentId,\n }),\n );\n\n const [\n { value: acknowledgeValue, error: acknowledgeError },\n handleAcknowledgeIncident,\n ] = useAsyncFn(\n async ({ incidentId, incidentType }: TriggerAlarmRequest) =>\n await api.incidentAction({\n routingKey: team,\n incidentType,\n incidentId,\n }),\n );\n\n useEffect(() => {\n if (acknowledgeValue) {\n toastApi.post({\n title: `Incident successfully acknowledged`,\n });\n }\n\n if (resolveValue) {\n toastApi.post({\n title: `Incident successfully resolved`,\n });\n }\n if (resolveValue || acknowledgeValue) {\n onIncidentAction();\n }\n }, [acknowledgeValue, resolveValue, toastApi, onIncidentAction]);\n\n if (acknowledgeError) {\n toastApi.post({\n title: `Failed to acknowledge incident. ${acknowledgeError.message}`,\n status: 'danger',\n });\n }\n\n if (resolveError) {\n toastApi.post({\n title: `Failed to resolve incident. ${resolveError.message}`,\n status: 'danger',\n });\n }\n\n return (\n <ListItem dense key={incident.entityId}>\n <ListItemIcon className={classes.listItemIcon}>\n <Tooltip\n title={incidentPhaseTooltip(incident.currentPhase)}\n placement=\"top\"\n >\n <div className={classes.denseListIcon}>\n <IncidentPhaseStatus currentPhase={incident.currentPhase} />\n </div>\n </Tooltip>\n </ListItemIcon>\n <ListItemText\n primary={incident.entityDisplayName}\n primaryTypographyProps={{\n variant: 'body1',\n className: classes.listItemPrimary,\n }}\n secondary={\n <Typography noWrap variant=\"body2\" color=\"textSecondary\">\n #{incident.incidentNumber} - Created {createdAt}{' '}\n {source() && `by ${source()}`}\n </Typography>\n }\n />\n\n {incident.incidentLink && incident.incidentNumber && (\n <ListItemSecondaryAction>\n {!readOnly && (\n <IncidentAction\n currentPhase={incident.currentPhase || ''}\n incidentId={incident.entityId}\n resolveAction={handleResolveIncident}\n acknowledgeAction={handleAcknowledgeIncident}\n />\n )}\n <Tooltip title=\"View in Splunk On-Call\" placement=\"top\">\n <IconButton\n href={incident.incidentLink}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n color=\"primary\"\n >\n <OpenInBrowserIcon />\n </IconButton>\n </Tooltip>\n </ListItemSecondaryAction>\n )}\n </ListItem>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -16,7 +16,8 @@ import { makeStyles, createStyles } from '@material-ui/core/styles';
|
|
|
16
16
|
import useAsyncFn from 'react-use/esm/useAsyncFn';
|
|
17
17
|
import { splunkOnCallApiRef } from '../../api/client.esm.js';
|
|
18
18
|
import Alert from '@material-ui/lab/Alert';
|
|
19
|
-
import { useApi
|
|
19
|
+
import { useApi } from '@backstage/core-plugin-api';
|
|
20
|
+
import { toastApiRef } from '@backstage/frontend-plugin-api';
|
|
20
21
|
|
|
21
22
|
const useStyles = makeStyles(
|
|
22
23
|
(theme) => createStyles({
|
|
@@ -53,7 +54,7 @@ const TriggerDialog = ({
|
|
|
53
54
|
handleDialog,
|
|
54
55
|
onIncidentCreated
|
|
55
56
|
}) => {
|
|
56
|
-
const
|
|
57
|
+
const toastApi = useApi(toastApiRef);
|
|
57
58
|
const api = useApi(splunkOnCallApiRef);
|
|
58
59
|
const classes = useStyles();
|
|
59
60
|
const [incidentType, setIncidentType] = useState("");
|
|
@@ -86,17 +87,17 @@ const TriggerDialog = ({
|
|
|
86
87
|
};
|
|
87
88
|
useEffect(() => {
|
|
88
89
|
if (value) {
|
|
89
|
-
|
|
90
|
-
|
|
90
|
+
toastApi.post({
|
|
91
|
+
title: `Alarm successfully triggered`
|
|
91
92
|
});
|
|
92
93
|
onIncidentCreated();
|
|
93
94
|
handleDialog();
|
|
94
95
|
}
|
|
95
|
-
}, [value,
|
|
96
|
+
}, [value, toastApi, handleDialog, onIncidentCreated]);
|
|
96
97
|
if (triggerError) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
toastApi.post({
|
|
99
|
+
title: `Failed to trigger alarm. ${triggerError.message}`,
|
|
100
|
+
status: "danger"
|
|
100
101
|
});
|
|
101
102
|
}
|
|
102
103
|
return /* @__PURE__ */ jsxs(Dialog, { maxWidth: "md", open: showDialog, onClose: handleDialog, fullWidth: true, children: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TriggerDialog.esm.js","sources":["../../../src/components/TriggerDialog/TriggerDialog.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { ChangeEvent } from 'react';\n\nimport { useState, useEffect } from 'react';\nimport Dialog from '@material-ui/core/Dialog';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport TextField from '@material-ui/core/TextField';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport Button from '@material-ui/core/Button';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport Typography from '@material-ui/core/Typography';\nimport CircularProgress from '@material-ui/core/CircularProgress';\nimport Select from '@material-ui/core/Select';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport FormControl from '@material-ui/core/FormControl';\nimport InputLabel from '@material-ui/core/InputLabel';\nimport { createStyles, makeStyles, Theme } from '@material-ui/core/styles';\nimport useAsyncFn from 'react-use/esm/useAsyncFn';\nimport { splunkOnCallApiRef } from '../../api';\nimport Alert from '@material-ui/lab/Alert';\nimport { TriggerAlarmRequest } from '../../api';\nimport { useApi, alertApiRef } from '@backstage/core-plugin-api';\n\ntype Props = {\n routingKey: string;\n showDialog: boolean;\n handleDialog: () => void;\n onIncidentCreated: () => void;\n};\n\nconst useStyles = makeStyles((theme: Theme) =>\n createStyles({\n chips: {\n display: 'flex',\n flexWrap: 'wrap',\n },\n chip: {\n margin: 2,\n },\n formControl: {\n margin: theme.spacing(1),\n display: 'flex',\n flexDirection: 'row',\n alignItems: 'center',\n minWidth: `calc(100% - ${theme.spacing(2)}px)`,\n },\n formHeader: {\n width: '50%',\n },\n incidentType: {\n width: '90%',\n },\n targets: {\n display: 'flex',\n flexDirection: 'column',\n width: '100%',\n },\n }),\n);\n\nexport const TriggerDialog = ({\n routingKey,\n showDialog,\n handleDialog,\n onIncidentCreated: onIncidentCreated,\n}: Props) => {\n const alertApi = useApi(alertApiRef);\n const api = useApi(splunkOnCallApiRef);\n const classes = useStyles();\n\n const [incidentType, setIncidentType] = useState<string>('');\n const [incidentId, setIncidentId] = useState<string>();\n const [incidentDisplayName, setIncidentDisplayName] = useState<string>('');\n const [incidentMessage, setIncidentMessage] = useState<string>('');\n const [incidentStartTime, setIncidentStartTime] = useState<number>();\n\n const [\n { value, loading: triggerLoading, error: triggerError },\n handleTriggerAlarm,\n ] = useAsyncFn(\n async (params: TriggerAlarmRequest) => await api.incidentAction(params),\n );\n\n const handleIncidentType = (event: ChangeEvent<{ value: unknown }>) => {\n setIncidentType(event.target.value as string);\n };\n\n const handleIncidentId = (event: ChangeEvent<HTMLTextAreaElement>) => {\n setIncidentId(event.target.value as string);\n };\n\n const handleIncidentDisplayName = (\n event: ChangeEvent<HTMLTextAreaElement>,\n ) => {\n setIncidentDisplayName(event.target.value);\n };\n\n const handleIncidentMessage = (event: ChangeEvent<HTMLTextAreaElement>) => {\n setIncidentMessage(event.target.value);\n };\n\n const handleIncidentStartTime = (event: ChangeEvent<HTMLTextAreaElement>) => {\n const dateTime = new Date(event.target.value).getTime();\n const dateTimeInSeconds = Math.floor(dateTime / 1000);\n setIncidentStartTime(dateTimeInSeconds);\n };\n\n useEffect(() => {\n if (value) {\n alertApi.post({\n message: `Alarm successfully triggered`,\n });\n onIncidentCreated();\n handleDialog();\n }\n }, [value, alertApi, handleDialog, onIncidentCreated]);\n\n if (triggerError) {\n alertApi.post({\n message: `Failed to trigger alarm. ${triggerError.message}`,\n severity: 'error',\n });\n }\n\n return (\n <Dialog maxWidth=\"md\" open={showDialog} onClose={handleDialog} fullWidth>\n <DialogTitle>This action will trigger an incident</DialogTitle>\n <DialogContent>\n <Typography variant=\"subtitle1\" gutterBottom align=\"justify\">\n Created by: <b>{`{ REST } Endpoint`}</b>\n </Typography>\n <Alert severity=\"info\">\n <Typography variant=\"body1\" align=\"justify\">\n If the issue you are seeing does not need urgent attention, please\n get in touch with the responsible team using their preferred\n communications channel. You can find information about the owner of\n this entity in the \"About\" card. If the issue is urgent, please\n don't hesitate to trigger the alert.\n </Typography>\n </Alert>\n <Typography\n variant=\"body1\"\n style={{ marginTop: '1em' }}\n gutterBottom\n align=\"justify\"\n >\n Please describe the problem you want to report. Be as descriptive as\n possible. <br />\n Note that only the <b>Incident type</b>, <b>Incident display name</b>{' '}\n and the <b>Incident message</b> fields are <b>required</b>.\n </Typography>\n <FormControl className={classes.formControl}>\n <div className={classes.formHeader}>\n <InputLabel id=\"demo-simple-select-label\">Incident type</InputLabel>\n <Select\n id=\"incident-type\"\n className={classes.incidentType}\n value={incidentType}\n onChange={handleIncidentType}\n inputProps={{ 'data-testid': 'trigger-incident-type' }}\n >\n <MenuItem value=\"CRITICAL\">Critical</MenuItem>\n <MenuItem value=\"WARNING\">Warning</MenuItem>\n <MenuItem value=\"INFO\">Info</MenuItem>\n </Select>\n </div>\n <TextField\n className={classes.formHeader}\n id=\"datetime-local\"\n label=\"Incident start time\"\n type=\"datetime-local\"\n onChange={handleIncidentStartTime}\n InputLabelProps={{\n shrink: true,\n }}\n />\n </FormControl>\n <TextField\n inputProps={{ 'data-testid': 'trigger-incident-id' }}\n id=\"summary\"\n fullWidth\n margin=\"normal\"\n label=\"Incident id\"\n variant=\"outlined\"\n onChange={handleIncidentId}\n />\n <TextField\n required\n inputProps={{ 'data-testid': 'trigger-incident-displayName' }}\n id=\"summary\"\n fullWidth\n margin=\"normal\"\n label=\"Incident display name\"\n variant=\"outlined\"\n onChange={handleIncidentDisplayName}\n />\n <TextField\n required\n inputProps={{ 'data-testid': 'trigger-incident-message' }}\n id=\"details\"\n multiline\n fullWidth\n minRows=\"2\"\n margin=\"normal\"\n label=\"Incident message\"\n variant=\"outlined\"\n onChange={handleIncidentMessage}\n />\n </DialogContent>\n <DialogActions>\n <Button\n data-testid=\"trigger-button\"\n id=\"trigger\"\n color=\"secondary\"\n disabled={\n !incidentType.length ||\n !incidentDisplayName ||\n !incidentMessage ||\n triggerLoading\n }\n variant=\"contained\"\n onClick={() =>\n handleTriggerAlarm({\n routingKey,\n incidentType,\n incidentDisplayName,\n incidentMessage,\n ...(incidentId ? { incidentId } : {}),\n ...(incidentStartTime ? { incidentStartTime } : {}),\n } as TriggerAlarmRequest)\n }\n endIcon={triggerLoading && <CircularProgress size={16} />}\n >\n Trigger Incident\n </Button>\n <Button id=\"close\" color=\"primary\" onClick={handleDialog}>\n Close\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TriggerDialog.esm.js","sources":["../../../src/components/TriggerDialog/TriggerDialog.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { ChangeEvent } from 'react';\n\nimport { useState, useEffect } from 'react';\nimport Dialog from '@material-ui/core/Dialog';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport TextField from '@material-ui/core/TextField';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport Button from '@material-ui/core/Button';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport Typography from '@material-ui/core/Typography';\nimport CircularProgress from '@material-ui/core/CircularProgress';\nimport Select from '@material-ui/core/Select';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport FormControl from '@material-ui/core/FormControl';\nimport InputLabel from '@material-ui/core/InputLabel';\nimport { createStyles, makeStyles, Theme } from '@material-ui/core/styles';\nimport useAsyncFn from 'react-use/esm/useAsyncFn';\nimport { splunkOnCallApiRef } from '../../api';\nimport Alert from '@material-ui/lab/Alert';\nimport { TriggerAlarmRequest } from '../../api';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { toastApiRef } from '@backstage/frontend-plugin-api';\n\ntype Props = {\n routingKey: string;\n showDialog: boolean;\n handleDialog: () => void;\n onIncidentCreated: () => void;\n};\n\nconst useStyles = makeStyles((theme: Theme) =>\n createStyles({\n chips: {\n display: 'flex',\n flexWrap: 'wrap',\n },\n chip: {\n margin: 2,\n },\n formControl: {\n margin: theme.spacing(1),\n display: 'flex',\n flexDirection: 'row',\n alignItems: 'center',\n minWidth: `calc(100% - ${theme.spacing(2)}px)`,\n },\n formHeader: {\n width: '50%',\n },\n incidentType: {\n width: '90%',\n },\n targets: {\n display: 'flex',\n flexDirection: 'column',\n width: '100%',\n },\n }),\n);\n\nexport const TriggerDialog = ({\n routingKey,\n showDialog,\n handleDialog,\n onIncidentCreated: onIncidentCreated,\n}: Props) => {\n const toastApi = useApi(toastApiRef);\n const api = useApi(splunkOnCallApiRef);\n const classes = useStyles();\n\n const [incidentType, setIncidentType] = useState<string>('');\n const [incidentId, setIncidentId] = useState<string>();\n const [incidentDisplayName, setIncidentDisplayName] = useState<string>('');\n const [incidentMessage, setIncidentMessage] = useState<string>('');\n const [incidentStartTime, setIncidentStartTime] = useState<number>();\n\n const [\n { value, loading: triggerLoading, error: triggerError },\n handleTriggerAlarm,\n ] = useAsyncFn(\n async (params: TriggerAlarmRequest) => await api.incidentAction(params),\n );\n\n const handleIncidentType = (event: ChangeEvent<{ value: unknown }>) => {\n setIncidentType(event.target.value as string);\n };\n\n const handleIncidentId = (event: ChangeEvent<HTMLTextAreaElement>) => {\n setIncidentId(event.target.value as string);\n };\n\n const handleIncidentDisplayName = (\n event: ChangeEvent<HTMLTextAreaElement>,\n ) => {\n setIncidentDisplayName(event.target.value);\n };\n\n const handleIncidentMessage = (event: ChangeEvent<HTMLTextAreaElement>) => {\n setIncidentMessage(event.target.value);\n };\n\n const handleIncidentStartTime = (event: ChangeEvent<HTMLTextAreaElement>) => {\n const dateTime = new Date(event.target.value).getTime();\n const dateTimeInSeconds = Math.floor(dateTime / 1000);\n setIncidentStartTime(dateTimeInSeconds);\n };\n\n useEffect(() => {\n if (value) {\n toastApi.post({\n title: `Alarm successfully triggered`,\n });\n onIncidentCreated();\n handleDialog();\n }\n }, [value, toastApi, handleDialog, onIncidentCreated]);\n\n if (triggerError) {\n toastApi.post({\n title: `Failed to trigger alarm. ${triggerError.message}`,\n status: 'danger',\n });\n }\n\n return (\n <Dialog maxWidth=\"md\" open={showDialog} onClose={handleDialog} fullWidth>\n <DialogTitle>This action will trigger an incident</DialogTitle>\n <DialogContent>\n <Typography variant=\"subtitle1\" gutterBottom align=\"justify\">\n Created by: <b>{`{ REST } Endpoint`}</b>\n </Typography>\n <Alert severity=\"info\">\n <Typography variant=\"body1\" align=\"justify\">\n If the issue you are seeing does not need urgent attention, please\n get in touch with the responsible team using their preferred\n communications channel. You can find information about the owner of\n this entity in the \"About\" card. If the issue is urgent, please\n don't hesitate to trigger the alert.\n </Typography>\n </Alert>\n <Typography\n variant=\"body1\"\n style={{ marginTop: '1em' }}\n gutterBottom\n align=\"justify\"\n >\n Please describe the problem you want to report. Be as descriptive as\n possible. <br />\n Note that only the <b>Incident type</b>, <b>Incident display name</b>{' '}\n and the <b>Incident message</b> fields are <b>required</b>.\n </Typography>\n <FormControl className={classes.formControl}>\n <div className={classes.formHeader}>\n <InputLabel id=\"demo-simple-select-label\">Incident type</InputLabel>\n <Select\n id=\"incident-type\"\n className={classes.incidentType}\n value={incidentType}\n onChange={handleIncidentType}\n inputProps={{ 'data-testid': 'trigger-incident-type' }}\n >\n <MenuItem value=\"CRITICAL\">Critical</MenuItem>\n <MenuItem value=\"WARNING\">Warning</MenuItem>\n <MenuItem value=\"INFO\">Info</MenuItem>\n </Select>\n </div>\n <TextField\n className={classes.formHeader}\n id=\"datetime-local\"\n label=\"Incident start time\"\n type=\"datetime-local\"\n onChange={handleIncidentStartTime}\n InputLabelProps={{\n shrink: true,\n }}\n />\n </FormControl>\n <TextField\n inputProps={{ 'data-testid': 'trigger-incident-id' }}\n id=\"summary\"\n fullWidth\n margin=\"normal\"\n label=\"Incident id\"\n variant=\"outlined\"\n onChange={handleIncidentId}\n />\n <TextField\n required\n inputProps={{ 'data-testid': 'trigger-incident-displayName' }}\n id=\"summary\"\n fullWidth\n margin=\"normal\"\n label=\"Incident display name\"\n variant=\"outlined\"\n onChange={handleIncidentDisplayName}\n />\n <TextField\n required\n inputProps={{ 'data-testid': 'trigger-incident-message' }}\n id=\"details\"\n multiline\n fullWidth\n minRows=\"2\"\n margin=\"normal\"\n label=\"Incident message\"\n variant=\"outlined\"\n onChange={handleIncidentMessage}\n />\n </DialogContent>\n <DialogActions>\n <Button\n data-testid=\"trigger-button\"\n id=\"trigger\"\n color=\"secondary\"\n disabled={\n !incidentType.length ||\n !incidentDisplayName ||\n !incidentMessage ||\n triggerLoading\n }\n variant=\"contained\"\n onClick={() =>\n handleTriggerAlarm({\n routingKey,\n incidentType,\n incidentDisplayName,\n incidentMessage,\n ...(incidentId ? { incidentId } : {}),\n ...(incidentStartTime ? { incidentStartTime } : {}),\n } as TriggerAlarmRequest)\n }\n endIcon={triggerLoading && <CircularProgress size={16} />}\n >\n Trigger Incident\n </Button>\n <Button id=\"close\" color=\"primary\" onClick={handleDialog}>\n Close\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;AA8CA,MAAM,SAAY,GAAA,UAAA;AAAA,EAAW,CAAC,UAC5B,YAAa,CAAA;AAAA,IACX,KAAO,EAAA;AAAA,MACL,OAAS,EAAA,MAAA;AAAA,MACT,QAAU,EAAA;AAAA,KACZ;AAAA,IACA,IAAM,EAAA;AAAA,MACJ,MAAQ,EAAA;AAAA,KACV;AAAA,IACA,WAAa,EAAA;AAAA,MACX,MAAA,EAAQ,KAAM,CAAA,OAAA,CAAQ,CAAC,CAAA;AAAA,MACvB,OAAS,EAAA,MAAA;AAAA,MACT,aAAe,EAAA,KAAA;AAAA,MACf,UAAY,EAAA,QAAA;AAAA,MACZ,QAAU,EAAA,CAAA,YAAA,EAAe,KAAM,CAAA,OAAA,CAAQ,CAAC,CAAC,CAAA,GAAA;AAAA,KAC3C;AAAA,IACA,UAAY,EAAA;AAAA,MACV,KAAO,EAAA;AAAA,KACT;AAAA,IACA,YAAc,EAAA;AAAA,MACZ,KAAO,EAAA;AAAA,KACT;AAAA,IACA,OAAS,EAAA;AAAA,MACP,OAAS,EAAA,MAAA;AAAA,MACT,aAAe,EAAA,QAAA;AAAA,MACf,KAAO,EAAA;AAAA;AACT,GACD;AACH,CAAA;AAEO,MAAM,gBAAgB,CAAC;AAAA,EAC5B,UAAA;AAAA,EACA,UAAA;AAAA,EACA,YAAA;AAAA,EACA;AACF,CAAa,KAAA;AACX,EAAM,MAAA,QAAA,GAAW,OAAO,WAAW,CAAA;AACnC,EAAM,MAAA,GAAA,GAAM,OAAO,kBAAkB,CAAA;AACrC,EAAA,MAAM,UAAU,SAAU,EAAA;AAE1B,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI,SAAiB,EAAE,CAAA;AAC3D,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAI,QAAiB,EAAA;AACrD,EAAA,MAAM,CAAC,mBAAA,EAAqB,sBAAsB,CAAA,GAAI,SAAiB,EAAE,CAAA;AACzE,EAAA,MAAM,CAAC,eAAA,EAAiB,kBAAkB,CAAA,GAAI,SAAiB,EAAE,CAAA;AACjE,EAAA,MAAM,CAAC,iBAAA,EAAmB,oBAAoB,CAAA,GAAI,QAAiB,EAAA;AAEnE,EAAM,MAAA;AAAA,IACJ,EAAE,KAAA,EAAO,OAAS,EAAA,cAAA,EAAgB,OAAO,YAAa,EAAA;AAAA,IACtD;AAAA,GACE,GAAA,UAAA;AAAA,IACF,OAAO,MAAA,KAAgC,MAAM,GAAA,CAAI,eAAe,MAAM;AAAA,GACxE;AAEA,EAAM,MAAA,kBAAA,GAAqB,CAAC,KAA2C,KAAA;AACrE,IAAgB,eAAA,CAAA,KAAA,CAAM,OAAO,KAAe,CAAA;AAAA,GAC9C;AAEA,EAAM,MAAA,gBAAA,GAAmB,CAAC,KAA4C,KAAA;AACpE,IAAc,aAAA,CAAA,KAAA,CAAM,OAAO,KAAe,CAAA;AAAA,GAC5C;AAEA,EAAM,MAAA,yBAAA,GAA4B,CAChC,KACG,KAAA;AACH,IAAuB,sBAAA,CAAA,KAAA,CAAM,OAAO,KAAK,CAAA;AAAA,GAC3C;AAEA,EAAM,MAAA,qBAAA,GAAwB,CAAC,KAA4C,KAAA;AACzE,IAAmB,kBAAA,CAAA,KAAA,CAAM,OAAO,KAAK,CAAA;AAAA,GACvC;AAEA,EAAM,MAAA,uBAAA,GAA0B,CAAC,KAA4C,KAAA;AAC3E,IAAA,MAAM,WAAW,IAAI,IAAA,CAAK,MAAM,MAAO,CAAA,KAAK,EAAE,OAAQ,EAAA;AACtD,IAAA,MAAM,iBAAoB,GAAA,IAAA,CAAK,KAAM,CAAA,QAAA,GAAW,GAAI,CAAA;AACpD,IAAA,oBAAA,CAAqB,iBAAiB,CAAA;AAAA,GACxC;AAEA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,KAAO,EAAA;AACT,MAAA,QAAA,CAAS,IAAK,CAAA;AAAA,QACZ,KAAO,EAAA,CAAA,4BAAA;AAAA,OACR,CAAA;AACD,MAAkB,iBAAA,EAAA;AAClB,MAAa,YAAA,EAAA;AAAA;AACf,KACC,CAAC,KAAA,EAAO,QAAU,EAAA,YAAA,EAAc,iBAAiB,CAAC,CAAA;AAErD,EAAA,IAAI,YAAc,EAAA;AAChB,IAAA,QAAA,CAAS,IAAK,CAAA;AAAA,MACZ,KAAA,EAAO,CAA4B,yBAAA,EAAA,YAAA,CAAa,OAAO,CAAA,CAAA;AAAA,MACvD,MAAQ,EAAA;AAAA,KACT,CAAA;AAAA;AAGH,EACE,uBAAA,IAAA,CAAC,UAAO,QAAS,EAAA,IAAA,EAAK,MAAM,UAAY,EAAA,OAAA,EAAS,YAAc,EAAA,SAAA,EAAS,IACtE,EAAA,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,eAAY,QAAoC,EAAA,sCAAA,EAAA,CAAA;AAAA,yBAChD,aACC,EAAA,EAAA,QAAA,EAAA;AAAA,sBAAA,IAAA,CAAC,cAAW,OAAQ,EAAA,WAAA,EAAY,YAAY,EAAA,IAAA,EAAC,OAAM,SAAU,EAAA,QAAA,EAAA;AAAA,QAAA,cAAA;AAAA,wBAC/C,GAAA,CAAC,OAAG,QAAoB,EAAA,CAAA,iBAAA,CAAA,EAAA;AAAA,OACtC,EAAA,CAAA;AAAA,sBACA,GAAA,CAAC,KAAM,EAAA,EAAA,QAAA,EAAS,MACd,EAAA,QAAA,kBAAA,GAAA,CAAC,UAAW,EAAA,EAAA,OAAA,EAAQ,OAAQ,EAAA,KAAA,EAAM,SAAU,EAAA,QAAA,EAAA,CAAA,wSAAA,CAAA,EAM5C,CACF,EAAA,CAAA;AAAA,sBACA,IAAA;AAAA,QAAC,UAAA;AAAA,QAAA;AAAA,UACC,OAAQ,EAAA,OAAA;AAAA,UACR,KAAA,EAAO,EAAE,SAAA,EAAW,KAAM,EAAA;AAAA,UAC1B,YAAY,EAAA,IAAA;AAAA,UACZ,KAAM,EAAA,SAAA;AAAA,UACP,QAAA,EAAA;AAAA,YAAA,iFAAA;AAAA,gCAEY,IAAG,EAAA,EAAA,CAAA;AAAA,YAAE,qBAAA;AAAA,4BACG,GAAA,CAAC,OAAE,QAAa,EAAA,eAAA,EAAA,CAAA;AAAA,YAAI,IAAA;AAAA,4BAAE,GAAA,CAAC,OAAE,QAAqB,EAAA,uBAAA,EAAA,CAAA;AAAA,YAAK,GAAA;AAAA,YAAI,UAAA;AAAA,4BAClE,GAAA,CAAC,OAAE,QAAgB,EAAA,kBAAA,EAAA,CAAA;AAAA,YAAI,cAAA;AAAA,4BAAY,GAAA,CAAC,OAAE,QAAQ,EAAA,UAAA,EAAA,CAAA;AAAA,YAAI;AAAA;AAAA;AAAA,OAC5D;AAAA,sBACC,IAAA,CAAA,WAAA,EAAA,EAAY,SAAW,EAAA,OAAA,CAAQ,WAC9B,EAAA,QAAA,EAAA;AAAA,wBAAC,IAAA,CAAA,KAAA,EAAA,EAAI,SAAW,EAAA,OAAA,CAAQ,UACtB,EAAA,QAAA,EAAA;AAAA,0BAAC,GAAA,CAAA,UAAA,EAAA,EAAW,EAAG,EAAA,0BAAA,EAA2B,QAAa,EAAA,eAAA,EAAA,CAAA;AAAA,0BACvD,IAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACC,EAAG,EAAA,eAAA;AAAA,cACH,WAAW,OAAQ,CAAA,YAAA;AAAA,cACnB,KAAO,EAAA,YAAA;AAAA,cACP,QAAU,EAAA,kBAAA;AAAA,cACV,UAAA,EAAY,EAAE,aAAA,EAAe,uBAAwB,EAAA;AAAA,cAErD,QAAA,EAAA;AAAA,gCAAC,GAAA,CAAA,QAAA,EAAA,EAAS,KAAM,EAAA,UAAA,EAAW,QAAQ,EAAA,UAAA,EAAA,CAAA;AAAA,gCAClC,GAAA,CAAA,QAAA,EAAA,EAAS,KAAM,EAAA,SAAA,EAAU,QAAO,EAAA,SAAA,EAAA,CAAA;AAAA,gCAChC,GAAA,CAAA,QAAA,EAAA,EAAS,KAAM,EAAA,MAAA,EAAO,QAAI,EAAA,MAAA,EAAA;AAAA;AAAA;AAAA;AAC7B,SACF,EAAA,CAAA;AAAA,wBACA,GAAA;AAAA,UAAC,SAAA;AAAA,UAAA;AAAA,YACC,WAAW,OAAQ,CAAA,UAAA;AAAA,YACnB,EAAG,EAAA,gBAAA;AAAA,YACH,KAAM,EAAA,qBAAA;AAAA,YACN,IAAK,EAAA,gBAAA;AAAA,YACL,QAAU,EAAA,uBAAA;AAAA,YACV,eAAiB,EAAA;AAAA,cACf,MAAQ,EAAA;AAAA;AACV;AAAA;AACF,OACF,EAAA,CAAA;AAAA,sBACA,GAAA;AAAA,QAAC,SAAA;AAAA,QAAA;AAAA,UACC,UAAA,EAAY,EAAE,aAAA,EAAe,qBAAsB,EAAA;AAAA,UACnD,EAAG,EAAA,SAAA;AAAA,UACH,SAAS,EAAA,IAAA;AAAA,UACT,MAAO,EAAA,QAAA;AAAA,UACP,KAAM,EAAA,aAAA;AAAA,UACN,OAAQ,EAAA,UAAA;AAAA,UACR,QAAU,EAAA;AAAA;AAAA,OACZ;AAAA,sBACA,GAAA;AAAA,QAAC,SAAA;AAAA,QAAA;AAAA,UACC,QAAQ,EAAA,IAAA;AAAA,UACR,UAAA,EAAY,EAAE,aAAA,EAAe,8BAA+B,EAAA;AAAA,UAC5D,EAAG,EAAA,SAAA;AAAA,UACH,SAAS,EAAA,IAAA;AAAA,UACT,MAAO,EAAA,QAAA;AAAA,UACP,KAAM,EAAA,uBAAA;AAAA,UACN,OAAQ,EAAA,UAAA;AAAA,UACR,QAAU,EAAA;AAAA;AAAA,OACZ;AAAA,sBACA,GAAA;AAAA,QAAC,SAAA;AAAA,QAAA;AAAA,UACC,QAAQ,EAAA,IAAA;AAAA,UACR,UAAA,EAAY,EAAE,aAAA,EAAe,0BAA2B,EAAA;AAAA,UACxD,EAAG,EAAA,SAAA;AAAA,UACH,SAAS,EAAA,IAAA;AAAA,UACT,SAAS,EAAA,IAAA;AAAA,UACT,OAAQ,EAAA,GAAA;AAAA,UACR,MAAO,EAAA,QAAA;AAAA,UACP,KAAM,EAAA,kBAAA;AAAA,UACN,OAAQ,EAAA,UAAA;AAAA,UACR,QAAU,EAAA;AAAA;AAAA;AACZ,KACF,EAAA,CAAA;AAAA,yBACC,aACC,EAAA,EAAA,QAAA,EAAA;AAAA,sBAAA,GAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,aAAY,EAAA,gBAAA;AAAA,UACZ,EAAG,EAAA,SAAA;AAAA,UACH,KAAM,EAAA,WAAA;AAAA,UACN,UACE,CAAC,YAAA,CAAa,UACd,CAAC,mBAAA,IACD,CAAC,eACD,IAAA,cAAA;AAAA,UAEF,OAAQ,EAAA,WAAA;AAAA,UACR,OAAA,EAAS,MACP,kBAAmB,CAAA;AAAA,YACjB,UAAA;AAAA,YACA,YAAA;AAAA,YACA,mBAAA;AAAA,YACA,eAAA;AAAA,YACA,GAAI,UAAA,GAAa,EAAE,UAAA,KAAe,EAAC;AAAA,YACnC,GAAI,iBAAA,GAAoB,EAAE,iBAAA,KAAsB;AAAC,WAC3B,CAAA;AAAA,UAE1B,OAAS,EAAA,cAAA,oBAAmB,GAAA,CAAA,gBAAA,EAAA,EAAiB,MAAM,EAAI,EAAA,CAAA;AAAA,UACxD,QAAA,EAAA;AAAA;AAAA,OAED;AAAA,sBACA,GAAA,CAAC,UAAO,EAAG,EAAA,OAAA,EAAQ,OAAM,SAAU,EAAA,OAAA,EAAS,cAAc,QAE1D,EAAA,OAAA,EAAA;AAAA,KACF,EAAA;AAAA,GACF,EAAA,CAAA;AAEJ;;;;"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,18 +1,10 @@
|
|
|
1
|
-
/// <reference types="react" />
|
|
2
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
-
import { Entity } from '@backstage/catalog-model';
|
|
4
2
|
import * as react from 'react';
|
|
3
|
+
import { Entity } from '@backstage/catalog-model';
|
|
5
4
|
import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
|
|
6
|
-
import { DiscoveryApi, ConfigApi } from '@backstage/core-plugin-api';
|
|
5
|
+
import { DiscoveryApi, FetchApi, ConfigApi } from '@backstage/core-plugin-api';
|
|
7
6
|
import * as _backstage_frontend_plugin_api from '@backstage/frontend-plugin-api';
|
|
8
7
|
|
|
9
|
-
/** @public */
|
|
10
|
-
declare const isSplunkOnCallAvailable: (entity: Entity) => boolean;
|
|
11
|
-
/** @public */
|
|
12
|
-
type EntitySplunkOnCallCardProps = {
|
|
13
|
-
readOnly?: boolean;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
8
|
/** @public */
|
|
17
9
|
type SplunkOnCallPageProps = {
|
|
18
10
|
title?: string;
|
|
@@ -21,20 +13,11 @@ type SplunkOnCallPageProps = {
|
|
|
21
13
|
};
|
|
22
14
|
|
|
23
15
|
/** @public */
|
|
24
|
-
declare const
|
|
25
|
-
root: _backstage_core_plugin_api.RouteRef<undefined>;
|
|
26
|
-
}, {}, {}>;
|
|
16
|
+
declare const isSplunkOnCallAvailable: (entity: Entity) => boolean;
|
|
27
17
|
/** @public */
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
defaultProps: {
|
|
31
|
-
title: string;
|
|
32
|
-
subtitle: string;
|
|
33
|
-
pageTitle: string;
|
|
34
|
-
};
|
|
18
|
+
type EntitySplunkOnCallCardProps = {
|
|
19
|
+
readOnly?: boolean;
|
|
35
20
|
};
|
|
36
|
-
/** @public */
|
|
37
|
-
declare const EntitySplunkOnCallCard: (props: EntitySplunkOnCallCardProps) => react_jsx_runtime.JSX.Element;
|
|
38
21
|
|
|
39
22
|
/** @public */
|
|
40
23
|
type Team = {
|
|
@@ -153,6 +136,22 @@ type RoutingKeyTarget = {
|
|
|
153
136
|
_teamUrl: string;
|
|
154
137
|
};
|
|
155
138
|
|
|
139
|
+
/** @public */
|
|
140
|
+
declare const splunkOnCallPlugin: _backstage_core_plugin_api.BackstagePlugin<{
|
|
141
|
+
root: _backstage_core_plugin_api.RouteRef<undefined>;
|
|
142
|
+
}, {}, {}>;
|
|
143
|
+
/** @public */
|
|
144
|
+
declare const SplunkOnCallPage: {
|
|
145
|
+
(props: SplunkOnCallPageProps): react.JSX.Element;
|
|
146
|
+
defaultProps: {
|
|
147
|
+
title: string;
|
|
148
|
+
subtitle: string;
|
|
149
|
+
pageTitle: string;
|
|
150
|
+
};
|
|
151
|
+
};
|
|
152
|
+
/** @public */
|
|
153
|
+
declare const EntitySplunkOnCallCard: (props: EntitySplunkOnCallCardProps) => react_jsx_runtime.JSX.Element;
|
|
154
|
+
|
|
156
155
|
/** @public */
|
|
157
156
|
type MessageType = 'CRITICAL' | 'WARNING' | 'ACKNOWLEDGEMENT' | 'INFO' | 'RECOVERY';
|
|
158
157
|
/** @public */
|
|
@@ -221,6 +220,7 @@ type OnCallsResponse = {
|
|
|
221
220
|
type ClientApiConfig = {
|
|
222
221
|
eventsRestEndpoint: string | null;
|
|
223
222
|
discoveryApi: DiscoveryApi;
|
|
223
|
+
fetchApi: FetchApi;
|
|
224
224
|
};
|
|
225
225
|
/** @public */
|
|
226
226
|
type RequestOptions = {
|
|
@@ -233,11 +233,14 @@ type RequestOptions = {
|
|
|
233
233
|
declare class UnauthorizedError extends Error {
|
|
234
234
|
}
|
|
235
235
|
/** @public */
|
|
236
|
+
declare class MissingEventsRestEndpointError extends Error {
|
|
237
|
+
}
|
|
238
|
+
/** @public */
|
|
236
239
|
declare const splunkOnCallApiRef: _backstage_frontend_plugin_api.ApiRef<SplunkOnCallApi>;
|
|
237
240
|
/** @public */
|
|
238
241
|
declare class SplunkOnCallClient implements SplunkOnCallApi {
|
|
239
242
|
private readonly config;
|
|
240
|
-
static fromConfig(configApi: ConfigApi, discoveryApi: DiscoveryApi): SplunkOnCallClient;
|
|
243
|
+
static fromConfig(configApi: ConfigApi, discoveryApi: DiscoveryApi, fetchApi: FetchApi): SplunkOnCallClient;
|
|
241
244
|
constructor(config: ClientApiConfig);
|
|
242
245
|
getIncidents(): Promise<Incident[]>;
|
|
243
246
|
getOnCallUsers(): Promise<OnCall[]>;
|
|
@@ -248,6 +251,7 @@ declare class SplunkOnCallClient implements SplunkOnCallApi {
|
|
|
248
251
|
incidentAction(options: TriggerAlarmRequest): Promise<Response>;
|
|
249
252
|
private findByUrl;
|
|
250
253
|
private request;
|
|
254
|
+
private getEventsRestEndpoint;
|
|
251
255
|
}
|
|
252
256
|
|
|
253
|
-
export { type ClientApiConfig, EntitySplunkOnCallCard, type EntitySplunkOnCallCardProps, type EscalationPolicyInfo, type EscalationPolicyResponse, type EscalationPolicySummary, type EscalationPolicyTeam, type Incident, type IncidentPhase, type IncidentTransition, type IncidentsResponse, type ListRoutingKeyResponse, type ListUserResponse, type MessageType, type OnCall, type OnCallEscalationPolicyResource, type OnCallNowResource, type OnCallTeamResource, type OnCallUser, type OnCallUsersResource, type OnCallsResponse, type RequestOptions, type RoutingKey, type RoutingKeyTarget, type SplunkOnCallApi, SplunkOnCallClient, SplunkOnCallPage, type SplunkOnCallPageProps, type Team, type TriggerAlarmRequest, UnauthorizedError, type User, isSplunkOnCallAvailable, splunkOnCallPlugin as plugin, splunkOnCallApiRef, splunkOnCallPlugin };
|
|
257
|
+
export { type ClientApiConfig, EntitySplunkOnCallCard, type EntitySplunkOnCallCardProps, type EscalationPolicyInfo, type EscalationPolicyResponse, type EscalationPolicySummary, type EscalationPolicyTeam, type Incident, type IncidentPhase, type IncidentTransition, type IncidentsResponse, type ListRoutingKeyResponse, type ListUserResponse, type MessageType, MissingEventsRestEndpointError, type OnCall, type OnCallEscalationPolicyResource, type OnCallNowResource, type OnCallTeamResource, type OnCallUser, type OnCallUsersResource, type OnCallsResponse, type RequestOptions, type RoutingKey, type RoutingKeyTarget, type SplunkOnCallApi, SplunkOnCallClient, SplunkOnCallPage, type SplunkOnCallPageProps, type Team, type TriggerAlarmRequest, UnauthorizedError, type User, isSplunkOnCallAvailable, splunkOnCallPlugin as plugin, splunkOnCallApiRef, splunkOnCallPlugin };
|
package/dist/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { EntitySplunkOnCallCard, SplunkOnCallPage, splunkOnCallPlugin as plugin, splunkOnCallPlugin } from './plugin.esm.js';
|
|
2
2
|
export { isSplunkOnCallAvailable } from './components/EntitySplunkOnCallCard.esm.js';
|
|
3
|
-
export { SplunkOnCallClient, UnauthorizedError, splunkOnCallApiRef } from './api/client.esm.js';
|
|
3
|
+
export { MissingEventsRestEndpointError, SplunkOnCallClient, UnauthorizedError, splunkOnCallApiRef } from './api/client.esm.js';
|
|
4
4
|
//# sourceMappingURL=index.esm.js.map
|
package/dist/plugin.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { splunkOnCallApiRef, SplunkOnCallClient } from './api/client.esm.js';
|
|
2
|
-
import { createRouteRef, createPlugin, createApiFactory, discoveryApiRef, configApiRef, createRoutableExtension, createComponentExtension } from '@backstage/core-plugin-api';
|
|
2
|
+
import { createRouteRef, createPlugin, createApiFactory, discoveryApiRef, configApiRef, fetchApiRef, createRoutableExtension, createComponentExtension } from '@backstage/core-plugin-api';
|
|
3
3
|
|
|
4
4
|
const rootRouteRef = createRouteRef({ id: "splunk-on-call" });
|
|
5
5
|
const splunkOnCallPlugin = createPlugin({
|
|
@@ -7,8 +7,12 @@ const splunkOnCallPlugin = createPlugin({
|
|
|
7
7
|
apis: [
|
|
8
8
|
createApiFactory({
|
|
9
9
|
api: splunkOnCallApiRef,
|
|
10
|
-
deps: {
|
|
11
|
-
|
|
10
|
+
deps: {
|
|
11
|
+
discoveryApi: discoveryApiRef,
|
|
12
|
+
configApi: configApiRef,
|
|
13
|
+
fetchApi: fetchApiRef
|
|
14
|
+
},
|
|
15
|
+
factory: ({ configApi, discoveryApi, fetchApi }) => SplunkOnCallClient.fromConfig(configApi, discoveryApi, fetchApi)
|
|
12
16
|
})
|
|
13
17
|
],
|
|
14
18
|
routes: {
|
package/dist/plugin.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.esm.js","sources":["../src/plugin.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { splunkOnCallApiRef, SplunkOnCallClient } from './api';\nimport {\n createApiFactory,\n createPlugin,\n createRouteRef,\n discoveryApiRef,\n configApiRef,\n createRoutableExtension,\n createComponentExtension,\n} from '@backstage/core-plugin-api';\n\nexport const rootRouteRef = createRouteRef({ id: 'splunk-on-call' });\n\n/** @public */\nexport const splunkOnCallPlugin = createPlugin({\n id: 'splunk-on-call',\n apis: [\n createApiFactory({\n api: splunkOnCallApiRef,\n deps: {
|
|
1
|
+
{"version":3,"file":"plugin.esm.js","sources":["../src/plugin.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { splunkOnCallApiRef, SplunkOnCallClient } from './api';\nimport {\n createApiFactory,\n createPlugin,\n createRouteRef,\n discoveryApiRef,\n configApiRef,\n fetchApiRef,\n createRoutableExtension,\n createComponentExtension,\n} from '@backstage/core-plugin-api';\n\nexport const rootRouteRef = createRouteRef({ id: 'splunk-on-call' });\n\n/** @public */\nexport const splunkOnCallPlugin = createPlugin({\n id: 'splunk-on-call',\n apis: [\n createApiFactory({\n api: splunkOnCallApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n configApi: configApiRef,\n fetchApi: fetchApiRef,\n },\n factory: ({ configApi, discoveryApi, fetchApi }) =>\n SplunkOnCallClient.fromConfig(configApi, discoveryApi, fetchApi),\n }),\n ],\n routes: {\n root: rootRouteRef,\n },\n});\n\n/** @public */\nexport const SplunkOnCallPage = splunkOnCallPlugin.provide(\n createRoutableExtension({\n name: 'SplunkOnCallPage',\n component: () =>\n import('./components/SplunkOnCallPage').then(m => m.SplunkOnCallPage),\n mountPoint: rootRouteRef,\n }),\n);\n\n/** @public */\nexport const EntitySplunkOnCallCard = splunkOnCallPlugin.provide(\n createComponentExtension({\n name: 'EntitySplunkOnCallCard',\n component: {\n lazy: () =>\n import('./components/EntitySplunkOnCallCard').then(\n m => m.EntitySplunkOnCallCard,\n ),\n },\n }),\n);\n"],"names":[],"mappings":";;;AA2BO,MAAM,YAAe,GAAA,cAAA,CAAe,EAAE,EAAA,EAAI,kBAAkB;AAG5D,MAAM,qBAAqB,YAAa,CAAA;AAAA,EAC7C,EAAI,EAAA,gBAAA;AAAA,EACJ,IAAM,EAAA;AAAA,IACJ,gBAAiB,CAAA;AAAA,MACf,GAAK,EAAA,kBAAA;AAAA,MACL,IAAM,EAAA;AAAA,QACJ,YAAc,EAAA,eAAA;AAAA,QACd,SAAW,EAAA,YAAA;AAAA,QACX,QAAU,EAAA;AAAA,OACZ;AAAA,MACA,OAAA,EAAS,CAAC,EAAE,SAAW,EAAA,YAAA,EAAc,QAAS,EAAA,KAC5C,kBAAmB,CAAA,UAAA,CAAW,SAAW,EAAA,YAAA,EAAc,QAAQ;AAAA,KAClE;AAAA,GACH;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA;AAAA;AAEV,CAAC;AAGM,MAAM,mBAAmB,kBAAmB,CAAA,OAAA;AAAA,EACjD,uBAAwB,CAAA;AAAA,IACtB,IAAM,EAAA,kBAAA;AAAA,IACN,SAAA,EAAW,MACT,OAAO,sCAA+B,EAAE,IAAK,CAAA,CAAA,CAAA,KAAK,EAAE,gBAAgB,CAAA;AAAA,IACtE,UAAY,EAAA;AAAA,GACb;AACH;AAGO,MAAM,yBAAyB,kBAAmB,CAAA,OAAA;AAAA,EACvD,wBAAyB,CAAA;AAAA,IACvB,IAAM,EAAA,wBAAA;AAAA,IACN,SAAW,EAAA;AAAA,MACT,IAAM,EAAA,MACJ,OAAO,4CAAqC,CAAE,CAAA,IAAA;AAAA,QAC5C,OAAK,CAAE,CAAA;AAAA;AACT;AACJ,GACD;AACH;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage-community/plugin-splunk-on-call",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "A Backstage plugin that integrates towards Splunk On-Call",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "frontend-plugin",
|
|
@@ -67,12 +67,12 @@
|
|
|
67
67
|
"test": "backstage-cli package test"
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
|
-
"@backstage/catalog-model": "^1.7.
|
|
71
|
-
"@backstage/core-compat-api": "^0.5.
|
|
72
|
-
"@backstage/core-components": "^0.18.
|
|
73
|
-
"@backstage/core-plugin-api": "^1.12.
|
|
74
|
-
"@backstage/frontend-plugin-api": "^0.
|
|
75
|
-
"@backstage/plugin-catalog-react": "^1.
|
|
70
|
+
"@backstage/catalog-model": "^1.7.7",
|
|
71
|
+
"@backstage/core-compat-api": "^0.5.9",
|
|
72
|
+
"@backstage/core-components": "^0.18.8",
|
|
73
|
+
"@backstage/core-plugin-api": "^1.12.4",
|
|
74
|
+
"@backstage/frontend-plugin-api": "^0.15.1",
|
|
75
|
+
"@backstage/plugin-catalog-react": "^2.1.0",
|
|
76
76
|
"@material-ui/core": "^4.12.2",
|
|
77
77
|
"@material-ui/icons": "^4.9.1",
|
|
78
78
|
"@material-ui/lab": "4.0.0-alpha.61",
|
|
@@ -81,10 +81,10 @@
|
|
|
81
81
|
"react-use": "^17.2.4"
|
|
82
82
|
},
|
|
83
83
|
"devDependencies": {
|
|
84
|
-
"@backstage/cli": "^0.
|
|
85
|
-
"@backstage/core-app-api": "^1.19.
|
|
86
|
-
"@backstage/dev-utils": "^1.1.
|
|
87
|
-
"@backstage/test-utils": "^1.7.
|
|
84
|
+
"@backstage/cli": "^0.36.0",
|
|
85
|
+
"@backstage/core-app-api": "^1.19.6",
|
|
86
|
+
"@backstage/dev-utils": "^1.1.21",
|
|
87
|
+
"@backstage/test-utils": "^1.7.16",
|
|
88
88
|
"@testing-library/dom": "^10.0.0",
|
|
89
89
|
"@testing-library/jest-dom": "^6.0.0",
|
|
90
90
|
"@testing-library/react": "^15.0.0",
|