diff --git a/heureka/ui/package-lock.json b/heureka/ui/package-lock.json
index 33064b91..77b17cba 100644
--- a/heureka/ui/package-lock.json
+++ b/heureka/ui/package-lock.json
@@ -1,19 +1,18 @@
{
"name": "heureka",
- "version": "2.2.2",
+ "version": "2.3.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "heureka",
- "version": "2.2.2",
+ "version": "2.3.0",
"license": "Apache-2.0",
"dependencies": {
"@cloudoperators/juno-communicator": "^2.2.11",
"@cloudoperators/juno-messages-provider": "^0.1.17",
"@cloudoperators/juno-ui-components": "^2.15.4",
- "@cloudoperators/juno-url-state-provider-v1": "^1.3.2",
- "@cloudoperators/juno-utils": "^1.1.12"
+ "@cloudoperators/juno-url-state-provider-v1": "^1.3.2"
},
"devDependencies": {
"@babel/core": "^7.20.2",
@@ -36,7 +35,7 @@
"immer": "^10.0.0",
"jest": "^29.3.1",
"jest-environment-jsdom": "^29.3.1",
- "luxon": "^3.0.0",
+ "luxon": "^3.4.4",
"postcss": "^8.4.21",
"postcss-url": "^10.1.3",
"prop-types": "^15.8.1",
@@ -1947,18 +1946,6 @@
"juri": "^1.0.3"
}
},
- "node_modules/@cloudoperators/juno-utils": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/@cloudoperators/juno-utils/-/juno-utils-1.1.12.tgz",
- "integrity": "sha512-thUgU/Kg7gmjhIZ6yALZSLCTKycBZ5y/LwwgSpinAVNbVebK8AassEcqloTgayTn6J3rAryDdSptfqnrzbuFLA==",
- "engines": {
- "node": ">=20.0.0 <21.0.0",
- "npm": ">=10.0.0 <11.0.0"
- },
- "peerDependencies": {
- "react": "^18.2.0"
- }
- },
"node_modules/@esbuild/aix-ppc64": {
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz",
diff --git a/heureka/ui/package.json b/heureka/ui/package.json
index 12959d98..c8f9553a 100644
--- a/heureka/ui/package.json
+++ b/heureka/ui/package.json
@@ -1,6 +1,6 @@
{
"name": "heureka",
- "version": "2.2.2",
+ "version": "2.3.0",
"author": "UI-Team",
"contributors": [
"Hoda Noori, Arturo Reuschenbach Pucernau"
@@ -31,7 +31,7 @@
"immer": "^10.0.0",
"jest": "^29.3.1",
"jest-environment-jsdom": "^29.3.1",
- "luxon": "^3.0.0",
+ "luxon": "^3.4.4",
"postcss": "^8.4.21",
"postcss-url": "^10.1.3",
"prop-types": "^15.8.1",
diff --git a/heureka/ui/src/components/components/ComponentsList.jsx b/heureka/ui/src/components/components/ComponentsList.jsx
new file mode 100644
index 00000000..dffd5757
--- /dev/null
+++ b/heureka/ui/src/components/components/ComponentsList.jsx
@@ -0,0 +1,51 @@
+/*
+ * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Greenhouse contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import React from "react"
+import {
+ DataGrid,
+ DataGridRow,
+ DataGridHeadCell,
+ DataGridCell,
+} from "@cloudoperators/juno-ui-components"
+import HintNotFound from "../shared/HintNotFound"
+import HintLoading from "../shared/HintLoading"
+import ComponentsListItem from "./ComponentsListItem"
+
+const ComponentsList = ({ components, isLoading }) => {
+ return (
+
+
+ Name
+ Type
+ Total Number of Versions
+
+ {isLoading && !components ? (
+
+ ) : (
+ <>
+ {components?.length > 0 ? (
+ <>
+ {components.map((item, index) => (
+
+ ))}
+ >
+ ) : (
+
+
+
+
+
+ )}
+ >
+ )}
+
+ )
+}
+
+export default ComponentsList
diff --git a/heureka/ui/src/components/components/ComponentsListController.jsx b/heureka/ui/src/components/components/ComponentsListController.jsx
new file mode 100644
index 00000000..445c5ddd
--- /dev/null
+++ b/heureka/ui/src/components/components/ComponentsListController.jsx
@@ -0,0 +1,96 @@
+/*
+ * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Greenhouse contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import React, { useMemo, useState } from "react"
+import { useQuery } from "@tanstack/react-query"
+import {
+ useQueryClientFnReady,
+ useQueryOptions,
+ useActions,
+} from "../StoreProvider"
+import ComponentsList from "./ComponentsList"
+import {
+ Pagination,
+ Container,
+ Stack,
+} from "@cloudoperators/juno-ui-components"
+
+const ComponentsListController = () => {
+ const queryClientFnReady = useQueryClientFnReady()
+ const queryOptions = useQueryOptions("components")
+ const { setQueryOptions } = useActions()
+
+ const { isLoading, isFetching, isError, data, error } = useQuery({
+ queryKey: [`components`, queryOptions],
+ enabled: !!queryClientFnReady,
+ })
+
+ const [currentPage, setCurrentPage] = useState(1) // State for current page
+
+ const components = useMemo(() => {
+ if (!data) return null
+ return data?.Components?.edges
+ }, [data])
+
+ const pageInfo = useMemo(() => {
+ if (!data) return null
+ return data?.Components?.pageInfo
+ }, [data])
+
+ const totalPages = useMemo(() => {
+ if (!data?.Components?.pageInfo?.pages) return 0
+ return data?.Components?.pageInfo?.pages.length
+ }, [data?.Components?.pageInfo])
+ const onPaginationChanged = (newPage) => {
+ setCurrentPage(newPage) // Update currentPage
+ if (!data?.Components?.pageInfo?.pages) return
+ const pages = data?.Components?.pageInfo?.pages
+ const currentPageIndex = pages?.findIndex(
+ (page) => page?.pageNumber === parseInt(newPage)
+ )
+ if (currentPageIndex > -1) {
+ const after = pages[currentPageIndex]?.after
+ setQueryOptions("components", {
+ ...queryOptions,
+ after: `${after}`,
+ })
+ }
+ }
+
+ const onPressNext = () => {
+ onPaginationChanged(parseInt(currentPage) + 1)
+ }
+ const onPressPrevious = () => {
+ onPaginationChanged(parseInt(currentPage) - 1)
+ }
+ const onKeyPress = (oKey) => {
+ if (oKey.code === "Enter") {
+ onPaginationChanged(parseInt(oKey.currentTarget.value))
+ }
+ }
+
+ return (
+ <>
+
+
+
+
+
+
+ >
+ )
+}
+
+export default ComponentsListController
diff --git a/heureka/ui/src/components/components/ComponentsListItem.jsx b/heureka/ui/src/components/components/ComponentsListItem.jsx
new file mode 100644
index 00000000..da4ed811
--- /dev/null
+++ b/heureka/ui/src/components/components/ComponentsListItem.jsx
@@ -0,0 +1,19 @@
+/*
+ * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Greenhouse contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import React from "react"
+import { DataGridRow, DataGridCell } from "@cloudoperators/juno-ui-components"
+
+const ComponentsListItem = ({ item }) => {
+ return (
+
+ {item?.node?.name}
+ {item?.node?.type}
+ {item?.node?.componentVersions?.totalCount}
+
+ )
+}
+
+export default ComponentsListItem
diff --git a/heureka/ui/src/components/components/ComponentsTab.jsx b/heureka/ui/src/components/components/ComponentsTab.jsx
new file mode 100644
index 00000000..581a4caf
--- /dev/null
+++ b/heureka/ui/src/components/components/ComponentsTab.jsx
@@ -0,0 +1,19 @@
+/*
+ * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Greenhouse contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import React from "react"
+import ComponentsListController from "./ComponentsListController"
+import Filters from "../filters/Filters"
+
+const ComponentsTab = () => {
+ return (
+ <>
+
+
+ >
+ )
+}
+
+export default ComponentsTab
diff --git a/heureka/ui/src/components/issues/IssuesList.jsx b/heureka/ui/src/components/issues/IssuesList.jsx
index ddd65387..df806788 100644
--- a/heureka/ui/src/components/issues/IssuesList.jsx
+++ b/heureka/ui/src/components/issues/IssuesList.jsx
@@ -16,10 +16,12 @@ import IssuesListItem from "./IssuesListItem"
const IssuesList = ({ issues, isLoading }) => {
return (
-
+
Primary Name
- Secondary Name
+ Type
+ {/* Secondary Name */}
+ Remediation Date
Status
Severity
Component Name
@@ -40,7 +42,7 @@ const IssuesList = ({ issues, isLoading }) => {
>
) : (
-
+
diff --git a/heureka/ui/src/components/issues/IssuesListController.jsx b/heureka/ui/src/components/issues/IssuesListController.jsx
index 47a59f76..0ce51aca 100644
--- a/heureka/ui/src/components/issues/IssuesListController.jsx
+++ b/heureka/ui/src/components/issues/IssuesListController.jsx
@@ -11,7 +11,11 @@ import {
useActions,
} from "../StoreProvider"
import IssuesList from "./IssuesList"
-import { Pagination } from "@cloudoperators/juno-ui-components"
+import {
+ Container,
+ Pagination,
+ Stack,
+} from "@cloudoperators/juno-ui-components"
const IssuesListController = () => {
const queryClientFnReady = useQueryClientFnReady()
@@ -69,18 +73,22 @@ const IssuesListController = () => {
return (
<>
-
-
+
+
+
+
+
+
>
)
}
diff --git a/heureka/ui/src/components/issues/IssuesListItem.jsx b/heureka/ui/src/components/issues/IssuesListItem.jsx
index eeae4a9c..7250e902 100644
--- a/heureka/ui/src/components/issues/IssuesListItem.jsx
+++ b/heureka/ui/src/components/issues/IssuesListItem.jsx
@@ -6,19 +6,24 @@
import React from "react"
import { DataGridRow, DataGridCell } from "@cloudoperators/juno-ui-components"
import { listOfCommaSeparatedObjs } from "../shared/Helper"
+import { DateTime } from "luxon"
const IssuesListItem = ({ item }) => {
- // Log the item structure
- console.log("Item structure:", item)
+ const formatDate = (dateStr) => {
+ const dateObj = DateTime.fromISO(dateStr)
+ return dateObj.toFormat("yyyy.MM.dd.HH:mm:ss")
+ }
return (
{item?.node?.issue?.primaryName}
-
+ {item?.node?.issue?.type}
+ {/*
{listOfCommaSeparatedObjs(
item?.node?.effectiveIssueVariants,
"secondaryName"
- )}
-
+ )}
+ */}
+ {formatDate(item?.node?.remediationDate)}
{item?.node?.status}
{item?.node?.severity?.value}
diff --git a/heureka/ui/src/components/services/ServicesListController.jsx b/heureka/ui/src/components/services/ServicesListController.jsx
index 7eae7098..16f2311b 100644
--- a/heureka/ui/src/components/services/ServicesListController.jsx
+++ b/heureka/ui/src/components/services/ServicesListController.jsx
@@ -10,7 +10,11 @@ import {
useQueryOptions,
useActions,
} from "../StoreProvider"
-import { Pagination } from "@cloudoperators/juno-ui-components"
+import {
+ Pagination,
+ Container,
+ Stack,
+} from "@cloudoperators/juno-ui-components"
import ServicesList from "./ServicesList"
import {
Messages,
@@ -81,18 +85,22 @@ const ServicesListController = () => {
return (
<>
-
-
+
+
+
+
+
+
>
)
}
diff --git a/heureka/ui/src/components/tabs/TabContext.jsx b/heureka/ui/src/components/tabs/TabContext.jsx
index 8f577e5d..071846dd 100644
--- a/heureka/ui/src/components/tabs/TabContext.jsx
+++ b/heureka/ui/src/components/tabs/TabContext.jsx
@@ -14,6 +14,7 @@ import { useActions, useActiveTab } from "../StoreProvider"
import ServicesTab from "../services/ServicesTab"
import IssuesTab from "../issues/IssuesTab"
+import ComponentsTab from "../components/ComponentsTab"
const TAB_CONFIG = [
{
@@ -28,6 +29,12 @@ const TAB_CONFIG = [
icon: "autoAwesomeMotion",
component: IssuesTab,
},
+ {
+ label: "Components",
+ value: "components",
+ icon: "autoAwesomeMotion",
+ component: ComponentsTab,
+ },
]
const TabContext = () => {
diff --git a/heureka/ui/src/hooks/useQueryClientFn.js b/heureka/ui/src/hooks/useQueryClientFn.js
index 3e4df721..42f9ce34 100644
--- a/heureka/ui/src/hooks/useQueryClientFn.js
+++ b/heureka/ui/src/hooks/useQueryClientFn.js
@@ -10,6 +10,7 @@ import { request } from "graphql-request"
import sevicesQuery from "../lib/queries/services"
import issueMatchesQuery from "../lib/queries/issueMatches"
import ServiceFilterQuery from "../lib/queries/serviceFilters"
+import componentsQuery from "../lib/queries/components"
// hook to register query defaults that depends on the queryClient and options
const useQueryClientFn = () => {
@@ -40,6 +41,14 @@ const useQueryClientFn = () => {
},
})
+ queryClient.setQueryDefaults(["components"], {
+ queryFn: async ({ queryKey }) => {
+ const [_key, options] = queryKey
+ console.log("useQueryClientFn::: queryKey: ", queryKey)
+ return await request(endpoint, componentsQuery(), options)
+ },
+ })
+
queryClient.setQueryDefaults(["serviceFilters"], {
queryFn: async ({ queryKey }) => {
console.log("useQueryClientFn::: queryKey: ", queryKey)
diff --git a/heureka/ui/src/lib/queries/components.js b/heureka/ui/src/lib/queries/components.js
new file mode 100644
index 00000000..f39041f0
--- /dev/null
+++ b/heureka/ui/src/lib/queries/components.js
@@ -0,0 +1,60 @@
+/*
+ * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Greenhouse contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { gql } from "graphql-request"
+
+// gql
+// It is there for convenience so that you can get the tooling support
+// like prettier formatting and IDE syntax highlighting.
+// You can use gql from graphql-tag if you need it for some reason too.
+export default () => gql`
+ query ($filter: ComponentFilter, $first: Int, $after: String) {
+ Components(filter: $filter, first: $first, after: $after) {
+ totalCount
+ edges {
+ node {
+ id
+ name
+ type
+ componentVersions {
+ totalCount
+ edges {
+ node {
+ id
+ version
+ issues {
+ totalCount
+ }
+ componentInstances {
+ totalCount
+ edges {
+ node {
+ id
+ }
+ }
+ }
+ }
+ cursor
+ }
+ }
+ }
+ cursor
+ }
+ pageInfo {
+ hasNextPage
+ hasPreviousPage
+ isValidPage
+ pageNumber
+ nextPageAfter
+ pages {
+ after
+ isCurrent
+ pageNumber
+ pageCount
+ }
+ }
+ }
+ }
+`
diff --git a/heureka/ui/src/lib/store.js b/heureka/ui/src/lib/store.js
index d440bba4..8bd1da52 100644
--- a/heureka/ui/src/lib/store.js
+++ b/heureka/ui/src/lib/store.js
@@ -26,6 +26,11 @@ export default (options) =>
first: 20,
},
},
+ components: {
+ queryOptions: {
+ first: 20,
+ },
+ },
},
actions: {