-
-
-
-
-
-
-
+
+
+
+
+ {location.pathname !== "/login" && (
+
+
-
- >
- )}
+ )}
+
+
>
);
};
diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx
index 9607a1a..06566bd 100644
--- a/src/pages/Login.tsx
+++ b/src/pages/Login.tsx
@@ -22,6 +22,12 @@ const LoginPage: React.FC = () => {
})
.then((response) => {
if (response.status === 200) {
+ axios.get("/api/users/me").then((res) => {
+ localStorage.setItem("username", res.data.username);
+ if (res.data.roles.includes("root")) {
+ localStorage.setItem("root", true);
+ }
+ });
navigate(from);
}
})
diff --git a/src/pages/Practical.tsx b/src/pages/Practical.tsx
index 03de6cb..bf859a1 100644
--- a/src/pages/Practical.tsx
+++ b/src/pages/Practical.tsx
@@ -1,12 +1,18 @@
-import { ArrowDownTrayIcon } from "@heroicons/react/24/outline";
+import { ArrowDownTrayIcon, ClipboardIcon } from "@heroicons/react/24/outline";
import axios from "axios";
import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
+import { toast } from "react-toastify";
function Practical() {
const { id } = useParams();
const [tp, setTp] = useState(null);
+ const copyText = (copy: string) => {
+ navigator.clipboard.writeText(copy);
+ toast("Copied!");
+ };
+
useEffect(() => {
console.log("akljsbcascb");
axios.get(`/api/tps/${id}`).then((res) => {
@@ -60,14 +66,30 @@ function Practical() {
Resources
-
- -
+
+ -
SSH:
- {tp.ssh}
+
copyText(tp.ssh)}
+ >
+
{tp.ssh}
+
+
+
+
- -
+
-
Password:
- {tp.pwd}
+
navigator.clipboard.writeText(tp.pwd)}
+ >
+
{tp.pwd}
+
+
+
+
diff --git a/src/pages/admin/BulkCreateUser.tsx b/src/pages/admin/BulkCreateUser.tsx
index f919401..0be3b64 100644
--- a/src/pages/admin/BulkCreateUser.tsx
+++ b/src/pages/admin/BulkCreateUser.tsx
@@ -1,101 +1,114 @@
import axios from "axios";
-import { useState } from "react";
+import { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
function BulkUsers() {
- const [file, setFile] = useState(null);
- const [userData, setUserData] = useState([]);
- const [practical, setPractical] = useState("0");
- const navigate = useNavigate();
+ const [file, setFile] = useState(null);
+ const [userData, setUserData] = useState([]);
+ const [practical, setPractical] = useState("0");
+ const navigate = useNavigate();
+ const [tps, setTps] = useState([]);
- const handlePracticalChange = (e) => {
- setPractical(e.target.value);
- }
+ const handlePracticalChange = (e) => {
+ setPractical(e.target.value);
+ };
- const handleFileChange = (event) => {
- const selectedFile = event.target.files[0];
- if (selectedFile && selectedFile.type === 'text/csv') {
- setFile(selectedFile);
- parseCSV(selectedFile);
- } else {
- alert('Please upload a valid CSV file.');
- }
+ useEffect(() => {
+ axios.get("/api/tps").then((res) => {
+ setTps(res.data);
+ });
+ }, []);
+
+ const handleFileChange = (event) => {
+ const selectedFile = event.target.files[0];
+ // if (selectedFile && selectedFile.type === "text/csv") {
+ setFile(selectedFile);
+ parseCSV(selectedFile);
+ // } else {
+ // alert("Please upload a valid CSV file.");
+ // }
+ };
+
+ const parseCSV = (file) => {
+ const reader = new FileReader();
+ reader.onload = (event) => {
+ const text = event.target.result;
+ const rows = text.split("\n").map((row) => row.split(","));
+ const formattedData = rows.map((row) => ({
+ name: row[0],
+ email: row[1],
+ // Add other fields as necessary
+ }));
+ setUserData(formattedData);
};
+ reader.readAsText(file);
+ };
- const parseCSV = (file) => {
- const reader = new FileReader();
- reader.onload = (event) => {
- const text = event.target.result;
- const rows = text.split('\n').map((row) => row.split(','));
- const formattedData = rows.map((row) => ({
- name: row[0],
- email: row[1],
- // Add other fields as necessary
- }));
- setUserData(formattedData);
- };
- reader.readAsText(file);
- };
+ const handleSubmit = () => {
+ // Handle submission logic (e.g., sending data to the backend)
+ console.log(practical);
+ axios
+ .post("/api/users/jdmi", {
+ users: userData.filter((user) => user.name !== ""),
+ tpId: practical,
+ })
+ .then(() => navigate(`/admin/users`));
+ };
- const handleSubmit = () => {
- // Handle submission logic (e.g., sending data to the backend)
- axios.post("/api/users/jdmi", userData.filter(user => user.name !== "")).then(res => navigate(`/tps/${res.data.id}`));
- };
-
- return (
-
-
Bulk User Creation
-
- {userData.length > 0 && (
-
-
-
-
- Name |
- Email |
- {/* Add other headers as necessary */}
-
-
-
- {userData.map((user, index) => (
-
- {user.name} |
- {user.email} |
-
- ))}
-
-
-
- )}
-
-
-
-
-
-
+ return (
+
+
Bulk User Creation
+
+ {userData.length > 0 && (
+
+
+
+
+ Name |
+ Email |
+ {/* Add other headers as necessary */}
+
+
+
+ {userData.map((user, index) => (
+
+ {user.name} |
+ {user.email} |
+
+ ))}
+
+
- );
+ )}
+
+
+
+
+
+
+
+ );
}
export default BulkUsers;
diff --git a/src/pages/admin/Users.tsx b/src/pages/admin/Users.tsx
new file mode 100644
index 0000000..06fe1ee
--- /dev/null
+++ b/src/pages/admin/Users.tsx
@@ -0,0 +1,63 @@
+import axios from "axios";
+import { useEffect, useState } from "react";
+
+function Users() {
+ const [users, setUsers] = useState([]);
+
+ useEffect(() => {
+ axios.get("/api/users").then((res) => {
+ setUsers(res.data);
+ console.log(res.data)
+ });
+ }, []);
+
+ const handleEditUser = (userId) => {
+ // Logic for editing the user (e.g., opening a modal)
+ alert(`Edit user with ID: ${userId}`);
+ };
+
+ return (
+
+
+
Manage Users
+
+ {/* Users Table */}
+
+
+
+
+ # |
+ Name |
+ Email |
+ Roles |
+ Instances |
+ Actions |
+
+
+
+ {users.map((user, index) => (
+
+ {index + 1} |
+ {user.name} |
+ {user.email} |
+ {user.roles} |
+ {user.instances.length} |
+
+
+ |
+
+ ))}
+
+
+
+
+
+ );
+}
+
+export default Users;