@backstage-community/plugin-servicenow 1.5.0 → 1.6.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 +12 -0
- package/README.md +3 -3
- package/dist/alpha/plugin.esm.js +1 -0
- package/dist/alpha/plugin.esm.js.map +1 -1
- package/dist/alpha.d.ts +95 -1
- package/dist/alpha.esm.js +3 -1
- package/dist/alpha.esm.js.map +1 -1
- package/dist/api/ServiceNowBackendClient.esm.js +10 -1
- package/dist/api/ServiceNowBackendClient.esm.js.map +1 -1
- package/dist/components/Router.esm.js +10 -0
- package/dist/components/Router.esm.js.map +1 -0
- package/dist/components/Servicenow/EntityServicenowContent.esm.js +35 -17
- package/dist/components/Servicenow/EntityServicenowContent.esm.js.map +1 -1
- package/dist/components/Servicenow/IncidentsFilter.esm.js +9 -5
- package/dist/components/Servicenow/IncidentsFilter.esm.js.map +1 -1
- package/dist/components/Servicenow/IncidentsListColumns.esm.js +43 -39
- package/dist/components/Servicenow/IncidentsListColumns.esm.js.map +1 -1
- package/dist/components/Servicenow/IncidentsTableBody.esm.js +6 -3
- package/dist/components/Servicenow/IncidentsTableBody.esm.js.map +1 -1
- package/dist/components/Servicenow/IncidentsTableHeader.esm.js +3 -2
- package/dist/components/Servicenow/IncidentsTableHeader.esm.js.map +1 -1
- package/dist/components/Servicenow/IncidentsTableRow.esm.js +8 -4
- package/dist/components/Servicenow/IncidentsTableRow.esm.js.map +1 -1
- package/dist/components/shared-components/IncidentEnumFilter.esm.js +2 -3
- package/dist/components/shared-components/IncidentEnumFilter.esm.js.map +1 -1
- package/dist/hooks/useTranslation.esm.js +13 -0
- package/dist/hooks/useTranslation.esm.js.map +1 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.esm.js +1 -1
- package/dist/plugin.esm.js +9 -1
- package/dist/plugin.esm.js.map +1 -1
- package/dist/translations/de.esm.js +37 -0
- package/dist/translations/de.esm.js.map +1 -0
- package/dist/translations/es.esm.js +37 -0
- package/dist/translations/es.esm.js.map +1 -0
- package/dist/translations/fr.esm.js +37 -0
- package/dist/translations/fr.esm.js.map +1 -0
- package/dist/translations/index.esm.js +16 -0
- package/dist/translations/index.esm.js.map +1 -0
- package/dist/translations/it.esm.js +37 -0
- package/dist/translations/it.esm.js.map +1 -0
- package/dist/translations/ja.esm.js +37 -0
- package/dist/translations/ja.esm.js.map +1 -0
- package/dist/translations/ref.esm.js +53 -0
- package/dist/translations/ref.esm.js.map +1 -0
- package/dist/utils/incidentUtils.esm.js +75 -3
- package/dist/utils/incidentUtils.esm.js.map +1 -1
- package/dist/utils/queryParamsUtils.esm.js +7 -5
- package/dist/utils/queryParamsUtils.esm.js.map +1 -1
- package/package.json +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @backstage-community/plugin-servicenow
|
|
2
2
|
|
|
3
|
+
## 1.6.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 8472540: Support custom ServiceNow incident table fields in entity annotations
|
|
8
|
+
|
|
9
|
+
## 1.5.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 40b4d6c: - Added internationalization (i18n) support with translations for German, French, Spanish, Italian, and Japanese
|
|
14
|
+
|
|
3
15
|
## 1.5.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ Software Catalog integration:
|
|
|
25
25
|
|
|
26
26
|
```tsx
|
|
27
27
|
import {
|
|
28
|
-
|
|
28
|
+
Router,
|
|
29
29
|
isServicenowAvailable,
|
|
30
30
|
isMyProfile,
|
|
31
31
|
} from '@backstage-community/plugin-servicenow';
|
|
@@ -40,7 +40,7 @@ Software Catalog integration:
|
|
|
40
40
|
title="ServiceNow"
|
|
41
41
|
if={isServicenowAvailable}
|
|
42
42
|
>
|
|
43
|
-
<
|
|
43
|
+
<Router />
|
|
44
44
|
</EntityLayout.Route>
|
|
45
45
|
```
|
|
46
46
|
|
|
@@ -49,7 +49,7 @@ Software Catalog integration:
|
|
|
49
49
|
|
|
50
50
|
```tsx
|
|
51
51
|
<EntityLayout.Route path="/servicenow" title="ServiceNow" if={isMyProfile}>
|
|
52
|
-
<
|
|
52
|
+
<Router />
|
|
53
53
|
</EntityLayout.Route>
|
|
54
54
|
```
|
|
55
55
|
|
package/dist/alpha/plugin.esm.js
CHANGED
|
@@ -3,6 +3,7 @@ import { ApiBlueprint, identityApiRef, fetchApiRef, discoveryApiRef, createFront
|
|
|
3
3
|
import { EntityContentBlueprint } from '@backstage/plugin-catalog-react/alpha';
|
|
4
4
|
import { ServiceNowBackendClient, serviceNowApiRef } from '../api/ServiceNowBackendClient.esm.js';
|
|
5
5
|
import { isServicenowAvailable } from '@backstage-community/plugin-servicenow-common';
|
|
6
|
+
export { servicenowTranslations } from '../translations/index.esm.js';
|
|
6
7
|
|
|
7
8
|
const servicenowApi = ApiBlueprint.make({
|
|
8
9
|
params: (defineParams) => defineParams({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.esm.js","sources":["../../src/alpha/plugin.tsx"],"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 */\n\nimport {\n ApiBlueprint,\n createFrontendPlugin,\n discoveryApiRef,\n fetchApiRef,\n identityApiRef,\n} from '@backstage/frontend-plugin-api';\nimport { EntityContentBlueprint } from '@backstage/plugin-catalog-react/alpha';\nimport {\n serviceNowApiRef,\n ServiceNowBackendClient,\n} from '../api/ServiceNowBackendClient';\n\nimport { isServicenowAvailable } from '@backstage-community/plugin-servicenow-common';\n\n/** @alpha */\nexport const servicenowApi = ApiBlueprint.make({\n params: defineParams =>\n defineParams({\n api: serviceNowApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n identityApi: identityApiRef,\n },\n factory: ({ discoveryApi, fetchApi, identityApi }) =>\n new ServiceNowBackendClient(discoveryApi, fetchApi, identityApi),\n }),\n});\n\n/**\n * Servicenow entity content that shows an incident table with a\n * filter similar to the catalog table\n * @alpha\n */\nexport const entityServicenowContent = EntityContentBlueprint.make({\n name: 'EntityServicenowContent',\n params: {\n path: 'servicenow',\n title: 'ServiceNow',\n filter: isServicenowAvailable,\n loader: () =>\n import('../components/Servicenow').then(m => (\n <m.EntityServicenowContent />\n )),\n },\n});\n\n/** @alpha */\nexport default createFrontendPlugin({\n pluginId: 'servicenow',\n extensions: [servicenowApi, entityServicenowContent],\n});\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"plugin.esm.js","sources":["../../src/alpha/plugin.tsx"],"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 */\n\nimport {\n ApiBlueprint,\n createFrontendPlugin,\n discoveryApiRef,\n fetchApiRef,\n identityApiRef,\n} from '@backstage/frontend-plugin-api';\nimport { EntityContentBlueprint } from '@backstage/plugin-catalog-react/alpha';\nimport {\n serviceNowApiRef,\n ServiceNowBackendClient,\n} from '../api/ServiceNowBackendClient';\n\nimport { isServicenowAvailable } from '@backstage-community/plugin-servicenow-common';\n\n/** @alpha */\nexport const servicenowApi = ApiBlueprint.make({\n params: defineParams =>\n defineParams({\n api: serviceNowApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n identityApi: identityApiRef,\n },\n factory: ({ discoveryApi, fetchApi, identityApi }) =>\n new ServiceNowBackendClient(discoveryApi, fetchApi, identityApi),\n }),\n});\n\n/**\n * Servicenow entity content that shows an incident table with a\n * filter similar to the catalog table\n * @alpha\n */\nexport const entityServicenowContent = EntityContentBlueprint.make({\n name: 'EntityServicenowContent',\n params: {\n path: 'servicenow',\n title: 'ServiceNow',\n filter: isServicenowAvailable,\n loader: () =>\n import('../components/Servicenow').then(m => (\n <m.EntityServicenowContent />\n )),\n },\n});\n\n/** @alpha */\nexport default createFrontendPlugin({\n pluginId: 'servicenow',\n extensions: [servicenowApi, entityServicenowContent],\n});\n\n/**\n * @alpha\n * Translation resources for the ServiceNow plugin\n */\nexport * from '../translations';\n"],"names":[],"mappings":";;;;;;;AAgCa,MAAA,aAAA,GAAgB,aAAa,IAAK,CAAA;AAAA,EAC7C,MAAA,EAAQ,kBACN,YAAa,CAAA;AAAA,IACX,GAAK,EAAA,gBAAA;AAAA,IACL,IAAM,EAAA;AAAA,MACJ,YAAc,EAAA,eAAA;AAAA,MACd,QAAU,EAAA,WAAA;AAAA,MACV,WAAa,EAAA;AAAA,KACf;AAAA,IACA,OAAA,EAAS,CAAC,EAAE,YAAc,EAAA,QAAA,EAAU,WAAY,EAAA,KAC9C,IAAI,uBAAA,CAAwB,YAAc,EAAA,QAAA,EAAU,WAAW;AAAA,GAClE;AACL,CAAC;AAOY,MAAA,uBAAA,GAA0B,uBAAuB,IAAK,CAAA;AAAA,EACjE,IAAM,EAAA,yBAAA;AAAA,EACN,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA,YAAA;AAAA,IACN,KAAO,EAAA,YAAA;AAAA,IACP,MAAQ,EAAA,qBAAA;AAAA,IACR,MAAA,EAAQ,MACN,OAAO,uCAA0B,CAAA,CAAE,IAAK,CAAA,CAAA,CAAA,qBACrC,GAAA,CAAA,CAAA,CAAE,uBAAF,EAAA,EAA0B,CAC5B;AAAA;AAEP,CAAC;AAGD,aAAe,oBAAqB,CAAA;AAAA,EAClC,QAAU,EAAA,YAAA;AAAA,EACV,UAAA,EAAY,CAAC,aAAA,EAAe,uBAAuB;AACrD,CAAC,CAAA;;;;"}
|
package/dist/alpha.d.ts
CHANGED
|
@@ -4,7 +4,101 @@ import * as react from 'react';
|
|
|
4
4
|
import * as _backstage_plugin_catalog_react_alpha from '@backstage/plugin-catalog-react/alpha';
|
|
5
5
|
import * as _backstage_frontend_plugin_api from '@backstage/frontend-plugin-api';
|
|
6
6
|
import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
|
|
7
|
+
import * as _backstage_core_plugin_api_alpha from '@backstage/core-plugin-api/alpha';
|
|
7
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Translation reference for the ServiceNow plugin.
|
|
11
|
+
* @alpha
|
|
12
|
+
*/
|
|
13
|
+
declare const servicenowTranslationRef: _backstage_core_plugin_api_alpha.TranslationRef<"plugin.servicenow", {
|
|
14
|
+
readonly "table.searchPlaceholder": string;
|
|
15
|
+
readonly "table.labelRowsSelect": string;
|
|
16
|
+
readonly "table.columns.description": string;
|
|
17
|
+
readonly "table.columns.priority": string;
|
|
18
|
+
readonly "table.columns.incidentNumber": string;
|
|
19
|
+
readonly "table.columns.created": string;
|
|
20
|
+
readonly "table.columns.state": string;
|
|
21
|
+
readonly "table.columns.actions": string;
|
|
22
|
+
readonly "table.emptyContent": string;
|
|
23
|
+
readonly "filter.priority": string;
|
|
24
|
+
readonly "filter.state": string;
|
|
25
|
+
readonly "priority.critical": string;
|
|
26
|
+
readonly "priority.high": string;
|
|
27
|
+
readonly "priority.moderate": string;
|
|
28
|
+
readonly "priority.low": string;
|
|
29
|
+
readonly "priority.planning": string;
|
|
30
|
+
readonly "page.title": string;
|
|
31
|
+
readonly "page.titleWithCount": string;
|
|
32
|
+
readonly "actions.openInServicenow": string;
|
|
33
|
+
readonly "incidentState.new": string;
|
|
34
|
+
readonly "incidentState.inProgress": string;
|
|
35
|
+
readonly "incidentState.onHold": string;
|
|
36
|
+
readonly "incidentState.resolved": string;
|
|
37
|
+
readonly "incidentState.closed": string;
|
|
38
|
+
readonly "incidentState.cancelled": string;
|
|
39
|
+
readonly "errors.loadingIncidents": string;
|
|
40
|
+
}>;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Translation resources for the ServiceNow plugin.
|
|
44
|
+
* @alpha
|
|
45
|
+
*/
|
|
46
|
+
declare const servicenowTranslations: _backstage_core_plugin_api_alpha.TranslationResource<"plugin.servicenow">;
|
|
47
|
+
|
|
48
|
+
/** @alpha */
|
|
49
|
+
declare const servicenowApi: _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
|
|
50
|
+
kind: "api";
|
|
51
|
+
name: undefined;
|
|
52
|
+
config: {};
|
|
53
|
+
configInput: {};
|
|
54
|
+
output: _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_core_plugin_api.AnyApiFactory, "core.api.factory", {}>;
|
|
55
|
+
inputs: {};
|
|
56
|
+
params: <TApi, TImpl extends TApi, TDeps extends {
|
|
57
|
+
[x: string]: unknown;
|
|
58
|
+
}>(params: _backstage_core_plugin_api.ApiFactory<TApi, TImpl, TDeps>) => _backstage_frontend_plugin_api.ExtensionBlueprintParams<_backstage_core_plugin_api.AnyApiFactory>;
|
|
59
|
+
}>;
|
|
60
|
+
/**
|
|
61
|
+
* Servicenow entity content that shows an incident table with a
|
|
62
|
+
* filter similar to the catalog table
|
|
63
|
+
* @alpha
|
|
64
|
+
*/
|
|
65
|
+
declare const entityServicenowContent: _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
|
|
66
|
+
kind: "entity-content";
|
|
67
|
+
name: "EntityServicenowContent";
|
|
68
|
+
config: {
|
|
69
|
+
path: string | undefined;
|
|
70
|
+
title: string | undefined;
|
|
71
|
+
filter: _backstage_plugin_catalog_react_alpha.EntityPredicate | undefined;
|
|
72
|
+
group: string | false | undefined;
|
|
73
|
+
};
|
|
74
|
+
configInput: {
|
|
75
|
+
filter?: _backstage_plugin_catalog_react_alpha.EntityPredicate | undefined;
|
|
76
|
+
title?: string | undefined;
|
|
77
|
+
path?: string | undefined;
|
|
78
|
+
group?: string | false | undefined;
|
|
79
|
+
};
|
|
80
|
+
output: _backstage_frontend_plugin_api.ExtensionDataRef<string, "core.routing.path", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<react.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.RouteRef<_backstage_frontend_plugin_api.AnyRouteRefParams>, "core.routing.ref", {
|
|
81
|
+
optional: true;
|
|
82
|
+
}> | _backstage_frontend_plugin_api.ExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
|
|
83
|
+
optional: true;
|
|
84
|
+
}> | _backstage_frontend_plugin_api.ExtensionDataRef<string, "catalog.entity-filter-expression", {
|
|
85
|
+
optional: true;
|
|
86
|
+
}> | _backstage_frontend_plugin_api.ExtensionDataRef<string, "catalog.entity-content-title", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<string, "catalog.entity-content-group", {
|
|
87
|
+
optional: true;
|
|
88
|
+
}>;
|
|
89
|
+
inputs: {};
|
|
90
|
+
params: {
|
|
91
|
+
defaultPath?: [Error: "Use the 'path' param instead"] | undefined;
|
|
92
|
+
path: string;
|
|
93
|
+
defaultTitle?: [Error: "Use the 'title' param instead"] | undefined;
|
|
94
|
+
title: string;
|
|
95
|
+
defaultGroup?: [Error: "Use the 'group' param instead"] | undefined;
|
|
96
|
+
group?: (string & {}) | "overview" | "documentation" | "development" | "deployment" | "operation" | "observability" | undefined;
|
|
97
|
+
loader: () => Promise<JSX.Element>;
|
|
98
|
+
routeRef?: _backstage_frontend_plugin_api.RouteRef<_backstage_frontend_plugin_api.AnyRouteRefParams> | undefined;
|
|
99
|
+
filter?: _backstage_plugin_catalog_react_alpha.EntityPredicate | ((entity: _backstage_catalog_model.Entity) => boolean) | undefined;
|
|
100
|
+
};
|
|
101
|
+
}>;
|
|
8
102
|
/** @alpha */
|
|
9
103
|
declare const _default: _backstage_frontend_plugin_api.OverridableFrontendPlugin<{}, {}, {
|
|
10
104
|
"api:servicenow": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
|
|
@@ -57,4 +151,4 @@ declare const _default: _backstage_frontend_plugin_api.OverridableFrontendPlugin
|
|
|
57
151
|
}>;
|
|
58
152
|
}>;
|
|
59
153
|
|
|
60
|
-
export { _default as default };
|
|
154
|
+
export { _default as default, entityServicenowContent, servicenowApi, servicenowTranslationRef, servicenowTranslations };
|
package/dist/alpha.esm.js
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
export { default } from './alpha/plugin.esm.js';
|
|
1
|
+
export { default, entityServicenowContent, servicenowApi } from './alpha/plugin.esm.js';
|
|
2
|
+
export { servicenowTranslations } from './translations/index.esm.js';
|
|
3
|
+
export { servicenowTranslationRef } from './translations/ref.esm.js';
|
|
2
4
|
//# sourceMappingURL=alpha.esm.js.map
|
package/dist/alpha.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alpha.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"alpha.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
|
|
@@ -18,7 +18,16 @@ class ServiceNowBackendClient {
|
|
|
18
18
|
};
|
|
19
19
|
const response = await this.fetchApi.fetch(url, { headers });
|
|
20
20
|
if (!response.ok) {
|
|
21
|
-
|
|
21
|
+
let errorBody;
|
|
22
|
+
try {
|
|
23
|
+
errorBody = await response.json();
|
|
24
|
+
} catch (e) {
|
|
25
|
+
throw new Error(
|
|
26
|
+
`ServiceNow API request failed: ${response.status} - Could not parse error response.`
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
const errorMessage = errorBody?.error?.message ?? `ServiceNow API request failed: ${response.status}`;
|
|
30
|
+
throw new Error(errorMessage);
|
|
22
31
|
}
|
|
23
32
|
return await response.json();
|
|
24
33
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServiceNowBackendClient.esm.js","sources":["../../src/api/ServiceNowBackendClient.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 { IncidentPick } from '@backstage-community/plugin-servicenow-common';\nimport {\n createApiRef,\n DiscoveryApi,\n FetchApi,\n IdentityApi,\n} from '@backstage/core-plugin-api';\nimport { IncidentsData, PaginatedIncidentsData } from '../types';\n\nexport interface ServiceNowBackendAPI {\n getIncidents(queryParams: URLSearchParams): Promise<PaginatedIncidentsData>;\n}\n\nexport const serviceNowApiRef = createApiRef<ServiceNowBackendAPI>({\n id: 'plugin.servicenow.service',\n});\n\nexport class ServiceNowBackendClient implements ServiceNowBackendAPI {\n constructor(\n private readonly discoveryApi: DiscoveryApi,\n private readonly fetchApi: FetchApi,\n private readonly identityApi: IdentityApi,\n ) {}\n\n private async fetchFromServiceNow<T>(\n path: string,\n queryParams?: URLSearchParams,\n ): Promise<{ items: T; totalCount: number }> {\n const proxyBase = await this.discoveryApi.getBaseUrl('servicenow');\n const url = `${proxyBase}${path}${queryParams ? `?${queryParams}` : ''}`;\n\n const { token } = await this.identityApi.getCredentials();\n const headers = {\n Authorization: `Bearer ${token}`,\n };\n\n const response = await this.fetchApi.fetch(url, { headers });\n if (!response.ok) {\n throw new Error(`ServiceNow API request failed: ${response.status}`);\n }\n\n return (await response.json()) as { items: T; totalCount: number };\n }\n\n async getIncidents(\n queryParams: URLSearchParams,\n ): Promise<PaginatedIncidentsData> {\n const { items, totalCount } = await this.fetchFromServiceNow<\n IncidentPick[]\n >('/incidents', queryParams);\n\n const incidents = incidentsPickToIncidentsData(items);\n return { incidents, totalCount };\n }\n}\n\nexport function incidentsPickToIncidentsData(\n data: IncidentPick[],\n): IncidentsData[] {\n return data.map(item => ({\n sysId: item.sys_id,\n number: item.number,\n shortDescription: item.short_description,\n description: item.description,\n sysCreatedOn: item.sys_created_on,\n priority: item.priority,\n incidentState: item.incident_state,\n url: item.url,\n }));\n}\n"],"names":[],"mappings":";;AA4BO,MAAM,mBAAmB,YAAmC,CAAA;AAAA,EACjE,EAAI,EAAA;AACN,CAAC;AAEM,MAAM,uBAAwD,CAAA;AAAA,EACnE,WAAA,CACmB,YACA,EAAA,QAAA,EACA,WACjB,EAAA;AAHiB,IAAA,IAAA,CAAA,YAAA,GAAA,YAAA;AACA,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AACA,IAAA,IAAA,CAAA,WAAA,GAAA,WAAA;AAAA;AAChB,EAEH,MAAc,mBACZ,CAAA,IAAA,EACA,WAC2C,EAAA;AAC3C,IAAA,MAAM,SAAY,GAAA,MAAM,IAAK,CAAA,YAAA,CAAa,WAAW,YAAY,CAAA;AACjE,IAAM,MAAA,GAAA,GAAM,CAAG,EAAA,SAAS,CAAG,EAAA,IAAI,GAAG,WAAc,GAAA,CAAA,CAAA,EAAI,WAAW,CAAA,CAAA,GAAK,EAAE,CAAA,CAAA;AAEtE,IAAA,MAAM,EAAE,KAAM,EAAA,GAAI,MAAM,IAAA,CAAK,YAAY,cAAe,EAAA;AACxD,IAAA,MAAM,OAAU,GAAA;AAAA,MACd,aAAA,EAAe,UAAU,KAAK,CAAA;AAAA,KAChC;AAEA,IAAM,MAAA,QAAA,GAAW,MAAM,IAAK,CAAA,QAAA,CAAS,MAAM,GAAK,EAAA,EAAE,SAAS,CAAA;AAC3D,IAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,
|
|
1
|
+
{"version":3,"file":"ServiceNowBackendClient.esm.js","sources":["../../src/api/ServiceNowBackendClient.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 { IncidentPick } from '@backstage-community/plugin-servicenow-common';\nimport {\n createApiRef,\n DiscoveryApi,\n FetchApi,\n IdentityApi,\n} from '@backstage/core-plugin-api';\nimport { IncidentsData, PaginatedIncidentsData } from '../types';\n\nexport interface ServiceNowBackendAPI {\n getIncidents(queryParams: URLSearchParams): Promise<PaginatedIncidentsData>;\n}\n\nexport const serviceNowApiRef = createApiRef<ServiceNowBackendAPI>({\n id: 'plugin.servicenow.service',\n});\n\nexport class ServiceNowBackendClient implements ServiceNowBackendAPI {\n constructor(\n private readonly discoveryApi: DiscoveryApi,\n private readonly fetchApi: FetchApi,\n private readonly identityApi: IdentityApi,\n ) {}\n\n private async fetchFromServiceNow<T>(\n path: string,\n queryParams?: URLSearchParams,\n ): Promise<{ items: T; totalCount: number }> {\n const proxyBase = await this.discoveryApi.getBaseUrl('servicenow');\n const url = `${proxyBase}${path}${queryParams ? `?${queryParams}` : ''}`;\n\n const { token } = await this.identityApi.getCredentials();\n const headers = {\n Authorization: `Bearer ${token}`,\n };\n\n const response = await this.fetchApi.fetch(url, { headers });\n if (!response.ok) {\n let errorBody;\n try {\n errorBody = await response.json();\n } catch (e) {\n throw new Error(\n `ServiceNow API request failed: ${response.status} - Could not parse error response.`,\n );\n }\n\n const errorMessage =\n errorBody?.error?.message ??\n `ServiceNow API request failed: ${response.status}`;\n throw new Error(errorMessage);\n }\n\n return (await response.json()) as { items: T; totalCount: number };\n }\n\n async getIncidents(\n queryParams: URLSearchParams,\n ): Promise<PaginatedIncidentsData> {\n const { items, totalCount } = await this.fetchFromServiceNow<\n IncidentPick[]\n >('/incidents', queryParams);\n\n const incidents = incidentsPickToIncidentsData(items);\n return { incidents, totalCount };\n }\n}\n\nexport function incidentsPickToIncidentsData(\n data: IncidentPick[],\n): IncidentsData[] {\n return data.map(item => ({\n sysId: item.sys_id,\n number: item.number,\n shortDescription: item.short_description,\n description: item.description,\n sysCreatedOn: item.sys_created_on,\n priority: item.priority,\n incidentState: item.incident_state,\n url: item.url,\n }));\n}\n"],"names":[],"mappings":";;AA4BO,MAAM,mBAAmB,YAAmC,CAAA;AAAA,EACjE,EAAI,EAAA;AACN,CAAC;AAEM,MAAM,uBAAwD,CAAA;AAAA,EACnE,WAAA,CACmB,YACA,EAAA,QAAA,EACA,WACjB,EAAA;AAHiB,IAAA,IAAA,CAAA,YAAA,GAAA,YAAA;AACA,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AACA,IAAA,IAAA,CAAA,WAAA,GAAA,WAAA;AAAA;AAChB,EAEH,MAAc,mBACZ,CAAA,IAAA,EACA,WAC2C,EAAA;AAC3C,IAAA,MAAM,SAAY,GAAA,MAAM,IAAK,CAAA,YAAA,CAAa,WAAW,YAAY,CAAA;AACjE,IAAM,MAAA,GAAA,GAAM,CAAG,EAAA,SAAS,CAAG,EAAA,IAAI,GAAG,WAAc,GAAA,CAAA,CAAA,EAAI,WAAW,CAAA,CAAA,GAAK,EAAE,CAAA,CAAA;AAEtE,IAAA,MAAM,EAAE,KAAM,EAAA,GAAI,MAAM,IAAA,CAAK,YAAY,cAAe,EAAA;AACxD,IAAA,MAAM,OAAU,GAAA;AAAA,MACd,aAAA,EAAe,UAAU,KAAK,CAAA;AAAA,KAChC;AAEA,IAAM,MAAA,QAAA,GAAW,MAAM,IAAK,CAAA,QAAA,CAAS,MAAM,GAAK,EAAA,EAAE,SAAS,CAAA;AAC3D,IAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,MAAI,IAAA,SAAA;AACJ,MAAI,IAAA;AACF,QAAY,SAAA,GAAA,MAAM,SAAS,IAAK,EAAA;AAAA,eACzB,CAAG,EAAA;AACV,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,+BAAA,EAAkC,SAAS,MAAM,CAAA,kCAAA;AAAA,SACnD;AAAA;AAGF,MAAA,MAAM,eACJ,SAAW,EAAA,KAAA,EAAO,OAClB,IAAA,CAAA,+BAAA,EAAkC,SAAS,MAAM,CAAA,CAAA;AACnD,MAAM,MAAA,IAAI,MAAM,YAAY,CAAA;AAAA;AAG9B,IAAQ,OAAA,MAAM,SAAS,IAAK,EAAA;AAAA;AAC9B,EAEA,MAAM,aACJ,WACiC,EAAA;AACjC,IAAM,MAAA,EAAE,OAAO,UAAW,EAAA,GAAI,MAAM,IAAK,CAAA,mBAAA,CAEvC,cAAc,WAAW,CAAA;AAE3B,IAAM,MAAA,SAAA,GAAY,6BAA6B,KAAK,CAAA;AACpD,IAAO,OAAA,EAAE,WAAW,UAAW,EAAA;AAAA;AAEnC;AAEO,SAAS,6BACd,IACiB,EAAA;AACjB,EAAO,OAAA,IAAA,CAAK,IAAI,CAAS,IAAA,MAAA;AAAA,IACvB,OAAO,IAAK,CAAA,MAAA;AAAA,IACZ,QAAQ,IAAK,CAAA,MAAA;AAAA,IACb,kBAAkB,IAAK,CAAA,iBAAA;AAAA,IACvB,aAAa,IAAK,CAAA,WAAA;AAAA,IAClB,cAAc,IAAK,CAAA,cAAA;AAAA,IACnB,UAAU,IAAK,CAAA,QAAA;AAAA,IACf,eAAe,IAAK,CAAA,cAAA;AAAA,IACpB,KAAK,IAAK,CAAA;AAAA,GACV,CAAA,CAAA;AACJ;;;;"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { MemoryRouter } from 'react-router-dom';
|
|
3
|
+
import { EntityServicenowContent } from './Servicenow/EntityServicenowContent.esm.js';
|
|
4
|
+
|
|
5
|
+
const Router = () => {
|
|
6
|
+
return /* @__PURE__ */ jsx(MemoryRouter, { children: /* @__PURE__ */ jsx(EntityServicenowContent, {}) });
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export { Router };
|
|
10
|
+
//# sourceMappingURL=Router.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Router.esm.js","sources":["../../src/components/Router.tsx"],"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 { MemoryRouter } from 'react-router-dom';\nimport { EntityServicenowContent } from './Servicenow';\n\n/**\n * separately export the router\n *\n * @public\n */\nexport const Router = () => {\n return (\n <MemoryRouter>\n <EntityServicenowContent />\n </MemoryRouter>\n );\n};\n"],"names":[],"mappings":";;;;AAuBO,MAAM,SAAS,MAAM;AAC1B,EAAA,uBACG,GAAA,CAAA,YAAA,EAAA,EACC,QAAC,kBAAA,GAAA,CAAA,uBAAA,EAAA,EAAwB,CAC3B,EAAA,CAAA;AAEJ;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
-
import { useState, useEffect } from 'react';
|
|
2
|
+
import { useState, useMemo, useEffect } from 'react';
|
|
3
3
|
import { useApi, identityApiRef } from '@backstage/core-plugin-api';
|
|
4
4
|
import { useEntity, CatalogFilterLayout } from '@backstage/plugin-catalog-react';
|
|
5
5
|
import { Table } from '@backstage/core-components';
|
|
@@ -9,9 +9,9 @@ import TableBody from '@mui/material/TableBody';
|
|
|
9
9
|
import TableRow from '@mui/material/TableRow';
|
|
10
10
|
import TableCell from '@mui/material/TableCell';
|
|
11
11
|
import TablePagination from '@mui/material/TablePagination';
|
|
12
|
-
import { SortingOrderEnum
|
|
12
|
+
import { SortingOrderEnum } from '@backstage-community/plugin-servicenow-common';
|
|
13
13
|
import { IncidentsFilter } from './IncidentsFilter.esm.js';
|
|
14
|
-
import {
|
|
14
|
+
import { useIncidentsListColumns } from './IncidentsListColumns.esm.js';
|
|
15
15
|
import { IncidentsTableBody } from './IncidentsTableBody.esm.js';
|
|
16
16
|
import { IncidentsTableHeader } from './IncidentsTableHeader.esm.js';
|
|
17
17
|
import { IncidentTableFieldEnum } from '../../types.esm.js';
|
|
@@ -22,10 +22,13 @@ import { useQueryArrayState } from '../../hooks/useQueryArrayState.esm.js';
|
|
|
22
22
|
import { serviceNowApiRef } from '../../api/ServiceNowBackendClient.esm.js';
|
|
23
23
|
import { useUserEmail } from '../../hooks/useUserEmail.esm.js';
|
|
24
24
|
import { useUpdateQueryParams } from '../../hooks/useQueryHelpers.esm.js';
|
|
25
|
+
import { useTranslation } from '../../hooks/useTranslation.esm.js';
|
|
25
26
|
|
|
26
27
|
const EntityServicenowContent = () => {
|
|
28
|
+
const { t } = useTranslation();
|
|
27
29
|
const { entity } = useEntity();
|
|
28
30
|
const serviceNowApi = useApi(serviceNowApiRef);
|
|
31
|
+
const incidentsListColumns = useIncidentsListColumns();
|
|
29
32
|
const [search, setSearch] = useQueryState("search", "");
|
|
30
33
|
const [input, setInput] = useState(search);
|
|
31
34
|
const debouncedInput = useDebouncedValue(input, 300);
|
|
@@ -44,7 +47,23 @@ const EntityServicenowContent = () => {
|
|
|
44
47
|
const [loading, setLoading] = useState(false);
|
|
45
48
|
const [error, setError] = useState(null);
|
|
46
49
|
const updateQueryParams = useUpdateQueryParams();
|
|
47
|
-
const
|
|
50
|
+
const servicenowAnnotations = useMemo(() => {
|
|
51
|
+
const annotations = entity.metadata.annotations;
|
|
52
|
+
const snAnnotations = {};
|
|
53
|
+
if (annotations) {
|
|
54
|
+
for (const [key, value] of Object.entries(annotations)) {
|
|
55
|
+
if (key.startsWith("servicenow.com/entity-id")) {
|
|
56
|
+
snAnnotations.entityId = value;
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (key.startsWith("servicenow.com/")) {
|
|
60
|
+
const field = key.substring("servicenow.com/".length);
|
|
61
|
+
snAnnotations[field] = value;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return snAnnotations;
|
|
66
|
+
}, [entity.metadata.annotations]);
|
|
48
67
|
const kind = entity.kind.toLocaleLowerCase("en-US");
|
|
49
68
|
const userEmail = useUserEmail(kind);
|
|
50
69
|
const identityApi = useApi(identityApiRef);
|
|
@@ -65,7 +84,7 @@ const EntityServicenowContent = () => {
|
|
|
65
84
|
async function fetchIncidents() {
|
|
66
85
|
setLoading(true);
|
|
67
86
|
setError(null);
|
|
68
|
-
if (!userEmail &&
|
|
87
|
+
if (!userEmail && Object.keys(servicenowAnnotations).length === 0) {
|
|
69
88
|
setIncidentsData([]);
|
|
70
89
|
setLoading(false);
|
|
71
90
|
return;
|
|
@@ -80,7 +99,7 @@ const EntityServicenowContent = () => {
|
|
|
80
99
|
priority: priority ?? void 0,
|
|
81
100
|
state: state ?? void 0,
|
|
82
101
|
userEmail,
|
|
83
|
-
|
|
102
|
+
...servicenowAnnotations
|
|
84
103
|
});
|
|
85
104
|
const { incidents, totalCount } = await serviceNowApi.getIncidents(
|
|
86
105
|
queryParams
|
|
@@ -102,7 +121,7 @@ const EntityServicenowContent = () => {
|
|
|
102
121
|
orderBy,
|
|
103
122
|
search,
|
|
104
123
|
serviceNowApi,
|
|
105
|
-
|
|
124
|
+
servicenowAnnotations,
|
|
106
125
|
priority,
|
|
107
126
|
state,
|
|
108
127
|
userEmail
|
|
@@ -134,14 +153,14 @@ const EntityServicenowContent = () => {
|
|
|
134
153
|
onRequestSort: handleRequestSort
|
|
135
154
|
}
|
|
136
155
|
);
|
|
137
|
-
const IncidentsTableBodyComponent = () => loading ? /* @__PURE__ */ jsx(TableBody, { children: /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan:
|
|
156
|
+
const IncidentsTableBodyComponent = () => loading ? /* @__PURE__ */ jsx(TableBody, { children: /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: incidentsListColumns.length, align: "center", children: /* @__PURE__ */ jsx(Box, { sx: { py: 3 }, children: /* @__PURE__ */ jsx(CircularProgress, {}) }) }) }) }) : /* @__PURE__ */ jsx(IncidentsTableBody, { rows: incidentsData });
|
|
138
157
|
const TablePaginationComponent = () => {
|
|
139
158
|
return /* @__PURE__ */ jsx(
|
|
140
159
|
TablePagination,
|
|
141
160
|
{
|
|
142
161
|
rowsPerPageOptions: [5, 10, 20, 50, 100].map((n) => ({
|
|
143
162
|
value: n,
|
|
144
|
-
label:
|
|
163
|
+
label: t("table.labelRowsSelect", { count: String(n) })
|
|
145
164
|
})),
|
|
146
165
|
component: "div",
|
|
147
166
|
sx: { mr: 1 },
|
|
@@ -158,17 +177,16 @@ const EntityServicenowContent = () => {
|
|
|
158
177
|
};
|
|
159
178
|
return /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(CatalogFilterLayout, { children: [
|
|
160
179
|
/* @__PURE__ */ jsx(CatalogFilterLayout.Filters, { children: /* @__PURE__ */ jsx(IncidentsFilter, {}) }),
|
|
161
|
-
/* @__PURE__ */ jsx(CatalogFilterLayout.Content, { children: error ? /* @__PURE__ */
|
|
162
|
-
"Error loading incidents: ",
|
|
163
|
-
error
|
|
164
|
-
] }) : /* @__PURE__ */ jsx(
|
|
180
|
+
/* @__PURE__ */ jsx(CatalogFilterLayout.Content, { children: error ? /* @__PURE__ */ jsx(Box, { sx: { padding: 2, color: "error.main" }, children: t("errors.loadingIncidents", { error }) }) : /* @__PURE__ */ jsx(
|
|
165
181
|
Table,
|
|
166
182
|
{
|
|
167
183
|
data: loading ? [] : incidentsData,
|
|
168
|
-
columns:
|
|
184
|
+
columns: incidentsListColumns,
|
|
169
185
|
onSearchChange: handleSearch,
|
|
170
|
-
title: count === 0 ? "
|
|
171
|
-
localization: {
|
|
186
|
+
title: count === 0 ? t("page.title") : t("page.titleWithCount", { count: String(count) }),
|
|
187
|
+
localization: {
|
|
188
|
+
toolbar: { searchPlaceholder: t("table.searchPlaceholder") }
|
|
189
|
+
},
|
|
172
190
|
components: {
|
|
173
191
|
Header: IncidentsTableHeaderComponent,
|
|
174
192
|
Body: IncidentsTableBodyComponent,
|
|
@@ -183,7 +201,7 @@ const EntityServicenowContent = () => {
|
|
|
183
201
|
display: "flex",
|
|
184
202
|
justifyContent: "center"
|
|
185
203
|
},
|
|
186
|
-
children: "
|
|
204
|
+
children: t("table.emptyContent")
|
|
187
205
|
}
|
|
188
206
|
),
|
|
189
207
|
isLoading: loading
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityServicenowContent.esm.js","sources":["../../../src/components/Servicenow/EntityServicenowContent.tsx"],"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 */\n\nimport { useEffect, useState, MouseEvent, ChangeEvent } from 'react';\nimport { identityApiRef, useApi } from '@backstage/core-plugin-api';\n\nimport {\n CatalogFilterLayout,\n useEntity,\n} from '@backstage/plugin-catalog-react';\nimport { Table } from '@backstage/core-components';\n\nimport Box from '@mui/material/Box';\nimport CircularProgress from '@mui/material/CircularProgress';\nimport TableBody from '@mui/material/TableBody';\nimport TableRow from '@mui/material/TableRow';\nimport TableCell from '@mui/material/TableCell';\nimport TablePagination from '@mui/material/TablePagination';\n\nimport {\n Order,\n SortingOrderEnum,\n ServiceAnnotationFieldName,\n} from '@backstage-community/plugin-servicenow-common';\n\nimport { IncidentsFilter } from './IncidentsFilter';\nimport { IncidentsListColumns } from './IncidentsListColumns';\nimport { IncidentsTableBody } from './IncidentsTableBody';\nimport { IncidentsTableHeader } from './IncidentsTableHeader';\nimport {\n IncidentTableFieldEnum,\n type IncidentsData,\n type IncidentTableField,\n} from '../../types';\nimport { buildIncidentQueryParams } from '../../utils/queryParamsUtils';\nimport { useDebouncedValue } from '../../hooks/useDebouncedValue';\nimport { useQueryState } from '../../hooks/useQueryState';\nimport { useQueryArrayState } from '../../hooks/useQueryArrayState';\nimport { serviceNowApiRef } from '../../api/ServiceNowBackendClient';\nimport useUserEmail from '../../hooks/useUserEmail';\nimport { useUpdateQueryParams } from '../../hooks/useQueryHelpers';\n\nexport const EntityServicenowContent = () => {\n const { entity } = useEntity();\n const serviceNowApi = useApi(serviceNowApiRef);\n\n const [search, setSearch] = useQueryState<string>('search', '');\n const [input, setInput] = useState(search);\n const debouncedInput = useDebouncedValue(input, 300);\n\n const [order, setOrder] = useQueryState<Order>('order', SortingOrderEnum.Asc);\n const [orderBy, setOrderBy] = useQueryState<IncidentTableField>(\n 'orderBy',\n IncidentTableFieldEnum.Number,\n );\n\n const [rowsPerPage] = useQueryState<number>('limit', 5);\n const [offset, setOffset] = useQueryState<number>('offset', 0);\n const [state] = useQueryArrayState('state', []);\n const [priority] = useQueryArrayState('priority', []);\n\n const pageNumber = Math.floor(offset / rowsPerPage);\n\n const [count, setCount] = useState<number>(0);\n const [incidentsData, setIncidentsData] = useState<IncidentsData[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const updateQueryParams = useUpdateQueryParams();\n\n const entityId = entity.metadata.annotations?.[ServiceAnnotationFieldName];\n\n const kind = entity.kind.toLocaleLowerCase('en-US');\n const userEmail = useUserEmail(kind);\n\n const identityApi = useApi(identityApiRef);\n\n useEffect(() => {\n identityApi.getBackstageIdentity().then(identity => {\n if (identity.userEntityRef) {\n localStorage.setItem('userEntityRef', identity.userEntityRef);\n }\n });\n }, [identityApi]);\n\n useEffect(() => {\n if (debouncedInput !== search) {\n setSearch(debouncedInput);\n setOffset(0);\n }\n }, [debouncedInput, search, setSearch, setOffset]);\n\n useEffect(() => {\n async function fetchIncidents() {\n setLoading(true);\n setError(null);\n\n if (!userEmail && !entityId) {\n setIncidentsData([]);\n setLoading(false);\n return;\n }\n\n try {\n const queryParams = buildIncidentQueryParams({\n limit: rowsPerPage,\n offset,\n order,\n orderBy,\n search: search,\n priority: priority ?? undefined,\n state: state ?? undefined,\n userEmail,\n entityId,\n });\n\n const { incidents, totalCount } = await serviceNowApi.getIncidents(\n queryParams,\n );\n setIncidentsData(incidents);\n setCount(totalCount);\n } catch (e) {\n setError((e as Error).message);\n setIncidentsData([]);\n } finally {\n setLoading(false);\n }\n }\n\n fetchIncidents();\n }, [\n rowsPerPage,\n offset,\n order,\n orderBy,\n search,\n serviceNowApi,\n entityId,\n priority,\n state,\n userEmail,\n ]);\n\n const handleRowsPerPageChange = (event: ChangeEvent<HTMLInputElement>) => {\n const newLimit = parseInt(event.target.value, 10);\n updateQueryParams({\n limit: String(newLimit),\n offset: '0',\n });\n };\n\n const handlePageChange = (_event: unknown, page: number) => {\n setOffset(page * rowsPerPage);\n };\n\n const handleRequestSort = (\n _event: MouseEvent<unknown>,\n property: IncidentTableField,\n ) => {\n const isAsc = orderBy === property && order === SortingOrderEnum.Asc;\n setOrder(isAsc ? SortingOrderEnum.Desc : SortingOrderEnum.Asc);\n setOrderBy(property);\n setOffset(0);\n };\n\n const handleSearch = (str: string) => {\n setInput(str);\n };\n\n const IncidentsTableHeaderComponent = () => (\n <IncidentsTableHeader\n order={order}\n orderBy={orderBy}\n onRequestSort={handleRequestSort}\n />\n );\n\n const IncidentsTableBodyComponent = () =>\n loading ? (\n <TableBody>\n <TableRow>\n <TableCell colSpan={IncidentsListColumns.length} align=\"center\">\n <Box sx={{ py: 3 }}>\n <CircularProgress />\n </Box>\n </TableCell>\n </TableRow>\n </TableBody>\n ) : (\n <IncidentsTableBody rows={incidentsData} />\n );\n\n const TablePaginationComponent = () => {\n return (\n <TablePagination\n rowsPerPageOptions={[5, 10, 20, 50, 100].map(n => ({\n value: n,\n label: `${n} rows`,\n }))}\n component=\"div\"\n sx={{ mr: 1 }}\n count={count ?? 0}\n rowsPerPage={rowsPerPage}\n page={pageNumber}\n onPageChange={handlePageChange}\n onRowsPerPageChange={handleRowsPerPageChange}\n labelRowsPerPage={null}\n showFirstButton\n showLastButton\n />\n );\n };\n\n return (\n <Box>\n <CatalogFilterLayout>\n <CatalogFilterLayout.Filters>\n <IncidentsFilter />\n </CatalogFilterLayout.Filters>\n <CatalogFilterLayout.Content>\n {error ? (\n <Box sx={{ padding: 2, color: 'error.main' }}>\n Error loading incidents: {error}\n </Box>\n ) : (\n <Table\n data={loading ? [] : incidentsData}\n columns={IncidentsListColumns}\n onSearchChange={handleSearch}\n title={\n count === 0\n ? 'ServiceNow tickets'\n : `ServiceNow tickets (${count})`\n }\n localization={{ toolbar: { searchPlaceholder: 'Search' } }}\n components={{\n Header: IncidentsTableHeaderComponent,\n Body: IncidentsTableBodyComponent,\n Pagination: TablePaginationComponent,\n }}\n emptyContent={\n loading ? null : (\n <Box\n data-testid=\"no-incidents-found\"\n sx={{\n padding: 2,\n display: 'flex',\n justifyContent: 'center',\n }}\n >\n No records found\n </Box>\n )\n }\n isLoading={loading}\n />\n )}\n </CatalogFilterLayout.Content>\n </CatalogFilterLayout>\n </Box>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EntityServicenowContent.esm.js","sources":["../../../src/components/Servicenow/EntityServicenowContent.tsx"],"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 */\n\nimport { useEffect, useState, MouseEvent, ChangeEvent, useMemo } from 'react';\nimport { identityApiRef, useApi } from '@backstage/core-plugin-api';\n\nimport {\n CatalogFilterLayout,\n useEntity,\n} from '@backstage/plugin-catalog-react';\nimport { Table } from '@backstage/core-components';\n\nimport Box from '@mui/material/Box';\nimport CircularProgress from '@mui/material/CircularProgress';\nimport TableBody from '@mui/material/TableBody';\nimport TableRow from '@mui/material/TableRow';\nimport TableCell from '@mui/material/TableCell';\nimport TablePagination from '@mui/material/TablePagination';\n\nimport {\n Order,\n SortingOrderEnum,\n} from '@backstage-community/plugin-servicenow-common';\n\nimport { IncidentsFilter } from './IncidentsFilter';\nimport { useIncidentsListColumns } from './IncidentsListColumns';\nimport { IncidentsTableBody } from './IncidentsTableBody';\nimport { IncidentsTableHeader } from './IncidentsTableHeader';\nimport {\n IncidentTableFieldEnum,\n type IncidentsData,\n type IncidentTableField,\n} from '../../types';\nimport { buildIncidentQueryParams } from '../../utils/queryParamsUtils';\nimport { useDebouncedValue } from '../../hooks/useDebouncedValue';\nimport { useQueryState } from '../../hooks/useQueryState';\nimport { useQueryArrayState } from '../../hooks/useQueryArrayState';\nimport { serviceNowApiRef } from '../../api/ServiceNowBackendClient';\nimport useUserEmail from '../../hooks/useUserEmail';\nimport { useUpdateQueryParams } from '../../hooks/useQueryHelpers';\nimport { useTranslation } from '../../hooks/useTranslation';\n\nexport const EntityServicenowContent = () => {\n const { t } = useTranslation();\n const { entity } = useEntity();\n const serviceNowApi = useApi(serviceNowApiRef);\n const incidentsListColumns = useIncidentsListColumns();\n\n const [search, setSearch] = useQueryState<string>('search', '');\n const [input, setInput] = useState(search);\n const debouncedInput = useDebouncedValue(input, 300);\n\n const [order, setOrder] = useQueryState<Order>('order', SortingOrderEnum.Asc);\n const [orderBy, setOrderBy] = useQueryState<IncidentTableField>(\n 'orderBy',\n IncidentTableFieldEnum.Number,\n );\n\n const [rowsPerPage] = useQueryState<number>('limit', 5);\n const [offset, setOffset] = useQueryState<number>('offset', 0);\n const [state] = useQueryArrayState('state', []);\n const [priority] = useQueryArrayState('priority', []);\n\n const pageNumber = Math.floor(offset / rowsPerPage);\n\n const [count, setCount] = useState<number>(0);\n const [incidentsData, setIncidentsData] = useState<IncidentsData[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const updateQueryParams = useUpdateQueryParams();\n\n const servicenowAnnotations = useMemo(() => {\n const annotations = entity.metadata.annotations;\n const snAnnotations: Record<string, string> = {};\n if (annotations) {\n for (const [key, value] of Object.entries(annotations)) {\n if (key.startsWith('servicenow.com/entity-id')) {\n snAnnotations.entityId = value;\n continue;\n }\n if (key.startsWith('servicenow.com/')) {\n const field = key.substring('servicenow.com/'.length);\n snAnnotations[field] = value;\n }\n }\n }\n return snAnnotations;\n }, [entity.metadata.annotations]);\n\n const kind = entity.kind.toLocaleLowerCase('en-US');\n const userEmail = useUserEmail(kind);\n\n const identityApi = useApi(identityApiRef);\n\n useEffect(() => {\n identityApi.getBackstageIdentity().then(identity => {\n if (identity.userEntityRef) {\n localStorage.setItem('userEntityRef', identity.userEntityRef);\n }\n });\n }, [identityApi]);\n\n useEffect(() => {\n if (debouncedInput !== search) {\n setSearch(debouncedInput);\n setOffset(0);\n }\n }, [debouncedInput, search, setSearch, setOffset]);\n\n useEffect(() => {\n async function fetchIncidents() {\n setLoading(true);\n setError(null);\n\n if (!userEmail && Object.keys(servicenowAnnotations).length === 0) {\n setIncidentsData([]);\n setLoading(false);\n return;\n }\n\n try {\n const queryParams = buildIncidentQueryParams({\n limit: rowsPerPage,\n offset,\n order,\n orderBy,\n search: search,\n priority: priority ?? undefined,\n state: state ?? undefined,\n userEmail,\n ...servicenowAnnotations,\n });\n\n const { incidents, totalCount } = await serviceNowApi.getIncidents(\n queryParams,\n );\n setIncidentsData(incidents);\n setCount(totalCount);\n } catch (e) {\n setError((e as Error).message);\n setIncidentsData([]);\n } finally {\n setLoading(false);\n }\n }\n\n fetchIncidents();\n }, [\n rowsPerPage,\n offset,\n order,\n orderBy,\n search,\n serviceNowApi,\n servicenowAnnotations,\n priority,\n state,\n userEmail,\n ]);\n\n const handleRowsPerPageChange = (event: ChangeEvent<HTMLInputElement>) => {\n const newLimit = parseInt(event.target.value, 10);\n updateQueryParams({\n limit: String(newLimit),\n offset: '0',\n });\n };\n\n const handlePageChange = (_event: unknown, page: number) => {\n setOffset(page * rowsPerPage);\n };\n\n const handleRequestSort = (\n _event: MouseEvent<unknown>,\n property: IncidentTableField,\n ) => {\n const isAsc = orderBy === property && order === SortingOrderEnum.Asc;\n setOrder(isAsc ? SortingOrderEnum.Desc : SortingOrderEnum.Asc);\n setOrderBy(property);\n setOffset(0);\n };\n\n const handleSearch = (str: string) => {\n setInput(str);\n };\n\n const IncidentsTableHeaderComponent = () => (\n <IncidentsTableHeader\n order={order}\n orderBy={orderBy}\n onRequestSort={handleRequestSort}\n />\n );\n\n const IncidentsTableBodyComponent = () =>\n loading ? (\n <TableBody>\n <TableRow>\n <TableCell colSpan={incidentsListColumns.length} align=\"center\">\n <Box sx={{ py: 3 }}>\n <CircularProgress />\n </Box>\n </TableCell>\n </TableRow>\n </TableBody>\n ) : (\n <IncidentsTableBody rows={incidentsData} />\n );\n\n const TablePaginationComponent = () => {\n return (\n <TablePagination\n rowsPerPageOptions={[5, 10, 20, 50, 100].map(n => ({\n value: n,\n label: t('table.labelRowsSelect', { count: String(n) }),\n }))}\n component=\"div\"\n sx={{ mr: 1 }}\n count={count ?? 0}\n rowsPerPage={rowsPerPage}\n page={pageNumber}\n onPageChange={handlePageChange}\n onRowsPerPageChange={handleRowsPerPageChange}\n labelRowsPerPage={null}\n showFirstButton\n showLastButton\n />\n );\n };\n\n return (\n <Box>\n <CatalogFilterLayout>\n <CatalogFilterLayout.Filters>\n <IncidentsFilter />\n </CatalogFilterLayout.Filters>\n <CatalogFilterLayout.Content>\n {error ? (\n <Box sx={{ padding: 2, color: 'error.main' }}>\n {t('errors.loadingIncidents', { error })}\n </Box>\n ) : (\n <Table\n data={loading ? [] : incidentsData}\n columns={incidentsListColumns}\n onSearchChange={handleSearch}\n title={\n count === 0\n ? t('page.title')\n : t('page.titleWithCount', { count: String(count) })\n }\n localization={{\n toolbar: { searchPlaceholder: t('table.searchPlaceholder') },\n }}\n components={{\n Header: IncidentsTableHeaderComponent,\n Body: IncidentsTableBodyComponent,\n Pagination: TablePaginationComponent,\n }}\n emptyContent={\n loading ? null : (\n <Box\n data-testid=\"no-incidents-found\"\n sx={{\n padding: 2,\n display: 'flex',\n justifyContent: 'center',\n }}\n >\n {t('table.emptyContent')}\n </Box>\n )\n }\n isLoading={loading}\n />\n )}\n </CatalogFilterLayout.Content>\n </CatalogFilterLayout>\n </Box>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -2,14 +2,18 @@ import { jsxs, jsx } from 'react/jsx-runtime';
|
|
|
2
2
|
import { useMemo, useCallback } from 'react';
|
|
3
3
|
import Box from '@mui/material/Box';
|
|
4
4
|
import { IncidentEnumFilter } from '../shared-components/IncidentEnumFilter.esm.js';
|
|
5
|
-
import {
|
|
5
|
+
import { useIncidentStateMap, usePriorityMap } from '../../utils/incidentUtils.esm.js';
|
|
6
6
|
import { useQueryArrayFilter } from '../../hooks/useQueryArrayFilter.esm.js';
|
|
7
7
|
import { useUpdateQueryParams } from '../../hooks/useQueryHelpers.esm.js';
|
|
8
|
+
import { useTranslation } from '../../hooks/useTranslation.esm.js';
|
|
8
9
|
|
|
9
10
|
const IncidentsFilter = () => {
|
|
11
|
+
const { t } = useTranslation();
|
|
10
12
|
const stateFilter = useQueryArrayFilter("state");
|
|
11
13
|
const priorityFilter = useQueryArrayFilter("priority");
|
|
12
14
|
const updateQueryParams = useUpdateQueryParams();
|
|
15
|
+
const incidentStateMap = useIncidentStateMap();
|
|
16
|
+
const priorityMap = usePriorityMap();
|
|
13
17
|
const stateValue = useMemo(() => stateFilter.current, [stateFilter]);
|
|
14
18
|
const priorityValue = useMemo(() => priorityFilter.current, [priorityFilter]);
|
|
15
19
|
const handleStateChange = useCallback(
|
|
@@ -43,9 +47,9 @@ const IncidentsFilter = () => {
|
|
|
43
47
|
/* @__PURE__ */ jsx(
|
|
44
48
|
IncidentEnumFilter,
|
|
45
49
|
{
|
|
46
|
-
label: "
|
|
50
|
+
label: t("filter.state"),
|
|
47
51
|
filterKey: "state",
|
|
48
|
-
dataMap:
|
|
52
|
+
dataMap: incidentStateMap,
|
|
49
53
|
value: stateValue,
|
|
50
54
|
onChange: handleStateChange
|
|
51
55
|
}
|
|
@@ -53,9 +57,9 @@ const IncidentsFilter = () => {
|
|
|
53
57
|
/* @__PURE__ */ jsx(
|
|
54
58
|
IncidentEnumFilter,
|
|
55
59
|
{
|
|
56
|
-
label: "
|
|
60
|
+
label: t("filter.priority"),
|
|
57
61
|
filterKey: "priority",
|
|
58
|
-
dataMap:
|
|
62
|
+
dataMap: priorityMap,
|
|
59
63
|
value: priorityValue,
|
|
60
64
|
onChange: handlePriorityChange
|
|
61
65
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IncidentsFilter.esm.js","sources":["../../../src/components/Servicenow/IncidentsFilter.tsx"],"sourcesContent":["/*\n * Copyright 2024 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 { useMemo, useCallback } from 'react';\n\nimport { SelectItem } from '@backstage/core-components';\n\nimport Box from '@mui/material/Box';\n\nimport { IncidentEnumFilter } from '../shared-components/IncidentEnumFilter';\nimport {
|
|
1
|
+
{"version":3,"file":"IncidentsFilter.esm.js","sources":["../../../src/components/Servicenow/IncidentsFilter.tsx"],"sourcesContent":["/*\n * Copyright 2024 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 { useMemo, useCallback } from 'react';\n\nimport { SelectItem } from '@backstage/core-components';\n\nimport Box from '@mui/material/Box';\n\nimport { IncidentEnumFilter } from '../shared-components/IncidentEnumFilter';\nimport { useIncidentStateMap, usePriorityMap } from '../../utils/incidentUtils';\nimport { useQueryArrayFilter } from '../../hooks/useQueryArrayFilter';\nimport { useUpdateQueryParams } from '../../hooks/useQueryHelpers';\nimport { useTranslation } from '../../hooks/useTranslation';\n\nexport const IncidentsFilter = () => {\n const { t } = useTranslation();\n const stateFilter = useQueryArrayFilter('state');\n const priorityFilter = useQueryArrayFilter('priority');\n const updateQueryParams = useUpdateQueryParams();\n const incidentStateMap = useIncidentStateMap();\n const priorityMap = usePriorityMap();\n\n const stateValue = useMemo(() => stateFilter.current, [stateFilter]);\n const priorityValue = useMemo(() => priorityFilter.current, [priorityFilter]);\n\n const handleStateChange = useCallback(\n (_e: any, value: SelectItem[]) => {\n updateQueryParams({\n state: value.map(v => v.value).join(','),\n offset: '0',\n });\n },\n [updateQueryParams],\n );\n\n const handlePriorityChange = useCallback(\n (_e: any, value: SelectItem[]) => {\n updateQueryParams({\n priority: value.map(v => v.value).join(','),\n offset: '0',\n });\n },\n [updateQueryParams],\n );\n\n return (\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'column',\n gap: 2,\n minWidth: { xs: 200, lg: 'auto' },\n }}\n >\n <IncidentEnumFilter\n label={t('filter.state')}\n filterKey=\"state\"\n dataMap={incidentStateMap}\n value={stateValue}\n onChange={handleStateChange}\n />\n <IncidentEnumFilter\n label={t('filter.priority')}\n filterKey=\"priority\"\n dataMap={priorityMap}\n value={priorityValue}\n onChange={handlePriorityChange}\n />\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;AA4BO,MAAM,kBAAkB,MAAM;AACnC,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,cAAe,EAAA;AAC7B,EAAM,MAAA,WAAA,GAAc,oBAAoB,OAAO,CAAA;AAC/C,EAAM,MAAA,cAAA,GAAiB,oBAAoB,UAAU,CAAA;AACrD,EAAA,MAAM,oBAAoB,oBAAqB,EAAA;AAC/C,EAAA,MAAM,mBAAmB,mBAAoB,EAAA;AAC7C,EAAA,MAAM,cAAc,cAAe,EAAA;AAEnC,EAAA,MAAM,aAAa,OAAQ,CAAA,MAAM,YAAY,OAAS,EAAA,CAAC,WAAW,CAAC,CAAA;AACnE,EAAA,MAAM,gBAAgB,OAAQ,CAAA,MAAM,eAAe,OAAS,EAAA,CAAC,cAAc,CAAC,CAAA;AAE5E,EAAA,MAAM,iBAAoB,GAAA,WAAA;AAAA,IACxB,CAAC,IAAS,KAAwB,KAAA;AAChC,MAAkB,iBAAA,CAAA;AAAA,QAChB,KAAA,EAAO,MAAM,GAAI,CAAA,CAAA,CAAA,KAAK,EAAE,KAAK,CAAA,CAAE,KAAK,GAAG,CAAA;AAAA,QACvC,MAAQ,EAAA;AAAA,OACT,CAAA;AAAA,KACH;AAAA,IACA,CAAC,iBAAiB;AAAA,GACpB;AAEA,EAAA,MAAM,oBAAuB,GAAA,WAAA;AAAA,IAC3B,CAAC,IAAS,KAAwB,KAAA;AAChC,MAAkB,iBAAA,CAAA;AAAA,QAChB,QAAA,EAAU,MAAM,GAAI,CAAA,CAAA,CAAA,KAAK,EAAE,KAAK,CAAA,CAAE,KAAK,GAAG,CAAA;AAAA,QAC1C,MAAQ,EAAA;AAAA,OACT,CAAA;AAAA,KACH;AAAA,IACA,CAAC,iBAAiB;AAAA,GACpB;AAEA,EACE,uBAAA,IAAA;AAAA,IAAC,GAAA;AAAA,IAAA;AAAA,MACC,EAAI,EAAA;AAAA,QACF,OAAS,EAAA,MAAA;AAAA,QACT,aAAe,EAAA,QAAA;AAAA,QACf,GAAK,EAAA,CAAA;AAAA,QACL,QAAU,EAAA,EAAE,EAAI,EAAA,GAAA,EAAK,IAAI,MAAO;AAAA,OAClC;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAA,GAAA;AAAA,UAAC,kBAAA;AAAA,UAAA;AAAA,YACC,KAAA,EAAO,EAAE,cAAc,CAAA;AAAA,YACvB,SAAU,EAAA,OAAA;AAAA,YACV,OAAS,EAAA,gBAAA;AAAA,YACT,KAAO,EAAA,UAAA;AAAA,YACP,QAAU,EAAA;AAAA;AAAA,SACZ;AAAA,wBACA,GAAA;AAAA,UAAC,kBAAA;AAAA,UAAA;AAAA,YACC,KAAA,EAAO,EAAE,iBAAiB,CAAA;AAAA,YAC1B,SAAU,EAAA,UAAA;AAAA,YACV,OAAS,EAAA,WAAA;AAAA,YACT,KAAO,EAAA,aAAA;AAAA,YACP,QAAU,EAAA;AAAA;AAAA;AACZ;AAAA;AAAA,GACF;AAEJ;;;;"}
|
|
@@ -1,43 +1,47 @@
|
|
|
1
1
|
import { IncidentTableFieldEnum } from '../../types.esm.js';
|
|
2
|
+
import { useTranslation } from '../../hooks/useTranslation.esm.js';
|
|
2
3
|
|
|
3
|
-
const
|
|
4
|
-
{
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
4
|
+
const useIncidentsListColumns = () => {
|
|
5
|
+
const { t } = useTranslation();
|
|
6
|
+
return [
|
|
7
|
+
{
|
|
8
|
+
id: "incidentNumber",
|
|
9
|
+
title: t("table.columns.incidentNumber"),
|
|
10
|
+
field: IncidentTableFieldEnum.Number,
|
|
11
|
+
type: "string"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
id: "description",
|
|
15
|
+
title: t("table.columns.description"),
|
|
16
|
+
field: IncidentTableFieldEnum.ShortDescription,
|
|
17
|
+
type: "string"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
id: "created",
|
|
21
|
+
title: t("table.columns.created"),
|
|
22
|
+
field: IncidentTableFieldEnum.Created,
|
|
23
|
+
type: "string"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
id: "priority",
|
|
27
|
+
title: t("table.columns.priority"),
|
|
28
|
+
field: IncidentTableFieldEnum.Priority,
|
|
29
|
+
type: "numeric"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: "state",
|
|
33
|
+
title: t("table.columns.state"),
|
|
34
|
+
field: IncidentTableFieldEnum.IncidentState,
|
|
35
|
+
type: "datetime"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: "actions",
|
|
39
|
+
title: t("table.columns.actions"),
|
|
40
|
+
sorting: false,
|
|
41
|
+
type: "string"
|
|
42
|
+
}
|
|
43
|
+
];
|
|
44
|
+
};
|
|
41
45
|
|
|
42
|
-
export {
|
|
46
|
+
export { useIncidentsListColumns };
|
|
43
47
|
//# sourceMappingURL=IncidentsListColumns.esm.js.map
|