@backstage-community/plugin-servicenow 1.5.0 → 1.5.1

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.
Files changed (39) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/alpha/plugin.esm.js +1 -0
  3. package/dist/alpha/plugin.esm.js.map +1 -1
  4. package/dist/alpha.d.ts +95 -1
  5. package/dist/alpha.esm.js +3 -1
  6. package/dist/alpha.esm.js.map +1 -1
  7. package/dist/components/Servicenow/EntityServicenowContent.esm.js +13 -11
  8. package/dist/components/Servicenow/EntityServicenowContent.esm.js.map +1 -1
  9. package/dist/components/Servicenow/IncidentsFilter.esm.js +9 -5
  10. package/dist/components/Servicenow/IncidentsFilter.esm.js.map +1 -1
  11. package/dist/components/Servicenow/IncidentsListColumns.esm.js +43 -39
  12. package/dist/components/Servicenow/IncidentsListColumns.esm.js.map +1 -1
  13. package/dist/components/Servicenow/IncidentsTableBody.esm.js +6 -3
  14. package/dist/components/Servicenow/IncidentsTableBody.esm.js.map +1 -1
  15. package/dist/components/Servicenow/IncidentsTableHeader.esm.js +3 -2
  16. package/dist/components/Servicenow/IncidentsTableHeader.esm.js.map +1 -1
  17. package/dist/components/Servicenow/IncidentsTableRow.esm.js +8 -4
  18. package/dist/components/Servicenow/IncidentsTableRow.esm.js.map +1 -1
  19. package/dist/components/shared-components/IncidentEnumFilter.esm.js +2 -3
  20. package/dist/components/shared-components/IncidentEnumFilter.esm.js.map +1 -1
  21. package/dist/hooks/useTranslation.esm.js +13 -0
  22. package/dist/hooks/useTranslation.esm.js.map +1 -0
  23. package/dist/translations/de.esm.js +37 -0
  24. package/dist/translations/de.esm.js.map +1 -0
  25. package/dist/translations/es.esm.js +37 -0
  26. package/dist/translations/es.esm.js.map +1 -0
  27. package/dist/translations/fr.esm.js +37 -0
  28. package/dist/translations/fr.esm.js.map +1 -0
  29. package/dist/translations/index.esm.js +16 -0
  30. package/dist/translations/index.esm.js.map +1 -0
  31. package/dist/translations/it.esm.js +37 -0
  32. package/dist/translations/it.esm.js.map +1 -0
  33. package/dist/translations/ja.esm.js +37 -0
  34. package/dist/translations/ja.esm.js.map +1 -0
  35. package/dist/translations/ref.esm.js +53 -0
  36. package/dist/translations/ref.esm.js.map +1 -0
  37. package/dist/utils/incidentUtils.esm.js +75 -3
  38. package/dist/utils/incidentUtils.esm.js.map +1 -1
  39. package/package.json +3 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @backstage-community/plugin-servicenow
2
2
 
3
+ ## 1.5.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 40b4d6c: - Added internationalization (i18n) support with translations for German, French, Spanish, Italian, and Japanese
8
+
3
9
  ## 1.5.0
4
10
 
5
11
  ### Minor Changes
@@ -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":";;;;;;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;;;;"}
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
@@ -1 +1 @@
1
- {"version":3,"file":"alpha.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
1
+ {"version":3,"file":"alpha.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
@@ -11,7 +11,7 @@ import TableCell from '@mui/material/TableCell';
11
11
  import TablePagination from '@mui/material/TablePagination';
12
12
  import { SortingOrderEnum, ServiceAnnotationFieldName } from '@backstage-community/plugin-servicenow-common';
13
13
  import { IncidentsFilter } from './IncidentsFilter.esm.js';
14
- import { IncidentsListColumns } from './IncidentsListColumns.esm.js';
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);
@@ -134,14 +137,14 @@ const EntityServicenowContent = () => {
134
137
  onRequestSort: handleRequestSort
135
138
  }
136
139
  );
