diff --git a/src/APIServices/ReportRunnerAPI.js b/src/APIServices/ReportRunnerAPI.js
index 0f4ac94..8b2a2f4 100644
--- a/src/APIServices/ReportRunnerAPI.js
+++ b/src/APIServices/ReportRunnerAPI.js
@@ -21,6 +21,7 @@ export const fetchAllReportsApi = async () => {
try {
const response = await apiService.get('/Rpt_builder2/Rpt_builder2'); // API call to fetch all reports
console.log("Fetch all reports response:", response.data);
+
return response.data; // Assuming response data comes in `data` field
} catch (error) {
console.error("Error while fetching all reports:", error);
diff --git a/src/App.js b/src/App.js
index 772d707..43680cf 100644
--- a/src/App.js
+++ b/src/App.js
@@ -43,7 +43,7 @@ import Login from "views/examples/Login";
import ResetPassword from "views/examples/resetPassword";
import ReportBuild2All from "components/Dashboard/Reportbuild2/Report-build2all/ReportBuild2All";
import ReportBuild2Add from "components/Dashboard/Reportbuild2/Report-build2add/ReportBuild2Add";
-import ReportBuild2Edit from "./components/Dashboard/Reportbuild2/Report-build2edit/ReportBuildEdit";
+import ReportBuild2Edit from "./components/Dashboard/Reportbuild2/Report-build2edit/ReportBuildEdit";
import ReportQuery from "components/Dashboard/Reportbuilder/reportQuery";
import DynamicForm from "components/Dashboard/DynamicForm/DynamicForm2";
import DynamicFormAdd from "components/Dashboard/DynamicForm/DynamicFormAdd";
@@ -67,90 +67,90 @@ import SequenceGenerator from "components/Dashboard/sequencegenerator";
const App = () => {
return (
-
- {/* ToastContainer should be placed in the root component */}
-
+
+ {/* ToastContainer should be placed in the root component */}
+
-
-
- } />
- } />
+
+
+ } />
+ } />
- {/* ptotecting the admin page */}
+{/* ptotecting the admin page */}
-
-
-
+
+
+
}>
- } />
- } />
- } />
-
- } />
- } />
- } />
- } />
- } />
-
- {/* Dynamic Routes */}
- } />
- } />
- } />
- } />
- } />
- {/* Static Routes */}
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
-
-
-
-
-
- {/* buildercomponents */}
-
- }>
- } />
- } />
-
-
-
-
+ {/*
} /> */}
+
} />
+
} />
+
+
}/>
+ } />
+ } />
+ } />
+ } />
+
+ {/* Dynamic Routes */}
+ } />
+ } />
+ } />
+ } />
+ } />
+ {/* Static Routes */}
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ }/>
+ }/>
+ }/>
+ }/>
+ }/>
+ }/>
+ {/* } /> */}
+ {/* buildercomponents */}
+
+
+
+
+
+ }>
+ } />
+ } />
+
+
+
+
);
};
diff --git a/src/ProtectedRoute.js b/src/ProtectedRoute.js
index a3e042f..5419a7e 100644
--- a/src/ProtectedRoute.js
+++ b/src/ProtectedRoute.js
@@ -1,11 +1,11 @@
+// ProtectedRoute.js
import React from "react";
import { Navigate } from "react-router-dom";
import { getToken } from "utils/tokenService";
const ProtectedRoute = ({ children }) => {
- console.log(`token for checking whether authenticated: ${getToken()}`);
- const isAuthenticated = getToken() !== null; // Check if user is authenticated
+ const isAuthenticated = getToken() !== null;
return isAuthenticated ? children : ;
};
-export default ProtectedRoute;
+export default ProtectedRoute;
\ No newline at end of file
diff --git a/src/components/Dashboard/AccessType.js b/src/components/Dashboard/AccessType.js
index b8b57e1..e0fc575 100644
--- a/src/components/Dashboard/AccessType.js
+++ b/src/components/Dashboard/AccessType.js
@@ -57,7 +57,7 @@ function AccessTypeManagement() {
useEffect(() => {
const fetchAccessTypes = async () => {
- const apiUrl = `${process.env.REACT_APP_API_URL}api/getAllAccessTypes`;
+ const apiUrl = `${process.env.REACT_APP_API_URL}token/access_type/Accesstype`;
const token = localStorage.getItem("authToken");
if (!token) {
diff --git a/src/components/Dashboard/TOKENRegistry.js b/src/components/Dashboard/TOKENRegistry.js
index b246ede..47412d7 100644
--- a/src/components/Dashboard/TOKENRegistry.js
+++ b/src/components/Dashboard/TOKENRegistry.js
@@ -20,31 +20,31 @@ function TOKENRegistry() {
id: "",
tokenName: "",
tokenValue: "",
- isActive: true
+ isActive: true,
+ scopes: []
});
const [currentPage, setCurrentPage] = useState(1);
const [searchQuery, setSearchQuery] = useState("");
const [isEditing, setIsEditing] = useState(false);
const [recordsPerPage, setRecordsPerPage] = useState(10);
- // Add to your state:
-const [visibleColumns, setVisibleColumns] = useState({
- id: true,
- tokenName: true,
- tokenValue: true,
- scopes: true,
- isActive: true,
- actions: true
-});
-
-
+ const [visibleColumns, setVisibleColumns] = useState({
+ id: true,
+ tokenName: true,
+ tokenValue: true,
+ scopes: true,
+ isActive: true,
+ actions: true
+ });
const [loading, setLoading] = useState(true);
+ const [selectedScope, setSelectedScope] = useState("");
const [selectedScopes, setSelectedScopes] = useState([]);
- const [availableScopes] = useState([
- { value: 'read', label: 'Read Access' },
- { value: 'write', label: 'Write Access' },
- { value: 'delete', label: 'Delete Access' },
- { value: 'admin', label: 'Admin Access' },
+ const [availableScopes] = useState([
+ { value: 'read', label: 'Read Access' },
+ { value: 'write', label: 'Write Access' },
+ { value: 'delete', label: 'Delete Access' },
+ { value: 'admin', label: 'Admin Access' },
]);
+
useEffect(() => {
fetchTokens();
}, []);
@@ -95,6 +95,7 @@ const [visibleColumns, setVisibleColumns] = useState({
setShowGenerateTokenModal(false);
setGeneratedToken("");
setNewTokenName("");
+ setSelectedScopes([]);
};
const handleRecordsPerPageChange = (number) => {
@@ -135,9 +136,10 @@ const [visibleColumns, setVisibleColumns] = useState({
}
};
- const openModal = (token = { id: "", tokenName: "", tokenValue: "", isActive: false }) => {
+ const openModal = (token = { id: "", tokenName: "", tokenValue: "", isActive: false, scopes: [] }) => {
setIsEditing(!!token.id);
setCurrentToken(token);
+ setSelectedScopes(token.scopes || []);
setShowAddEditModal(true);
};
@@ -153,24 +155,35 @@ const [visibleColumns, setVisibleColumns] = useState({
}
};
- const generateNewToken = async () => {
- if (!newTokenName.trim()) {
- toast.error("Please enter a token name");
- return;
- }
+ const addScope = () => {
+ if (selectedScope && !selectedScopes.includes(selectedScope)) {
+ setSelectedScopes([...selectedScopes, selectedScope]);
+ setSelectedScope("");
+ }
+ };
- try {
- const data = await tokenRegistryAPI.generateToken({
- name: newTokenName,
- scopes: selectedScopes
- });
- setGeneratedToken(data.tokenValue);
- toast.success("Token generated successfully!");
- fetchTokens();
- } catch (error) {
- handleApiError(error, "generate token");
- }
-};
+ const removeScope = (scopeToRemove) => {
+ setSelectedScopes(selectedScopes.filter(scope => scope !== scopeToRemove));
+ };
+
+ const generateNewToken = async () => {
+ if (!newTokenName.trim()) {
+ toast.error("Please enter a token name");
+ return;
+ }
+
+ try {
+ const data = await tokenRegistryAPI.generateToken({
+ name: newTokenName,
+ scopes: selectedScopes
+ });
+ setGeneratedToken(data.tokenValue);
+ toast.success("Token generated successfully!");
+ fetchTokens();
+ } catch (error) {
+ handleApiError(error, "generate token");
+ }
+ };
return (
@@ -305,6 +318,21 @@ const [visibleColumns, setVisibleColumns] = useState({
>
{token.isActive ? "Active" : "Inactive"}
+ ) : key === "scopes" ? (
+
+ {token.scopes && token.scopes.map(scope => {
+ const scopeInfo = availableScopes.find(s => s.value === scope);
+ return (
+
+ {scopeInfo?.label || scope}
+
+ );
+ })}
+
) : (
token[key]
)}
@@ -383,93 +411,245 @@ const [visibleColumns, setVisibleColumns] = useState({
- {/* Add/Edit Token Modal */}
+ {/* Generate Token Modal */}
-
- Generate New Token
-
-
-
-
- Token Name
- setNewTokenName(e.target.value)}
- required
- className="custom-hover-border"
- placeholder="Enter a name for the new token"
- />
-
+
+ Generate New Token
+
+
+
+
+ Token Name
+ setNewTokenName(e.target.value)}
+ required
+ className="custom-hover-border"
+ placeholder="Enter a name for the new token"
+ />
+
-
- Token Scopes
- {
- const options = [...e.target.options];
- const selectedValues = options
- .filter(option => option.selected)
- .map(option => option.value);
- setSelectedScopes(selectedValues);
- }}
- className="custom-hover-border"
- style={{ height: 'auto' }}
- >
- {availableScopes.map(scope => (
-
- {scope.label}
-
- ))}
-
-
- Select the permissions this token should have (hold Ctrl/Cmd to select multiple)
-
-
+
+ Token Scopes
+
+
setSelectedScope(e.target.value)}
+ className="custom-hover-border me-2"
+ >
+ Select a scope
+ {availableScopes.map(scope => (
+
+ {scope.label}
+
+ ))}
+
+
+ Add Scope
+
+
+
+ Select and add the permissions this token should have
+
+
+ {/* Display selected scopes as chips */}
+ {selectedScopes.length > 0 && (
+
+ {selectedScopes.map(scope => {
+ const scopeInfo = availableScopes.find(s => s.value === scope);
+ return (
+
+ {scopeInfo?.label || scope}
+ removeScope(scope)}
+ />
+
+ );
+ })}
+
+ )}
+
- {generatedToken && (
-
- Generated Token
-
-
- Copy this token and store it securely. You won't be able to see it again.
-
-
- )}
-
-
-
- Close
-
-
- Generate Token
-
-
-
-
-
+ {generatedToken && (
+
+ Generated Token
+
+
+ Copy this token and store it securely. You won't be able to see it again.
+
+
+ )}
+
+
+
+ Close
+
+
+ Generate Token
+
+
+
+
+
+
+ {/* Add/Edit Token Modal */}
+
+
+ {isEditing ? "Edit Token" : "Add Token"}
+
+
+
+
+ Token Name
+
+
+
+ Token Value
+
+
+
+ Token Scopes
+
+
setSelectedScope(e.target.value)}
+ className="custom-hover-border me-2"
+ >
+ Select a scope
+ {availableScopes.map(scope => (
+
+ {scope.label}
+
+ ))}
+
+ {
+ if (selectedScope && !currentToken.scopes.includes(selectedScope)) {
+ setCurrentToken(prev => ({
+ ...prev,
+ scopes: [...prev.scopes, selectedScope]
+ }));
+ setSelectedScope("");
+ }
+ }}
+ disabled={!selectedScope}
+ >
+ Add Scope
+
+
+
+ Select and add the permissions this token should have
+
+
+ {/* Display selected scopes as chips */}
+ {currentToken.scopes && currentToken.scopes.length > 0 && (
+
+ {currentToken.scopes.map(scope => {
+ const scopeInfo = availableScopes.find(s => s.value === scope);
+ return (
+
+ {scopeInfo?.label || scope}
+ {
+ setCurrentToken(prev => ({
+ ...prev,
+ scopes: prev.scopes.filter(s => s !== scope)
+ }));
+ }}
+ />
+
+ );
+ })}
+
+ )}
+
+
+
+
+
+
+ Close
+
+
+ {isEditing ? "Update Token" : "Add Token"}
+
+
+
+
+
)}
diff --git a/src/components/Sidebar/Sidebar.js b/src/components/Sidebar/Sidebar.js
index bc78fa8..b35c8e6 100644
--- a/src/components/Sidebar/Sidebar.js
+++ b/src/components/Sidebar/Sidebar.js
@@ -1,4 +1,4 @@
-import { useState } from "react";
+import { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import PropTypes from "prop-types";
import {
@@ -7,20 +7,86 @@ import {
MenuItem,
SubMenu,
} from "react-pro-sidebar";
-import { FaChevronLeft, FaChevronRight, FaDatabase, FaExclamationCircle } from "react-icons/fa";
+import { FaChevronLeft, FaChevronRight, FaDatabase, FaExclamationCircle, FaCircle } from "react-icons/fa";
+import { fetchMenuItems, getSubmenuItems } from "../../APIServices/MenuMaintenanceAPI";
import "../Sidebar/Sidebar.css";
const Sidebar = (props) => {
const [collapsed, setCollapsed] = useState(true);
+ const [menuItems, setMenuItems] = useState([]);
+ const [subMenuItems, setSubMenuItems] = useState({});
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState(null);
const navigate = useNavigate();
+ useEffect(() => {
+ const loadMenuData = async () => {
+ try {
+ const mainMenuItems = await fetchMenuItems();
+ setMenuItems(mainMenuItems);
+
+ const subMenuPromises = mainMenuItems.map(item =>
+ getSubmenuItems(item.menuItemId)
+ .then(subItems => subItems || [])
+ .catch(() => [])
+ );
+
+ const subMenus = await Promise.all(subMenuPromises);
+ const subMenuMap = {};
+ mainMenuItems.forEach((item, index) => {
+ subMenuMap[item.menuItemId] = subMenus[index];
+ });
+ setSubMenuItems(subMenuMap);
+ } catch (err) {
+ console.error("Failed to load menu data:", err);
+ setError(err.message);
+ } finally {
+ setLoading(false);
+ }
+ };
+ loadMenuData();
+ }, []);
+
const toggleSidebar = () => {
setCollapsed(!collapsed);
- if (props.onSidebarToggle) {
- props.onSidebarToggle(!collapsed);
+ props.onSidebarToggle?.(!collapsed);
+ };
+
+ const validatePath = (path) => {
+ if (!path || path === "#" || path === "null" || path === "undefined") {
+ return false;
+ }
+ return true;
+ };
+
+ const safeNavigate = (path) => {
+ if (!validatePath(path)) {
+ navigate("/admin/error404");
+ return;
+ }
+
+ // Ensure path starts with /admin/
+ const adminPath = path.startsWith("/admin/") ? path : `/admin/${path.replace(/^\//, '')}`;
+
+ try {
+ navigate(adminPath);
+ } catch (error) {
+ console.error(`Navigation failed:`, error);
+ navigate("/admin/error404");
}
};
+ const getIconComponent = (iconName) => {
+ switch (iconName) {
+ case "fa-database": return ;
+ case "fa-exclamation-circle": return ;
+ default: return ;
+ }
+ };
+
+ if (loading) return Loading...
;
+ if (error) return Error: {error}
;
+
return (
- }>
- navigate("/admin/regform")}>
- Regform
-
- navigate("/admin/error404")}>
- Additional container
-
-
-
- }
- onClick={() => navigate("/admin/error404")}
- >
- Masters
-
+ {menuItems.map((menuItem) => {
+ const subItems = subMenuItems[menuItem.menuItemId] || [];
+
+ if (subItems.length > 0) {
+ return (
+
+ {subItems.map((subItem) => (
+ safeNavigate(subItem.main_menu_action_name)}
+ >
+ {subItem.menuItemDesc}
+
+ ))}
+
+ );
+ }
+
+ return (
+ safeNavigate(menuItem.main_menu_action_name)}
+ >
+ {menuItem.menuItemDesc}
+
+ );
+ })}
@@ -71,4 +154,4 @@ Sidebar.propTypes = {
onSidebarToggle: PropTypes.func,
};
-export default Sidebar;
+export default Sidebar;
\ No newline at end of file