Skip to content

Commit

Permalink
chore(dashboard): enable standalone deployments of Greenhouse UI (#524)
Browse files Browse the repository at this point in the history
* chore(dashboard): remove dependencies to auth app and utils

* chore(dashboard): remove dependency to auth app and adopt dockerfile

* chore(ui): improve Dockerfile

* chore(ui): add oauth to jest config ignore section

* chore(ui): add Readme for dockerized version

* fix(org-admin-ui): use the new signature of mount method

* chore(ui): remove obsolete code

* Automatic application of license header

---------

Co-authored-by: License Bot <license_bot@github.com>
  • Loading branch information
andypf and License Bot authored Sep 5, 2024
1 parent fb613c3 commit c06290b
Show file tree
Hide file tree
Showing 23 changed files with 840 additions and 117 deletions.
2 changes: 1 addition & 1 deletion ui/dashboard/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module.exports = {
testEnvironment: "jsdom",
setupFilesAfterEnv: ["<rootDir>/setupTests.js"],
transformIgnorePatterns: [
"node_modules/(?!(@cloudoperators/juno-ui-components|@cloudoperators/juno-communicator|@cloudoperators/juno-messages-provider|@cloudoperators/juno-utils|@cloudoperators/juno-url-state-provider-v1)/)",
"node_modules/(?!(@cloudoperators/juno-ui-components|@cloudoperators/juno-communicator|@cloudoperators/juno-messages-provider|@cloudoperators/juno-url-state-provider-v1|@cloudoperators/juno-oauth)/)",
],
moduleNameMapper: {
// Jest currently doesn't support resources with query parameters.
Expand Down
56 changes: 31 additions & 25 deletions ui/dashboard/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 8 additions & 11 deletions ui/dashboard/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "greenhouse-dashboard",
"version": "0.1.26",
"orgAdminVersion": "1.1.20",
"orgAdminVersion": "latest",
"author": "UI-Team",
"contributors": [
"Andreas Pfau",
Expand Down Expand Up @@ -35,9 +35,9 @@
"postcss": "^8.4.21",
"postcss-url": "^10.1.3",
"prop-types": "^15.8.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-test-renderer": "18.2.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-test-renderer": "^18.2.0",
"sapcc-k8sclient": "^1.0.2",
"sass": "^1.77.5",
"shadow-dom-testing-library": "^1.7.1",
Expand All @@ -52,19 +52,16 @@
},
"peerDependencies": {
"prop-types": "^15.8.1",
"react": "18.2.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"zustand": "4.5.5"
},
"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"
},
"importmapExtras": {
"zustand/middleware": "4.5.2"
"@cloudoperators/juno-oauth": "^1.2.7",
"@cloudoperators/juno-ui-components": "^2.16.0",
"@cloudoperators/juno-url-state-provider-v1": "^1.3.2"
},
"appProps": {
"authIssuerUrl": {
Expand Down
28 changes: 26 additions & 2 deletions ui/dashboard/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
~ SPDX-License-Identifier: Apache-2.0
-->



<!DOCTYPE html>
<html lang="en">
<head>
Expand Down Expand Up @@ -35,6 +33,32 @@
location.reload()
)
</script>
<script type="importmap">
{
"imports": {
"@tanstack/react-query": "https://esm.sh/v135/*@tanstack/react-query@5.51.23",
"react-dom": "https://esm.sh/v135/*react-dom@18.3.1",
"react-dom/": "https://esm.sh/v135/*react-dom@18.3.1/",
"react": "https://esm.sh/v135/react@18.3.1",
"react/": "https://esm.sh/v135/react@18.3.1/",
"zustand": "https://esm.sh/v135/*zustand@4.5.4",
"zustand/": "https://esm.sh/v135/*zustand@4.5.4/",
"prop-types": "https://esm.sh/v135/*prop-types@15.8.1",
"luxon": "https://esm.sh/v135/luxon@3.5.0",
"oauth": "https://esm.sh/@cloudoperators/juno-oauth@1.2.7",
"juno-ui-components": "https://esm.sh/@cloudoperators/juno-ui-components@2.16.0"
},
"scopes": {
"https://esm.sh/v135/": {
"@tanstack/query-core": "https://esm.sh/v135/@tanstack/query-core@5.51.21",
"loose-envify": "https://esm.sh/v135/loose-envify@1.4.0",
"scheduler": "https://esm.sh/v135/scheduler@0.23.2",
"use-sync-external-store": "https://esm.sh/v135/use-sync-external-store@1.2.2",
"use-sync-external-store/": "https://esm.sh/v135/use-sync-external-store@1.2.2/"
}
}
}
</script>
</head>
<body>
<script type="module">
Expand Down
12 changes: 12 additions & 0 deletions ui/dashboard/secretProps.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Greenhouse contributors
* SPDX-License-Identifier: Apache-2.0
*/

module.exports = {
authIssuerUrl: "https://auth.greenhouse-qa.eu-nl-1.cloud.sap",
authClientId: "greenhouse",
currentHost: "https://assets.juno.qa-de-1.cloud.sap",
apiEndpoint: "https://api.greenhouse-qa.eu-nl-1.cloud.sap",
environment: "dev",
}
53 changes: 13 additions & 40 deletions ui/dashboard/src/components/Auth.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ import {
useGlobalsActions,
useGlobalsAssetsHost,
} from "../components/StoreProvider"
import { useAppLoader } from "@cloudoperators/juno-utils"
import { useActions } from "@cloudoperators/juno-messages-provider"
import { useAuthentication } from "../hooks/useAuthentication"

const currentUrl = new URL(window.location.href)
let match = currentUrl.host.match(/^(.+)\.dashboard\..+/)
Expand All @@ -36,10 +35,6 @@ let orgName = match ? match[1] : currentUrl.searchParams.get("org")
* - mock: A flag indicating whether to use mock authentication.
* - children: The content to be displayed when the user is logged in.
*
* The component uses custom hooks to handle authentication states and data. It dynamically loads the authentication
* app via the use of the useAppLoader hook. When mounted, the component connects to the authentication events,
* allowing seamless authentication experiences.
*
* The Auth component renders three main sections:
* 1. A div element with a data-app attribute set to "greenhouse-auth" and a ref for loading the authentication app.
* 2. If the user is logged in, the children are rendered.
Expand All @@ -49,35 +44,19 @@ let orgName = match ? match[1] : currentUrl.searchParams.get("org")
*
* Note: The component reads organization information from the token and adjusts the URL accordingly after the user is logged in.
*/
const Auth = ({
clientId,
issuerUrl,
mock,
children,
demoOrg,
demoUserToken,
}) => {
const assetsHost = useGlobalsAssetsHost()
const Auth = ({ clientId, issuerUrl, mock, children, demoOrg }) => {
const authAppLoaded = useAuthAppLoaded()
const authLoggedIn = useAuthLoggedIn()
const authIsProcessing = useAuthIsProcessing()
const authError = useAuthError()
const { login } = useAuthActions()
const { setDemoMode } = useGlobalsActions()
const { addMessage } = useActions()

const ref = createRef()
const { mount } = useAppLoader(assetsHost)
const [loading, setLoading] = useState(!authAppLoaded)
const [longLoading, setLongLoading] = useState(false)

// in this useEffect we load the auth app via import (see mount)
// It should happen just once!
// The connection to the auth events happens in the useCommunication hook!
// wait until assetsHost is set to avoid a warning on mount
useEffect(() => {
if (!assetsHost || !clientId || !issuerUrl) return

// if current orgName is the demo org, we mock the auth app
if (demoOrg === orgName) {
// we mock the auth app with default groups
Expand All @@ -88,24 +67,18 @@ const Auth = ({
// see in useCommunication hook, there we redefine the authData.JWT wit demoUserToken if demo mode is set
setDemoMode(true)
}
}, [setDemoMode])

mount(ref.current, {
id: "auth",
name: "auth",
version: "latest",
props: {
issuerUrl: issuerUrl,
clientId: clientId,
mock: mock,
debug: true,
initialLogin: true,
requestParams: JSON.stringify({
connector_id: !orgName ? undefined : orgName,
}),
},
})
// add mount to the dependencies since it changes depending on the assetsHost
}, [mount, clientId, issuerUrl, assetsHost])
useAuthentication({
issuerURL: issuerUrl,
clientID: clientId,
mock,
debug: true,
initialLogin: true,
requestParams: JSON.stringify({
connector_id: !orgName ? undefined : orgName,
}),
})

// timeout for waiting for auth
useEffect(() => {
Expand Down
8 changes: 4 additions & 4 deletions ui/dashboard/src/components/Plugin.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@
*/

import React, { useEffect, useState, useMemo, useRef } from "react"
import { useAppLoader } from "@cloudoperators/juno-utils"
import { mount } from "../lib/appLoader"
import { usePlugin, useGlobalsAssetsHost } from "../components/StoreProvider"
import { Messages, useActions } from "@cloudoperators/juno-messages-provider"
import { parseError } from "../lib/helpers"
import { Stack, Button } from "@cloudoperators/juno-ui-components"

const Plugin = ({ id }) => {
const assetsHost = useGlobalsAssetsHost()
const { mount } = useAppLoader(assetsHost)
const holder = useRef()
const config = usePlugin().config()
const activeApps = usePlugin().active()
Expand All @@ -29,11 +28,12 @@ const Plugin = ({ id }) => {

// mount the app each time the component is reloaded losing the state
useEffect(() => {
if (!mount || !assetsHost || !config) return
if (!assetsHost || !config) return
// mount the app
mount(app.current, {
...config[id],
props: { ...config[id]?.props, embedded: true },
assetsHost,
appProps: { ...config[id]?.props, embedded: true },
})
.then((loaded) => {
if (!loaded) return
Expand Down
4 changes: 4 additions & 0 deletions ui/dashboard/src/hooks/useApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ const useApi = () => {
const version = conf.status?.uiApplication?.version
const url = conf.status?.uiApplication?.url

// console.log("===", name, version, manifest[name]?.[version])

// only add plugin if the url is from another host or the name with the given version is in the manifest!
if ((url && url.indexOf(assetsHost) < 0) || manifest[name]?.[version]) {
const newConf = createPluginConfig({
Expand All @@ -80,6 +82,8 @@ const useApi = () => {
}
})

// console.log(config)

return config
})
}, [client, assetsHost, namespace])
Expand Down
Loading

0 comments on commit c06290b

Please sign in to comment.