137
- 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 });
140
+ 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
141
  const TablePaginationComponent = () => {
139
142
  return /* @__PURE__ */ jsx(
140
143
  TablePagination,
141
144
  {
142
145
  rowsPerPageOptions: [5, 10, 20, 50, 100].map((n) => ({
143
146
  value: n,
144
- label: `${n} rows`
147
+ label: t("table.labelRowsSelect", { count: String(n) })
145
148
  })),
146
149
  component: "div",
147
150
  sx: { mr: 1 },
@@ -158,17 +161,16 @@ const EntityServicenowContent = () => {
158
161
  };
159
162
  return /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(CatalogFilterLayout, { children: [
160
163
  /* @__PURE__ */ jsx(CatalogFilterLayout.Filters, { children: /* @__PURE__ */ jsx(IncidentsFilter, {}) }),
161
- /* @__PURE__ */ jsx(CatalogFilterLayout.Content, { children: error ? /* @__PURE__ */ jsxs(Box, { sx: { padding: 2, color: "error.main" }, children: [
162
- "Error loading incidents: ",
163
- error
164
- ] }) : /* @__PURE__ */ jsx(
164
+ /* @__PURE__ */ jsx(CatalogFilterLayout.Content, { children: error ? /* @__PURE__ */ jsx(Box, { sx: { padding: 2, color: "error.main" }, children: t("errors.loadingIncidents", { error }) }) : /* @__PURE__ */ jsx(
165
165
  Table,
166
166
  {
167
167
  data: loading ? [] : incidentsData,
168
- columns: IncidentsListColumns,
168
+ columns: incidentsListColumns,
169
169
  onSearchChange: handleSearch,
170
- title: count === 0 ? "ServiceNow tickets" : `ServiceNow tickets (${count})`,
171
- localization: { toolbar: { searchPlaceholder: "Search" } },
170
+ title: count === 0 ? t("page.title") : t("page.titleWithCount", { count: String(count) }),
171
+ localization: {
172
+ toolbar: { searchPlaceholder: t("table.searchPlaceholder") }
173
+ },
172
174
  components: {
173
175
  Header: IncidentsTableHeaderComponent,
174
176
  Body: IncidentsTableBodyComponent,
@@ -183,7 +185,7 @@ const EntityServicenowContent = () => {
183
185
  display: "flex",
184
186
  justifyContent: "center"
185
187
  },
186
- children: "No records found"
188
+ children: t("table.emptyContent")
187
189
  }
188
190
  ),
189
191
  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 } 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 { 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 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: 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 { INCIDENT_STATE_MAP, PRIORITY_MAP } from '../../utils/incidentUtils.esm.js';
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: "State",
50
+ label: t("filter.state"),
47
51
  filterKey: "state",
48
- dataMap: INCIDENT_STATE_MAP,
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: "Priority",
60
+ label: t("filter.priority"),
57
61
  filterKey: "priority",
58
- dataMap: PRIORITY_MAP,
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 { INCIDENT_STATE_MAP, PRIORITY_MAP } from '../../utils/incidentUtils';\nimport { useQueryArrayFilter } from '../../hooks/useQueryArrayFilter';\nimport { useUpdateQueryParams } from '../../hooks/useQueryHelpers';\n\nexport const IncidentsFilter = () => {\n const stateFilter = useQueryArrayFilter('state');\n const priorityFilter = useQueryArrayFilter('priority');\n const updateQueryParams = useUpdateQueryParams();\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=\"State\"\n filterKey=\"state\"\n dataMap={INCIDENT_STATE_MAP}\n value={stateValue}\n onChange={handleStateChange}\n />\n <IncidentEnumFilter\n label=\"Priority\"\n filterKey=\"priority\"\n dataMap={PRIORITY_MAP}\n value={priorityValue}\n onChange={handlePriorityChange}\n />\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;;;;AA2BO,MAAM,kBAAkB,MAAM;AACnC,EAAM,MAAA,WAAA,GAAc,oBAAoB,OAAO,CAAA;AAC/C,EAAM,MAAA,cAAA,GAAiB,oBAAoB,UAAU,CAAA;AACrD,EAAA,MAAM,oBAAoB,oBAAqB,EAAA;AAE/C,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,KAAM,EAAA,OAAA;AAAA,YACN,SAAU,EAAA,OAAA;AAAA,YACV,OAAS,EAAA,kBAAA;AAAA,YACT,KAAO,EAAA,UAAA;AAAA,YACP,QAAU,EAAA;AAAA;AAAA,SACZ;AAAA,wBACA,GAAA;AAAA,UAAC,kBAAA;AAAA,UAAA;AAAA,YACC,KAAM,EAAA,UAAA;AAAA,YACN,SAAU,EAAA,UAAA;AAAA,YACV,OAAS,EAAA,YAAA;AAAA,YACT,KAAO,EAAA,aAAA;AAAA,YACP,QAAU,EAAA;AAAA;AAAA;AACZ;AAAA;AAAA,GACF;AAEJ;;;;"}
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 IncidentsListColumns = [
4
- {
5
- id: "incidentNumber",
6
- title: "Incident Number",
7
- field: IncidentTableFieldEnum.Number,
8
- type: "string"
9
- },
10
- {
11
- id: "description",
12
- title: "Description",
13
- field: IncidentTableFieldEnum.ShortDescription,
14
- type: "string"
15
- },
16
- {
17
- id: "created",
18
- title: "Created",
19
- field: IncidentTableFieldEnum.Created,
20
- type: "string"
21
- },
22
- {
23
- id: "priority",
24
- title: "Priority",
25
- field: IncidentTableFieldEnum.Priority,
26
- type: "numeric"
27
- },
28
- {
29
- id: "state",
30
- title: "State",
31
- field: IncidentTableFieldEnum.IncidentState,
32
- type: "datetime"
33
- },
34
- {
35
- id: "actions",
36
- title: "Actions",
37
- sorting: false,
38
- type: "string"
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 { IncidentsListColumns };
46
+ export { useIncidentsListColumns };
43
47
  //# sourceMappingURL=IncidentsListColumns.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"IncidentsListColumns.esm.js","sources":["../../../src/components/Servicenow/IncidentsListColumns.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 { TableColumn } from '@backstage/core-components';\n\nimport { IncidentsData, IncidentTableFieldEnum } from '../../types';\n\nexport const IncidentsListColumns: TableColumn<IncidentsData>[] = [\n {\n id: 'incidentNumber',\n title: 'Incident Number',\n field: IncidentTableFieldEnum.Number,\n type: 'string',\n },\n {\n id: 'description',\n title: 'Description',\n field: IncidentTableFieldEnum.ShortDescription,\n type: 'string',\n },\n {\n id: 'created',\n title: 'Created',\n field: IncidentTableFieldEnum.Created,\n type: 'string',\n },\n {\n id: 'priority',\n title: 'Priority',\n field: IncidentTableFieldEnum.Priority,\n type: 'numeric',\n },\n {\n id: 'state',\n title: 'State',\n field: IncidentTableFieldEnum.IncidentState,\n type: 'datetime',\n },\n {\n id: 'actions',\n title: 'Actions',\n sorting: false,\n type: 'string',\n },\n];\n"],"names":[],"mappings":";;AAmBO,MAAM,oBAAqD,GAAA;AAAA,EAChE;AAAA,IACE,EAAI,EAAA,gBAAA;AAAA,IACJ,KAAO,EAAA,iBAAA;AAAA,IACP,OAAO,sBAAuB,CAAA,MAAA;AAAA,IAC9B,IAAM,EAAA;AAAA,GACR;AAAA,EACA;AAAA,IACE,EAAI,EAAA,aAAA;AAAA,IACJ,KAAO,EAAA,aAAA;AAAA,IACP,OAAO,sBAAuB,CAAA,gBAAA;AAAA,IAC9B,IAAM,EAAA;AAAA,GACR;AAAA,EACA;AAAA,IACE,EAAI,EAAA,SAAA;AAAA,IACJ,KAAO,EAAA,SAAA;AAAA,IACP,OAAO,sBAAuB,CAAA,OAAA;AAAA,IAC9B,IAAM,EAAA;AAAA,GACR;AAAA,EACA;AAAA,IACE,EAAI,EAAA,UAAA;AAAA,IACJ,KAAO,EAAA,UAAA;AAAA,IACP,OAAO,sBAAuB,CAAA,QAAA;AAAA,IAC9B,IAAM,EAAA;AAAA,GACR;AAAA,EACA;AAAA,IACE,EAAI,EAAA,OAAA;AAAA,IACJ,KAAO,EAAA,OAAA;AAAA,IACP,OAAO,sBAAuB,CAAA,aAAA;AAAA,IAC9B,IAAM,EAAA;AAAA,GACR;AAAA,EACA;AAAA,IACE,EAAI,EAAA,SAAA;AAAA,IACJ,KAAO,EAAA,SAAA;AAAA,IACP,OAAS,EAAA,KAAA;AAAA,IACT,IAAM,EAAA;AAAA;AAEV;;;;"}
1
+ {"version":3,"file":"IncidentsListColumns.esm.js","sources":["../../../src/components/Servicenow/IncidentsListColumns.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 { TableColumn } from '@backstage/core-components';\n\nimport { IncidentsData, IncidentTableFieldEnum } from '../../types';\nimport { useTranslation } from '../../hooks/useTranslation';\n\n/**\n * Hook to get translated incidents list columns\n */\nexport const useIncidentsListColumns = (): TableColumn<IncidentsData>[] => {\n const { t } = useTranslation();\n\n return [\n {\n id: 'incidentNumber',\n title: t('table.columns.incidentNumber'),\n field: IncidentTableFieldEnum.Number,\n type: 'string',\n },\n {\n id: 'description',\n title: t('table.columns.description'),\n field: IncidentTableFieldEnum.ShortDescription,\n type: 'string',\n },\n {\n id: 'created',\n title: t('table.columns.created'),\n field: IncidentTableFieldEnum.Created,\n type: 'string',\n },\n {\n id: 'priority',\n title: t('table.columns.priority'),\n field: IncidentTableFieldEnum.Priority,\n type: 'numeric',\n },\n {\n id: 'state',\n title: t('table.columns.state'),\n field: IncidentTableFieldEnum.IncidentState,\n type: 'datetime',\n },\n {\n id: 'actions',\n title: t('table.columns.actions'),\n sorting: false,\n type: 'string',\n },\n ];\n};\n\n/**\n * @deprecated Use useIncidentsListColumns hook instead\n */\nexport const IncidentsListColumns: TableColumn<IncidentsData>[] = [\n {\n id: 'incidentNumber',\n title: 'Incident Number',\n field: IncidentTableFieldEnum.Number,\n type: 'string',\n },\n {\n id: 'description',\n title: 'Description',\n field: IncidentTableFieldEnum.ShortDescription,\n type: 'string',\n },\n {\n id: 'created',\n title: 'Created',\n field: IncidentTableFieldEnum.Created,\n type: 'string',\n },\n {\n id: 'priority',\n title: 'Priority',\n field: IncidentTableFieldEnum.Priority,\n type: 'numeric',\n },\n {\n id: 'state',\n title: 'State',\n field: IncidentTableFieldEnum.IncidentState,\n type: 'datetime',\n },\n {\n id: 'actions',\n title: 'Actions',\n sorting: false,\n type: 'string',\n },\n];\n"],"names":[],"mappings":";;;AAuBO,MAAM,0BAA0B,MAAoC;AACzE,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,cAAe,EAAA;AAE7B,EAAO,OAAA;AAAA,IACL;AAAA,MACE,EAAI,EAAA,gBAAA;AAAA,MACJ,KAAA,EAAO,EAAE,8BAA8B,CAAA;AAAA,MACvC,OAAO,sBAAuB,CAAA,MAAA;AAAA,MAC9B,IAAM,EAAA;AAAA,KACR;AAAA,IACA;AAAA,MACE,EAAI,EAAA,aAAA;AAAA,MACJ,KAAA,EAAO,EAAE,2BAA2B,CAAA;AAAA,MACpC,OAAO,sBAAuB,CAAA,gBAAA;AAAA,MAC9B,IAAM,EAAA;AAAA,KACR;AAAA,IACA;AAAA,MACE,EAAI,EAAA,SAAA;AAAA,MACJ,KAAA,EAAO,EAAE,uBAAuB,CAAA;AAAA,MAChC,OAAO,sBAAuB,CAAA,OAAA;AAAA,MAC9B,IAAM,EAAA;AAAA,KACR;AAAA,IACA;AAAA,MACE,EAAI,EAAA,UAAA;AAAA,MACJ,KAAA,EAAO,EAAE,wBAAwB,CAAA;AAAA,MACjC,OAAO,sBAAuB,CAAA,QAAA;AAAA,MAC9B,IAAM,EAAA;AAAA,KACR;AAAA,IACA;AAAA,MACE,EAAI,EAAA,OAAA;AAAA,MACJ,KAAA,EAAO,EAAE,qBAAqB,CAAA;AAAA,MAC9B,OAAO,sBAAuB,CAAA,aAAA;AAAA,MAC9B,IAAM,EAAA;AAAA,KACR;AAAA,IACA;AAAA,MACE,EAAI,EAAA,SAAA;AAAA,MACJ,KAAA,EAAO,EAAE,uBAAuB,CAAA;AAAA,MAChC,OAAS,EAAA,KAAA;AAAA,MACT,IAAM,EAAA;AAAA;AACR,GACF;AACF;;;;"}
@@ -3,14 +3,17 @@ import Box from '@mui/material/Box';
3
3
  import TableBody from '@mui/material/TableBody';
4
4
  import TableRow from '@mui/material/TableRow';
5
5
  import TableCell from '@mui/material/TableCell';
6
- import { IncidentsListColumns } from './IncidentsListColumns.esm.js';
6
+ import { useIncidentsListColumns } from './IncidentsListColumns.esm.js';
7
7
  import { IncidentsTableRow } from './IncidentsTableRow.esm.js';
8
+ import { useTranslation } from '../../hooks/useTranslation.esm.js';
8
9
 
9
10
  const IncidentsTableBody = ({ rows }) => {
11
+ const { t } = useTranslation();
12
+ const incidentsListColumns = useIncidentsListColumns();
10
13
  if (rows?.length > 0) {
11
14
  return /* @__PURE__ */ jsx(TableBody, { "data-testid": "incidents", children: rows.map((row) => /* @__PURE__ */ jsx(IncidentsTableRow, { data: row }, row.sysId)) });
12
15
  }
13
- return /* @__PURE__ */ jsx(TableBody, { children: /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: IncidentsListColumns.length, children: /* @__PURE__ */ jsx(
16
+ return /* @__PURE__ */ jsx(TableBody, { children: /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: incidentsListColumns.length, children: /* @__PURE__ */ jsx(
14
17
  Box,
15
18
  {
16
19
  "data-testid": "no-incidents-found",
@@ -19,7 +22,7 @@ const IncidentsTableBody = ({ rows }) => {
19
22
  display: "flex",
20
23
  justifyContent: "center"
21
24
  },
22
- children: "No records found"
25
+ children: t("table.emptyContent")
23
26
  }
24
27
  ) }) }) });
25
28
  };
@@ -1 +1 @@
1
- {"version":3,"file":"IncidentsTableBody.esm.js","sources":["../../../src/components/Servicenow/IncidentsTableBody.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 Box from '@mui/material/Box';\nimport TableBody from '@mui/material/TableBody';\nimport TableRow from '@mui/material/TableRow';\nimport TableCell from '@mui/material/TableCell';\n\nimport { IncidentsListColumns } from './IncidentsListColumns';\nimport { IncidentsTableRow } from './IncidentsTableRow';\nimport type { IncidentsData } from '../../types';\n\nexport const IncidentsTableBody = ({ rows }: { rows: IncidentsData[] }) => {\n // TODO: Add loading and error states\n\n if (rows?.length > 0) {\n return (\n <TableBody data-testid=\"incidents\">\n {rows.map(row => (\n <IncidentsTableRow key={row.sysId} data={row} />\n ))}\n </TableBody>\n );\n }\n\n return (\n <TableBody>\n <TableRow>\n <TableCell colSpan={IncidentsListColumns.length}>\n <Box\n data-testid=\"no-incidents-found\"\n sx={{\n p: 2,\n display: 'flex',\n justifyContent: 'center',\n }}\n >\n No records found\n </Box>\n </TableCell>\n </TableRow>\n </TableBody>\n );\n};\n"],"names":[],"mappings":";;;;;;;;AAyBO,MAAM,kBAAqB,GAAA,CAAC,EAAE,IAAA,EAAsC,KAAA;AAGzE,EAAI,IAAA,IAAA,EAAM,SAAS,CAAG,EAAA;AACpB,IAAA,uBACG,GAAA,CAAA,SAAA,EAAA,EAAU,aAAY,EAAA,WAAA,EACpB,eAAK,GAAI,CAAA,CAAA,GAAA,qBACP,GAAA,CAAA,iBAAA,EAAA,EAAkC,IAAM,EAAA,GAAA,EAAA,EAAjB,GAAI,CAAA,KAAkB,CAC/C,CACH,EAAA,CAAA;AAAA;AAIJ,EACE,uBAAA,GAAA,CAAC,aACC,QAAC,kBAAA,GAAA,CAAA,QAAA,EAAA,EACC,8BAAC,SAAU,EAAA,EAAA,OAAA,EAAS,qBAAqB,MACvC,EAAA,QAAA,kBAAA,GAAA;AAAA,IAAC,GAAA;AAAA,IAAA;AAAA,MACC,aAAY,EAAA,oBAAA;AAAA,MACZ,EAAI,EAAA;AAAA,QACF,CAAG,EAAA,CAAA;AAAA,QACH,OAAS,EAAA,MAAA;AAAA,QACT,cAAgB,EAAA;AAAA,OAClB;AAAA,MACD,QAAA,EAAA;AAAA;AAAA,GAED,EACF,GACF,CACF,EAAA,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"IncidentsTableBody.esm.js","sources":["../../../src/components/Servicenow/IncidentsTableBody.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 Box from '@mui/material/Box';\nimport TableBody from '@mui/material/TableBody';\nimport TableRow from '@mui/material/TableRow';\nimport TableCell from '@mui/material/TableCell';\n\nimport { useIncidentsListColumns } from './IncidentsListColumns';\nimport { IncidentsTableRow } from './IncidentsTableRow';\nimport type { IncidentsData } from '../../types';\nimport { useTranslation } from '../../hooks/useTranslation';\n\nexport const IncidentsTableBody = ({ rows }: { rows: IncidentsData[] }) => {\n const { t } = useTranslation();\n const incidentsListColumns = useIncidentsListColumns();\n\n if (rows?.length > 0) {\n return (\n <TableBody data-testid=\"incidents\">\n {rows.map(row => (\n <IncidentsTableRow key={row.sysId} data={row} />\n ))}\n </TableBody>\n );\n }\n\n return (\n <TableBody>\n <TableRow>\n <TableCell colSpan={incidentsListColumns.length}>\n <Box\n data-testid=\"no-incidents-found\"\n sx={{\n p: 2,\n display: 'flex',\n justifyContent: 'center',\n }}\n >\n {t('table.emptyContent')}\n </Box>\n </TableCell>\n </TableRow>\n </TableBody>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;AA0BO,MAAM,kBAAqB,GAAA,CAAC,EAAE,IAAA,EAAsC,KAAA;AACzE,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,cAAe,EAAA;AAC7B,EAAA,MAAM,uBAAuB,uBAAwB,EAAA;AAErD,EAAI,IAAA,IAAA,EAAM,SAAS,CAAG,EAAA;AACpB,IAAA,uBACG,GAAA,CAAA,SAAA,EAAA,EAAU,aAAY,EAAA,WAAA,EACpB,eAAK,GAAI,CAAA,CAAA,GAAA,qBACP,GAAA,CAAA,iBAAA,EAAA,EAAkC,IAAM,EAAA,GAAA,EAAA,EAAjB,GAAI,CAAA,KAAkB,CAC/C,CACH,EAAA,CAAA;AAAA;AAIJ,EACE,uBAAA,GAAA,CAAC,aACC,QAAC,kBAAA,GAAA,CAAA,QAAA,EAAA,EACC,8BAAC,SAAU,EAAA,EAAA,OAAA,EAAS,qBAAqB,MACvC,EAAA,QAAA,kBAAA,GAAA;AAAA,IAAC,GAAA;AAAA,IAAA;AAAA,MACC,aAAY,EAAA,oBAAA;AAAA,MACZ,EAAI,EAAA;AAAA,QACF,CAAG,EAAA,CAAA;AAAA,QACH,OAAS,EAAA,MAAA;AAAA,QACT,cAAgB,EAAA;AAAA,OAClB;AAAA,MAEC,YAAE,oBAAoB;AAAA;AAAA,GACzB,EACF,GACF,CACF,EAAA,CAAA;AAEJ;;;;"}
@@ -3,17 +3,18 @@ import TableCell from '@mui/material/TableCell';
3
3
  import TableHead from '@mui/material/TableHead';
4
4
  import TableRow from '@mui/material/TableRow';
5
5
  import TableSortLabel from '@mui/material/TableSortLabel';
6
- import { IncidentsListColumns } from './IncidentsListColumns.esm.js';
6
+ import { useIncidentsListColumns } from './IncidentsListColumns.esm.js';
7
7
 
8
8
  const IncidentsTableHeader = ({
9
9
  order,
10
10
  orderBy,
11
11
  onRequestSort
12
12
  }) => {
13
+ const incidentsListColumns = useIncidentsListColumns();
13
14
  const createSortHandler = (property) => (event) => {
14
15
  onRequestSort(event, property);
15
16
  };
16
- return /* @__PURE__ */ jsx(TableHead, { children: /* @__PURE__ */ jsx(TableRow, { sx: { marginLeft: "6px", borderBottom: "1px solid #e0e0e0" }, children: IncidentsListColumns.map((column) => /* @__PURE__ */ jsx(
17
+ return /* @__PURE__ */ jsx(TableHead, { children: /* @__PURE__ */ jsx(TableRow, { sx: { marginLeft: "6px", borderBottom: "1px solid #e0e0e0" }, children: incidentsListColumns.map((column) => /* @__PURE__ */ jsx(
17
18
  TableCell,
18
19
  {
19
20
  align: "left",
@@ -1 +1 @@
1
- {"version":3,"file":"IncidentsTableHeader.esm.js","sources":["../../../src/components/Servicenow/IncidentsTableHeader.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 { MouseEvent } from 'react';\nimport TableCell from '@mui/material/TableCell';\nimport TableHead from '@mui/material/TableHead';\nimport TableRow from '@mui/material/TableRow';\nimport TableSortLabel from '@mui/material/TableSortLabel';\n\nimport type { Order } from '@backstage-community/plugin-servicenow-common';\n\nimport { IncidentsListColumns } from './IncidentsListColumns';\nimport { IncidentTableField } from '../../types';\n\ntype IncidentsTableHeaderProps = {\n order: Order;\n orderBy: IncidentTableField | undefined;\n onRequestSort: (\n event: MouseEvent<unknown>,\n property: IncidentTableField,\n ) => void;\n};\n\nexport const IncidentsTableHeader = ({\n order,\n orderBy,\n onRequestSort,\n}: IncidentsTableHeaderProps) => {\n const createSortHandler =\n (property: IncidentTableField) => (event: MouseEvent<unknown>) => {\n onRequestSort(event, property);\n };\n\n return (\n <TableHead>\n <TableRow sx={{ marginLeft: '6px', borderBottom: '1px solid #e0e0e0' }}>\n {IncidentsListColumns.map(column => (\n <TableCell\n key={column.id as string}\n align=\"left\"\n padding=\"normal\"\n style={{\n lineHeight: '1.5rem',\n fontSize: '0.875rem',\n padding: '24px 16px 24px 20px',\n fontWeight: '700',\n }}\n sortDirection={orderBy === column.field ? order : 'asc'}\n >\n <TableSortLabel\n active={orderBy === column.field}\n direction={orderBy === column.field ? order : 'asc'}\n onClick={\n column.sorting === false\n ? undefined\n : createSortHandler(column.field as IncidentTableField)\n }\n disabled={column.sorting === false}\n >\n {column.title}\n </TableSortLabel>\n </TableCell>\n ))}\n </TableRow>\n </TableHead>\n );\n};\n"],"names":[],"mappings":";;;;;;;AAoCO,MAAM,uBAAuB,CAAC;AAAA,EACnC,KAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAiC,KAAA;AAC/B,EAAA,MAAM,iBACJ,GAAA,CAAC,QAAiC,KAAA,CAAC,KAA+B,KAAA;AAChE,IAAA,aAAA,CAAc,OAAO,QAAQ,CAAA;AAAA,GAC/B;AAEF,EAAA,uBACG,GAAA,CAAA,SAAA,EAAA,EACC,QAAC,kBAAA,GAAA,CAAA,QAAA,EAAA,EAAS,EAAI,EAAA,EAAE,UAAY,EAAA,KAAA,EAAO,YAAc,EAAA,mBAAA,EAC9C,EAAA,QAAA,EAAA,oBAAA,CAAqB,IAAI,CACxB,MAAA,qBAAA,GAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MAEC,KAAM,EAAA,MAAA;AAAA,MACN,OAAQ,EAAA,QAAA;AAAA,MACR,KAAO,EAAA;AAAA,QACL,UAAY,EAAA,QAAA;AAAA,QACZ,QAAU,EAAA,UAAA;AAAA,QACV,OAAS,EAAA,qBAAA;AAAA,QACT,UAAY,EAAA;AAAA,OACd;AAAA,MACA,aAAe,EAAA,OAAA,KAAY,MAAO,CAAA,KAAA,GAAQ,KAAQ,GAAA,KAAA;AAAA,MAElD,QAAA,kBAAA,GAAA;AAAA,QAAC,cAAA;AAAA,QAAA;AAAA,UACC,MAAA,EAAQ,YAAY,MAAO,CAAA,KAAA;AAAA,UAC3B,SAAW,EAAA,OAAA,KAAY,MAAO,CAAA,KAAA,GAAQ,KAAQ,GAAA,KAAA;AAAA,UAC9C,SACE,MAAO,CAAA,OAAA,KAAY,QACf,MACA,GAAA,iBAAA,CAAkB,OAAO,KAA2B,CAAA;AAAA,UAE1D,QAAA,EAAU,OAAO,OAAY,KAAA,KAAA;AAAA,UAE5B,QAAO,EAAA,MAAA,CAAA;AAAA;AAAA;AACV,KAAA;AAAA,IAtBK,MAAO,CAAA;AAAA,GAwBf,GACH,CACF,EAAA,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"IncidentsTableHeader.esm.js","sources":["../../../src/components/Servicenow/IncidentsTableHeader.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 { MouseEvent } from 'react';\nimport TableCell from '@mui/material/TableCell';\nimport TableHead from '@mui/material/TableHead';\nimport TableRow from '@mui/material/TableRow';\nimport TableSortLabel from '@mui/material/TableSortLabel';\n\nimport type { Order } from '@backstage-community/plugin-servicenow-common';\n\nimport { useIncidentsListColumns } from './IncidentsListColumns';\nimport { IncidentTableField } from '../../types';\n\ntype IncidentsTableHeaderProps = {\n order: Order;\n orderBy: IncidentTableField | undefined;\n onRequestSort: (\n event: MouseEvent<unknown>,\n property: IncidentTableField,\n ) => void;\n};\n\nexport const IncidentsTableHeader = ({\n order,\n orderBy,\n onRequestSort,\n}: IncidentsTableHeaderProps) => {\n const incidentsListColumns = useIncidentsListColumns();\n\n const createSortHandler =\n (property: IncidentTableField) => (event: MouseEvent<unknown>) => {\n onRequestSort(event, property);\n };\n\n return (\n <TableHead>\n <TableRow sx={{ marginLeft: '6px', borderBottom: '1px solid #e0e0e0' }}>\n {incidentsListColumns.map(column => (\n <TableCell\n key={column.id as string}\n align=\"left\"\n padding=\"normal\"\n style={{\n lineHeight: '1.5rem',\n fontSize: '0.875rem',\n padding: '24px 16px 24px 20px',\n fontWeight: '700',\n }}\n sortDirection={orderBy === column.field ? order : 'asc'}\n >\n <TableSortLabel\n active={orderBy === column.field}\n direction={orderBy === column.field ? order : 'asc'}\n onClick={\n column.sorting === false\n ? undefined\n : createSortHandler(column.field as IncidentTableField)\n }\n disabled={column.sorting === false}\n >\n {column.title}\n </TableSortLabel>\n </TableCell>\n ))}\n </TableRow>\n </TableHead>\n );\n};\n"],"names":[],"mappings":";;;;;;;AAoCO,MAAM,uBAAuB,CAAC;AAAA,EACnC,KAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAiC,KAAA;AAC/B,EAAA,MAAM,uBAAuB,uBAAwB,EAAA;AAErD,EAAA,MAAM,iBACJ,GAAA,CAAC,QAAiC,KAAA,CAAC,KAA+B,KAAA;AAChE,IAAA,aAAA,CAAc,OAAO,QAAQ,CAAA;AAAA,GAC/B;AAEF,EAAA,uBACG,GAAA,CAAA,SAAA,EAAA,EACC,QAAC,kBAAA,GAAA,CAAA,QAAA,EAAA,EAAS,EAAI,EAAA,EAAE,UAAY,EAAA,KAAA,EAAO,YAAc,EAAA,mBAAA,EAC9C,EAAA,QAAA,EAAA,oBAAA,CAAqB,IAAI,CACxB,MAAA,qBAAA,GAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MAEC,KAAM,EAAA,MAAA;AAAA,MACN,OAAQ,EAAA,QAAA;AAAA,MACR,KAAO,EAAA;AAAA,QACL,UAAY,EAAA,QAAA;AAAA,QACZ,QAAU,EAAA,UAAA;AAAA,QACV,OAAS,EAAA,qBAAA;AAAA,QACT,UAAY,EAAA;AAAA,OACd;AAAA,MACA,aAAe,EAAA,OAAA,KAAY,MAAO,CAAA,KAAA,GAAQ,KAAQ,GAAA,KAAA;AAAA,MAElD,QAAA,kBAAA,GAAA;AAAA,QAAC,cAAA;AAAA,QAAA;AAAA,UACC,MAAA,EAAQ,YAAY,MAAO,CAAA,KAAA;AAAA,UAC3B,SAAW,EAAA,OAAA,KAAY,MAAO,CAAA,KAAA,GAAQ,KAAQ,GAAA,KAAA;AAAA,UAC9C,SACE,MAAO,CAAA,OAAA,KAAY,QACf,MACA,GAAA,iBAAA,CAAkB,OAAO,KAA2B,CAAA;AAAA,UAE1D,QAAA,EAAU,OAAO,OAAY,KAAA,KAAA;AAAA,UAE5B,QAAO,EAAA,MAAA,CAAA;AAAA;AAAA;AACV,KAAA;AAAA,IAtBK,MAAO,CAAA;AAAA,GAwBf,GACH,CACF,EAAA,CAAA;AAEJ;;;;"}
@@ -7,7 +7,8 @@ import { makeStyles } from '@mui/styles';
7
7
  import Tooltip from '@mui/material/Tooltip';
8
8
  import Typography from '@mui/material/Typography';
9
9
  import { convertDateFormat } from '../../utils/stringUtils.esm.js';
10
- import { getPriorityValue, getIncidentStateValue } from '../../utils/incidentUtils.esm.js';
10
+ import { usePriorityMap, useIncidentStateMap, renderStatusLabel } from '../../utils/incidentUtils.esm.js';
11
+ import { useTranslation } from '../../hooks/useTranslation.esm.js';
11
12
 
12
13
  const useStyles = makeStyles(() => ({
13
14
  tableCellStyle: {
@@ -17,6 +18,9 @@ const useStyles = makeStyles(() => ({
17
18
  }));
18
19
  const IncidentsTableRow = ({ data }) => {
19
20
  const classes = useStyles();
21
+ const { t } = useTranslation();
22
+ const priorityMap = usePriorityMap();
23
+ const incidentStateMap = useIncidentStateMap();
20
24
  return /* @__PURE__ */ jsxs(
21
25
  TableRow,
22
26
  {
@@ -42,9 +46,9 @@ const IncidentsTableRow = ({ data }) => {
42
46
  }
43
47
  ) }) }),
44
48
  /* @__PURE__ */ jsx(TableCell, { align: "left", className: classes.tableCellStyle, children: convertDateFormat(data?.sysCreatedOn) }),
45
- /* @__PURE__ */ jsx(TableCell, { align: "left", className: classes.tableCellStyle, children: getPriorityValue(data?.priority) }),
46
- /* @__PURE__ */ jsx(TableCell, { align: "left", className: classes.tableCellStyle, children: getIncidentStateValue(data?.incidentState) }),
47
- /* @__PURE__ */ jsx(TableCell, { align: "left", className: classes.tableCellStyle, children: /* @__PURE__ */ jsx(IconButton, { onClick: () => window.open(data.url, "_blank"), children: /* @__PURE__ */ jsx(OpenInNewIcon, { fontSize: "small", style: { color: "inherit" } }) }) })
49
+ /* @__PURE__ */ jsx(TableCell, { align: "left", className: classes.tableCellStyle, children: renderStatusLabel(priorityMap[data?.priority]) }),
50
+ /* @__PURE__ */ jsx(TableCell, { align: "left", className: classes.tableCellStyle, children: renderStatusLabel(incidentStateMap[data?.incidentState]) }),
51
+ /* @__PURE__ */ jsx(TableCell, { align: "left", className: classes.tableCellStyle, children: /* @__PURE__ */ jsx(Tooltip, { title: t("actions.openInServicenow"), arrow: true, placement: "top", children: /* @__PURE__ */ jsx(IconButton, { onClick: () => window.open(data.url, "_blank"), children: /* @__PURE__ */ jsx(OpenInNewIcon, { fontSize: "small", style: { color: "inherit" } }) }) }) })
48
52
  ]
49
53
  }
50
54
  );