Compare commits

..

No commits in common. "main" and "saksham" have entirely different histories.

12 changed files with 25186 additions and 446 deletions

3
.env
View File

@ -1,3 +0,0 @@
GENERATE_SOURCEMAP=false
REACT_APP_API_URL=http://157.66.191.31:33730/back/

View File

@ -1,12 +0,0 @@
name: Autocloser
on: [issues]
jobs:
autoclose:
runs-on: ubuntu-latest
steps:
- name: Issue auto-closer
uses: roots/issue-closer-action@v1.1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
issue-close-message: "@${issue.user.login} this issue was automatically closed because it did not follow our rules:\n\n<pre>\n\n\n\nIMPORTANT: Please use the following link to create a new issue:\n\nhttps://www.creative-tim.com/new-issue/argon-dashboard-react\n\n**If your issue was not created using the app above, it will be closed immediately.**\n\n\n\nLove Creative Tim? Do you need Angular, React, Vuejs or HTML? You can visit:\n👉 https://www.creative-tim.com/bundles\n👉 https://www.creative-tim.com\n\n\n</pre>\n\n"
issue-pattern: (\#\#\# Version([\S\s.*]*?)\#\#\# Reproduction link([\S\s.*]*?)\#\#\# Operating System([\S\s.*]*?)\#\#\# Device([\S\s.*]*?)\#\#\# Browser & Version([\S\s.*]*?)\#\#\# Steps to reproduce([\S\s.*]*?)\#\#\# What is expected([\S\s.*]*?)\#\#\# What is actually happening([\S\s.*]*?)---([\S\s.*]*?)\#\#\# Solution([\S\s.*]*?)\#\#\# Additional comments([\S\s.*]*?)\<\!-- generated by creative-tim-issues\. DO NOT REMOVE --\>)|(\#\#\# What is your enhancement([\S\s.*]*?)\<\!-- generated by creative-tim-issues\. DO NOT REMOVE --\>)

12
.gitignore vendored
View File

@ -1,12 +0,0 @@
<<<<<<< HEAD
/build
/node_modules
package-lock.json
/build
=======
node_modules/
node_modules/
/build
package-lock.json
>>>>>>> 1c0592d (commit new code)
.eslintcache

3
.npmrc
View File

@ -1,3 +0,0 @@
legacy-peer-deps=true
auto-install-peers=true
strict-peer-dependencies=false

25036
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -26,7 +26,7 @@
"homepage": "https://demos.creative-tim.com/argon-dashboard-react/", "homepage": "https://demos.creative-tim.com/argon-dashboard-react/",
"scripts": { "scripts": {
"start": "react-scripts start", "start": "react-scripts start",
"build": "react-scripts build", "build": "cross-env PUBLIC_URL=/ react-scripts build",
"test": "react-scripts test", "test": "react-scripts test",
"eject": "react-scripts eject", "eject": "react-scripts eject",
"install:clean": "rm -rf node_modules/ && rm -rf package-lock.json && npm install && npm start", "install:clean": "rm -rf node_modules/ && rm -rf package-lock.json && npm install && npm start",
@ -71,7 +71,6 @@
"classnames": "2.3.2", "classnames": "2.3.2",
"cors-anywhere": "^0.4.4", "cors-anywhere": "^0.4.4",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"html2canvas": "^1.4.1",
"moment": "2.29.4", "moment": "2.29.4",
"multiselect-react-dropdown": "^2.0.25", "multiselect-react-dropdown": "^2.0.25",
"nouislider": "15.4.0", "nouislider": "15.4.0",

View File

@ -21,7 +21,6 @@ export const fetchAllReportsApi = async () => {
try { try {
const response = await apiService.get('/Rpt_builder2/Rpt_builder2'); // API call to fetch all reports const response = await apiService.get('/Rpt_builder2/Rpt_builder2'); // API call to fetch all reports
console.log("Fetch all reports response:", response.data); console.log("Fetch all reports response:", response.data);
return response.data; // Assuming response data comes in `data` field return response.data; // Assuming response data comes in `data` field
} catch (error) { } catch (error) {
console.error("Error while fetching all reports:", error); console.error("Error while fetching all reports:", error);

View File

@ -93,7 +93,7 @@ const App = () => {
<AdminLayout /> <AdminLayout />
</ProtectedRoute> </ProtectedRoute>
}> }>
{/* <Route path="regform" element={<Regform />} /> */} <Route path="regform" element={<Regform />} />
<Route path="error404" element={<Error404 />} /> <Route path="error404" element={<Error404 />} />
<Route path="resetpassword" element={<ResetPassword />} /> <Route path="resetpassword" element={<ResetPassword />} />
@ -137,13 +137,12 @@ const App = () => {
<Route path="dashboard-new-edit/:id" element={<DashboardNewEdit/>}/> <Route path="dashboard-new-edit/:id" element={<DashboardNewEdit/>}/>
<Route path="edit-new-dash/:id" element={<EditNewDash/>}/> <Route path="edit-new-dash/:id" element={<EditNewDash/>}/>
<Route path="dashrunner/:id" element={<DashboardRunner/>}/> <Route path="dashrunner/:id" element={<DashboardRunner/>}/>
{/* <Route path="test" element={<Regform />} /> */}
{/* buildercomponents */}
{/* buildercomponents */}
</Route> </Route>
<Route path="/auth/*" element={<AuthLayout />}> <Route path="/auth/*" element={<AuthLayout />}>
<Route path="login" element={<Login />} /> <Route path="login" element={<Login />} />
<Route path="register" element={<Register />} /> <Route path="register" element={<Register />} />

View File

@ -1,11 +1,11 @@
// ProtectedRoute.js
import React from "react"; import React from "react";
import { Navigate } from "react-router-dom"; import { Navigate } from "react-router-dom";
import { getToken } from "utils/tokenService"; import { getToken } from "utils/tokenService";
const ProtectedRoute = ({ children }) => { const ProtectedRoute = ({ children }) => {
const isAuthenticated = getToken() !== null; console.log(`token for checking whether authenticated: ${getToken()}`);
const isAuthenticated = getToken() !== null; // Check if user is authenticated
return isAuthenticated ? children : <Navigate to="/auth/login" replace />; return isAuthenticated ? children : <Navigate to="/auth/login" replace />;
}; };
export default ProtectedRoute; export default ProtectedRoute;

View File

@ -57,7 +57,7 @@ function AccessTypeManagement() {
useEffect(() => { useEffect(() => {
const fetchAccessTypes = async () => { const fetchAccessTypes = async () => {
const apiUrl = `${process.env.REACT_APP_API_URL}token/access_type/Accesstype`; const apiUrl = `${process.env.REACT_APP_API_URL}api/getAllAccessTypes`;
const token = localStorage.getItem("authToken"); const token = localStorage.getItem("authToken");
if (!token) { if (!token) {

View File

@ -20,31 +20,31 @@ function TOKENRegistry() {
id: "", id: "",
tokenName: "", tokenName: "",
tokenValue: "", tokenValue: "",
isActive: true, isActive: true
scopes: []
}); });
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
const [searchQuery, setSearchQuery] = useState(""); const [searchQuery, setSearchQuery] = useState("");
const [isEditing, setIsEditing] = useState(false); const [isEditing, setIsEditing] = useState(false);
const [recordsPerPage, setRecordsPerPage] = useState(10); const [recordsPerPage, setRecordsPerPage] = useState(10);
const [visibleColumns, setVisibleColumns] = useState({ // Add to your state:
id: true, const [visibleColumns, setVisibleColumns] = useState({
tokenName: true, id: true,
tokenValue: true, tokenName: true,
scopes: true, tokenValue: true,
isActive: true, scopes: true,
actions: 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 [loading, setLoading] = useState(true);
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' },
]);
useEffect(() => { useEffect(() => {
fetchTokens(); fetchTokens();
}, []); }, []);
@ -95,7 +95,6 @@ function TOKENRegistry() {
setShowGenerateTokenModal(false); setShowGenerateTokenModal(false);
setGeneratedToken(""); setGeneratedToken("");
setNewTokenName(""); setNewTokenName("");
setSelectedScopes([]);
}; };
const handleRecordsPerPageChange = (number) => { const handleRecordsPerPageChange = (number) => {
@ -136,10 +135,9 @@ function TOKENRegistry() {
} }
}; };
const openModal = (token = { id: "", tokenName: "", tokenValue: "", isActive: false, scopes: [] }) => { const openModal = (token = { id: "", tokenName: "", tokenValue: "", isActive: false }) => {
setIsEditing(!!token.id); setIsEditing(!!token.id);
setCurrentToken(token); setCurrentToken(token);
setSelectedScopes(token.scopes || []);
setShowAddEditModal(true); setShowAddEditModal(true);
}; };
@ -155,35 +153,24 @@ function TOKENRegistry() {
} }
}; };
const addScope = () => {
if (selectedScope && !selectedScopes.includes(selectedScope)) {
setSelectedScopes([...selectedScopes, selectedScope]);
setSelectedScope("");
}
};
const removeScope = (scopeToRemove) => {
setSelectedScopes(selectedScopes.filter(scope => scope !== scopeToRemove));
};
const generateNewToken = async () => { const generateNewToken = async () => {
if (!newTokenName.trim()) { if (!newTokenName.trim()) {
toast.error("Please enter a token name"); toast.error("Please enter a token name");
return; return;
} }
try { try {
const data = await tokenRegistryAPI.generateToken({ const data = await tokenRegistryAPI.generateToken({
name: newTokenName, name: newTokenName,
scopes: selectedScopes scopes: selectedScopes
}); });
setGeneratedToken(data.tokenValue); setGeneratedToken(data.tokenValue);
toast.success("Token generated successfully!"); toast.success("Token generated successfully!");
fetchTokens(); fetchTokens();
} catch (error) { } catch (error) {
handleApiError(error, "generate token"); handleApiError(error, "generate token");
} }
}; };
return ( return (
<div style={{ marginTop: "1rem" }}> <div style={{ marginTop: "1rem" }}>
@ -318,21 +305,6 @@ function TOKENRegistry() {
> >
{token.isActive ? "Active" : "Inactive"} {token.isActive ? "Active" : "Inactive"}
</span> </span>
) : key === "scopes" ? (
<div>
{token.scopes && token.scopes.map(scope => {
const scopeInfo = availableScopes.find(s => s.value === scope);
return (
<span
key={scope}
className="badge bg-primary me-1 mb-1"
style={{ fontSize: '0.8rem', padding: '3px 6px' }}
>
{scopeInfo?.label || scope}
</span>
);
})}
</div>
) : ( ) : (
token[key] token[key]
)} )}
@ -411,245 +383,93 @@ function TOKENRegistry() {
</PaginationItem> </PaginationItem>
</Pagination> </Pagination>
{/* Generate Token Modal */}
<Modal show={showGenerateTokenModal} onHide={handleClose}>
<Modal.Header>
<Modal.Title>Generate New Token</Modal.Title>
<FontAwesomeIcon
icon={faTimes}
size="lg"
onClick={handleClose}
style={{
position: "absolute",
top: "25px",
right: "25px",
cursor: "pointer",
}}
/>
</Modal.Header>
<Modal.Body>
<Form>
<Form.Group controlId="formNewTokenName" className="mb-3">
<Form.Label>Token Name</Form.Label>
<Form.Control
type="text"
value={newTokenName}
onChange={(e) => setNewTokenName(e.target.value)}
required
className="custom-hover-border"
placeholder="Enter a name for the new token"
/>
</Form.Group>
<Form.Group controlId="formTokenScopes" className="mb-3">
<Form.Label>Token Scopes</Form.Label>
<div className="d-flex">
<Form.Select
value={selectedScope}
onChange={(e) => setSelectedScope(e.target.value)}
className="custom-hover-border me-2"
>
<option value="">Select a scope</option>
{availableScopes.map(scope => (
<option key={scope.value} value={scope.value}>
{scope.label}
</option>
))}
</Form.Select>
<Button
variant="outline-primary"
onClick={addScope}
disabled={!selectedScope}
>
Add Scope
</Button>
</div>
<Form.Text className="text-muted">
Select and add the permissions this token should have
</Form.Text>
{/* Display selected scopes as chips */}
{selectedScopes.length > 0 && (
<div className="mt-2">
{selectedScopes.map(scope => {
const scopeInfo = availableScopes.find(s => s.value === scope);
return (
<span
key={scope}
className="badge bg-primary me-2 mb-2"
style={{ fontSize: '0.9rem', padding: '5px 10px' }}
>
{scopeInfo?.label || scope}
<FontAwesomeIcon
icon={faTimes}
className="ms-2"
style={{ cursor: 'pointer' }}
onClick={() => removeScope(scope)}
/>
</span>
);
})}
</div>
)}
</Form.Group>
{generatedToken && (
<Form.Group controlId="formGeneratedToken" className="mb-3">
<Form.Label>Generated Token</Form.Label>
<Form.Control
as="textarea"
rows={3}
value={generatedToken}
readOnly
className="custom-hover-border"
/>
<Form.Text className="text-muted">
Copy this token and store it securely. You won't be able to see it again.
</Form.Text>
</Form.Group>
)}
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
<Button
variant="primary"
onClick={generateNewToken}
disabled={!newTokenName.trim()}
>
Generate Token
</Button>
</Modal.Footer>
</Form>
</Modal.Body>
</Modal>
{/* Add/Edit Token Modal */} {/* Add/Edit Token Modal */}
<Modal show={showAddEditModal} onHide={handleClose}> <Modal show={showGenerateTokenModal} onHide={handleClose}>
<Modal.Header> <Modal.Header>
<Modal.Title>{isEditing ? "Edit Token" : "Add Token"}</Modal.Title> <Modal.Title>Generate New Token</Modal.Title>
<FontAwesomeIcon <FontAwesomeIcon
icon={faTimes} icon={faTimes}
size="lg" size="lg"
onClick={handleClose} onClick={handleClose}
style={{ style={{
position: "absolute", position: "absolute",
top: "25px", top: "25px",
right: "25px", right: "25px",
cursor: "pointer", cursor: "pointer",
}} }}
/> />
</Modal.Header> </Modal.Header>
<Modal.Body> <Modal.Body>
<Form onSubmit={handleSubmit}> <Form>
<Form.Group controlId="formTokenName" className="mb-3"> <Form.Group controlId="formNewTokenName" className="mb-3">
<Form.Label>Token Name</Form.Label> <Form.Label>Token Name</Form.Label>
<Form.Control <Form.Control
type="text" type="text"
name="tokenName" value={newTokenName}
value={currentToken.tokenName} onChange={(e) => setNewTokenName(e.target.value)}
onChange={handleInputChange} required
required className="custom-hover-border"
className="custom-hover-border" placeholder="Enter a name for the new token"
/> />
</Form.Group> </Form.Group>
<Form.Group controlId="formTokenValue" className="mb-3">
<Form.Label>Token Value</Form.Label> <Form.Group controlId="formTokenScopes" className="mb-3">
<Form.Control <Form.Label>Token Scopes</Form.Label>
type="text" <Form.Select
name="tokenValue" multiple
value={currentToken.tokenValue} value={selectedScopes}
onChange={handleInputChange} onChange={(e) => {
required const options = [...e.target.options];
className="custom-hover-border" const selectedValues = options
/> .filter(option => option.selected)
</Form.Group> .map(option => option.value);
<Form.Group controlId="formTokenScopes" className="mb-3"> setSelectedScopes(selectedValues);
<Form.Label>Token Scopes</Form.Label> }}
<div className="d-flex"> className="custom-hover-border"
<Form.Select style={{ height: 'auto' }}
value={selectedScope} >
onChange={(e) => setSelectedScope(e.target.value)} {availableScopes.map(scope => (
className="custom-hover-border me-2" <option key={scope.value} value={scope.value}>
> {scope.label}
<option value="">Select a scope</option> </option>
{availableScopes.map(scope => ( ))}
<option key={scope.value} value={scope.value}> </Form.Select>
{scope.label} <Form.Text className="text-muted">
</option> Select the permissions this token should have (hold Ctrl/Cmd to select multiple)
))} </Form.Text>
</Form.Select> </Form.Group>
<Button
variant="outline-primary" {generatedToken && (
onClick={() => { <Form.Group controlId="formGeneratedToken" className="mb-3">
if (selectedScope && !currentToken.scopes.includes(selectedScope)) { <Form.Label>Generated Token</Form.Label>
setCurrentToken(prev => ({ <Form.Control
...prev, as="textarea"
scopes: [...prev.scopes, selectedScope] rows={3}
})); value={generatedToken}
setSelectedScope(""); readOnly
} className="custom-hover-border"
}} />
disabled={!selectedScope} <Form.Text className="text-muted">
> Copy this token and store it securely. You won't be able to see it again.
Add Scope </Form.Text>
</Button> </Form.Group>
</div> )}
<Form.Text className="text-muted">
Select and add the permissions this token should have <Modal.Footer>
</Form.Text> <Button variant="secondary" onClick={handleClose}>
Close
{/* Display selected scopes as chips */} </Button>
{currentToken.scopes && currentToken.scopes.length > 0 && ( <Button
<div className="mt-2"> variant="primary"
{currentToken.scopes.map(scope => { onClick={generateNewToken}
const scopeInfo = availableScopes.find(s => s.value === scope); disabled={!newTokenName.trim()}
return ( >
<span Generate Token
key={scope} </Button>
className="badge bg-primary me-2 mb-2" </Modal.Footer>
style={{ fontSize: '0.9rem', padding: '5px 10px' }} </Form>
> </Modal.Body>
{scopeInfo?.label || scope} </Modal>
<FontAwesomeIcon
icon={faTimes}
className="ms-2"
style={{ cursor: 'pointer' }}
onClick={() => {
setCurrentToken(prev => ({
...prev,
scopes: prev.scopes.filter(s => s !== scope)
}));
}}
/>
</span>
);
})}
</div>
)}
</Form.Group>
<Form.Group controlId="formActive" className="mb-3">
<Form.Check
type="checkbox"
label="Active?"
name="isActive"
checked={currentToken.isActive}
onChange={handleInputChange}
className="custom-checkbox"
/>
</Form.Group>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
<Button variant="primary" type="submit">
{isEditing ? "Update Token" : "Add Token"}
</Button>
</Modal.Footer>
</Form>
</Modal.Body>
</Modal>
</div> </div>
)} )}
</div> </div>

View File

@ -1,4 +1,4 @@
import { useState, useEffect } from "react"; import { useState } from "react";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { import {
@ -7,86 +7,20 @@ import {
MenuItem, MenuItem,
SubMenu, SubMenu,
} from "react-pro-sidebar"; } from "react-pro-sidebar";
import { FaChevronLeft, FaChevronRight, FaDatabase, FaExclamationCircle, FaCircle } from "react-icons/fa"; import { FaChevronLeft, FaChevronRight, FaDatabase, FaExclamationCircle } from "react-icons/fa";
import { fetchMenuItems, getSubmenuItems } from "../../APIServices/MenuMaintenanceAPI";
import "../Sidebar/Sidebar.css"; import "../Sidebar/Sidebar.css";
const Sidebar = (props) => { const Sidebar = (props) => {
const [collapsed, setCollapsed] = useState(true); 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(); 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 = () => { const toggleSidebar = () => {
setCollapsed(!collapsed); setCollapsed(!collapsed);
props.onSidebarToggle?.(!collapsed); if (props.onSidebarToggle) {
}; 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 <FaDatabase />;
case "fa-exclamation-circle": return <FaExclamationCircle />;
default: return <FaCircle />;
}
};
if (loading) return <div className="sidebar-wrapper">Loading...</div>;
if (error) return <div className="sidebar-wrapper">Error: {error}</div>;
return ( return (
<div className="sidebar-wrapper"> <div className="sidebar-wrapper">
<ProSidebar <ProSidebar
@ -107,38 +41,21 @@ const Sidebar = (props) => {
</div> </div>
<Menu> <Menu>
{menuItems.map((menuItem) => { <SubMenu label="Transactions" icon={<FaExclamationCircle />}>
const subItems = subMenuItems[menuItem.menuItemId] || []; <MenuItem onClick={() => navigate("/admin/regform")}>
Regform
if (subItems.length > 0) { </MenuItem>
return ( <MenuItem onClick={() => navigate("/admin/error404")}>
<SubMenu Additional container
key={menuItem.menuItemId} </MenuItem>
label={menuItem.menuItemDesc} </SubMenu>
icon={getIconComponent(menuItem.main_menu_icon_name)}
> <MenuItem
{subItems.map((subItem) => ( icon={<FaDatabase />}
<MenuItem onClick={() => navigate("/admin/error404")}
key={subItem.menuItemId} >
onClick={() => safeNavigate(subItem.main_menu_action_name)} Masters
> </MenuItem>
{subItem.menuItemDesc}
</MenuItem>
))}
</SubMenu>
);
}
return (
<MenuItem
key={menuItem.menuItemId}
icon={getIconComponent(menuItem.main_menu_icon_name)}
onClick={() => safeNavigate(menuItem.main_menu_action_name)}
>
{menuItem.menuItemDesc}
</MenuItem>
);
})}
</Menu> </Menu>
</ProSidebar> </ProSidebar>
</div> </div>
@ -154,4 +71,4 @@ Sidebar.propTypes = {
onSidebarToggle: PropTypes.func, onSidebarToggle: PropTypes.func,
}; };
export default Sidebar; export default Sidebar;