Skip to content

Commit 0d81285

Browse files
committed
feat(heureka): list services
1 parent c770519 commit 0d81285

File tree

15 files changed

+151
-102
lines changed

15 files changed

+151
-102
lines changed

.changeset/many-jars-obey.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"heureka-next": minor
3+
---
4+
5+
The app is now able to communicate with the GraphQL backend.

apps/heureka-next/.env.template

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
API_ENDPOINT=SOME_URL

apps/heureka-next/README.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,52 @@
44

55
This app will eventually become a successor to the existing Heureka app.
66

7+
## How to run locally?
8+
9+
1. Go to app directory:
10+
```bash
11+
cd apps/heureka-next
12+
```
13+
2. If you are running the app for the first time, follow these steps. Otherwise, skip to step 3:
14+
1. Create `appProps.json` and change the configurations accordingly:
15+
```bash
16+
cp appProps.template.json appProps.json
17+
```
18+
2. Create `.env` file and change configurations accordingly:
19+
```bash
20+
cp .env.template .env
21+
```
22+
3. Install dependencies:
23+
```bash
24+
npm i
25+
```
26+
4. Run the development server:
27+
```bash
28+
npm run dev
29+
```
30+
31+
## How to update GraphQL types?
32+
33+
1. Go to app directory:
34+
```bash
35+
cd apps/heureka-next
36+
```
37+
2. Update GraphQL types from the latest GraphQL schema:
38+
```bash
39+
npm run generate:types
40+
```
41+
42+
## How to run tests?
43+
44+
1. Go to app directory:
45+
```bash
46+
cd apps/heureka-next
47+
```
48+
2. Run tests:
49+
```bash
50+
npm run test
51+
```
52+
753
## Contributing
854

955
We welcome contributions from the community. Please follow our [contribution guidelines] to contribute to this project.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"apiEndpoint": "YOUR_GRAPHQL_API_ENDPOINT",
3+
"embedded": false
4+
}

apps/heureka-next/codegen.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@ import * as dotenv from "dotenv"
33

44
// Load environment variables from .env file
55
dotenv.config()
6-
const schemaUrl = ""
76

