Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(heureka): heureka old goes to ts #777

Merged
merged 5 commits into from
Feb 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/wild-islands-accept.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cloudoperators/juno-app-heureka": patch
---

Heureka move to TS
21 changes: 19 additions & 2 deletions apps/heureka/eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,31 @@
* SPDX-License-Identifier: Apache-2.0
*/

import junoConfigs from "@cloudoperators/juno-config/eslint/juno.mjs"
import junoConfigs from "@cloudoperators/juno-config/eslint/juno-typescript.mjs"

export default [
...junoConfigs,
{
files: ["**/*.js", "**/*.mjs", "**/*.jsx"],
files: ["**/*.ts", "**/*.mjs", "**/*.tsx"],
languageOptions: { sourceType: "module" },
rules: {
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/no-unsafe-argument": "off",
"@typescript-eslint/no-unsafe-return": "off",
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/no-floating-promises": "off",
"@typescript-eslint/require-await": "off",
"@typescript-eslint/unbound-method": "off",
"@typescript-eslint/restrict-template-expressions": "off",
"@typescript-eslint/no-unnecessary-type-assertion": "off",
"@typescript-eslint/no-redundant-type-constituents": "off",
"@typescript-eslint/no-misused-promises": "off",
"@typescript-eslint/no-base-to-string": "off",
"no-empty": "off",
"no-unused-vars": "off",
"prefer-const": "off",
"no-fallthrough": "off",
// disable for now, till we switch to TypeScript
"react/prop-types": "off",
},
Expand Down
1 change: 1 addition & 0 deletions apps/heureka/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
},
"scripts": {
"test": "vitest run",
"typecheck": "tsc --project tsconfig.json --noEmit",
"dev": "vite",
"build": "vite build",
"build:static": "vite build --mode static",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ describe("App", () => {
render(<App id="123" />)
})
waitFor(() => (loginTitles = screen.queryAllByShadowText(/HEUREKA/i)))
// @ts-expect-error TS(2454): Variable 'loginTitles' is used before being assign... Remove this comment to see the full error message
expect(loginTitles.length).toBeGreaterThan(0)
})
})
7 changes: 5 additions & 2 deletions apps/heureka/src/App.jsx → apps/heureka/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ function App(props = {}) {
w-full
`

const fallbackRender = ({ error }) => {
const fallbackRender = ({ error }: any) => {
return (
<div className="w-1/2">
<CodeBlock className={preErrorClasses} copy={false}>
Expand All @@ -39,6 +39,7 @@ function App(props = {}) {
// global default options that apply to all queries
queries: {
// staleTime: Infinity, // if you wish to keep data from the keys until reload
// @ts-ignore
keepPreviousData: true, // nice when paginating
refetchOnWindowFocus: false, // default: true
},
Expand All @@ -50,6 +51,7 @@ function App(props = {}) {
<MessagesProvider>
<CustomAppShell>
<ErrorBoundary fallbackRender={fallbackRender}>
{/* @ts-expect-error TS(2322): Type '{ consumerId: any; }' is not assignable to t... Remove this comment to see the full error message */}
<AsyncWorker consumerId={props.id} />
<PanelManager />
</ErrorBoundary>
Expand All @@ -59,8 +61,9 @@ function App(props = {}) {
)
}

const StyledApp = (props) => {
const StyledApp = (props: any) => {
return (
// @ts-expect-error TS(2322): Type '{ theme: string; }' is not assignable to type 'IntrinsicAttributes & { children?: ReactNode; }'. Property 'theme' does not exist on type 'IntrinsicAttributes & { children?: ReactNode; }'. Remove this comment to see the full error message
<AppShellProvider theme={`${props.theme ? props.theme : "theme-dark"}`}>
{/* load styles inside the shadow dom */}
<style>{styles.toString()}</style>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,34 @@ const VIEW_CONFIG = {
Components: { label: "Images", icon: "autoAwesomeMotion", component: ComponentsView }, // Commented out to remove ComponentsView for MVP version
}

const CustomAppShell = ({ children }) => {
const CustomAppShell = ({ children }: any) => {
// @ts-expect-error TS(2339): Property 'setActiveView' does not exist on type '() => void'. // @ts-expect-error
const { setActiveView, setShowPanel } = useGlobalsActions()
const activeView = useGlobalsActiveView()
const embedded = useGlobalsEmbedded()

const handleNavItemChange = (item) => {
const handleNavItemChange = (item: any) => {
setActiveView(item)
setShowPanel(constants.PANEL_NONE) // Hide the panel when switching
}

// Create topNavigation with NavItems based on VIEW_CONFIG
const topNavigation = (
// @ts-ignore
<TopNavigation activeItem={activeView} onActiveItemChange={handleNavItemChange}>
{Object.entries(VIEW_CONFIG).map(([key, nav]) => (
// @ts-ignore
<TopNavigationItem key={key} icon={nav.icon} value={key} label={nav.label} />
))}
</TopNavigation>
)

// Get the component to render based on activeView
// @ts-expect-error TS(7053): Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
const ActiveComponent = VIEW_CONFIG[activeView]?.component

return (
// @ts-ignore
<AppShell pageHeader={<PageHeader heading="Heureka" />} topNavigation={topNavigation} embedded={embedded}>
<Container py px>
{ActiveComponent && <ActiveComponent />}
Expand Down
99 changes: 0 additions & 99 deletions apps/heureka/src/components/StoreProvider.jsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ describe("createGlobalsSlice", () => {
embedded: "false",
}

const wrapper = ({ children }) => <StoreProvider options={mockOptions}>{children}</StoreProvider>
const wrapper = ({ children }: any) => <StoreProvider options={mockOptions}>{children}</StoreProvider>

it("should initialize with correct default values", () => {
const { result } = renderHook(
Expand All @@ -35,6 +35,7 @@ describe("createGlobalsSlice", () => {
{ wrapper }
)
act(() => {
// @ts-ignore
result.current.actions.setEmbedded(true)
})

Expand Down
104 changes: 104 additions & 0 deletions apps/heureka/src/components/StoreProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Greenhouse contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React, { createContext, useContext } from "react"
import { createStore, useStore } from "zustand"
import { devtools } from "zustand/middleware"

import createFiltersSlice from "../lib/slices/createFiltersSlice"
import createAuthDataSlice from "../lib/slices/createAuthDataSlice"
import createGlobalsSlice from "../lib/slices/createGlobalsSlice"
import createUserActivitySlice from "../lib/slices/createUserActivitySlice"

// Entity constants
const ISSUEMATCHES = "IssueMatches"
const SERVICES = "Services"
const COMPONENTS = "Components"

// @ts-expect-error TS(2554): Expected 1 arguments, but got 0.
const StoreContext = createContext()

export const StoreProvider = ({ options, children }: any) => {
return (
<StoreContext.Provider
value={createStore(
devtools((set, get) => ({
...createGlobalsSlice(set, get, options),
...createAuthDataSlice(set, get),
// @ts-expect-error TS(2554): Expected 1 arguments, but got 2.
...createUserActivitySlice(set, get),
...createFiltersSlice(set, get),
}))
)}
>
{children}
</StoreContext.Provider>
)
}
// @ts-ignore
const useAppStore = (selector: any) => useStore(useContext(StoreContext), selector)

// Globals exports
export const useGlobalsEmbedded = () => useAppStore((state: any) => state.globals.embedded)
export const useGlobalsQueryClientFnReady = () => useAppStore((state: any) => state.globals.queryClientFnReady)
export const useGlobalsActiveView = () => useAppStore((state: any) => state.globals.activeView)
export const useGlobalsQueryOptions = (viewName: any) =>
useAppStore((state: any) => state.globals.views[viewName].queryOptions)
export const useGlobalsApiEndpoint = () => useAppStore((state: any) => state.globals.apiEndpoint)
export const useGlobalsShowPanel = () => useAppStore((state: any) => state.globals.showPanel)
export const useGlobalsShowServiceDetail = () => useAppStore((state: any) => state.globals.showServiceDetail)
export const useGlobalsShowIssueDetail = () => useAppStore((state: any) => state.globals.showIssueDetail)
export const useGlobalsActions = () => useAppStore((state: any) => state.globals.actions)

// AUTH exports
export const useAuthData = () => useAppStore((state: any) => state.auth.data)
export const useAuthIsProcessing = () => useAppStore((state: any) => state.auth.isProcessing)
export const useAuthLoggedIn = () => useAppStore((state: any) => state.auth.loggedIn)
export const useAuthError = () => useAppStore((state: any) => state.auth.error)
export const useAuthLastAction = () => useAppStore((state: any) => state.auth.lastAction)
export const useAuthAppLoaded = () => useAppStore((state: any) => state.auth.appLoaded)
export const useAuthAppIsLoading = () => useAppStore((state: any) => state.auth.appIsLoading)
export const useAuthActions = () => useAppStore((state: any) => state.auth.actions)

// UserActivity exports
export const useUserIsActive = () => useAppStore((state: any) => state.userActivity.isActive)

export const useUserActivityActions = () => useAppStore((state: any) => state.userActivity.actions)

// Filter exports for Issues
export const useIssueMatchesFilterLabels = () => useAppStore((state: any) => state.filters[ISSUEMATCHES].labels)
export const useIssueMatchesActiveFilters = () => useAppStore((state: any) => state.filters[ISSUEMATCHES].activeFilters)
export const useIssueMatchesSearchTerm = () => useAppStore((state: any) => state.filters[ISSUEMATCHES].search)
export const useIssueMatchesFilterLabelValues = () =>
useAppStore((state: any) => state.filters[ISSUEMATCHES].filterLabelValues)
export const useIssueMatchesPredefinedFilters = () =>
useAppStore((state: any) => state.filters[ISSUEMATCHES].predefinedFilters)
export const useIssueMatchesActivePredefinedFilter = () =>
useAppStore((state: any) => state.filters[ISSUEMATCHES].activePredefinedFilter)

// Filter exports for Services
export const useServiceFilterLabels = () => useAppStore((state: any) => state.filters[SERVICES].labels)
export const useServiceActiveFilters = () => useAppStore((state: any) => state.filters[SERVICES].activeFilters)
export const useServiceSearchTerm = () => useAppStore((state: any) => state.filters[SERVICES].search)
export const useServiceFilterLabelValues = () => useAppStore((state: any) => state.filters[SERVICES].filterLabelValues)
export const useServicePredefinedFilters = () => useAppStore((state: any) => state.filters[SERVICES].predefinedFilters)
export const useServiceActivePredefinedFilter = () =>
useAppStore((state: any) => state.filters[SERVICES].activePredefinedFilter)

// Filter exports for Components
export const useComponentFilterLabels = () => useAppStore((state: any) => state.filters[COMPONENTS].labels)
export const useComponentActiveFilters = () => useAppStore((state: any) => state.filters[COMPONENTS].activeFilters)
export const useComponentSearchTerm = () => useAppStore((state: any) => state.filters[COMPONENTS].search)
export const useComponentFilterLabelValues = () =>
useAppStore((state: any) => state.filters[COMPONENTS].filterLabelValues)
export const useComponentPredefinedFilters = () =>
useAppStore((state: any) => state.filters[COMPONENTS].predefinedFilters)
export const useComponentActivePredefinedFilter = () =>
useAppStore((state: any) => state.filters[COMPONENTS].activePredefinedFilter)

// Filter actions
export const useFilterActions = () => useAppStore((state: any) => state.filters.actions)

export default StoreProvider
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import HintNotFound from "../shared/HintNotFound"
import HintLoading from "../shared/HintLoading"
import ComponentsListItem from "./ComponentsListItem"

const ComponentsList = ({ items, isLoading }) => {
const ComponentsList = ({ items, isLoading }: any) => {
return (
<DataGrid minContentColumns={[2, 3]} columns={4}>
<DataGridRow>
Expand Down Expand Up @@ -52,7 +52,7 @@ const ComponentsList = ({ items, isLoading }) => {
<>
{items?.length > 0 ? (
<>
{items.map((item, index) => (
{items.map((item: any, index: any) => (
<ComponentsListItem key={index} item={item}></ComponentsListItem>
))}
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
import React from "react"
import { DataGridRow, DataGridCell } from "@cloudoperators/juno-ui-components"

const sumTotalInstances = (versions) => {
const sumTotalInstances = (versions: any) => {
let sum = 0
versions.forEach((v) => (sum += v?.node?.componentInstances?.totalCount))
versions.forEach((v: any) => (sum += v?.node?.componentInstances?.totalCount))
return sum
}
const ComponentsListItem = ({ item }) => {
const ComponentsListItem = ({ item }: any) => {
return (
<DataGridRow>
<DataGridCell>{item?.node?.ccrn}</DataGridCell>
Expand Down
Loading
Loading