react
This commit is contained in:
@@ -168,7 +168,7 @@ function AccessTypeManagement() {
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{marginTop:"11rem"}}>
|
||||
<div style={{marginTop:"1rem"}}>
|
||||
{loading ? (
|
||||
<Spinner/>
|
||||
):(
|
||||
|
||||
@@ -3,6 +3,13 @@
|
||||
border-radius: 0.8rem;
|
||||
|
||||
}
|
||||
/* Ensures checkboxes behave like regular table content */
|
||||
.table-responsive input[type="checkbox"] {
|
||||
position: static !important;
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.thead-light{
|
||||
font-size: 1.1rem;
|
||||
@@ -80,6 +87,7 @@
|
||||
padding-top: 11rem;
|
||||
padding-bottom: 5rem;/* Adjust as needed for the space between the navbar and component */
|
||||
margin-top: -10rem;
|
||||
margin-right: 2rem;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr); /* 4 columns */
|
||||
gap: 15px;
|
||||
margin-top:9rem;
|
||||
margin-top:4rem;
|
||||
margin-right: 2rem;
|
||||
margin-left:2rem;
|
||||
margin-bottom:2rem;
|
||||
@@ -19,7 +19,7 @@
|
||||
}
|
||||
|
||||
.usercard i {
|
||||
color:#0E6591;
|
||||
color:rgba(255, 0, 0, 0.688);
|
||||
}
|
||||
|
||||
.usercard:hover{
|
||||
@@ -28,7 +28,7 @@
|
||||
}
|
||||
|
||||
.usercard h3{
|
||||
color: #0E6591; /* Change the card title color to red */
|
||||
color: rgba(255, 0, 0, 0.739); /* Change the card title color to red */
|
||||
font-family: 'GoogleFontName', sans-serif;
|
||||
font-size: large; /* Apply the Google font */
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ const DynamicForm2 = () => {
|
||||
);
|
||||
|
||||
return (
|
||||
<div style={{ marginTop: "11rem" }}>
|
||||
<div style={{ marginTop: "7rem" }}>
|
||||
{loading ? (
|
||||
<Spinner />
|
||||
) : (
|
||||
|
||||
@@ -296,7 +296,7 @@ function DynamicFormAdd() {
|
||||
|
||||
|
||||
return (
|
||||
<div style={{ marginTop: "11rem" }}>
|
||||
<div style={{ marginTop: "7rem" }}>
|
||||
{loading ? (
|
||||
<Spinner/>
|
||||
) : (
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1240,10 +1240,12 @@ const MenuAccessControl = () => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
console.log("data:", data); // Log the fetched data
|
||||
setAlldata(data.items);
|
||||
setPagination({ ...pagination, totalItems: data.totalItems });
|
||||
setLoading(false); // Stop loading
|
||||
const data = await response.json();
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
setLoading(false); // Stop loading in case of error
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
// main_menu_action_name: true,
|
||||
// status: true
|
||||
// });
|
||||
// const [isSubMenu, setIsSubMenu] = useState(false);
|
||||
// const [dd, setIsSubMenu] = useState(false);
|
||||
// const [parentMenuItemId, setParentMenuItemId] = useState(null);
|
||||
|
||||
// useEffect(() => {
|
||||
@@ -70,7 +70,7 @@
|
||||
// const handleSubmit = (event) => {
|
||||
// event.preventDefault();
|
||||
// if (isEditing) {
|
||||
// if (isSubMenu) {
|
||||
// if (dd) {
|
||||
// setSubMenuItems(subMenuItems.map(item =>
|
||||
// item.menuItemId === currentMenuItem.menuItemId ? currentMenuItem : item
|
||||
// ));
|
||||
@@ -80,7 +80,7 @@
|
||||
// ));
|
||||
// }
|
||||
// } else {
|
||||
// if (isSubMenu) {
|
||||
// if (dd) {
|
||||
// setSubMenuItems([...subMenuItems, { ...currentMenuItem, menuItemId: `ID-${subMenuItems.length + 1}` }]);
|
||||
// } else {
|
||||
// setMenuItems([...menuItems, { ...currentMenuItem, menuItemId: `ID-${menuItems.length + 1}` }]);
|
||||
@@ -301,18 +301,19 @@ import {
|
||||
|
||||
|
||||
function MenuMaintenance() {
|
||||
|
||||
const [menuItems, setMenuItems] = useState([]);
|
||||
const [subMenuItems, setSubMenuItems] = useState([]);
|
||||
const [showAddEditPopup, setShowAddEditPopup] = useState(false);
|
||||
const [currentMenuItem, setCurrentMenuItem] = useState({
|
||||
menuItemDesc: "",
|
||||
menu_id: "",
|
||||
itemSeq: "",
|
||||
moduleName: "",
|
||||
main_menu_action_name: "",
|
||||
main_menu_icon_name: "",
|
||||
status: true,
|
||||
});
|
||||
menuItemDesc: "",
|
||||
menuId: 0, // Important: Use menuId instead of menu_id
|
||||
itemSeq: "",
|
||||
moduleName: "",
|
||||
main_menu_action_name: "",
|
||||
main_menu_icon_name: "",
|
||||
status: "true" // As string to match select input
|
||||
});
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const [recordsPerPage, setRecordsPerPage] = useState(10);
|
||||
const [selectedMainMenuId, setSelectedMainMenuId] = useState("");
|
||||
@@ -390,6 +391,7 @@ function MenuMaintenance() {
|
||||
console.log("Selected file:", file.name); // For debugging or processing
|
||||
}
|
||||
};
|
||||
const dd = isSubMenu; // or set based on your logic
|
||||
|
||||
const exportToExcel = () => {
|
||||
const worksheet = XLSX.utils.json_to_sheet([]);
|
||||
@@ -421,68 +423,93 @@ function MenuMaintenance() {
|
||||
setSearchQuery(query);
|
||||
};
|
||||
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
try {
|
||||
if (isEditing) {
|
||||
if (isSubMenu) {
|
||||
setSubMenuItems(
|
||||
subMenuItems.map((item) =>
|
||||
item.menuItemId === currentMenuItem.menuItemId
|
||||
? currentMenuItem
|
||||
: item
|
||||
)
|
||||
);
|
||||
} else {
|
||||
const formData = {
|
||||
...currentMenuItem, // Include required fields for API payload
|
||||
};
|
||||
// const handleSubmit = async (event) => {
|
||||
// event.preventDefault();
|
||||
// try {
|
||||
// if (isEditing) {
|
||||
// if (isSubMenu) {
|
||||
// setSubMenuItems(
|
||||
// subMenuItems.map((item) =>
|
||||
// item.menuItemId === currentMenuItem.menuItemId
|
||||
// ? currentMenuItem
|
||||
// : item
|
||||
// )
|
||||
// );
|
||||
// } else {
|
||||
// const formData = {
|
||||
// ...currentMenuItem, // Include required fields for API payload
|
||||
// };
|
||||
|
||||
// Call the API to update the menu item
|
||||
await updateMenuItem(currentMenuItem.menuItemId, formData);
|
||||
setMenuItems(
|
||||
menuItems.map((item) =>
|
||||
item.menuItemId === currentMenuItem.menuItemId
|
||||
? currentMenuItem
|
||||
: item
|
||||
)
|
||||
);
|
||||
toast.success("Menu item updated successfully!");
|
||||
}
|
||||
} else {
|
||||
if (isSubMenu) {
|
||||
// const formData = {
|
||||
// ...currentMenuItem, // Include fields required for submenu creation
|
||||
// };
|
||||
// const addedSubMenuItem = await addSubmenuItem(parentMenuItemId, formData);
|
||||
// setSubMenuItems([...subMenuItems, addedSubMenuItem]);
|
||||
// toast.success("Submenu item added successfully!");
|
||||
// // Local addition for submenus
|
||||
// setSubMenuItems([
|
||||
// ...subMenuItems,
|
||||
// { ...currentMenuItem, menuItemId: `ID-${subMenuItems.length + 1}` },
|
||||
// ]);
|
||||
} else {
|
||||
// Prepare form data for API
|
||||
const formData = {
|
||||
...currentMenuItem, // Include required fields for API payload
|
||||
};
|
||||
// // Call the API to update the menu item
|
||||
// await updateMenuItem(currentMenuItem.menuItemId, formData);
|
||||
// setMenuItems(
|
||||
// menuItems.map((item) =>
|
||||
// item.menuItemId === currentMenuItem.menuItemId
|
||||
// ? currentMenuItem
|
||||
// : item
|
||||
// )
|
||||
// );
|
||||
// toast.success("Menu item updated successfully!");
|
||||
// }
|
||||
// } else {
|
||||
// if (isSubMenu) {
|
||||
// // const formData = {
|
||||
// // ...currentMenuItem, // Include fields required for submenu creation
|
||||
// // };
|
||||
// // const addedSubMenuItem = await addSubmenuItem(parentMenuItemId, formData);
|
||||
// // setSubMenuItems([...subMenuItems, addedSubMenuItem]);
|
||||
// // toast.success("Submenu item added successfully!");
|
||||
// // // Local addition for submenus
|
||||
// // setSubMenuItems([
|
||||
// // ...subMenuItems,
|
||||
// // { ...currentMenuItem, menuItemId: `ID-${subMenuItems.length + 1}` },
|
||||
// // ]);
|
||||
// } else {
|
||||
// // Prepare form data for API
|
||||
// const formData = {
|
||||
// ...currentMenuItem, // Include required fields for API payload
|
||||
// };
|
||||
|
||||
// Call the API to add a new menu item
|
||||
const addedMenuItem = await addMenuItem(formData);
|
||||
// // Call the API to add a new menu item
|
||||
// const addedMenuItem = await addMenuItem(formData);
|
||||
|
||||
// Update menu items with the newly added item from the API response
|
||||
setMenuItems([...menuItems, addedMenuItem]);
|
||||
// // Update menu items with the newly added item from the API response
|
||||
// setMenuItems([...menuItems, addedMenuItem]);
|
||||
|
||||
toast.success("Menu item added successfully!");
|
||||
}
|
||||
}
|
||||
setShowAddEditPopup(false);
|
||||
} catch (error) {
|
||||
toast.error("There was an error while submitting the API.");
|
||||
console.error("Error in handleSubmit:", error); // Log the error for debugging
|
||||
// toast.success("Menu item added successfully!");
|
||||
// }
|
||||
// }
|
||||
// setShowAddEditPopup(false);
|
||||
// } catch (error) {
|
||||
// toast.error("There was an error while submitting the API.");
|
||||
// console.error("Error in handleSubmit:", error); // Log the error for debugging
|
||||
// }
|
||||
// };
|
||||
|
||||
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
try {
|
||||
if (isEditing) {
|
||||
// Update existing item
|
||||
const updatedItem = await updateMenuItem(currentMenuItem.menuItemId, currentMenuItem);
|
||||
setMenuItems(menuItems.map(item =>
|
||||
item.menuItemId === currentMenuItem.menuItemId ? updatedItem : item
|
||||
));
|
||||
toast.success("Menu item updated successfully!");
|
||||
} else {
|
||||
// Add new item
|
||||
const addedItem = await addMenuItem(currentMenuItem);
|
||||
setMenuItems([...menuItems, addedItem]);
|
||||
toast.success("Menu item added successfully!");
|
||||
}
|
||||
};
|
||||
setShowAddEditPopup(false);
|
||||
} catch (error) {
|
||||
toast.error(`Operation failed: ${error.message}`);
|
||||
console.error("Submit error:", error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const handleDelete = async (menuItemId) => {
|
||||
if (isSubMenu) {
|
||||
@@ -502,7 +529,7 @@ function MenuMaintenance() {
|
||||
|
||||
const handleSubMenuClick = (menuItemId) => {
|
||||
// Pehle navigate karke page open karein
|
||||
navigate(`/admin/sub-menu-maintenance/:menuItemId`);
|
||||
navigate(`/admin/sub-menu-maintenance/${menuItemId}`);
|
||||
|
||||
// Phir API logic handle karein
|
||||
fetchSubMenuItems(menuItemId);
|
||||
@@ -559,6 +586,8 @@ function MenuMaintenance() {
|
||||
console.log("sliced menu", slicedMenus); // Verify the data in slicedMenus
|
||||
|
||||
return (
|
||||
|
||||
|
||||
<div style={{ marginTop: "-20px" }}>
|
||||
{loading ? (
|
||||
<Spinner />
|
||||
@@ -597,6 +626,7 @@ function MenuMaintenance() {
|
||||
padding: "10px 15px",
|
||||
}}
|
||||
>
|
||||
|
||||
<FaSearch />
|
||||
</InputGroup.Text>
|
||||
<FormControl
|
||||
@@ -693,7 +723,7 @@ function MenuMaintenance() {
|
||||
/>
|
||||
</OverlayTrigger>
|
||||
|
||||
<OverlayTrigger
|
||||
{/* <OverlayTrigger
|
||||
placement="bottom"
|
||||
overlay={<Tooltip>Menu Items</Tooltip>}
|
||||
>
|
||||
@@ -705,7 +735,7 @@ function MenuMaintenance() {
|
||||
color: "#747264",
|
||||
}}
|
||||
/>
|
||||
</OverlayTrigger>
|
||||
</OverlayTrigger> */}
|
||||
</>
|
||||
</Col>
|
||||
</Row>
|
||||
@@ -757,7 +787,7 @@ function MenuMaintenance() {
|
||||
)
|
||||
)}
|
||||
<th>Actions</th>
|
||||
{!isSubMenu && <th>Sub-Menu</th>}
|
||||
{!dd && <th>Sub-Menu</th>}
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@@ -770,7 +800,7 @@ function MenuMaintenance() {
|
||||
Object.keys(visibleColumns).filter(
|
||||
(key) => visibleColumns[key]
|
||||
).length +
|
||||
(isSubMenu ? 1 : 2)
|
||||
(dd ? 1 : 2)
|
||||
}
|
||||
className="text-center"
|
||||
>
|
||||
@@ -830,7 +860,7 @@ function MenuMaintenance() {
|
||||
}}
|
||||
/>
|
||||
</td>
|
||||
{!isSubMenu && (
|
||||
{!dd && (
|
||||
<td className="text-center">
|
||||
<FontAwesomeIcon
|
||||
icon={faBars}
|
||||
@@ -947,99 +977,151 @@ function MenuMaintenance() {
|
||||
|
||||
{/* Add/Edit Modal */}
|
||||
{showAddEditPopup && (
|
||||
<Modal
|
||||
show={showAddEditPopup}
|
||||
onHide={() => setShowAddEditPopup(false)}
|
||||
centered
|
||||
>
|
||||
<Modal.Header>
|
||||
<Modal.Title>
|
||||
{isEditing ? "Edit Menu Item" : "Add New Menu Item"}
|
||||
</Modal.Title>
|
||||
<FontAwesomeIcon
|
||||
icon={faTimes}
|
||||
size="lg"
|
||||
onClick={handleClose}
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: "25px",
|
||||
right: "25px",
|
||||
cursor: "pointer",
|
||||
}}
|
||||
/>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
<Form onSubmit={handleSubmit}>
|
||||
<Form.Group controlId="menuId" className="mb-3">
|
||||
<Form.Label>menuId</Form.Label>
|
||||
<Form.Control
|
||||
type="number"
|
||||
name="menu_id" // Updated to match the state
|
||||
value={currentMenuItem.menu_id || ""}
|
||||
onChange={handleInputChange}
|
||||
required
|
||||
className="custom-hover-border"
|
||||
/>
|
||||
</Form.Group>
|
||||
<Form.Group controlId="menuItemDesc" className="mb-3">
|
||||
<Form.Label>Title</Form.Label>
|
||||
<Form.Control
|
||||
type="text"
|
||||
name="menuItemDesc"
|
||||
value={currentMenuItem.menuItemDesc || ""}
|
||||
onChange={handleInputChange}
|
||||
required
|
||||
className="custom-hover-border"
|
||||
/>
|
||||
</Form.Group>
|
||||
<Form.Group
|
||||
controlId="main_menu_action_name"
|
||||
className="mb-3"
|
||||
>
|
||||
<Form.Label>Link</Form.Label>
|
||||
<Form.Control
|
||||
type="text"
|
||||
name="main_menu_action_name"
|
||||
value={currentMenuItem.main_menu_action_name || ""}
|
||||
onChange={handleInputChange}
|
||||
required
|
||||
className="custom-hover-border"
|
||||
/>
|
||||
</Form.Group>
|
||||
<Form.Group controlId="status" className="mb-3">
|
||||
<Form.Label>Status</Form.Label>
|
||||
<Form.Select
|
||||
name="status"
|
||||
value={currentMenuItem.status ? "true" : "false"}
|
||||
onChange={handleInputChange}
|
||||
required
|
||||
className="custom-checkbox:checked"
|
||||
>
|
||||
<option value="">Select Status</option>
|
||||
<option value="true">Enable</option>
|
||||
<option value="false">Disable</option>
|
||||
</Form.Select>
|
||||
</Form.Group>
|
||||
<Modal.Footer>
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={() => setShowAddEditPopup(false)}
|
||||
className="custom_button"
|
||||
>
|
||||
Close
|
||||
</Button>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="primary"
|
||||
className="custom_button"
|
||||
>
|
||||
{isEditing ? "Update Item" : "Add Item"}
|
||||
</Button>
|
||||
</Modal.Footer>
|
||||
</Form>
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
)}
|
||||
<Modal
|
||||
show={showAddEditPopup}
|
||||
onHide={() => setShowAddEditPopup(false)}
|
||||
centered
|
||||
size="lg"
|
||||
>
|
||||
<Modal.Header>
|
||||
<Modal.Title>
|
||||
{isEditing ? "Edit Menu Item" : "Add New Menu Item"}
|
||||
</Modal.Title>
|
||||
<FontAwesomeIcon
|
||||
icon={faTimes}
|
||||
size="lg"
|
||||
onClick={handleClose}
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: "25px",
|
||||
right: "25px",
|
||||
cursor: "pointer",
|
||||
}}
|
||||
/>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
<Form onSubmit={handleSubmit}>
|
||||
<Row>
|
||||
{/* Menu ID (Fixed at 0) */}
|
||||
<Col md={6}>
|
||||
<Form.Group controlId="menuId" className="mb-3">
|
||||
<Form.Label>Menu ID*</Form.Label>
|
||||
<Form.Control
|
||||
type="number"
|
||||
name="menuId"
|
||||
value={0}
|
||||
readOnly
|
||||
plaintext
|
||||
className="form-control-plaintext"
|
||||
/>
|
||||
</Form.Group>
|
||||
</Col>
|
||||
|
||||
{/* Menu Item Name */}
|
||||
<Col md={6}>
|
||||
<Form.Group controlId="menuItemDesc" className="mb-3">
|
||||
<Form.Label>Menu Item Name*</Form.Label>
|
||||
<Form.Control
|
||||
type="text"
|
||||
name="menuItemDesc"
|
||||
value={currentMenuItem.menuItemDesc || ""}
|
||||
onChange={handleInputChange}
|
||||
required
|
||||
/>
|
||||
</Form.Group>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row>
|
||||
{/* Sequence */}
|
||||
<Col md={6}>
|
||||
<Form.Group controlId="itemSeq" className="mb-3">
|
||||
<Form.Label>Sequence</Form.Label>
|
||||
<Form.Control
|
||||
type="number"
|
||||
name="itemSeq"
|
||||
value={currentMenuItem.itemSeq || ""}
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
</Form.Group>
|
||||
</Col>
|
||||
|
||||
{/* Module Name */}
|
||||
<Col md={6}>
|
||||
<Form.Group controlId="moduleName" className="mb-3">
|
||||
<Form.Label>Module Name</Form.Label>
|
||||
<Form.Control
|
||||
type="text"
|
||||
name="moduleName"
|
||||
value={currentMenuItem.moduleName || ""}
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
</Form.Group>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row>
|
||||
{/* Menu Action Link */}
|
||||
<Col md={6}>
|
||||
<Form.Group controlId="main_menu_action_name" className="mb-3">
|
||||
<Form.Label>Menu Action Link</Form.Label>
|
||||
<Form.Control
|
||||
type="text"
|
||||
name="main_menu_action_name"
|
||||
value={currentMenuItem.main_menu_action_name || ""}
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
</Form.Group>
|
||||
</Col>
|
||||
|
||||
{/* Menu Icon Name */}
|
||||
<Col md={6}>
|
||||
<Form.Group controlId="main_menu_icon_name" className="mb-3">
|
||||
<Form.Label>Menu Icon Name</Form.Label>
|
||||
<Form.Control
|
||||
type="text"
|
||||
name="main_menu_icon_name"
|
||||
value={currentMenuItem.main_menu_icon_name || ""}
|
||||
onChange={handleInputChange}
|
||||
placeholder="e.g., fa-home"
|
||||
/>
|
||||
</Form.Group>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
{/* Status */}
|
||||
<Form.Group controlId="status" className="mb-3">
|
||||
<Form.Label>Status</Form.Label>
|
||||
<Form.Select
|
||||
name="status"
|
||||
value={currentMenuItem.status ? "true" : "false"}
|
||||
onChange={handleInputChange}
|
||||
>
|
||||
<option value="true">Enable</option>
|
||||
<option value="false">Disable</option>
|
||||
</Form.Select>
|
||||
</Form.Group>
|
||||
|
||||
<Modal.Footer>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => setShowAddEditPopup(false)}
|
||||
className="me-2"
|
||||
>
|
||||
CANCEL
|
||||
</Button>
|
||||
<Button
|
||||
type="submit"
|
||||
variant="primary"
|
||||
>
|
||||
{isEditing ? "UPDATE" : "ADD"}
|
||||
</Button>
|
||||
</Modal.Footer>
|
||||
</Form>
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
)}
|
||||
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -322,78 +322,74 @@ const ReportBuild2All = () => {
|
||||
{visibleColumns.action && <th className="text-center">Action</th>}
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody className="tbody">
|
||||
{filteredData.length === 0 ? (
|
||||
<tr>
|
||||
<td
|
||||
colSpan={
|
||||
Object.values(visibleColumns).filter(Boolean).length
|
||||
}
|
||||
className="text-center"
|
||||
>
|
||||
No data available
|
||||
</td>
|
||||
</tr>
|
||||
) : (
|
||||
filteredData.filter((user) => user.isSql === false).map((user) => (
|
||||
<tr key={user.id}>
|
||||
{visibleColumns.goTo && (
|
||||
<td>
|
||||
<Badge
|
||||
color="primary"
|
||||
pill
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
padding: "0.5em 1em",
|
||||
fontSize: "0.9rem",
|
||||
textTransform: "uppercase",
|
||||
}}
|
||||
onClick={() => goToLines(user)}
|
||||
>
|
||||
Set Up
|
||||
</Badge>
|
||||
</td>
|
||||
)}
|
||||
{visibleColumns.reportName && <td>{user.reportName}</td>}
|
||||
{visibleColumns.description && <td>{user.description}</td>}
|
||||
{visibleColumns.active && (
|
||||
<td
|
||||
style={{
|
||||
fontWeight: user.active ? "bold" : "normal",
|
||||
color: user.active ? "green" : "red",
|
||||
backgroundColor: user.active
|
||||
? "rgba(0, 128, 0, 0.1)"
|
||||
: "rgba(255, 0, 0, 0.1)",
|
||||
padding: "2px 4px",
|
||||
display: "inline-block",
|
||||
borderRadius: "4px",
|
||||
textAlign: "center",
|
||||
marginTop: "10px",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
{user.active ? "Yes" : "No"}
|
||||
</td>
|
||||
)}
|
||||
{visibleColumns.action && (
|
||||
<td>
|
||||
<FontAwesomeIcon
|
||||
icon={faTrash}
|
||||
onClick={(e) => confirmDelete(e, user)}
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
fontSize: "1rem",
|
||||
color: "red",
|
||||
marginRight: "15px",
|
||||
}}
|
||||
/>
|
||||
</td>
|
||||
)}
|
||||
{filteredData.length === 0 ? (
|
||||
<tr>
|
||||
<td
|
||||
colSpan={Object.values(visibleColumns).filter(Boolean).length}
|
||||
className="text-center"
|
||||
>
|
||||
No data available
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
)}
|
||||
</tbody>
|
||||
) : (
|
||||
filteredData.filter(user => user.isSql === false).map(user => (
|
||||
<tr key={user.id}>
|
||||
{visibleColumns.goTo && (
|
||||
<td>
|
||||
<Badge
|
||||
color="primary"
|
||||
pill
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
padding: "0.5em 1em",
|
||||
fontSize: "0.9rem",
|
||||
textTransform: "uppercase",
|
||||
}}
|
||||
onClick={() => goToLines(user)}
|
||||
>
|
||||
Set Up
|
||||
</Badge>
|
||||
</td>
|
||||
)}
|
||||
{visibleColumns.reportName && <td>{user.reportName}</td>}
|
||||
{visibleColumns.description && <td>{user.description}</td>}
|
||||
{visibleColumns.active && (
|
||||
<td
|
||||
style={{
|
||||
fontWeight: user.active ? "bold" : "normal",
|
||||
color: user.active ? "green" : "red",
|
||||
backgroundColor: user.active ? "rgba(0, 128, 0, 0.1)" : "rgba(255, 0, 0, 0.1)",
|
||||
padding: "2px 4px",
|
||||
display: "inline-block",
|
||||
borderRadius: "4px",
|
||||
textAlign: "center",
|
||||
marginTop: "10px",
|
||||
}}
|
||||
>
|
||||
{user.active ? "Yes" : "No"}
|
||||
</td>
|
||||
)}
|
||||
{visibleColumns.action && (
|
||||
<td>
|
||||
<FontAwesomeIcon
|
||||
icon={faTrash}
|
||||
onClick={(e) => confirmDelete(e, user)}
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
fontSize: "1rem",
|
||||
color: "red",
|
||||
marginRight: "15px",
|
||||
}}
|
||||
/>
|
||||
</td>
|
||||
)}
|
||||
</tr>
|
||||
))
|
||||
)}
|
||||
</tbody>
|
||||
|
||||
</Table>
|
||||
)}
|
||||
|
||||
|
||||
@@ -464,14 +464,16 @@ function UserDetailsView() {
|
||||
responsive
|
||||
hover
|
||||
className=" align-middle table-flush shadow-sm"
|
||||
|
||||
>
|
||||
<thead className="custom_header ">
|
||||
<tr>
|
||||
<th className="text-center">Go To</th>
|
||||
<th className="text-center">Report Name</th>
|
||||
<th className="text-center">Description</th>
|
||||
<th className="text-center">Status</th>
|
||||
<th className="text-center">Actions</th>
|
||||
<th className="text-center">Go To</th>
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="tbody">
|
||||
@@ -489,6 +491,20 @@ function UserDetailsView() {
|
||||
style={{ cursor: "pointer" }}
|
||||
onClick={() => handleRowClick(detail)}
|
||||
>
|
||||
<td className="text-center">
|
||||
<FontAwesomeIcon
|
||||
icon={faCogs}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation(); // Prevent row click event
|
||||
handleGoTo(detail);
|
||||
}}
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
fontSize: "1.2rem",
|
||||
color: "#0E6591",
|
||||
}}
|
||||
/>
|
||||
</td>
|
||||
<td>{detail.reportName}</td>
|
||||
<td>{detail.description || "No description available"}</td>
|
||||
<td
|
||||
@@ -532,20 +548,7 @@ function UserDetailsView() {
|
||||
}}
|
||||
/>
|
||||
</td>
|
||||
<td className="text-center">
|
||||
<FontAwesomeIcon
|
||||
icon={faCogs}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation(); // Prevent row click event
|
||||
handleGoTo(detail);
|
||||
}}
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
fontSize: "1.2rem",
|
||||
color: "#0E6591",
|
||||
}}
|
||||
/>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
))
|
||||
)}
|
||||
|
||||
@@ -38,161 +38,60 @@ function SetupView({
|
||||
<Spinner /> // Display the spinner while loading
|
||||
) : (
|
||||
<div className="usercards-container">
|
||||
<div className="usercards">
|
||||
<div
|
||||
className="usercard"
|
||||
onClick={() => {
|
||||
console.log("User Maintenance card clicked");
|
||||
console.log("Navigating to:", "/admin/user-maintenance");
|
||||
|
||||
navigate("/admin/user-maintenance");
|
||||
}}
|
||||
// onClick={onUserMaintenanceClick}
|
||||
>
|
||||
<i className="fa fa-user-cog card-icon"></i>
|
||||
<h3>User Maintenance</h3>
|
||||
<p>Content for Card 1</p>
|
||||
</div>
|
||||
<div
|
||||
className="usercard"
|
||||
onClick={() => {
|
||||
navigate("/admin/menu-access-control");
|
||||
// navigate("/admin/menu-access-control2")
|
||||
}}
|
||||
>
|
||||
<i className="fa-solid fa-lock"></i>
|
||||
<h3>Menu Access Control</h3>
|
||||
<p>Content for Card 2</p>
|
||||
</div>
|
||||
<div className="usercard" onClick={() => {
|
||||
navigate("/admin/user-Group-Maintenance");
|
||||
}}>
|
||||
<i className="fa-solid fa-users"></i>
|
||||
<h3>User Group Maintenance</h3>
|
||||
<p>Content for Card 3</p>
|
||||
</div>
|
||||
<div className="usercard" onClick={() => {
|
||||
navigate("/admin/system-parameter");
|
||||
}}>
|
||||
<i className="fa-solid fa-gears"></i>
|
||||
<h3>System Parameter</h3>
|
||||
<p>Content for Card 4</p>
|
||||
</div>
|
||||
<div className="usercard" onClick={() => {
|
||||
navigate("/admin/menu-maintenance");
|
||||
}}>
|
||||
<i className="fa-solid fa-utensils"></i>
|
||||
<h3>Menu Maintenance</h3>
|
||||
<p>Content for Card 5</p>
|
||||
</div>
|
||||
<div className="usercard" onClick={() => {
|
||||
navigate("/admin/access-type");
|
||||
}}>
|
||||
<i className="fa-solid fa-key"></i>
|
||||
<h3>Access Type</h3>
|
||||
<p>Content for Card 6</p>
|
||||
</div>
|
||||
<div className="usercard" onClick={() => {
|
||||
navigate("/admin/api-registry")
|
||||
}}>
|
||||
<i className="fas fa-database"></i>
|
||||
<h3>API Registry</h3>
|
||||
<p>Content for Card 7</p>
|
||||
</div>
|
||||
<div className="usercard" onClick={() => {
|
||||
navigate("/admin/token-registry")
|
||||
}}>
|
||||
<i className="fas fa-key"></i>
|
||||
<h3>Token Registry</h3>
|
||||
<p>Content for Card 8</p>
|
||||
</div>
|
||||
{/* <div className="usercard" onClick={()=>{
|
||||
navigate("/admin/datatype-1")
|
||||
}}>
|
||||
<i className="fa fa-file"></i>
|
||||
<h3>DATATYPE1</h3>
|
||||
<p>Content for Card 9</p>
|
||||
</div>
|
||||
<div className="usercard" onClick={()=>{
|
||||
navigate("/admin/datatype-2")
|
||||
}}>
|
||||
<i className="fa fa-file"></i>
|
||||
<h3>DATATYPE2</h3>
|
||||
<p>Content for Card 10</p>
|
||||
</div>
|
||||
<div className="usercard" onClick={()=>{
|
||||
navigate("/admin/datatype-3")
|
||||
}}>
|
||||
<i className="fa fa-file"></i>
|
||||
<h3>DATATYPE3</h3>
|
||||
<p>Content for Card 11</p>
|
||||
</div>
|
||||
<div className="usercard" onClick={()=>{
|
||||
navigate("/admin/datatype-4")
|
||||
}}>
|
||||
<i className="fa fa-file"></i>
|
||||
<h3>DATATYPE4</h3>
|
||||
<p>Content for Card 12</p>
|
||||
</div>
|
||||
<div className="usercard"onClick={()=>{
|
||||
navigate("/admin/datatype-5")
|
||||
}}>
|
||||
<i className="fa fa-file"></i>
|
||||
<h3>DATATYPE5</h3>
|
||||
<p>Content for Card 13</p>
|
||||
</div>
|
||||
<div className="usercard" onClick={()=>{
|
||||
navigate("/admin/datatype-6")
|
||||
}}>
|
||||
<i className="fa fa-file"></i>
|
||||
<h3>DATATYPE6</h3>
|
||||
<p>Content for Card 14</p>
|
||||
</div>
|
||||
<div className="usercard" onClick={()=>{
|
||||
navigate("/admin/basics-datatypes")
|
||||
}}>
|
||||
<i className="fa fa-file"></i>
|
||||
<h3>Basics Datatypes</h3>
|
||||
<p>Content for Card 15</p>
|
||||
</div>
|
||||
<div className="usercard" onClick={()=>{
|
||||
navigate("/admin/advance-datatypes")
|
||||
}}>
|
||||
<i className="fa fa-file"></i>
|
||||
<h3>Advanced Datatypes</h3>
|
||||
<p>Content for Card 16</p>
|
||||
</div>
|
||||
<div className="usercard" onClick={()=>{
|
||||
navigate("/admin/advance-datatypes2")
|
||||
}}>
|
||||
<i className="fa fa-file"></i>
|
||||
<h3>Advanced Datatypes 2</h3>
|
||||
<p>Content for Card 17</p>
|
||||
</div>
|
||||
<div className="usercard" onClick={()=>{
|
||||
navigate("/admin/premium-datatypes")
|
||||
}}>
|
||||
<i className="fa fa-file"></i>
|
||||
<h3>Premium Datatypes</h3>
|
||||
<p>Content for Card 18</p>
|
||||
</div> */}
|
||||
<div className="usercard" onClick={() => {
|
||||
navigate("/admin/user-report")
|
||||
}}>
|
||||
<i className="fa fa-file"></i>
|
||||
<h3>Reports</h3>
|
||||
<p>Report Description</p>
|
||||
</div>
|
||||
<div className="usercard" onClick={() => {
|
||||
navigate("/admin/dynamic-form")
|
||||
}}>
|
||||
<i className="fa fa-file"></i>
|
||||
<h3>DynamicForm</h3>
|
||||
<p>Content for Card 16</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div className="usercards">
|
||||
<div className="usercard" onClick={() => navigate("/admin/user-maintenance")}>
|
||||
<i className="fa fa-user-cog card-icon"></i>
|
||||
<h3>User Maintenance</h3>
|
||||
<p>User Maintainance</p>
|
||||
</div>
|
||||
<div className="usercard" onClick={() => navigate("/admin/user-Group-Maintenance")}>
|
||||
<i className="fa-solid fa-users"></i>
|
||||
<h3>User Group Maintenance</h3>
|
||||
<p>User Group Maintenance</p>
|
||||
</div>
|
||||
<div className="usercard" onClick={() => navigate("/admin/menu-maintenance")}>
|
||||
<i className="fa-solid fa-utensils"></i>
|
||||
<h3>Menu Maintenance</h3>
|
||||
<p>Menu Maintenance</p>
|
||||
</div>
|
||||
<div className="usercard" onClick={() => navigate("/admin/menu-access-control")}>
|
||||
<i className="fa-solid fa-lock"></i>
|
||||
<h3>Menu Access Control</h3>
|
||||
<p>Menu Access Control</p>
|
||||
</div>
|
||||
<div className="usercard" onClick={() => navigate("/admin/system-parameter")}>
|
||||
<i className="fa-solid fa-gears"></i>
|
||||
<h3>System Parameter</h3>
|
||||
<p>System Parameter</p>
|
||||
</div>
|
||||
<div className="usercard" onClick={() => navigate("/admin/access-type")}>
|
||||
<i className="fa-solid fa-key"></i>
|
||||
<h3>Access Type</h3>
|
||||
<p>Access Type</p>
|
||||
</div>
|
||||
<div className="usercard" onClick={() => navigate("/admin/sequence-generator")}>
|
||||
<i className="fa-solid fa-list-ol"></i>
|
||||
<h3>Document Sequence</h3>
|
||||
<p>Manage document sequences</p>
|
||||
</div>
|
||||
<div className="usercard" onClick={() => navigate("/admin/user-report")}>
|
||||
<i className="fa fa-file"></i>
|
||||
<h3>Reports</h3>
|
||||
<p>Reports Description</p>
|
||||
</div>
|
||||
<div className="usercard" onClick={() => navigate("/admin/api-registry")}>
|
||||
<i className="fas fa-database"></i>
|
||||
<h3>API Registry</h3>
|
||||
<p>API Registry</p>
|
||||
</div>
|
||||
<div className="usercard" onClick={() => navigate("/admin/token-registry")}>
|
||||
<i className="fas fa-database"></i>
|
||||
<h3>Token Registry</h3>
|
||||
<p>Token Registry</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -144,15 +144,230 @@
|
||||
|
||||
// export default SystemParameterForm;
|
||||
|
||||
// import React, { useState, useEffect } from "react";
|
||||
// import { Button, Form, Container, Row, Col } from "react-bootstrap";
|
||||
// import "bootstrap/dist/css/bootstrap.min.css";
|
||||
// import "../Dashboard/CSS/CSS/CommonStyle.css";
|
||||
// import { toast } from "react-toastify";
|
||||
// import Spinner from "../../UIComponants/Spinner";
|
||||
// import {getSysParameter,addSysParameter} from "../../APIServices/SystemparameterApi";
|
||||
// import { useSystemParameters } from "../../context/SystemParameterContext"; // update the path if needed
|
||||
|
||||
// const [loading, setLoading] = useState(true);
|
||||
|
||||
// const [formData, setFormData] = useState({
|
||||
// schedulerTime: "",
|
||||
// leaseTaxCode: "",
|
||||
// vesselConfProcessLimit: "",
|
||||
// rowToDisplay: "",
|
||||
// linkToDisplay: "",
|
||||
// rowToAdd: "",
|
||||
// lovRowToDisplay: "",
|
||||
// lovLinkToDisplay: "",
|
||||
// oidserverName: "",
|
||||
// oidBase: "",
|
||||
// oidAdminUser: "",
|
||||
// oidServerPort: "",
|
||||
// userDefaultGroup: "",
|
||||
// defaultDepartment: "",
|
||||
// defaultPosition: "",
|
||||
// singleCharge: "",
|
||||
// firstDayOftheWeek: "",
|
||||
// hourPerShift: "",
|
||||
// cnBillingFrequency: "",
|
||||
// billingDepartmentCode: "",
|
||||
// basePriceList: "",
|
||||
// nonContainerServiceOrder: "",
|
||||
// ediMaeSchedulerONOFF: "",
|
||||
// ediSchedulerONOFF: "",
|
||||
// upload_Logo: null,
|
||||
// company_Display_Name: "",
|
||||
// });
|
||||
// useEffect(() => {
|
||||
// if (systemParameters) {
|
||||
// setFormData((prevForm) => ({
|
||||
// ...prevForm,
|
||||
// ...systemParameters
|
||||
// }));
|
||||
// }
|
||||
// }, [systemParameters]);
|
||||
|
||||
// const handleInputChange = (event) => {
|
||||
// const { name, value } = event.target;
|
||||
// setFormData((prevState) => ({
|
||||
// ...prevState,
|
||||
// [name]: value,
|
||||
// }));
|
||||
// };
|
||||
|
||||
// const handleFileChange = (event) => {
|
||||
// setFormData((prevState) => ({
|
||||
// ...prevState,
|
||||
// logo: event.target.files[0],
|
||||
// }));
|
||||
// };
|
||||
|
||||
// // const handleSubmit = (event) => {
|
||||
// // event.preventDefault();
|
||||
|
||||
// // toast.success("Form submitted successfully!");
|
||||
// // // alert("Form submitted successfully!");
|
||||
// // console.log("Form Data:", formData);
|
||||
// // };
|
||||
|
||||
// const handleSubmit = async (event) => {
|
||||
// event.preventDefault();
|
||||
|
||||
// try {
|
||||
// console.log("Form Data:", formData);
|
||||
// const sysParamData = await addSysParameter(formData);
|
||||
// console.log("API Response:", sysParamData);
|
||||
|
||||
// toast.success("Form submitted successfully!");
|
||||
// } catch (error) {
|
||||
// console.error("Error:", error.response ? error.response.data : error.message);
|
||||
// toast.error("Failed to submit the form. Please try again.");
|
||||
// }
|
||||
// };
|
||||
|
||||
// const handleClear = () => {
|
||||
// setFormData({
|
||||
// schedulerTimer: "",
|
||||
// leaseTaxCode: "",
|
||||
// vesselConfirmationProcessLimit: "",
|
||||
|
||||
// rowToDisplay: "",
|
||||
// linkToDisplay: "",
|
||||
// rowToAdd: "",
|
||||
// lovRowToDisplay: "",
|
||||
// lovLinkToDisplay: "",
|
||||
// oldServerName: "",
|
||||
// oldBase: "",
|
||||
// oldAdminUser: "",
|
||||
// oldServerPort: "",
|
||||
// userDefaultGroup: "",
|
||||
// defaultDepartment: "",
|
||||
// defaultPosition: "",
|
||||
// singleCharge: "",
|
||||
// firstDayOfWeek: "",
|
||||
// hourPerShift: "",
|
||||
// cnBillingFrequency: "",
|
||||
// billingDepartmentCode: "",
|
||||
// basePriceList: "",
|
||||
// nonContainerServiceOrderAutoApprovalDeptCode: "",
|
||||
// ediMAESchedulerOnOff: "",
|
||||
// ediSchedulerOnOff: "",
|
||||
// logo: null,
|
||||
// companyDisplayName: "",
|
||||
// });
|
||||
// };
|
||||
|
||||
// return (
|
||||
// <div
|
||||
// style={{
|
||||
// marginTop: "10rem",
|
||||
// marginBottom: "2rem",
|
||||
// boxSizing: "border-box",
|
||||
// }}
|
||||
// >
|
||||
// {loading ? (
|
||||
// <Spinner />
|
||||
// ) : (
|
||||
// <Container
|
||||
// className="system_parameter mt-5 p-4 bg-light shadow-sm rounded"
|
||||
|
||||
// >
|
||||
// <h2
|
||||
// className="title_main text-center mb-4"
|
||||
// style={{ color: "#0E6591", fontWeight: "bold" }}
|
||||
// >
|
||||
// System Parameter Settings
|
||||
// </h2>
|
||||
// <Form onSubmit={handleSubmit}>
|
||||
// <Row className=" mb-3">
|
||||
// <Col xs={6}>
|
||||
// <h6 className="heading_main text-secondary">Setup Code</h6>
|
||||
// </Col>
|
||||
// <Col xs={6}>
|
||||
// <h6 className="heading_main text-secondary">Value</h6>
|
||||
// </Col>
|
||||
// </Row>
|
||||
|
||||
// {Object.keys(formData).map((key, index) =>
|
||||
// key !== "upload_Logo" ? (
|
||||
// <Row className="mb-3" key={index}>
|
||||
// <Col xs={6} className="d-flex align-items-center">
|
||||
// <Form.Label className="mb-0">
|
||||
// {key
|
||||
// .split(/(?=[A-Z])/)
|
||||
// .join(" ")
|
||||
// .replace(/\b\w/g, (l) => l.toUpperCase())}
|
||||
// </Form.Label>
|
||||
// </Col>
|
||||
// <Col xs={6}>
|
||||
// <Form.Control
|
||||
// className="p-2 custom-hover-border"
|
||||
// style={{ borderColor: "#ced4da" }}
|
||||
// type="text"
|
||||
// name={key}
|
||||
// value={formData[key]}
|
||||
// onChange={handleInputChange}
|
||||
// />
|
||||
// </Col>
|
||||
// </Row>
|
||||
// ) : (
|
||||
// <Row className="mb-3" key={index}>
|
||||
// <Col xs={6} className="d-flex align-items-center">
|
||||
// <Form.Label className="mb-0">Upload Logo</Form.Label>
|
||||
// </Col>
|
||||
// <Col xs={6}>
|
||||
// <Form.Control
|
||||
// className="p-2 "
|
||||
// style={{ borderColor: "#ced4da" }}
|
||||
// type="file"
|
||||
// onChange={handleFileChange}
|
||||
// />
|
||||
// </Col>
|
||||
// </Row>
|
||||
// )
|
||||
// )}
|
||||
|
||||
// <div className="d-flex justify-content-end mt-4">
|
||||
// <Button
|
||||
// variant="primary"
|
||||
// type="submit"
|
||||
// className="me-2 px-4 py-2 custom_button"
|
||||
// >
|
||||
// Save
|
||||
// </Button>
|
||||
// <Button
|
||||
// variant="outline"
|
||||
// onClick={handleClear}
|
||||
// className="px-4 py-2 custom_button"
|
||||
// >
|
||||
// Clear
|
||||
// </Button>
|
||||
// </div>
|
||||
// </Form>
|
||||
// </Container>
|
||||
// )}
|
||||
// </div>
|
||||
// );
|
||||
// };
|
||||
|
||||
// export default SystemParameterForm;
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { Button, Form, Container, Row, Col } from "react-bootstrap";
|
||||
import "bootstrap/dist/css/bootstrap.min.css";
|
||||
import "../Dashboard/CSS/CSS/CommonStyle.css";
|
||||
import { toast } from "react-toastify";
|
||||
import Spinner from "../../UIComponants/Spinner";
|
||||
import {getSysParameter,addSysParameter} from "../../APIServices/SystemparameterApi";
|
||||
import { getSysParameter, addSysParameter } from "../../APIServices/SystemparameterApi";
|
||||
import { useSystemParameters } from "../../context/SystemParameterContext";
|
||||
|
||||
const SystemParameterForm = () => {
|
||||
const { systemParameters, loading: contextLoading } = useSystemParameters();
|
||||
|
||||
const [formData, setFormData] = useState({
|
||||
schedulerTime: "",
|
||||
leaseTaxCode: "",
|
||||
@@ -181,14 +396,16 @@ const SystemParameterForm = () => {
|
||||
upload_Logo: null,
|
||||
company_Display_Name: "",
|
||||
});
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
// Simulate loading data
|
||||
setTimeout(() => {
|
||||
setLoading(false);
|
||||
}, 3000); // Simulated 3 seconds loading
|
||||
}, []);
|
||||
if (systemParameters) {
|
||||
setFormData((prevForm) => ({
|
||||
...prevForm,
|
||||
...systemParameters,
|
||||
}));
|
||||
}
|
||||
}, [systemParameters]);
|
||||
|
||||
const handleInputChange = (event) => {
|
||||
const { name, value } = event.target;
|
||||
setFormData((prevState) => ({
|
||||
@@ -200,62 +417,52 @@ const SystemParameterForm = () => {
|
||||
const handleFileChange = (event) => {
|
||||
setFormData((prevState) => ({
|
||||
...prevState,
|
||||
logo: event.target.files[0],
|
||||
upload_Logo: event.target.files[0],
|
||||
}));
|
||||
};
|
||||
|
||||
// const handleSubmit = (event) => {
|
||||
// event.preventDefault();
|
||||
|
||||
// toast.success("Form submitted successfully!");
|
||||
// // alert("Form submitted successfully!");
|
||||
// console.log("Form Data:", formData);
|
||||
// };
|
||||
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
try {
|
||||
console.log("Form Data:", formData);
|
||||
const sysParamData = await addSysParameter(formData);
|
||||
console.log("API Response:", sysParamData);
|
||||
|
||||
toast.success("Form submitted successfully!");
|
||||
console.log("Form Data:", formData);
|
||||
const sysParamData = await addSysParameter(formData);
|
||||
console.log("API Response:", sysParamData);
|
||||
toast.success("Form submitted successfully!");
|
||||
} catch (error) {
|
||||
console.error("Error:", error.response ? error.response.data : error.message);
|
||||
toast.error("Failed to submit the form. Please try again.");
|
||||
console.error("Error:", error.response ? error.response.data : error.message);
|
||||
toast.error("Failed to submit the form. Please try again.");
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const handleClear = () => {
|
||||
setFormData({
|
||||
schedulerTimer: "",
|
||||
schedulerTime: "",
|
||||
leaseTaxCode: "",
|
||||
vesselConfirmationProcessLimit: "",
|
||||
|
||||
vesselConfProcessLimit: "",
|
||||
rowToDisplay: "",
|
||||
linkToDisplay: "",
|
||||
rowToAdd: "",
|
||||
lovRowToDisplay: "",
|
||||
lovLinkToDisplay: "",
|
||||
oldServerName: "",
|
||||
oldBase: "",
|
||||
oldAdminUser: "",
|
||||
oldServerPort: "",
|
||||
oidserverName: "",
|
||||
oidBase: "",
|
||||
oidAdminUser: "",
|
||||
oidServerPort: "",
|
||||
userDefaultGroup: "",
|
||||
defaultDepartment: "",
|
||||
defaultPosition: "",
|
||||
singleCharge: "",
|
||||
firstDayOfWeek: "",
|
||||
firstDayOftheWeek: "",
|
||||
hourPerShift: "",
|
||||
cnBillingFrequency: "",
|
||||
billingDepartmentCode: "",
|
||||
basePriceList: "",
|
||||
nonContainerServiceOrderAutoApprovalDeptCode: "",
|
||||
ediMAESchedulerOnOff: "",
|
||||
ediSchedulerOnOff: "",
|
||||
logo: null,
|
||||
companyDisplayName: "",
|
||||
nonContainerServiceOrder: "",
|
||||
ediMaeSchedulerONOFF: "",
|
||||
ediSchedulerONOFF: "",
|
||||
upload_Logo: null,
|
||||
company_Display_Name: "",
|
||||
});
|
||||
};
|
||||
|
||||
@@ -267,13 +474,10 @@ const SystemParameterForm = () => {
|
||||
boxSizing: "border-box",
|
||||
}}
|
||||
>
|
||||
{loading ? (
|
||||
{contextLoading ? (
|
||||
<Spinner />
|
||||
) : (
|
||||
<Container
|
||||
className="system_parameter mt-5 p-4 bg-light shadow-sm rounded"
|
||||
|
||||
>
|
||||
<Container className="system_parameter mt-5 p-4 bg-light shadow-sm rounded">
|
||||
<h2
|
||||
className="title_main text-center mb-4"
|
||||
style={{ color: "#0E6591", fontWeight: "bold" }}
|
||||
@@ -281,7 +485,7 @@ const SystemParameterForm = () => {
|
||||
System Parameter Settings
|
||||
</h2>
|
||||
<Form onSubmit={handleSubmit}>
|
||||
<Row className=" mb-3">
|
||||
<Row className="mb-3">
|
||||
<Col xs={6}>
|
||||
<h6 className="heading_main text-secondary">Setup Code</h6>
|
||||
</Col>
|
||||
@@ -303,7 +507,7 @@ const SystemParameterForm = () => {
|
||||
</Col>
|
||||
<Col xs={6}>
|
||||
<Form.Control
|
||||
className="p-2 custom-hover-border"
|
||||
className="p-2 custom-hover-border"
|
||||
style={{ borderColor: "#ced4da" }}
|
||||
type="text"
|
||||
name={key}
|
||||
@@ -319,7 +523,7 @@ const SystemParameterForm = () => {
|
||||
</Col>
|
||||
<Col xs={6}>
|
||||
<Form.Control
|
||||
className="p-2 "
|
||||
className="p-2"
|
||||
style={{ borderColor: "#ced4da" }}
|
||||
type="file"
|
||||
onChange={handleFileChange}
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { Button, Dropdown,Modal, Form ,Row,Col,InputGroup,FormControl} from "react-bootstrap";
|
||||
import { Button, Dropdown, Modal, Form, Row, Col, InputGroup, FormControl, Card } from "react-bootstrap";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faEdit, faTrashAlt, faPlus,faBars,faTimes } from "@fortawesome/free-solid-svg-icons";
|
||||
import { faEdit, faTrashAlt, faPlus, faBars, faTimes } from "@fortawesome/free-solid-svg-icons";
|
||||
import "bootstrap/dist/css/bootstrap.min.css";
|
||||
import "../Dashboard/CSS/CSS/CommonStyle.css";
|
||||
import { Table, Pagination, PaginationItem, PaginationLink } from "reactstrap";
|
||||
import { FaSearch, FaTimes } from "react-icons/fa";
|
||||
import { FaSearch } from "react-icons/fa";
|
||||
import { BsJournals } from "react-icons/bs";
|
||||
import { toast } from "react-toastify";
|
||||
import Spinner from '../../UIComponants/Spinner';
|
||||
|
||||
import * as tokenRegistryAPI from './tokenregistryapi';
|
||||
|
||||
function TOKENRegistry() {
|
||||
const initialTokens = JSON.parse(localStorage.getItem("tokens")) || [];
|
||||
const [tokens, setTokens] = useState(initialTokens);
|
||||
const [tokens, setTokens] = useState([]);
|
||||
const [showAddEditModal, setShowAddEditModal] = useState(false);
|
||||
const [showGenerateTokenModal, setShowGenerateTokenModal] = useState(false);
|
||||
const [newTokenName, setNewTokenName] = useState("");
|
||||
const [generatedToken, setGeneratedToken] = useState("");
|
||||
const [currentToken, setCurrentToken] = useState({
|
||||
tokenId: "",
|
||||
id: "",
|
||||
tokenName: "",
|
||||
tokenValue: "",
|
||||
isActive: true
|
||||
@@ -25,50 +26,49 @@ function TOKENRegistry() {
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const [recordsPerPage, setRecordsPerPage] = useState(10);
|
||||
const [visibleColumns, setVisibleColumns] = useState({
|
||||
tokenId: true,
|
||||
tokenName: true,
|
||||
tokenValue: true,
|
||||
isActive: true,
|
||||
actions: true
|
||||
});
|
||||
// Add to your state:
|
||||
const [visibleColumns, setVisibleColumns] = useState({
|
||||
id: true,
|
||||
tokenName: true,
|
||||
tokenValue: true,
|
||||
scopes: true,
|
||||
isActive: true,
|
||||
actions: true
|
||||
});
|
||||
|
||||
|
||||
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(() => {
|
||||
const apiUrl = `${process.env.REACT_APP_API_URL}apiregistery/getall`;
|
||||
const token = localStorage.getItem("authToken");
|
||||
|
||||
const fetchTokens = async () => {
|
||||
try {
|
||||
const response = await fetch(apiUrl, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
setTokens(data);
|
||||
localStorage.setItem("tokens", JSON.stringify(data)); // Store tokens in local storage
|
||||
} catch (error) {
|
||||
console.error("Error fetching tokens:", error);
|
||||
}
|
||||
};
|
||||
|
||||
fetchTokens();
|
||||
}, []);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
// Simulate loading data
|
||||
setTimeout(() => {
|
||||
setLoading(false);
|
||||
}, 3000); // Simulated 3 seconds loading
|
||||
}, []);
|
||||
const fetchTokens = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const data = await tokenRegistryAPI.fetchAllTokens();
|
||||
setTokens(data);
|
||||
} catch (error) {
|
||||
handleApiError(error, "fetch tokens");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleApiError = (error, action) => {
|
||||
if (error.message === 'Unauthorized') {
|
||||
toast.error("Your session has expired. Please log in again.");
|
||||
} else {
|
||||
toast.error(`Failed to ${action}`);
|
||||
console.error(`Error ${action}:`, error);
|
||||
}
|
||||
};
|
||||
|
||||
const toggleColumn = (column) => {
|
||||
setVisibleColumns(prev => ({
|
||||
@@ -87,10 +87,14 @@ useEffect(() => {
|
||||
|
||||
const handleSearch = (query) => {
|
||||
setSearchQuery(query);
|
||||
setCurrentPage(1);
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setShowAddEditModal(false); // Close the modal by setting the state to false
|
||||
setShowAddEditModal(false);
|
||||
setShowGenerateTokenModal(false);
|
||||
setGeneratedToken("");
|
||||
setNewTokenName("");
|
||||
};
|
||||
|
||||
const handleRecordsPerPageChange = (number) => {
|
||||
@@ -98,365 +102,378 @@ useEffect(() => {
|
||||
setCurrentPage(1);
|
||||
};
|
||||
|
||||
const totalPages = Math.ceil(tokens.length / recordsPerPage);
|
||||
const filteredTokens = tokens.filter(
|
||||
(item) =>
|
||||
item.tokenName &&
|
||||
item.tokenName.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
);
|
||||
|
||||
const totalPages = Math.ceil(filteredTokens.length / recordsPerPage);
|
||||
const handlePageChange = (pageNumber) => {
|
||||
setCurrentPage(pageNumber);
|
||||
};
|
||||
|
||||
const slicedTokens = tokens
|
||||
.filter(
|
||||
(item) =>
|
||||
item.tokenName &&
|
||||
item.tokenName.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
)
|
||||
.slice((currentPage - 1) * recordsPerPage, currentPage * recordsPerPage);
|
||||
const slicedTokens = filteredTokens.slice(
|
||||
(currentPage - 1) * recordsPerPage,
|
||||
currentPage * recordsPerPage
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
const handleSubmit = (event) => {
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
try {
|
||||
if (isEditing) {
|
||||
setTokens(tokens.map(token =>
|
||||
token.tokenId === currentToken.tokenId ? currentToken : token
|
||||
));
|
||||
await tokenRegistryAPI.updateToken(currentToken.id, currentToken);
|
||||
toast.success("Token updated successfully!");
|
||||
} else {
|
||||
const newTokenId = `ID${tokens.length + 1}`;
|
||||
setTokens([...tokens, { ...currentToken, tokenId: newTokenId }]);
|
||||
await tokenRegistryAPI.createToken(currentToken);
|
||||
toast.success("Token added successfully!");
|
||||
}
|
||||
setShowAddEditModal(false);
|
||||
|
||||
localStorage.setItem("tokens", JSON.stringify(tokens)); // Update local storage with new tokens
|
||||
fetchTokens();
|
||||
} catch (error) {
|
||||
toast.error("There was an error while submitting the token.");
|
||||
console.error("Error in handleSubmit:", error); // Log the error for debugging
|
||||
handleApiError(error, isEditing ? "update token" : "add token");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const openModal = (token = { tokenId: "", tokenName: "", tokenValue: "", isActive: false }) => {
|
||||
setIsEditing(!!token.tokenId);
|
||||
const openModal = (token = { id: "", tokenName: "", tokenValue: "", isActive: false }) => {
|
||||
setIsEditing(!!token.id);
|
||||
setCurrentToken(token);
|
||||
setShowAddEditModal(true);
|
||||
};
|
||||
|
||||
const handleDelete = (tokenId) => {
|
||||
setTokens(tokens.filter(token => token.tokenId !== tokenId));
|
||||
localStorage.setItem("tokens", JSON.stringify(tokens.filter(token => token.tokenId !== tokenId))); // Update local storage after deletion
|
||||
toast.success('Token deleted ...');
|
||||
const handleDelete = async (id) => {
|
||||
if (window.confirm("Are you sure you want to delete this token?")) {
|
||||
try {
|
||||
await tokenRegistryAPI.deleteToken(id);
|
||||
toast.success('Token deleted successfully');
|
||||
fetchTokens();
|
||||
} catch (error) {
|
||||
handleApiError(error, "delete token");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
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 (
|
||||
<div style={{marginTop:"11rem"}}>
|
||||
<div style={{ marginTop: "1rem" }}>
|
||||
{loading ? (
|
||||
<Spinner/>
|
||||
):(
|
||||
<Spinner />
|
||||
) : (
|
||||
<div className="container-fluid mt-5">
|
||||
|
||||
<div className="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1 className="title_main">Token Registry</h1>
|
||||
</div>
|
||||
{/* Token Generation Card */}
|
||||
<Card className="mb-4 shadow-sm">
|
||||
<Card.Header className="d-flex justify-content-between align-items-center">
|
||||
<Card.Title>Token Management</Card.Title>
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={() => setShowGenerateTokenModal(true)}
|
||||
className="custom_button"
|
||||
>
|
||||
Generate New Token
|
||||
</Button>
|
||||
</Card.Header>
|
||||
<Card.Body>
|
||||
<p>Manage your API tokens here. Generate new tokens or delete existing ones.</p>
|
||||
</Card.Body>
|
||||
</Card>
|
||||
|
||||
<Row className="align-items-center my-3">
|
||||
{/* Left: Search Bar */}
|
||||
<Col
|
||||
xs={12}
|
||||
md={8}
|
||||
lg={6}
|
||||
className="d-flex justify-content-center my-3"
|
||||
>
|
||||
<InputGroup
|
||||
className="search-bar"
|
||||
style={{
|
||||
borderRadius: "10px",
|
||||
overflow: "hidden",
|
||||
boxShadow: "0px 4px 12px rgba(0, 0, 0, 0.1)",
|
||||
width: "100%",
|
||||
maxWidth: "528px", // Set max-width to limit overall width
|
||||
paddingRight: "-15px", // Increase padding on the right side
|
||||
}}
|
||||
>
|
||||
<InputGroup.Text
|
||||
style={{
|
||||
backgroundColor: "#0E6591",
|
||||
color: "#fff",
|
||||
padding: "10px 15px",
|
||||
}}
|
||||
>
|
||||
<FaSearch />
|
||||
</InputGroup.Text>
|
||||
<FormControl
|
||||
placeholder="Search"
|
||||
value={searchQuery}
|
||||
onChange={(e) => handleSearch(e.target.value)}
|
||||
style={{
|
||||
padding: "10px",
|
||||
border: "none",
|
||||
paddingRight: "5px", // More space on the right side of input field
|
||||
}}
|
||||
/>
|
||||
</InputGroup>
|
||||
</Col>
|
||||
<div className="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1 className="title_main">Token Registry</h1>
|
||||
</div>
|
||||
|
||||
{/*Add Icons */}
|
||||
<Col xs={12} md={4} lg={6} className="d-flex justify-content-end">
|
||||
<>
|
||||
{/* Add Icon */}
|
||||
<FontAwesomeIcon
|
||||
icon={faPlus}
|
||||
onClick={() => openModal(true)}
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
fontSize: "1.5rem",
|
||||
color: "#747264",
|
||||
marginRight: "20px",
|
||||
}}
|
||||
/>
|
||||
<FontAwesomeIcon
|
||||
icon={faBars}
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
fontSize: "1.5rem",
|
||||
color: "#747264",
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
|
||||
<div className="table-responsive">
|
||||
<Table striped responsive hover align="middle" className=" table-flush shadow-sm">
|
||||
<thead className="custom_header">
|
||||
<tr>
|
||||
{Object.keys(visibleColumns).filter(key => visibleColumns[key]).map(key => (
|
||||
<th key={key}>{key.charAt(0).toUpperCase() + key.slice(1)}</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="tbody">
|
||||
{slicedTokens.length === 0 ? (
|
||||
<tr>
|
||||
<td
|
||||
colSpan={
|
||||
Object.keys(visibleColumns).filter(
|
||||
(key) => visibleColumns[key]
|
||||
).length
|
||||
}
|
||||
className="text-center"
|
||||
>
|
||||
No Data Available
|
||||
</td>
|
||||
</tr>
|
||||
) : (
|
||||
slicedTokens.map((token, index) => (
|
||||
<tr key={index}>
|
||||
{Object.keys(visibleColumns).filter(key => visibleColumns[key]).map(key => (
|
||||
<td key={key}>
|
||||
{key === "actions" ? (
|
||||
<>
|
||||
<FontAwesomeIcon
|
||||
icon={faEdit}
|
||||
onClick={() => openModal(token)}
|
||||
className="me-2"
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
fontSize: "1rem",
|
||||
color: "green",
|
||||
marginRight: "15px",
|
||||
}}
|
||||
/>
|
||||
<FontAwesomeIcon
|
||||
icon={faTrashAlt}
|
||||
onClick={() => handleDelete(token.tokenId)}
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
fontSize: "1rem",
|
||||
color: "#dc3545",
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
) : key === "isActive" ? (
|
||||
<span
|
||||
className="status"
|
||||
<Row className="align-items-center my-3">
|
||||
<Col xs={12} md={8} lg={6} className="d-flex justify-content-center my-3">
|
||||
<InputGroup
|
||||
className="search-bar"
|
||||
style={{
|
||||
color: token.isActive ? "green" : "red",
|
||||
backgroundColor: token.isActive
|
||||
? "#d4f7d4"
|
||||
: "#f7d4d4",
|
||||
padding: "4px 8px",
|
||||
borderRadius: "4px",
|
||||
display: "inline-block",
|
||||
borderRadius: "10px",
|
||||
overflow: "hidden",
|
||||
boxShadow: "0px 4px 12px rgba(0, 0, 0, 0.1)",
|
||||
width: "100%",
|
||||
maxWidth: "528px",
|
||||
}}
|
||||
>
|
||||
{token.isActive ? "Active" : "Inactive"}
|
||||
</span>
|
||||
) : (
|
||||
token[key]
|
||||
)}
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
))
|
||||
)}
|
||||
</tbody>
|
||||
<InputGroup.Text style={{ backgroundColor: "#0E6591", color: "#fff", padding: "10px 15px" }}>
|
||||
<FaSearch />
|
||||
</InputGroup.Text>
|
||||
<FormControl
|
||||
placeholder="Search"
|
||||
value={searchQuery}
|
||||
onChange={(e) => handleSearch(e.target.value)}
|
||||
style={{ padding: "10px", border: "none" }}
|
||||
/>
|
||||
</InputGroup>
|
||||
</Col>
|
||||
|
||||
</Table>
|
||||
</div>
|
||||
<Col xs={12} md={4} lg={6} className="d-flex justify-content-end">
|
||||
<FontAwesomeIcon
|
||||
icon={faPlus}
|
||||
onClick={() => openModal()}
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
fontSize: "1.5rem",
|
||||
color: "#747264",
|
||||
marginRight: "20px",
|
||||
}}
|
||||
/>
|
||||
<FontAwesomeIcon
|
||||
icon={faBars}
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
fontSize: "1.5rem",
|
||||
color: "#747264",
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
{/* Manage Columns & Records Per Page */}
|
||||
<Row className="mt-4">
|
||||
<Col md={6} className="d-flex justify-content-start">
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle
|
||||
variant="outline-primary"
|
||||
className="custom_manage_column_button"
|
||||
>
|
||||
Manage Columns
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu>
|
||||
{Object.keys(visibleColumns).map((column) => (
|
||||
<Dropdown.Item
|
||||
key={column}
|
||||
onClick={() => toggleColumn(column)}
|
||||
<div className="table-responsive">
|
||||
<Table striped responsive hover align="middle" className="table-flush shadow-sm">
|
||||
<thead className="custom_header">
|
||||
<tr>
|
||||
{Object.keys(visibleColumns).filter(key => visibleColumns[key]).map(key => (
|
||||
<th key={key}>{key.charAt(0).toUpperCase() + key.slice(1)}</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="tbody">
|
||||
{slicedTokens.length === 0 ? (
|
||||
<tr>
|
||||
<td
|
||||
colSpan={Object.keys(visibleColumns).filter(key => visibleColumns[key]).length}
|
||||
className="text-center"
|
||||
>
|
||||
No Data Available
|
||||
</td>
|
||||
</tr>
|
||||
) : (
|
||||
slicedTokens.map((token, index) => (
|
||||
<tr key={index}>
|
||||
{Object.keys(visibleColumns).filter(key => visibleColumns[key]).map(key => (
|
||||
<td key={key}>
|
||||
{key === "actions" ? (
|
||||
<>
|
||||
<FontAwesomeIcon
|
||||
icon={faEdit}
|
||||
onClick={() => openModal(token)}
|
||||
className="me-2"
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
fontSize: "1rem",
|
||||
color: "green",
|
||||
marginRight: "15px",
|
||||
}}
|
||||
/>
|
||||
<FontAwesomeIcon
|
||||
icon={faTrashAlt}
|
||||
onClick={() => handleDelete(token.id)}
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
fontSize: "1rem",
|
||||
color: "#dc3545",
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
) : key === "isActive" ? (
|
||||
<span
|
||||
className="status"
|
||||
style={{
|
||||
color: token.isActive ? "green" : "red",
|
||||
backgroundColor: token.isActive ? "#d4f7d4" : "#f7d4d4",
|
||||
padding: "4px 8px",
|
||||
borderRadius: "4px",
|
||||
display: "inline-block",
|
||||
}}
|
||||
>
|
||||
{token.isActive ? "Active" : "Inactive"}
|
||||
</span>
|
||||
) : (
|
||||
token[key]
|
||||
)}
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
))
|
||||
)}
|
||||
</tbody>
|
||||
</Table>
|
||||
</div>
|
||||
|
||||
{/* Manage Columns & Records Per Page */}
|
||||
<Row className="mt-4">
|
||||
<Col md={6} className="d-flex justify-content-start">
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle variant="outline-primary" className="custom_manage_column_button">
|
||||
Manage Columns
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu>
|
||||
{Object.keys(visibleColumns).map((column) => (
|
||||
<Dropdown.Item key={column} onClick={() => toggleColumn(column)}>
|
||||
<Form.Check
|
||||
type="checkbox"
|
||||
label={column.charAt(0).toUpperCase() + column.slice(1).toLowerCase()}
|
||||
checked={visibleColumns[column]}
|
||||
readOnly
|
||||
className="custom-checkbox"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
))}
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
</Col>
|
||||
|
||||
<Col md={6} className="d-flex justify-content-end">
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle
|
||||
variant="outline-primary"
|
||||
className="custom_manage_column_button px-4 py-2 border-2 rounded-3 shadow-sm"
|
||||
>
|
||||
<Form.Check
|
||||
type="checkbox"
|
||||
label={
|
||||
column.charAt(0).toUpperCase() +
|
||||
column.slice(1).toLowerCase()
|
||||
}
|
||||
checked={visibleColumns[column]}
|
||||
readOnly
|
||||
className="custom-checkbox"
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
))}
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
</Col>
|
||||
<BsJournals />
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu className="border-0 rounded-3 shadow-lg" align="end">
|
||||
{[1, 5, 10, 20, 50].map((number) => (
|
||||
<Dropdown.Item
|
||||
key={number}
|
||||
onClick={() => handleRecordsPerPageChange(number)}
|
||||
className="text-dark d-flex justify-content-between align-items-center"
|
||||
>
|
||||
<span>{number}</span>
|
||||
<i
|
||||
className="fa fa-check-circle"
|
||||
style={{ display: recordsPerPage === number ? "inline" : "none" }}
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
))}
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Col md={6} className="d-flex justify-content-end">
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle
|
||||
variant="outline-primary"
|
||||
className="custom_manage_column_button px-4 py-2 border-2 rounded-3 shadow-sm"
|
||||
id="dropdown-custom-components"
|
||||
>
|
||||
<BsJournals />
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu className="border-0 rounded-3 shadow-lg" align="end">
|
||||
{[1, 5, 10, 20, 50].map((number) => (
|
||||
<Dropdown.Item
|
||||
key={number}
|
||||
onClick={() => handleRecordsPerPageChange(number)}
|
||||
className="text-dark d-flex justify-content-between align-items-center"
|
||||
>
|
||||
<span>{number}</span>
|
||||
<i
|
||||
className="fa fa-check-circle"
|
||||
style={{
|
||||
display: recordsPerPage === number ? "inline" : "none",
|
||||
}}
|
||||
/>
|
||||
</Dropdown.Item>
|
||||
))}
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
</Col>
|
||||
</Row>
|
||||
<Pagination className="pagination">
|
||||
<PaginationItem disabled={currentPage === 1}>
|
||||
<PaginationLink previous onClick={() => handlePageChange(currentPage - 1)} />
|
||||
</PaginationItem>
|
||||
{[...Array(totalPages)].map((_, index) => (
|
||||
<PaginationItem key={index} active={index + 1 === currentPage}>
|
||||
<PaginationLink onClick={() => handlePageChange(index + 1)} style={{ color: "#0b6592" }}>
|
||||
{index + 1}
|
||||
</PaginationLink>
|
||||
</PaginationItem>
|
||||
))}
|
||||
<PaginationItem disabled={currentPage === totalPages}>
|
||||
<PaginationLink next onClick={() => handlePageChange(currentPage + 1)} />
|
||||
</PaginationItem>
|
||||
</Pagination>
|
||||
|
||||
<Pagination className="pagination">
|
||||
<PaginationItem disabled={currentPage === 1}>
|
||||
<PaginationLink
|
||||
previous
|
||||
onClick={() => handlePageChange(currentPage - 1)}
|
||||
{/* Add/Edit 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>
|
||||
<Form.Select
|
||||
multiple
|
||||
value={selectedScopes}
|
||||
onChange={(e) => {
|
||||
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 => (
|
||||
<option key={scope.value} value={scope.value}>
|
||||
{scope.label}
|
||||
</option>
|
||||
))}
|
||||
</Form.Select>
|
||||
<Form.Text className="text-muted">
|
||||
Select the permissions this token should have (hold Ctrl/Cmd to select multiple)
|
||||
</Form.Text>
|
||||
</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"
|
||||
/>
|
||||
</PaginationItem>
|
||||
{[...Array(totalPages)].map((_, index) => (
|
||||
<PaginationItem key={index} active={index + 1 === currentPage}>
|
||||
<PaginationLink
|
||||
onClick={() => handlePageChange(index + 1)}
|
||||
style={{ color: "#0b6592" }}
|
||||
>
|
||||
{index + 1}
|
||||
</PaginationLink>
|
||||
</PaginationItem>
|
||||
))}
|
||||
<PaginationItem disabled={currentPage === totalPages}>
|
||||
<PaginationLink
|
||||
next
|
||||
onClick={() => handlePageChange(currentPage + 1)}
|
||||
/>
|
||||
</PaginationItem>
|
||||
</Pagination>
|
||||
|
||||
|
||||
|
||||
<Modal show={showAddEditModal} onHide={() => setShowAddEditModal(false)}>
|
||||
<Modal.Header >
|
||||
<Modal.Title>{isEditing ? "Edit Token" : "Add Token"}</Modal.Title>
|
||||
<FontAwesomeIcon
|
||||
icon={faTimes}
|
||||
size="lg"
|
||||
onClick={handleClose}
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: "25px",
|
||||
right: "25px",
|
||||
cursor: "pointer",
|
||||
}}
|
||||
/>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
<Form onSubmit={handleSubmit}>
|
||||
<Form.Group controlId="formTokenName">
|
||||
<Form.Label>Token Name</Form.Label>
|
||||
<Form.Control
|
||||
type="text"
|
||||
name="tokenName"
|
||||
value={currentToken.tokenName}
|
||||
onChange={handleInputChange}
|
||||
required
|
||||
className="custom-hover-border"
|
||||
/>
|
||||
</Form.Group>
|
||||
<Form.Group controlId="formTokenValue">
|
||||
<Form.Label>Token Value</Form.Label>
|
||||
<Form.Control
|
||||
type="text"
|
||||
name="tokenValue"
|
||||
value={currentToken.tokenValue}
|
||||
onChange={handleInputChange}
|
||||
required
|
||||
className="custom-hover-border"
|
||||
/>
|
||||
</Form.Group>
|
||||
<Form.Group controlId="formActive">
|
||||
<Form.Check
|
||||
type="checkbox"
|
||||
label="Active?"
|
||||
name="isActive"
|
||||
checked={currentToken.isActive}
|
||||
onChange={handleInputChange}
|
||||
className="custom-checkbox"
|
||||
/>
|
||||
</Form.Group>
|
||||
<Modal.Footer>
|
||||
<Button variant="primary" className="custom_button px-4" onClick={() => setShowAddEditModal(false)}>Close</Button>
|
||||
<Button variant="primary" className="custom_button px-4" type="submit">{isEditing ? "Update Token" : "Add Token"}</Button>
|
||||
</Modal.Footer>
|
||||
</Form>
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
</div>
|
||||
<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>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
export default TOKENRegistry;
|
||||
export default TOKENRegistry;
|
||||
@@ -313,7 +313,7 @@ export function UserGroupMaintenance() {
|
||||
)
|
||||
.slice((currentPage - 1) * recordsPerPage, currentPage * recordsPerPage);
|
||||
return (
|
||||
<div style={{ marginTop: "11rem" }}>
|
||||
<div style={{ marginTop: "7rem" }}>
|
||||
{loading ? (
|
||||
<Spinner />
|
||||
) : (
|
||||
@@ -366,11 +366,11 @@ export function UserGroupMaintenance() {
|
||||
{/*Add Icons */}
|
||||
<Col xs={12} md={4} lg={6} className="d-flex justify-content-end">
|
||||
<>
|
||||
<OverlayTrigger
|
||||
{/* <OverlayTrigger
|
||||
placement="bottom"
|
||||
overlay={<Tooltip>Add Group</Tooltip>}
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
> */}
|
||||
{/* <FontAwesomeIcon
|
||||
icon={faPlus}
|
||||
onClick={() => handleAddItem(true)}
|
||||
style={{
|
||||
@@ -379,8 +379,8 @@ export function UserGroupMaintenance() {
|
||||
color: "#747264",
|
||||
marginRight: "20px",
|
||||
}}
|
||||
/>
|
||||
</OverlayTrigger>
|
||||
/> */}
|
||||
{/* </OverlayTrigger> */}
|
||||
<OverlayTrigger
|
||||
placement="bottom"
|
||||
overlay={<Tooltip>Download template</Tooltip>}
|
||||
@@ -426,7 +426,7 @@ export function UserGroupMaintenance() {
|
||||
}}
|
||||
/>
|
||||
</OverlayTrigger>
|
||||
<OverlayTrigger
|
||||
{/* <OverlayTrigger
|
||||
placement="bottom"
|
||||
overlay={<Tooltip>Menu</Tooltip>}
|
||||
>
|
||||
@@ -438,7 +438,7 @@ export function UserGroupMaintenance() {
|
||||
color: "#747264",
|
||||
}}
|
||||
/>
|
||||
</OverlayTrigger>
|
||||
</OverlayTrigger> */}
|
||||
{/* Add Icon */}
|
||||
</>
|
||||
</Col>
|
||||
|
||||
@@ -579,7 +579,7 @@ function UserMaintenanceView() {
|
||||
.slice((currentPage - 1) * recordsPerPage, currentPage * recordsPerPage);
|
||||
|
||||
return (
|
||||
<div style={{marginTop:"8rem"}}>
|
||||
<div style={{marginTop:"7rem"}}>
|
||||
{loading ? (
|
||||
<Spinner/>
|
||||
):(
|
||||
@@ -634,7 +634,7 @@ function UserMaintenanceView() {
|
||||
<Col xs={12} md={4} lg={6} className="d-flex justify-content-end">
|
||||
<>
|
||||
{/* Add Icon */}
|
||||
<OverlayTrigger placement="bottom" overlay={<Tooltip>Add Items</Tooltip>}>
|
||||
{/* <OverlayTrigger placement="bottom" overlay={<Tooltip>Add Items</Tooltip>}>
|
||||
<FontAwesomeIcon
|
||||
icon={faPlus}
|
||||
onClick={() => handleAddItem(true)}
|
||||
@@ -649,7 +649,7 @@ function UserMaintenanceView() {
|
||||
title="Add Item"
|
||||
/>
|
||||
</OverlayTrigger>
|
||||
|
||||
*/}
|
||||
<OverlayTrigger placement="bottom" overlay={<Tooltip>Download template</Tooltip>}>
|
||||
<FontAwesomeIcon
|
||||
icon={faDownload}
|
||||
@@ -687,7 +687,7 @@ function UserMaintenanceView() {
|
||||
/>
|
||||
</OverlayTrigger>
|
||||
|
||||
<OverlayTrigger placement="bottom" overlay={<Tooltip>Menu Items</Tooltip>}>
|
||||
{/* <OverlayTrigger placement="bottom" overlay={<Tooltip>Menu Items</Tooltip>}>
|
||||
<FontAwesomeIcon
|
||||
icon={faBars}
|
||||
style={{
|
||||
@@ -697,7 +697,7 @@ function UserMaintenanceView() {
|
||||
}}
|
||||
/>
|
||||
</OverlayTrigger>
|
||||
|
||||
*/}
|
||||
</>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
@@ -7,6 +7,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faTrash, faGripLines, faPen } from '@fortawesome/free-solid-svg-icons';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import DashboardBuilderService from "../../../../APIServices/DashboardBuilderService";
|
||||
import TextField from '@mui/material/TextField';
|
||||
import FormControlLabel from '@mui/material/FormControlLabel';
|
||||
|
||||
// Import chart components
|
||||
import LineChartComponent from '../gadgets/line-chart/LineChart';
|
||||
@@ -248,6 +250,7 @@ const EditNewDash = () => {
|
||||
|
||||
// Edit widget
|
||||
const editWidget = (widget) => {
|
||||
console.log("Opening edit modal for:", widget);
|
||||
setCurrentEditWidget(widget);
|
||||
setEditModalOpen(true);
|
||||
};
|
||||
@@ -420,6 +423,7 @@ const EditNewDash = () => {
|
||||
>
|
||||
<ResponsiveGridLayout
|
||||
className="layout"
|
||||
draggableCancel=".MuiButton-root, .MuiIconButton-root, button, [role='button']"
|
||||
layouts={{
|
||||
lg: dashboardWidgets.map(widget => ({
|
||||
i: widget.i,
|
||||
@@ -458,17 +462,23 @@ const EditNewDash = () => {
|
||||
{widget.name}
|
||||
</Typography>
|
||||
<Box>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => editWidget(widget)}
|
||||
sx={{ minWidth: 'auto', padding: '4px' }}
|
||||
>
|
||||
<FontAwesomeIcon icon={faPen} />
|
||||
</Button>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
editWidget(widget);
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon icon={faPen} />
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
size="small"
|
||||
color="error"
|
||||
onClick={() => removeWidget(widget.i)}
|
||||
onClick={() => {
|
||||
console.log("Edit button clicked for widget:", widget);
|
||||
removeWidget(widget.i)}
|
||||
}
|
||||
sx={{ minWidth: 'auto', padding: '4px', ml: 1 }}
|
||||
>
|
||||
<FontAwesomeIcon icon={faTrash} />
|
||||
@@ -512,93 +522,69 @@ const EditNewDash = () => {
|
||||
|
||||
{/* Edit widget dialog */}
|
||||
<Dialog open={editModalOpen} onClose={() => setEditModalOpen(false)} maxWidth="sm" fullWidth>
|
||||
<DialogTitle>Edit {currentEditWidget.name}</DialogTitle>
|
||||
<DialogContent sx={{ paddingTop: 2 }}>
|
||||
<FormControl fullWidth sx={{ marginBottom: 2 }}>
|
||||
<Typography variant="subtitle2" sx={{ marginBottom: 1 }}>Chart Title</Typography>
|
||||
<Input
|
||||
value={currentEditWidget.chartTitle || ''}
|
||||
onChange={(e) => setCurrentEditWidget({
|
||||
...currentEditWidget,
|
||||
chartTitle: e.target.value
|
||||
})}
|
||||
placeholder="Enter chart title"
|
||||
fullWidth
|
||||
<DialogTitle>Edit {currentEditWidget?.name}</DialogTitle>
|
||||
<DialogContent dividers>
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
|
||||
<TextField
|
||||
label="Chart Title"
|
||||
fullWidth
|
||||
value={currentEditWidget?.chartTitle || ''}
|
||||
onChange={(e) =>
|
||||
setCurrentEditWidget((prev) => ({ ...prev, chartTitle: e.target.value }))
|
||||
}
|
||||
/>
|
||||
<TextField
|
||||
label="X Axis Label"
|
||||
fullWidth
|
||||
value={currentEditWidget?.xAxis || ''}
|
||||
onChange={(e) =>
|
||||
setCurrentEditWidget((prev) => ({ ...prev, xAxis: e.target.value }))
|
||||
}
|
||||
/>
|
||||
<TextField
|
||||
label="Y Axis Label"
|
||||
fullWidth
|
||||
value={currentEditWidget?.yAxis || ''}
|
||||
onChange={(e) =>
|
||||
setCurrentEditWidget((prev) => ({ ...prev, yAxis: e.target.value }))
|
||||
}
|
||||
/>
|
||||
<FormControl>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={currentEditWidget?.showLegend ?? true}
|
||||
onChange={(e) =>
|
||||
setCurrentEditWidget((prev) => ({ ...prev, showLegend: e.target.checked }))
|
||||
}
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
{currentEditWidget.name !== 'Grid View' && currentEditWidget.name !== 'Todo Chart' && (
|
||||
<>
|
||||
<Box sx={{ display: 'flex', gap: 2, marginBottom: 2 }}>
|
||||
<FormControl sx={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
|
||||
<Checkbox
|
||||
checked={currentEditWidget.showLegend || false}
|
||||
onChange={(e) => setCurrentEditWidget({
|
||||
...currentEditWidget,
|
||||
showLegend: e.target.checked
|
||||
})}
|
||||
/>
|
||||
<Typography>Show Legend</Typography>
|
||||
</FormControl>
|
||||
|
||||
<FormControl sx={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
|
||||
<Checkbox
|
||||
checked={currentEditWidget.showLabel || false}
|
||||
onChange={(e) => setCurrentEditWidget({
|
||||
...currentEditWidget,
|
||||
showLabel: e.target.checked
|
||||
})}
|
||||
/>
|
||||
<Typography>Show Labels</Typography>
|
||||
</FormControl>
|
||||
</Box>
|
||||
</>
|
||||
)}
|
||||
|
||||
<FormControl fullWidth sx={{ marginBottom: 2 }}>
|
||||
<Typography variant="subtitle2" sx={{ marginBottom: 1 }}>X-Axis</Typography>
|
||||
<Select
|
||||
value={currentEditWidget.xAxis || ''}
|
||||
onChange={(e) => setCurrentEditWidget({
|
||||
...currentEditWidget,
|
||||
xAxis: e.target.value
|
||||
})}
|
||||
displayEmpty
|
||||
>
|
||||
<MenuItem value="" disabled>Select X-Axis</MenuItem>
|
||||
{columnData.map((col, index) => (
|
||||
<MenuItem key={index} value={col}>{col}</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<FormControl fullWidth sx={{ marginBottom: 2 }}>
|
||||
<Typography variant="subtitle2" sx={{ marginBottom: 1 }}>Y-Axis</Typography>
|
||||
<Select
|
||||
value={currentEditWidget.yAxis || ''}
|
||||
onChange={(e) => setCurrentEditWidget({
|
||||
...currentEditWidget,
|
||||
yAxis: e.target.value
|
||||
})}
|
||||
displayEmpty
|
||||
>
|
||||
<MenuItem value="" disabled>Select Y-Axis</MenuItem>
|
||||
{columnData.map((col, index) => (
|
||||
<MenuItem key={index} value={col}>{col}</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</DialogContent>
|
||||
<DialogActions sx={{ padding: 2 }}>
|
||||
<Button onClick={() => setEditModalOpen(false)} color="inherit">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={saveWidgetChanges} variant="contained" color="primary">
|
||||
Save Changes
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
}
|
||||
label="Show Legend"
|
||||
/>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={currentEditWidget?.showLabel ?? true}
|
||||
onChange={(e) =>
|
||||
setCurrentEditWidget((prev) => ({ ...prev, showLabel: e.target.checked }))
|
||||
}
|
||||
/>
|
||||
}
|
||||
label="Show Labels"
|
||||
/>
|
||||
</FormControl>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setEditModalOpen(false)} color="secondary">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={saveWidgetChanges} variant="contained" color="primary">
|
||||
Save Changes
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
299
src/components/Dashboard/sequencegenerator.js
Normal file
299
src/components/Dashboard/sequencegenerator.js
Normal file
@@ -0,0 +1,299 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import {
|
||||
Table,
|
||||
Button,
|
||||
Modal,
|
||||
Form,
|
||||
Input,
|
||||
InputNumber,
|
||||
Dropdown,
|
||||
Alert,
|
||||
message,
|
||||
Card,
|
||||
Descriptions
|
||||
} from 'antd';
|
||||
import {
|
||||
EllipsisOutlined,
|
||||
PlusOutlined,
|
||||
EditOutlined,
|
||||
DeleteOutlined
|
||||
} from '@ant-design/icons';
|
||||
import SequenceGeneratorAPI from './sequencegeneratorapi';
|
||||
|
||||
const SequenceGenerator = () => {
|
||||
const [sequences, setSequences] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState(null);
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [editingId, setEditingId] = useState(null);
|
||||
const [currentSequence, setCurrentSequence] = useState(null);
|
||||
const [form] = Form.useForm();
|
||||
|
||||
useEffect(() => {
|
||||
fetchSequences();
|
||||
}, []);
|
||||
|
||||
const fetchSequences = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const data = await SequenceGeneratorAPI.getAll();
|
||||
setSequences(data);
|
||||
} catch (err) {
|
||||
setError(err.response?.data?.message || 'Failed to fetch sequences');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCreate = () => {
|
||||
form.resetFields();
|
||||
setCurrentSequence(null);
|
||||
setEditingId(null);
|
||||
setVisible(true);
|
||||
};
|
||||
|
||||
const handleEdit = (record) => {
|
||||
form.setFieldsValue(record);
|
||||
setCurrentSequence(record);
|
||||
setEditingId(record.id);
|
||||
setVisible(true);
|
||||
};
|
||||
|
||||
const handleDelete = async (id) => {
|
||||
Modal.confirm({
|
||||
title: 'Confirm Delete',
|
||||
content: 'Are you sure you want to delete this sequence?',
|
||||
okText: 'Delete',
|
||||
okType: 'danger',
|
||||
cancelText: 'Cancel',
|
||||
onOk: async () => {
|
||||
try {
|
||||
await SequenceGeneratorAPI.delete(id);
|
||||
message.success('Sequence deleted successfully');
|
||||
fetchSequences();
|
||||
} catch (err) {
|
||||
message.error(err.response?.data?.message || 'Failed to delete sequence');
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
try {
|
||||
const values = await form.validateFields();
|
||||
|
||||
if (editingId) {
|
||||
await SequenceGeneratorAPI.update(editingId, values);
|
||||
message.success('Sequence updated successfully');
|
||||
} else {
|
||||
await SequenceGeneratorAPI.create(values);
|
||||
message.success('Sequence created successfully');
|
||||
}
|
||||
|
||||
setVisible(false);
|
||||
fetchSequences();
|
||||
} catch (err) {
|
||||
message.error(err.response?.data?.message || 'Operation failed');
|
||||
}
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: 'Actions',
|
||||
key: 'actions',
|
||||
width: 100,
|
||||
render: (_, record) => (
|
||||
<Dropdown
|
||||
menu={{
|
||||
items: [
|
||||
{
|
||||
key: 'edit',
|
||||
label: 'Edit',
|
||||
icon: <EditOutlined />,
|
||||
onClick: () => handleEdit(record)
|
||||
},
|
||||
{
|
||||
key: 'delete',
|
||||
label: 'Delete',
|
||||
icon: <DeleteOutlined />,
|
||||
danger: true,
|
||||
onClick: () => handleDelete(record.id)
|
||||
}
|
||||
]
|
||||
}}
|
||||
trigger={['click']}
|
||||
>
|
||||
<Button type="text" icon={<EllipsisOutlined />} />
|
||||
</Dropdown>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'sequence_name',
|
||||
key: 'sequence_name',
|
||||
},
|
||||
{
|
||||
title: 'Sequence Code',
|
||||
dataIndex: 'sequence_code',
|
||||
key: 'sequence_code',
|
||||
},
|
||||
{
|
||||
title: 'Current No',
|
||||
dataIndex: 'current_no',
|
||||
key: 'current_no',
|
||||
},
|
||||
{
|
||||
title: 'Demonstration',
|
||||
dataIndex: 'demonstration',
|
||||
key: 'demonstration',
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="sequence-generator-container">
|
||||
{error && (
|
||||
<Alert
|
||||
message="Error"
|
||||
description={error}
|
||||
type="error"
|
||||
showIcon
|
||||
closable
|
||||
onClose={() => setError(null)}
|
||||
style={{ marginBottom: 16 }}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div style={{ marginBottom: 16, display: 'flex', justifyContent: 'space-between' }}>
|
||||
<h2>Document Sequence</h2>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<PlusOutlined />}
|
||||
onClick={handleCreate}
|
||||
>
|
||||
Add Sequence
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={sequences}
|
||||
rowKey="id"
|
||||
loading={loading}
|
||||
pagination={{
|
||||
pageSize: 10,
|
||||
showSizeChanger: true,
|
||||
showTotal: (total) => `Total ${total} sequences`,
|
||||
}}
|
||||
/>
|
||||
|
||||
<Modal
|
||||
title={<span style={{ fontWeight: 'bold' }}>Update Sequence Generator</span>}
|
||||
open={visible}
|
||||
onOk={handleSubmit}
|
||||
onCancel={() => setVisible(false)}
|
||||
confirmLoading={loading}
|
||||
width={700}
|
||||
>
|
||||
{currentSequence && (
|
||||
<div style={{
|
||||
marginLeft: 20,
|
||||
marginBottom: 24,
|
||||
border: '1px solid #d9d9d9',
|
||||
borderRadius: 4,
|
||||
padding: 16,
|
||||
backgroundColor: '#fafafa'
|
||||
}}>
|
||||
<table style={{ width: '100%', borderCollapse: 'collapse' }}>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style={{
|
||||
padding: '8px 16px',
|
||||
borderBottom: '1px solid #e8e8e8',
|
||||
fontWeight: 'bold',
|
||||
width: '30%'
|
||||
}}>Sequence ID</td>
|
||||
<td style={{
|
||||
padding: '8px 16px',
|
||||
borderBottom: '1px solid #e8e8e8'
|
||||
}}>{currentSequence.id}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={{
|
||||
padding: '8px 16px',
|
||||
fontWeight: 'bold'
|
||||
}}>Demonstration</td>
|
||||
<td style={{ padding: '8px 16px' }}>
|
||||
<div style={{
|
||||
backgroundColor: '#f5f5f5',
|
||||
padding: 8,
|
||||
textAlign: 'center',
|
||||
borderRadius: 4,
|
||||
fontWeight: 'bold'
|
||||
}}>
|
||||
{currentSequence.demonstration}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Form form={form} layout="vertical" style={{ marginLeft: 20, marginRight: 20 }}>
|
||||
<Form.Item
|
||||
name="sequence_name"
|
||||
label={<span style={{ fontWeight: 'bold' }}>Name*</span>}
|
||||
rules={[{ required: true, message: 'Please input the sequence name!' }]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="sequence_code"
|
||||
label={<span style={{ fontWeight: 'bold' }}>Sequence Code</span>}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="prefix"
|
||||
label={<span style={{ fontWeight: 'bold' }}>Prefix*</span>}
|
||||
rules={[{ required: true, message: 'Please input the prefix!' }]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="suffix"
|
||||
label={<span style={{ fontWeight: 'bold' }}>Suffix</span>}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="seperator"
|
||||
label={<span style={{ fontWeight: 'bold' }}>Separator</span>}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="starting_no"
|
||||
label={<span style={{ fontWeight: 'bold' }}>Starting No</span>}
|
||||
>
|
||||
<InputNumber min={1} style={{ width: '100%' }} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="current_no"
|
||||
label={<span style={{ fontWeight: 'bold' }}>Current No</span>}
|
||||
>
|
||||
<InputNumber min={1} style={{ width: '100%' }} />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SequenceGenerator;
|
||||
80
src/components/Dashboard/sequencegeneratorapi.js
Normal file
80
src/components/Dashboard/sequencegeneratorapi.js
Normal file
@@ -0,0 +1,80 @@
|
||||
import axios from 'axios';
|
||||
import { getToken } from '../../utils/tokenService.js';
|
||||
|
||||
const API_BASE_URL = process.env.REACT_APP_API_URL || '';
|
||||
|
||||
const api = axios.create({
|
||||
baseURL: API_BASE_URL,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
// Add request interceptor to attach token
|
||||
api.interceptors.request.use((config) => {
|
||||
// Always get fresh token for each request
|
||||
const token = getToken();
|
||||
console.log('[API] Current token:', token); // Log the token
|
||||
console.log('[API] Making request to:', config.url); // Log the request URL
|
||||
|
||||
if (token) {
|
||||
config.headers.Authorization = `Bearer ${token}`;
|
||||
} else {
|
||||
console.warn('No authToken found for request!');
|
||||
}
|
||||
|
||||
return config;
|
||||
}, (error) => {
|
||||
console.error('[API] Request error:', error);
|
||||
return Promise.reject(error);
|
||||
});
|
||||
|
||||
// ... rest of the interceptors and API methods remain the same ...
|
||||
|
||||
// Add response interceptor to log responses
|
||||
api.interceptors.response.use((response) => {
|
||||
console.log('[API] Response received:', {
|
||||
status: response.status,
|
||||
url: response.config.url,
|
||||
data: response.data
|
||||
});
|
||||
return response;
|
||||
}, (error) => {
|
||||
console.error('[API] Response error:', {
|
||||
status: error.response?.status,
|
||||
url: error.config?.url,
|
||||
message: error.message,
|
||||
response: error.response?.data
|
||||
});
|
||||
return Promise.reject(error);
|
||||
});
|
||||
|
||||
const SequenceGeneratorAPI = {
|
||||
getAll: async () => {
|
||||
try {
|
||||
console.log('[API] Fetching all sequences'); // Additional log
|
||||
const response = await api.get('/sureserve/sequence/seq');
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error('[API] Error fetching sequences:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
getById: async (id) => {
|
||||
try {
|
||||
console.log(`[API] Fetching sequence with ID: ${id}`);
|
||||
const response = await api.get(`/sureserve/sequence/seq/${id}`);
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error(`[API] Error fetching sequence ${id}:`, error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
create: async (data) => api.post('/sureserve/sequence/seq', data), // ✅ Make sure this exists
|
||||
update: async (id, data) => api.put(`/sureserve/sequence/seq/${id}`, data),
|
||||
delete: async (id) => api.delete(`/sureserve/sequence/seq/${id}`),
|
||||
};
|
||||
|
||||
export default SequenceGeneratorAPI;
|
||||
88
src/components/Dashboard/tokenregistryapi.js
Normal file
88
src/components/Dashboard/tokenregistryapi.js
Normal file
@@ -0,0 +1,88 @@
|
||||
// src/services/tokenRegistryAPI.js
|
||||
import axios from 'axios';
|
||||
import { getToken } from '../../utils/tokenService.js';
|
||||
|
||||
// Create axios instance with base configuration
|
||||
const apiClient = axios.create({
|
||||
baseURL: process.env.REACT_APP_API_URL || 'http://157.66.191.31:33730/back/',
|
||||
});
|
||||
|
||||
// Add request interceptor to inject token
|
||||
apiClient.interceptors.request.use((config) => {
|
||||
const token = getToken();
|
||||
if (token) {
|
||||
config.headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
return config;
|
||||
}, (error) => {
|
||||
return Promise.reject(error);
|
||||
});
|
||||
|
||||
// Response interceptor for error handling
|
||||
apiClient.interceptors.response.use(
|
||||
(response) => response.data,
|
||||
(error) => {
|
||||
if (error.response) {
|
||||
// Handle specific status codes
|
||||
if (error.response.status === 401) {
|
||||
// Handle unauthorized (token expired)
|
||||
console.error('Authentication failed');
|
||||
}
|
||||
throw new Error(error.response.data.message || 'Request failed');
|
||||
}
|
||||
throw new Error(error.message || 'Network error');
|
||||
}
|
||||
);
|
||||
|
||||
export const fetchAllTokens = async () => {
|
||||
try {
|
||||
return await apiClient.get('apiregistery/getall');
|
||||
} catch (error) {
|
||||
console.error('Fetch tokens error:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export const generateToken = async (token_name) => {
|
||||
try {
|
||||
return await apiClient.post(
|
||||
'apiregistery/generateToken',
|
||||
new URLSearchParams({ token_name }),
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Generate token error:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export const createToken = async (tokenData) => {
|
||||
try {
|
||||
return await apiClient.post('apiregistery/create', tokenData);
|
||||
} catch (error) {
|
||||
console.error('Create token error:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export const updateToken = async (id, tokenData) => {
|
||||
try {
|
||||
return await apiClient.put(`apiregistery/update/${id}`, tokenData);
|
||||
} catch (error) {
|
||||
console.error('Update token error:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export const deleteToken = async (id) => {
|
||||
try {
|
||||
return await apiClient.delete(`apiregistery/delete/${id}`);
|
||||
} catch (error) {
|
||||
console.error('Delete token error:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user