diff --git a/.changeset/little-onions-obey.md b/.changeset/little-onions-obey.md
new file mode 100644
index 000000000..50f37ac55
--- /dev/null
+++ b/.changeset/little-onions-obey.md
@@ -0,0 +1,5 @@
+---
+"@fake-scope/fake-pkg": minor
+---
+
+feat(heureka): switches to TopNavigationItem
diff --git a/apps/heureka/src/App.js b/apps/heureka/src/App.js
index 372e144ab..5dcf4aa1f 100644
--- a/apps/heureka/src/App.js
+++ b/apps/heureka/src/App.js
@@ -9,7 +9,7 @@ import { AppShell, AppShellProvider, CodeBlock } from "@cloudoperators/juno-ui-c
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
import { MessagesProvider } from "@cloudoperators/juno-messages-provider"
import AsyncWorker from "./components/AsyncWorker"
-import TabContext from "./components/tabs/TabContext"
+import NavEntryContext from "./components/navEntries/NavEntryContext"
import { ErrorBoundary } from "react-error-boundary"
import { useGlobalsActions, StoreProvider } from "./hooks/useAppStore"
import PanelManager from "./components/shared/PanelManager"
@@ -57,7 +57,7 @@ function App(props = {}) {
-
+
diff --git a/apps/heureka/src/components/components/ComponentsTab.jsx b/apps/heureka/src/components/components/ComponentsTopNavItem.jsx
similarity index 100%
rename from apps/heureka/src/components/components/ComponentsTab.jsx
rename to apps/heureka/src/components/components/ComponentsTopNavItem.jsx
diff --git a/apps/heureka/src/components/issueMatches/IssueMatchesTab.jsx b/apps/heureka/src/components/issueMatches/IssueMatchesTopNavItem.jsx
similarity index 100%
rename from apps/heureka/src/components/issueMatches/IssueMatchesTab.jsx
rename to apps/heureka/src/components/issueMatches/IssueMatchesTopNavItem.jsx
diff --git a/apps/heureka/src/components/tabs/TabPanel.jsx b/apps/heureka/src/components/navEntries/NavEntry.jsx
similarity index 55%
rename from apps/heureka/src/components/tabs/TabPanel.jsx
rename to apps/heureka/src/components/navEntries/NavEntry.jsx
index 5d6e4b8a0..8c3201b6b 100644
--- a/apps/heureka/src/components/tabs/TabPanel.jsx
+++ b/apps/heureka/src/components/navEntries/NavEntry.jsx
@@ -4,15 +4,15 @@
*/
import React, { useMemo } from "react"
-import { useGlobalsActiveTab } from "../../hooks/useAppStore"
+import { useGlobalsActiveNavEntry } from "../../hooks/useAppStore"
-const TabPanel = ({ value, children }) => {
- const activeTab = useGlobalsActiveTab()
+const NavEntry = ({ value, children }) => {
+ const activeNavEntry = useGlobalsActiveNavEntry()
// ATENTION!! compare with == since tabindex is int and value is string
- const displayChildren = useMemo(() => activeTab == value, [activeTab, value])
+ const displayChildren = useMemo(() => activeNavEntry == value, [activeNavEntry, value])
return
{children}
}
-export default TabPanel
+export default NavEntry
diff --git a/apps/heureka/src/components/navEntries/NavEntryContext.jsx b/apps/heureka/src/components/navEntries/NavEntryContext.jsx
new file mode 100644
index 000000000..876a416d9
--- /dev/null
+++ b/apps/heureka/src/components/navEntries/NavEntryContext.jsx
@@ -0,0 +1,73 @@
+/*
+ * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Greenhouse contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import React, { useMemo } from "react"
+import { Container, TopNavigation, TopNavigationItem } from "@cloudoperators/juno-ui-components"
+import NavEntry from "./NavEntry"
+import { useGlobalsActions, useGlobalsActiveNavEntry } from "../../hooks/useAppStore"
+
+import ServicesNav from "../services/ServicesTopNavItem"
+import IssueMatchesNav from "../issueMatches/IssueMatchesTopNavItem"
+import ComponentsNav from "../components/ComponentsTopNavItem"
+
+const NAV_CONFIG = [
+ {
+ label: "Services",
+ value: "Services",
+ icon: "dns",
+ component: ServicesNav,
+ },
+ {
+ label: "IssueMatches",
+ value: "IssueMatches",
+ icon: "autoAwesomeMotion",
+ component: IssueMatchesNav,
+ },
+ {
+ label: "Components",
+ value: "Components",
+ icon: "autoAwesomeMotion",
+ component: ComponentsNav,
+ },
+]
+
+const NavEntryContext = () => {
+ const { setActiveNavEntry } = useGlobalsActions()
+ const activeNavEntry = useGlobalsActiveNavEntry()
+
+ // Memorized top navigation items
+ const memorizedNavItems = useMemo(
+ () =>
+ NAV_CONFIG.map((nav) => (
+ setActiveNavEntry(nav.value)} // Trigger tab change
+ />
+ )),
+ [activeNavEntry, setActiveNavEntry]
+ )
+
+ // Memorized tab panels
+ const memorizedNavItemContents = useMemo(
+ () =>
+ NAV_CONFIG.map((nav) => (
+
+
+
+ )),
+ []
+ )
+
+ return (
+ <>
+ {}}>{memorizedNavItems}
+ {memorizedNavItemContents}
+ >
+ )
+}
+
+export default NavEntryContext
diff --git a/apps/heureka/src/components/services/ServicesTab.jsx b/apps/heureka/src/components/services/ServicesTopNavItem.jsx
similarity index 100%
rename from apps/heureka/src/components/services/ServicesTab.jsx
rename to apps/heureka/src/components/services/ServicesTopNavItem.jsx
diff --git a/apps/heureka/src/components/shared/ListController.jsx b/apps/heureka/src/components/shared/ListController.jsx
index 3d1d491ea..bee82db91 100644
--- a/apps/heureka/src/components/shared/ListController.jsx
+++ b/apps/heureka/src/components/shared/ListController.jsx
@@ -11,7 +11,7 @@ import {
useGlobalsActions,
useActiveFilters,
usePredefinedFilters,
- useGlobalsActiveTab,
+ useGlobalsActiveNavEntry,
useSearchTerm,
} from "../../hooks/useAppStore"
import { Pagination, Container, Stack } from "@cloudoperators/juno-ui-components"
@@ -23,7 +23,7 @@ const ListController = ({ queryKey, entityName, ListComponent }) => {
const queryOptions = useGlobalsQueryOptions(queryKey)
const { setQueryOptions } = useGlobalsActions()
const { addMessage, resetMessages } = messageActions()
- const activeTab = useGlobalsActiveTab()
+ const activeNavEntry = useGlobalsActiveNavEntry()
const activeFilters = useActiveFilters(entityName)
const predefinedFilters = usePredefinedFilters(entityName)
const searchTerm = useSearchTerm(entityName)
@@ -43,7 +43,7 @@ const ListController = ({ queryKey, entityName, ListComponent }) => {
},
},
],
- enabled: !!queryClientFnReady && queryKey === activeTab,
+ enabled: !!queryClientFnReady && queryKey === activeNavEntry,
})
const [currentPage, setCurrentPage] = useState(1)
diff --git a/apps/heureka/src/components/tabs/TabContext.jsx b/apps/heureka/src/components/tabs/TabContext.jsx
deleted file mode 100644
index bb58a90e1..000000000
--- a/apps/heureka/src/components/tabs/TabContext.jsx
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Greenhouse contributors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-import React, { useMemo } from "react"
-import { Container, TabNavigation, TabNavigationItem } from "@cloudoperators/juno-ui-components"
-import TabPanel from "./TabPanel"
-import { useGlobalsActions, useGlobalsActiveTab } from "../../hooks/useAppStore"
-
-import ServicesTab from "../services/ServicesTab"
-import IssueMatchesTab from "../issueMatches/IssueMatchesTab"
-import ComponentsTab from "../components/ComponentsTab"
-
-const TAB_CONFIG = [
- {
- label: "Services",
- value: "Services",
- icon: "dns",
- component: ServicesTab,
- },
- {
- label: "IssueMatches",
- value: "IssueMatches",
- icon: "autoAwesomeMotion",
- component: IssueMatchesTab,
- },
- {
- label: "Components",
- value: "Components",
- icon: "autoAwesomeMotion",
- component: ComponentsTab,
- },
-]
-
-const TabContext = () => {
- const { setActiveTab } = useGlobalsActions()
- const activeTab = useGlobalsActiveTab()
-
- const memoizedTabs = useMemo(
- () =>
- TAB_CONFIG.map((tab) => (
-
- )),
- []
- )
-
- const memoizedTabPanels = useMemo(
- () =>
- TAB_CONFIG.map((tab) => (
-
-
-
- )),
- []
- )
-
- return (
- <>
- setActiveTab(value)}>
- {memoizedTabs}
-
- {memoizedTabPanels}
- >
- )
-}
-
-export default TabContext
diff --git a/apps/heureka/src/hooks/useAppStore.js b/apps/heureka/src/hooks/useAppStore.js
index a0830da17..375b2518d 100644
--- a/apps/heureka/src/hooks/useAppStore.js
+++ b/apps/heureka/src/hooks/useAppStore.js
@@ -36,8 +36,9 @@ const useAppStore = (selector) => useStore(useContext(StoreContext), selector)
// Globals exports
export const useGlobalsEmbedded = () => useAppStore((state) => state.globals.embedded)
export const useGlobalsQueryClientFnReady = () => useAppStore((state) => state.globals.queryClientFnReady)
-export const useGlobalsActiveTab = () => useAppStore((state) => state.globals.activeTab)
-export const useGlobalsQueryOptions = (tab) => useAppStore((state) => state.globals.tabs[tab].queryOptions)
+export const useGlobalsActiveNavEntry = () => useAppStore((state) => state.globals.activeNavEntry)
+export const useGlobalsQueryOptions = (navEntry) =>
+ useAppStore((state) => state.globals.navEntries[navEntry].queryOptions)
export const useGlobalsApiEndpoint = () => useAppStore((state) => state.globals.apiEndpoint)
export const useGlobalsShowPanel = () => useAppStore((state) => state.globals.showPanel)
export const useGlobalsShowServiceDetail = () => useAppStore((state) => state.globals.showServiceDetail)
diff --git a/apps/heureka/src/hooks/useUrlState.js b/apps/heureka/src/hooks/useUrlState.js
index 2724b0dc8..f383b414c 100644
--- a/apps/heureka/src/hooks/useUrlState.js
+++ b/apps/heureka/src/hooks/useUrlState.js
@@ -5,10 +5,10 @@
import { useState, useEffect } from "react"
import { registerConsumer } from "@cloudoperators/juno-url-state-provider-v1"
-import { useGlobalsActions, useGlobalsActiveTab } from "./useAppStore"
+import { useGlobalsActions, useGlobalsActiveNavEntry } from "./useAppStore"
const DEFAULT_KEY = "heureka"
-const ACTIVE_TAB = "t"
+const ACTIVE_NAV = "t"
const useUrlState = (key) => {
const [isURLRead, setIsURLRead] = useState(false)
@@ -16,17 +16,17 @@ const useUrlState = (key) => {
// int his case the key should be different per app
const urlStateManager = registerConsumer(key || DEFAULT_KEY)
- const { setActiveTab } = useGlobalsActions()
- const activeTab = useGlobalsActiveTab()
+ const { setActiveNavEntry } = useGlobalsActions()
+ const activeNavEntry = useGlobalsActiveNavEntry()
// Set initial state from URL (on login)
useEffect(() => {
if (isURLRead) return
// READ the url state and set the state
- const newTabIndex = urlStateManager.currentState()?.[ACTIVE_TAB]
+ const newNavIndex = urlStateManager.currentState()?.[ACTIVE_NAV]
// SAVE the state
- if (newTabIndex) setActiveTab(newTabIndex)
+ if (newNavIndex) setActiveNavEntry(newNavIndex)
setIsURLRead(true)
}, [isURLRead])
@@ -34,9 +34,9 @@ const useUrlState = (key) => {
useEffect(() => {
if (!isURLRead) return
urlStateManager.push({
- [ACTIVE_TAB]: activeTab,
+ [ACTIVE_NAV]: activeNavEntry,
})
- }, [isURLRead, activeTab])
+ }, [isURLRead, activeNavEntry])
}
export default useUrlState
diff --git a/apps/heureka/src/lib/slices/createGlobalsSlice.js b/apps/heureka/src/lib/slices/createGlobalsSlice.js
index 75f446092..a12bfb193 100644
--- a/apps/heureka/src/lib/slices/createGlobalsSlice.js
+++ b/apps/heureka/src/lib/slices/createGlobalsSlice.js
@@ -12,12 +12,12 @@ const createGlobalsSlice = (set, get, options) => ({
apiEndpoint: options?.apiEndpoint, //The API endpoint to use for fetching data.
isUrlStateSetup: false, //Set to true when the URL state has been set up.
queryClientFnReady: false, //Set to true when the queryClient function is ready to be used.
- activeTab: "Services", //Set to the active tab.
+ activeNavEntry: "Services", //Set to the active navEntry.
showPanel: constants.PANEL_NONE, //Set to the which panel should be shown (e.g service details panel, issue matches details panel and so on), if any.
showServiceDetail: null,
showIssueDetail: null,
- tabs: {
+ navEntries: {
Services: {
queryOptions: {
first: 20,
@@ -45,10 +45,10 @@ const createGlobalsSlice = (set, get, options) => ({
"globals/setQueryClientFnReady"
),
- setQueryOptions: (tab, options) =>
+ setQueryOptions: (navEntry, options) =>
set(
produce((state) => {
- state.globals.tabs[tab].queryOptions = options
+ state.globals.navEntries[navEntry].queryOptions = options
}),
false,
"globals/setQueryOptions"
@@ -63,13 +63,13 @@ const createGlobalsSlice = (set, get, options) => ({
false,
"globals/setApiEndpoint"
),
- setActiveTab: (activeTab) =>
+ setActiveNavEntry: (activeNavEntry) =>
set(
(state) => ({
- globals: { ...state.globals, activeTab: activeTab },
+ globals: { ...state.globals, activeNavEntry: activeNavEntry },
}),
false,
- "globals/setActiveTab"
+ "globals/setActiveNavEntry"
),
setShowPanel: (panel) =>
set(