Skip to content

Commit

Permalink
Merge pull request #32 from unity-sds/features/create-health-dashboard
Browse files Browse the repository at this point in the history
Create health dashboard and integrate dynamic navbar
  • Loading branch information
anilnatha authored May 20, 2024
2 parents c38b6ec + 67cd0a1 commit a1f1659
Show file tree
Hide file tree
Showing 21 changed files with 1,135 additions and 477 deletions.
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
18.16.0
lts/hydrogen
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased (0.6.0)
- Added Health Dashboard using static JSON file containing example health information. [#29](https://github.com/unity-sds/unity-ui/issues/29)
- Updated navbar menu so that it is (partially) dynamic. External UI information is loaded via the Health JSON file. [#20](https://github.com/unity-sds/unity-ui/issues/20)

## [0.5.0] 2024-04-15
- Updated Navbar CSS styling to match Figma designs [#5](https://github.com/unity-sds/unity-ui/issues/5)
- Added CI/CD workflow to build application as a docker image. [#21](https://github.com/unity-sds/unity-ui/issues/21)
Expand Down
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
window.EventEmitter = EventEmitter;
</script>
<script type="module">
import "/src/styles/variables.scss";
import "/src/styles/styles.scss";
</script>

</head>
Expand Down
1,030 changes: 669 additions & 361 deletions package-lock.json

Large diffs are not rendered by default.

7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "unity-ui",
"private": true,
"version": "0.5.0",
"version": "0.6.0",
"type": "module",
"scripts": {
"dev": "vite",
Expand All @@ -10,8 +10,10 @@
"preview": "vite preview"
},
"dependencies": {
"@reduxjs/toolkit": "^2.2.3",
"ag-grid-community": "^30.0.0",
"ag-grid-react": "^30.0.0",
"axios": "^1.6.8",
"crypto-browserify": "^3.12.0",
"events": "^3.3.0",
"jwt-decode": "^3.1.2",
Expand All @@ -20,14 +22,15 @@
"react-dom": "^18.2.0",
"react-helmet-async": "^1.3.0",
"react-oauth2-pkce": "^2.0.7",
"react-redux": "^9.1.2",
"react-resizable-panels": "^0.0.51",
"react-router-dom": "^6.11.2",
"stream-browserify": "^3.0.0",
"styled-components": "^5.3.10",
"util": "^0.12.5"
},
"devDependencies": {
"@nasa-jpl/react-stellar": "^1.1.2",
"@nasa-jpl/react-stellar": "^1.1.10",
"@types/react": "^18.2.7",
"@types/react-dom": "^18.2.4",
"@types/styled-components": "^5.1.26",
Expand Down
32 changes: 32 additions & 0 deletions public/data/health.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[
{
"service": "airflow",
"landingPage":"https://unity.jpl.nasa.gov/project/venue/processing/ui",
"healthChecks": [
{
"status": "HEALTHY",
"date": "2024-04-09T18:01:08Z"
}
]
},
{
"service": "jupyter",
"landingPage":"https://unity.jpl.nasa.gov/project/venue/ads/jupyter",
"healthChecks": [
{
"status": "HEALTHY",
"date": "2024-04-09T18:01:08Z"
}
]
},
{
"service": "other_service",
"landingPage":"https://unity.jpl.nasa.gov/project/venue/other_service",
"healthChecks": [
{
"status": "UNHEALTHY",
"date": "2024-04-09T18:01:08Z"
}
]
}
]
2 changes: 0 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import Root from "./Root"

import './css/app.css'

function App() {
return (
<Root />
Expand Down
4 changes: 4 additions & 0 deletions src/AuthenticationWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import App from './App';
import {AuthProvider, AuthService, useAuth} from 'react-oauth2-pkce'
import jwt_decode from "jwt-decode";
import styled from 'styled-components';
import { Provider } from 'react-redux';
import { store } from './state/store.ts';

import Config from './Config';

Expand Down Expand Up @@ -178,7 +180,9 @@ function AuthenticationWrapper() {
refreshToken = "";

return (
<Provider store={store}>
<App />
</Provider>
);
}

Expand Down
107 changes: 72 additions & 35 deletions src/Root.tsx
Original file line number Diff line number Diff line change
@@ -1,51 +1,88 @@
import {
Route,
Routes,
Route,
Routes,
} from "react-router-dom"

import Home from "./routes/home"
import Home from "./routes/home";
import HealthDashboard from "./routes/health-dashboard";
import JobMonitoring from "./routes/jobs/monitoring";
import NewJob from "./routes/jobs/new";

import Navbar from "./components/Navbar"
import WebView from "./components/WebView";

import Config from "./Config";

import { getProcesses, getProcessRoute } from "./utils/processes";
import NotFound from "./routes/errors/not-found";
import { healthDataRequiresFetchOrUpdate } from "./state/selectors/healthSelectors";
import { useAppDispatch, useAppSelector } from "./state/hooks";
import { useEffect } from "react";
import { getHealthData } from "./state/slices/healthSlice";

function Root() {

const processes = getProcesses();

return (
<div className="viewWrapper">
<Navbar />
<div className="view">
<Routes>
<Route path="/applications/catalog" element={<WebView url={Config.ads.url} />} />
<Route path="/jobs/monitoring" element={<JobMonitoring />} />
<Route path="/jobs/monitoring/:jobid_param" element={<JobMonitoring />} />
<Route path="/jobs/new" element={<NewJob />} />

{
/* Add routes for job execution forms */
processes.map( (item) => {
const path = "/jobs/new/" + item['id'];
const route:JSX.Element | null = getProcessRoute(item['id']);
return (
<Route path={path} element={ (route) ? route : <NotFound />} key={"route_" + item['id']}/>
)
})
}

<Route path="/" element={<Home />} />
<Route path="*" element={<NotFound />} />
</Routes>
</div>
</div>
)

const dispatch = useAppDispatch();
const processes = getProcesses();

const healthState = useAppSelector((state) => {
return state.health;
});

useEffect(() => {

//let isMounted = true;

// Check if data manager status is 'idle', then fetch the investigations data from the API
if (healthDataRequiresFetchOrUpdate(healthState)) {
dispatch(getHealthData());
}

if (healthState.status === "pending") {
// Do something to inform user that investigation data is being fetched
} else if (healthState.status === "succeeded") {
// Do something to handle the successful fetching of data
} else if (healthState.error != null || healthState.error != undefined) {
// Do something to handle the error
console.log(healthState.error);
}

// Cleanup function
return () => {
//isMounted = false;
};

}, [healthState, dispatch]);

return (
<div className="viewWrapper">
<Navbar />
<div className="view">
<Routes>
{
healthState.items.map( (item, index) => {
return <Route key={index} path={"/applications/" + item.service} element={<WebView url={item.landingPage} />} />
})
}
{/*<Route path="/applications/catalog" element={<WebView url={Config.ads.url} />} />*/}
<Route path="/health-dashboard" element={<HealthDashboard />} />
<Route path="/jobs/monitoring" element={<JobMonitoring />} />
<Route path="/jobs/monitoring/:jobid_param" element={<JobMonitoring />} />
<Route path="/jobs/new" element={<NewJob />} />
{
/* Add routes for job execution forms */
processes.map( (item) => {
const path = "/jobs/new/" + item['id'];
const route:JSX.Element | null = getProcessRoute(item['id']);
return (
<Route path={path} element={ (route) ? route : <NotFound />} key={"route_" + item['id']}/>
)
})
}
<Route path="/" element={<Home />} />
<Route path="*" element={<NotFound />} />
</Routes>
</div>
</div>
)
}

export default Root;
Loading

0 comments on commit a1f1659

Please sign in to comment.