87
const config: CodegenConfig = {
9-
schema: schemaUrl,
8+
schema: process.env.API_ENDPOINT,
109
documents: "src/**/*.graphql",
1110

1211
generates: {

apps/heureka-next/index.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,19 @@
77
<title>Heureka Next</title>
88
</head>
99
<body>
10+
<script type="module">
11+
// appProps are excluded from standalone build and should be generated from outside
12+
fetch("./appProps.json")
13+
.then((res) => res.json())
14+
.catch((error) => {
15+
console.warn("No appProps found, using default props", error.message)
16+
})
17+
.then((props) => {
18+
import("./src/index").then((app) => {
19+
app.mount(document.getElementById("root"), props)
20+
})
21+
})
22+
</script>
1023
<div id="root"></div>
1124
<script type="module" src="/src/index.tsx"></script>
1225
</body>

apps/heureka-next/src/App.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,22 @@ import { AppShellProvider } from "@cloudoperators/juno-ui-components"
88
import { ErrorBoundary } from "./components/ErrorBoundary"
99
import { Shell } from "./components/Shell"
1010
import { ApolloProvider } from "@apollo/client"
11-
import { client } from "./apollo-client"
11+
import { getClient } from "./apollo-client"
1212

1313
export type AppProps = {
1414
theme?: "theme-dark" | "theme-light"
15+
apiEndpoint?: string
1516
embedded?: boolean
1617
}
1718

18-
export const App = (props: AppProps) => (
19-
<ApolloProvider client={client}>
19+
const App = (props: AppProps) => (
20+
<ApolloProvider client={getClient({ uri: props.apiEndpoint })}>
2021
<AppShellProvider theme={`${props.theme ? props.theme : "theme-dark"}`}>
2122
<ErrorBoundary>
2223
<Shell {...props} />
2324
</ErrorBoundary>
2425
</AppShellProvider>
25-
<App />
2626
</ApolloProvider>
2727
)
28+
29+
export default App
Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
import { ApolloClient, InMemoryCache } from "@apollo/client"
22

3-
export const client = new ApolloClient({
4-
uri: "",
5-
cache: new InMemoryCache(),
6-
})
3+
type ClientOptions = {
4+
uri?: string
5+
}
6+
7+
export const getClient = ({ uri }: ClientOptions) => {
8+
if (typeof uri === "undefined") {
9+
throw new Error("No API endpoint provided.")
10+
}
11+
return new ApolloClient({
12+
uri,
13+
cache: new InMemoryCache(),
14+
})
15+
}

apps/heureka-next/src/components/Services/Services.test.tsx

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,42 @@
55

66
import React from "react"
77
import { render, screen } from "@testing-library/react"
8+
import { MockedProvider } from "@apollo/client/testing"
89
import { Services } from "./Services"
10+
import { GetServicesDocument } from "../../generated/graphql"
11+
12+
const mocks = [
13+
{
14+
request: {
15+
query: GetServicesDocument,
16+
},
17+
result: {
18+
data: {
19+
Services: {
20+
edges: [
21+
{
22+
node: {
23+
id: "some-id",
24+
ccrn: "some-ccrn",
25+
__typename: "Service",
26+
},
27+
__typename: "ServiceEdge",
28+
},
29+
],
30+
__typename: "ServiceConnection",
31+
},
32+
},
33+
},
34+
},
35+
]
936

1037
describe("Services", () => {
11-
it("should render correctly", () => {
12-
render(<Services />)
13-
expect(screen.getByText("render services here...")).toBeInTheDocument()
38+
it("should render correctly", async () => {
39+
render(
40+
<MockedProvider mocks={mocks}>
41+
<Services />
42+
</MockedProvider>
43+
)
44+
expect(await screen.findByText("some-ccrn")).toBeInTheDocument()
1445
})
1546
})

apps/heureka-next/src/components/Services/Services.tsx

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,5 @@ export const Services = () => {
1111
if (loading) return <p>Loading...</p>
1212
if (error) return <p>Error</p>
1313

14-
return (
15-
<div>
16-
{data?.Services?.edges?.map((service) => {
17-
console.log("TEST NAME", service?.node.ccrn)
18-
return <p>{service?.node.ccrn}</p>
19-
})}
20-
</div>
21-
)
14+
return <div>{data?.Services?.edges?.map((service) => <div key={service?.node.id}>{service?.node.ccrn}</div>)}</div>
2215
}

apps/heureka-next/src/components/Shell/Shell.test.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ import { render, screen } from "@testing-library/react"
88
import userEvent from "@testing-library/user-event"
99
import { Shell } from "./Shell"
1010

11+
/**
12+
* let's mock Services because that is a dependency of Shell
13+
* and has been tested independently
14+
**/
15+
vitest.mock("../Services/Services", () => ({
16+
Services: () => <div>render services here...</div>,
17+
}))
18+
1119
const renderShell = () => ({
1220
user: userEvent.setup(),
1321
...render(<Shell />),

apps/heureka-next/src/generated/graphql.tsx

Lines changed: 1 addition & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,33 +1354,7 @@ export type GetServicesQuery = {
13541354
__typename?: "ServiceConnection"
13551355
edges?: Array<{
13561356
__typename?: "ServiceEdge"
1357-
cursor?: string | null
1358-
node: {
1359-
__typename?: "Service"
1360-
id: string
1361-
ccrn?: string | null
1362-
objectMetadata?: {
1363-
__typename?: "ServiceMetadata"
1364-
componentInstanceCount: number
1365-
issueMatchCount: number
1366-
} | null
1367-
owners?: {
1368-
__typename?: "UserConnection"
1369-
edges?: Array<{
1370-
__typename?: "UserEdge"
1371-
cursor?: string | null
1372-
node: { __typename?: "User"; id: string; uniqueUserId?: string | null; name?: string | null }
1373-
} | null> | null
1374-
} | null
1375-
supportGroups?: {
1376-
__typename?: "SupportGroupConnection"
1377-
edges?: Array<{
1378-
__typename?: "SupportGroupEdge"
1379-
cursor?: string | null
1380-
node: { __typename?: "SupportGroup"; id: string; ccrn?: string | null }
1381-
} | null> | null
1382-
} | null
1383-
}
1357+
node: { __typename?: "Service"; id: string; ccrn?: string | null }
13841358
} | null> | null
13851359
} | null
13861360
}
@@ -1392,31 +1366,7 @@ export const GetServicesDocument = gql`
13921366
node {
13931367
id
13941368
ccrn
1395-
objectMetadata {
1396-
componentInstanceCount
1397-
issueMatchCount
1398-
}
1399-
owners {
1400-
edges {
1401-
node {
1402-
id
1403-
uniqueUserId
1404-
name
1405-
}
1406-
cursor
1407-
}
1408-
}
1409-
supportGroups {
1410-
edges {
1411-
node {
1412-
id
1413-
ccrn
1414-
}
1415-
cursor
1416-
}
1417-
}
14181369
}
1419-
cursor
14201370
}
14211371
}
14221372
}

apps/heureka-next/src/graphql/Services/getServices.graphql

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,7 @@ query GetServices($filter: ServiceFilter, $first: Int, $after: String) {
44
node {
55
id
66
ccrn
7-
objectMetadata {
8-
componentInstanceCount
9-
issueMatchCount
10-
}
11-
owners {
12-
edges {
13-
node {
14-
id
15-
uniqueUserId
16-
name
17-
}
18-
cursor
19-
}
20-
}
21-
supportGroups {
22-
edges {
23-
node {
24-
id
25-
ccrn
26-
}
27-
cursor
28-
}
29-
}
307
}
31-
cursor
328
}
339
}
3410
}

apps/heureka-next/src/index.tsx

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,21 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Greenhouse contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
16
import React from "react"
2-
import { createRoot } from "react-dom/client"
7+
import { createRoot, Root } from "react-dom/client"
38
import "tailwindcss/tailwind.css"
49
import "./index.scss"
5-
import { App } from "./App"
10+
import { AppProps } from "./App"
11+
12+
let root: Root
613

7-
const container: HTMLElement = document.getElementById("root")!
8-
const root = createRoot(container)
14+
export const mount = (container: HTMLElement, props: AppProps = {}) => {
15+
import("./App").then((App) => {
16+
root = createRoot(container)
17+
root.render(React.createElement(App.default, props))
18+
})
19+
}
920

10-
root.render(<App />)
21+
export const unmount = () => root?.unmount()

apps/heureka-next/vite.config.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export default defineConfig(({ mode }) => {
2828
server: {
2929
host: "0.0.0.0",
3030
port: parseInt(process.env.PORT || "3000"),
31+
allowedHosts: true,
3132
},
3233
}
3334

@@ -52,7 +53,7 @@ export default defineConfig(({ mode }) => {
5253
lib: {
5354
entry: "src/index.tsx",
5455
formats: ["es"],
55-
fileName: (format) => `index.js`,
56+
fileName: () => `index.js`,
5657
},
5758
},
5859
}

0 commit comments

Comments
 (0)