Skip to content

Commit

Permalink
fixed react state issues and automated Risk Theme creation in friesto…
Browse files Browse the repository at this point in the history
…re (#1406)
  • Loading branch information
deekalra authored Dec 10, 2024
1 parent a553464 commit 0b3f5ac
Show file tree
Hide file tree
Showing 14 changed files with 343 additions and 223 deletions.
270 changes: 153 additions & 117 deletions examples/risk-analysis-asset/frontend/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,15 @@

import "./App.css";
import React, { useState, useEffect } from "react";
import { BrowserRouter, Routes, Route, Link, NavLink } from "react-router-dom";
import {
BrowserRouter,
Routes,
Route,
Link,
NavLink,
useNavigate,
useLocation,
} from "react-router-dom";
import UserJourneys from "./components/UserJourneys";
import NewRisk from "./components/NewRisk";
import NewApplication from "./components/NewApplication";
Expand All @@ -34,44 +42,73 @@ function App() {
const [appOptions, setAppOptions] = useState([]);
const [applicationId, setApplicationId] = useState(null);
const [isAddingNewApplication, setIsAddingNewApplication] = useState(false);
const [isSidebarOpen, setIsSidebarOpen] = useState(true); // Initially open
const [isSidebarOpen, setIsSidebarOpen] = useState(true);
const [idToken, setIdToken] = useState(null);

const toggleSidebar = () => {
setIsSidebarOpen(!isSidebarOpen);
};
const isOnNewApplicationPage = location.pathname === "/newApplication";

const backendURL =
process.env.REACT_APP_ENV === "local"
? "http://127.0.0.1:5000"
: process.env.REACT_APP_BACKEND_SERVICE_URL;

//console.log(backendURL)
const toggleSidebar = () => {
setIsSidebarOpen(!isSidebarOpen);
};

//fetching bearer token
const fetchJourneys = async () => {
if (!idToken || !selectedApplication.length) return;
try {
const response = await fetch(
`${backendURL}/api/${selectedApplication[0]?.id}/cujs`,
{
method: "GET",
headers: {
Authorization: `Bearer ${idToken}`,
"Content-Type": "application/json",
},
}
);
if (!response.ok) {
throw new Error("Network response was not ok");
}
const data = await response.json();

const journeyData = data
? data
.map((cuj) => ({
name: cuj.CUJName,
id: cuj.id,
}))
.sort((a, b) => a.name.localeCompare(b.name))
: [];
setJourneys(journeyData);
} catch (error) {
console.error("Error fetching journeys:", error);
toast.error("Error fetching journeys.");
}
};

// Fetch ID Token
useEffect(() => {
const fetchIdToken = async () => {
try {
const response = await fetch("http://localhost:3001/get-id-token");
const data = await response.json();
setIdToken(data.idToken);
console.log("ID Token:", data.idToken);
} catch (error) {
console.error("Error fetching ID token:", error);
}
};
fetchIdToken();
}, []);
console.log(idToken);

// Fetch Applications
useEffect(() => {
const fetchApplications = async () => {
if (!idToken) return;
try {
//fetch applications
const response = await fetch(`${backendURL}/api/apps`, {
method: "GET",
//mode: 'cors',
headers: {
Authorization: `Bearer ${idToken}`,
"Content-Type": "application/json",
Expand All @@ -82,7 +119,6 @@ function App() {
}
const appData = await response.json();

// Extract App names
const options = appData
.map((appInfo) => ({
name: appInfo.applicationName,
Expand All @@ -91,8 +127,17 @@ function App() {
.sort((a, b) => a.name.localeCompare(b.name));
setAppOptions(options);

if (appOptions.length > 0) {
setSelectedApplication(options[0]);
if (selectedApplication.length > 0) {
const currentSelection = options.find(
(option) => option.id === selectedApplication[0]?.id
);
if (currentSelection) {
setSelectedApplication([currentSelection]);
} else if (options.length > 0) {
setSelectedApplication([options[0]]);
}
} else if (options.length > 0) {
setSelectedApplication([options[0]]);
}
} catch (error) {
toast.error("Error fetching App Names.");
Expand All @@ -102,112 +147,45 @@ function App() {
fetchApplications();
}, [idToken]);

// Fetch Journeys
useEffect(() => {
const fetchJourneys = async () => {
if (!idToken) return;
try {
//fetch journeys for the selected pplication
console.log("fetching journeys, token", idToken);
const response = await fetch(
`${backendURL}/api/${selectedApplication[0]?.id}/cujs`,
{
method: "GET",
//mode: 'cors',
headers: {
Authorization: `Bearer ${idToken}`,
"Content-Type": "application/json",
},
}
);
if (!response.ok) {
throw new Error("Network response was not ok");
}
const data = await response.json();

if (data === null || data.length === 0) {
console.log("No journeys found for this application");
setJourneys([]);
} else {
// Extract journey names and IDs from the response
const journeyData = data
.map((cuj) => ({
name: cuj.CUJName,
id: cuj.id,
}))
.sort((a, b) => a.name.localeCompare(b.name));

setJourneys(journeyData);
}
} catch (error) {
console.error("Error fetching journeys:", error);
toast.error("Error fetching journeys.");
}
};
if (selectedApplication && selectedApplication.length > 0) {
if (selectedApplication.length) {
fetchJourneys();
}
}, [selectedApplication, idToken]);

const handleApplicationChange = (selectedList) => {
if (selectedList.length > 0) {
setSelectedApplication(selectedList);
setApplicationId(selectedList[0].id);
}
};

return (
<BrowserRouter>
<nav className="navbar">
<div className="nav-container">
<div>
<button className="toggle-button" onClick={toggleSidebar}>
<FontAwesomeIcon icon={faBars} />
</button>
</div>
<div className="navbar-title">
<a href="/newApplication">SRE Risk Analysis Tool</a>{" "}
{/* Current Home page is add a CUJ */}
</div>
</div>
<div className="application-dropdown">
<Multiselect
options={appOptions} // Options to display in the dropdown
selectedValues={selectedApplication} // Preselected value to persist in dropdown
onSelect={handleApplicationChange}
onRemove={handleApplicationChange}
displayValue="name" // Property name to display in the dropdown options
placeholder="Select Application"
singleSelect={true}
closeOnSelect={true}
disable={isAddingNewApplication}
/>
</div>
<div className="navbar-links">
<Link to={`/newApplication`}>Add a New Application</Link>
<Link to={`/newUserJourney`}>Add a User Journey</Link>
<Link to={`/newRisk`}>Add a New Risk</Link>
</div>
</nav>
<Navbar
appOptions={appOptions}
selectedApplication={selectedApplication}
setSelectedApplication={setSelectedApplication}
setApplicationId={setApplicationId}
isAddingNewApplication={isAddingNewApplication}
toggleSidebar={toggleSidebar}
showMultiselect={!isOnNewApplicationPage}
/>
<div className="container">
<div className={`sidebar ${isSidebarOpen ? "open" : "closed"}`}>
<ul>
{journeys.length > 0 ? ( // Render only if journeys has items
journeys.map((journey) => (
<li key={journey.id}>
<NavLink
to={`/riskCatalog/${journey.id}`}
state={{ journeyData: journey }}
>
{" "}
{journey.name}
</NavLink>
</li>
))
) : (
<p>No Journeys added</p>
)}
</ul>
</div>
{!isOnNewApplicationPage && (
<div className={`sidebar ${isSidebarOpen ? "open" : "closed"}`}>
<ul>
{journeys.length > 0 ? (
journeys.map((journey) => (
<li key={journey.id}>
<NavLink
to={`/riskCatalog/${journey.id}`}
state={{ journeyData: journey }}
>
{journey.name}
</NavLink>
</li>
))
) : (
<p>No Journeys added</p>
)}
</ul>
</div>
)}
<div className="key-content">
<Routes>
<Route
Expand All @@ -218,6 +196,7 @@ function App() {
backendURL={backendURL}
key={`newJourney-${applicationId}`}
idToken={idToken}
refreshJourneys={fetchJourneys}
/>
}
/>
Expand Down Expand Up @@ -245,12 +224,12 @@ function App() {
/>
<Route
path="/riskCatalog/:cujId"
key={`route-${applicationId}`}
element={
<RiskCatalog
journeys={journeys}
backendURL={backendURL}
applicationId={applicationId}
key={`riskcatalog-${applicationId}`}
idToken={idToken}
/>
}
Expand All @@ -274,11 +253,68 @@ function App() {
</Routes>
</div>
</div>
<div>
<ToastContainer />
</div>
<ToastContainer />
</BrowserRouter>
);
}

function Navbar({
appOptions,
selectedApplication,
setSelectedApplication,
setApplicationId,
isAddingNewApplication,
toggleSidebar,
showMultiselect,
}) {
const navigate = useNavigate();
const location = useLocation();

const handleApplicationChange = (selectedList) => {
if (selectedList.length > 0) {
setSelectedApplication(selectedList);
setApplicationId(selectedList[0].id);

if (location.pathname.startsWith("/riskCatalog/")) {
navigate("/riskCatalog", { replace: true });
}
}
};

return (
<nav className="navbar">
<div className="nav-container">
<div>
<button className="toggle-button" onClick={toggleSidebar}>
<FontAwesomeIcon icon={faBars} />
</button>
</div>
<div className="navbar-title">
<a href="/newApplication">SRE Risk Analysis Tool</a>
</div>
</div>
<div className="application-dropdown">
{showMultiselect && (
<Multiselect
options={appOptions}
selectedValues={selectedApplication}
onSelect={handleApplicationChange}
onRemove={handleApplicationChange}
displayValue="name"
placeholder="Select Application"
singleSelect={true}
closeOnSelect={true}
disable={isAddingNewApplication}
/>
)}
</div>
<div className="navbar-links">
<Link to={`/newApplication`}>Add a New Application</Link>
<Link to={`/newUserJourney`}>Add a User Journey</Link>
<Link to={`/newRisk`}>Add a New Risk</Link>
</div>
</nav>
);
}

export default App;
Loading

0 comments on commit 0b3f5ac

Please sign in to comment.