From fe360e55589854ae005d5ccb396cf81ca325e3c5 Mon Sep 17 00:00:00 2001 From: Tauke190 Date: Sun, 5 Nov 2023 12:28:38 -0500 Subject: [PATCH 1/3] Create API endpoint to view admin issue side --- back-end/app.js | 8 +++++++ .../adminIssueViewDetailsHandler.js | 24 +++++++++++++++++++ .../src/controllers/adminIssuesHandler.js | 24 +++++++++++++++++++ back-end/src/routes/adminIssues.js | 8 +++++++ back-end/src/routes/adminIssuesViewDetails.js | 8 +++++++ 5 files changed, 72 insertions(+) create mode 100644 back-end/src/controllers/adminIssueViewDetailsHandler.js create mode 100644 back-end/src/controllers/adminIssuesHandler.js create mode 100644 back-end/src/routes/adminIssues.js create mode 100644 back-end/src/routes/adminIssuesViewDetails.js diff --git a/back-end/app.js b/back-end/app.js index 3df9ee4..7ef37b7 100644 --- a/back-end/app.js +++ b/back-end/app.js @@ -6,6 +6,8 @@ import url from "url"; import path from "path"; import login from "./src/routes/login.js"; import studentIssues from "./src/routes/studentIssues.js"; +import adminIssues from "./src/routes/adminIssuesHandler.js"; +import adminIssuesViewDetails from "./src/routes/adminIssuesViewDetails.js"; // import multer from "multer"; - configure when required const app = express(); // instantiate an Express object @@ -45,5 +47,11 @@ app.use("/api/login", login); // Student Side Issue Retrieval app.use("/api/issues/student", studentIssues); +// Admin Side Issues Retrieval by department +app.use("/api/issues/admin", adminIssues); + +// Retrieve the specific Issue card from the admin Side +app.use("/api/issues/admin/dashboard", adminIssuesViewDetails); + // export the express app we created to make it available to other modules export default app; diff --git a/back-end/src/controllers/adminIssueViewDetailsHandler.js b/back-end/src/controllers/adminIssueViewDetailsHandler.js new file mode 100644 index 0000000..d1fc9bb --- /dev/null +++ b/back-end/src/controllers/adminIssueViewDetailsHandler.js @@ -0,0 +1,24 @@ +import axios from "axios"; + +// The function retrieves all the issues related to this departmen + +export async function adminIssuesHandler(req, res) { + const { paramName } = req.params; + try { + // Assuming the data you want is at the response.data property + const response = await axios.get( + `${process.env.BACKEND_URL}/json/contextual_mockapi.json` // will be replaced with db call + ); + + // Assuming response.data is an array of items and each item has a index + const filteredData = response.data.filter( + (item) => item.departments.includes(paramName) + ); + + res.json(filteredData); // Send only the data that matches the specific issue index + } catch (error) { + // Log the error and send an appropriate response + console.error("Error retrieving data:", error.message); + res.status(500).send("An error occurred while retrieving the data."); + } +} diff --git a/back-end/src/controllers/adminIssuesHandler.js b/back-end/src/controllers/adminIssuesHandler.js new file mode 100644 index 0000000..d1fc9bb --- /dev/null +++ b/back-end/src/controllers/adminIssuesHandler.js @@ -0,0 +1,24 @@ +import axios from "axios"; + +// The function retrieves all the issues related to this departmen + +export async function adminIssuesHandler(req, res) { + const { paramName } = req.params; + try { + // Assuming the data you want is at the response.data property + const response = await axios.get( + `${process.env.BACKEND_URL}/json/contextual_mockapi.json` // will be replaced with db call + ); + + // Assuming response.data is an array of items and each item has a index + const filteredData = response.data.filter( + (item) => item.departments.includes(paramName) + ); + + res.json(filteredData); // Send only the data that matches the specific issue index + } catch (error) { + // Log the error and send an appropriate response + console.error("Error retrieving data:", error.message); + res.status(500).send("An error occurred while retrieving the data."); + } +} diff --git a/back-end/src/routes/adminIssues.js b/back-end/src/routes/adminIssues.js new file mode 100644 index 0000000..358d2da --- /dev/null +++ b/back-end/src/routes/adminIssues.js @@ -0,0 +1,8 @@ +import express from "express"; +import { adminIssuesHandler } from "../controllers/adminIssuesHandler.js"; + +const router = express.Router(); + +router.get("/:paramName", adminIssuesHandler); + +export default router; diff --git a/back-end/src/routes/adminIssuesViewDetails.js b/back-end/src/routes/adminIssuesViewDetails.js new file mode 100644 index 0000000..45720fd --- /dev/null +++ b/back-end/src/routes/adminIssuesViewDetails.js @@ -0,0 +1,8 @@ +import express from "express"; +import { adminIssuesViewDetailsHandler } from "../controllers/adminIssuesViewDetailsHandler.js"; + +const router = express.Router(); + +router.get("/:paramName", adminIssuesViewDetailsHandler); + +export default router; From 468d91531b602e62cbb59f70b666f4d39e6ff46f Mon Sep 17 00:00:00 2001 From: Tauke190 Date: Sun, 5 Nov 2023 15:09:20 -0500 Subject: [PATCH 2/3] Implementing Admin Issue View Endpoint --- back-end/app.js | 6 +++--- back-end/src/controllers/adminIssueViewDetailsHandler.js | 4 ++-- back-end/src/controllers/adminIssuesHandler.js | 1 + back-end/src/routes/adminIssueViewDetails.js | 8 ++++++++ back-end/src/routes/adminIssuesViewDetails.js | 8 -------- 5 files changed, 14 insertions(+), 13 deletions(-) create mode 100644 back-end/src/routes/adminIssueViewDetails.js delete mode 100644 back-end/src/routes/adminIssuesViewDetails.js diff --git a/back-end/app.js b/back-end/app.js index 7ef37b7..d1d2d67 100644 --- a/back-end/app.js +++ b/back-end/app.js @@ -6,8 +6,8 @@ import url from "url"; import path from "path"; import login from "./src/routes/login.js"; import studentIssues from "./src/routes/studentIssues.js"; -import adminIssues from "./src/routes/adminIssuesHandler.js"; -import adminIssuesViewDetails from "./src/routes/adminIssuesViewDetails.js"; +import adminIssues from "./src/routes/adminIssues.js"; +import adminIssueViewDetails from "./src/routes/adminIssueViewDetails.js"; // import multer from "multer"; - configure when required const app = express(); // instantiate an Express object @@ -51,7 +51,7 @@ app.use("/api/issues/student", studentIssues); app.use("/api/issues/admin", adminIssues); // Retrieve the specific Issue card from the admin Side -app.use("/api/issues/admin/dashboard", adminIssuesViewDetails); +app.use("/api/issues/admin/:department", adminIssueViewDetails); // export the express app we created to make it available to other modules export default app; diff --git a/back-end/src/controllers/adminIssueViewDetailsHandler.js b/back-end/src/controllers/adminIssueViewDetailsHandler.js index d1fc9bb..d3566d1 100644 --- a/back-end/src/controllers/adminIssueViewDetailsHandler.js +++ b/back-end/src/controllers/adminIssueViewDetailsHandler.js @@ -2,7 +2,7 @@ import axios from "axios"; // The function retrieves all the issues related to this departmen -export async function adminIssuesHandler(req, res) { +export async function adminIssueViewDetailsHandler(req, res) { const { paramName } = req.params; try { // Assuming the data you want is at the response.data property @@ -12,7 +12,7 @@ export async function adminIssuesHandler(req, res) { // Assuming response.data is an array of items and each item has a index const filteredData = response.data.filter( - (item) => item.departments.includes(paramName) + (item) => String(item.index) === String(paramName) ); res.json(filteredData); // Send only the data that matches the specific issue index diff --git a/back-end/src/controllers/adminIssuesHandler.js b/back-end/src/controllers/adminIssuesHandler.js index d1fc9bb..836d3b2 100644 --- a/back-end/src/controllers/adminIssuesHandler.js +++ b/back-end/src/controllers/adminIssuesHandler.js @@ -4,6 +4,7 @@ import axios from "axios"; export async function adminIssuesHandler(req, res) { const { paramName } = req.params; + try { // Assuming the data you want is at the response.data property const response = await axios.get( diff --git a/back-end/src/routes/adminIssueViewDetails.js b/back-end/src/routes/adminIssueViewDetails.js new file mode 100644 index 0000000..c1d8d62 --- /dev/null +++ b/back-end/src/routes/adminIssueViewDetails.js @@ -0,0 +1,8 @@ +import express from "express"; +import { adminIssueViewDetailsHandler } from "../controllers/adminIssueViewDetailsHandler.js"; + +const router = express.Router(); + +router.get("/:paramName", adminIssueViewDetailsHandler); + +export default router; diff --git a/back-end/src/routes/adminIssuesViewDetails.js b/back-end/src/routes/adminIssuesViewDetails.js deleted file mode 100644 index 45720fd..0000000 --- a/back-end/src/routes/adminIssuesViewDetails.js +++ /dev/null @@ -1,8 +0,0 @@ -import express from "express"; -import { adminIssuesViewDetailsHandler } from "../controllers/adminIssuesViewDetailsHandler.js"; - -const router = express.Router(); - -router.get("/:paramName", adminIssuesViewDetailsHandler); - -export default router; From 1a8a362f8e87f623b1d828697e7fcf65c5659912 Mon Sep 17 00:00:00 2001 From: Tauke190 Date: Sun, 5 Nov 2023 17:56:37 -0500 Subject: [PATCH 3/3] Working on API endpoint for admin issue view side --- back-end/app.js | 6 +++ .../adminIssueViewDetailsHandler.js | 3 +- .../src/controllers/adminIssuesHandler.js | 23 ++++++++++++ back-end/src/routes/adminIssues.js | 8 ++++ .../AdminIssueDetails/AdminIssueDetails.css | 9 ++--- .../AdminIssueDetails/AdminIssueDetails.js | 28 ++++++++------ .../admin/AdminNavbar/AdminNavbar.js | 3 +- .../components/admin/IssueCard/IssueCard.js | 2 +- .../PriorityDropDown/PriorityDropdown.js | 9 ++--- .../ProgressionDropdown.js | 37 +++++++++---------- .../components/admin/TagSideBar/TagSidebar.js | 6 +-- .../components/admin/UpdateBox/UpdatesBox.js | 4 +- .../layouts/AdminDashboard/AdminDashboard.js | 1 + 13 files changed, 87 insertions(+), 52 deletions(-) diff --git a/back-end/app.js b/back-end/app.js index 3df9ee4..c4aba74 100644 --- a/back-end/app.js +++ b/back-end/app.js @@ -6,6 +6,8 @@ import url from "url"; import path from "path"; import login from "./src/routes/login.js"; import studentIssues from "./src/routes/studentIssues.js"; +import adminIssues from "./src/routes/adminIssues.js"; +import adminIssuesView from "./src/routes/adminIssueViewDetails.js"; // import multer from "multer"; - configure when required const app = express(); // instantiate an Express object @@ -45,5 +47,9 @@ app.use("/api/login", login); // Student Side Issue Retrieval app.use("/api/issues/student", studentIssues); +app.use("/api/issues/admin", adminIssues); + +app.use("/api/issues/admin/:dashboard", adminIssuesView); + // export the express app we created to make it available to other modules export default app; diff --git a/back-end/src/controllers/adminIssueViewDetailsHandler.js b/back-end/src/controllers/adminIssueViewDetailsHandler.js index d3566d1..c790a54 100644 --- a/back-end/src/controllers/adminIssueViewDetailsHandler.js +++ b/back-end/src/controllers/adminIssueViewDetailsHandler.js @@ -1,13 +1,12 @@ import axios from "axios"; // The function retrieves all the issues related to this departmen - export async function adminIssueViewDetailsHandler(req, res) { const { paramName } = req.params; try { // Assuming the data you want is at the response.data property const response = await axios.get( - `${process.env.BACKEND_URL}/json/contextual_mockapi.json` // will be replaced with db call + `${process.env.BACKEND_URL}/json/mockapi.json` // will be replaced with db call ); // Assuming response.data is an array of items and each item has a index diff --git a/back-end/src/controllers/adminIssuesHandler.js b/back-end/src/controllers/adminIssuesHandler.js index e69de29..d8bbd5f 100644 --- a/back-end/src/controllers/adminIssuesHandler.js +++ b/back-end/src/controllers/adminIssuesHandler.js @@ -0,0 +1,23 @@ +import axios from "axios"; + +export async function adminIssuesHandler(req, res) { + const { paramName } = req.params; + try { + // Assuming the data you want is at the response.data property + const response = await axios.get( + `${process.env.BACKEND_URL}/json/mockapi.json` // will be replaced with db call + ); + console.log(response); + + // Assuming response.data is an array of items and each item has a index + const filteredData = response.data.filter( + (item) => item.departments.includes(paramName) + ); + + res.json(filteredData); // Send only the data that matches the specific issue index + } catch (error) { + // Log the error and send an appropriate response + console.error("Error retrieving data:", error.message); + res.status(500).send("An error occurred while retrieving the data."); + } +} diff --git a/back-end/src/routes/adminIssues.js b/back-end/src/routes/adminIssues.js index e69de29..358d2da 100644 --- a/back-end/src/routes/adminIssues.js +++ b/back-end/src/routes/adminIssues.js @@ -0,0 +1,8 @@ +import express from "express"; +import { adminIssuesHandler } from "../controllers/adminIssuesHandler.js"; + +const router = express.Router(); + +router.get("/:paramName", adminIssuesHandler); + +export default router; diff --git a/front-end/src/components/admin/AdminIssueDetails/AdminIssueDetails.css b/front-end/src/components/admin/AdminIssueDetails/AdminIssueDetails.css index c01451d..18bd2f8 100644 --- a/front-end/src/components/admin/AdminIssueDetails/AdminIssueDetails.css +++ b/front-end/src/components/admin/AdminIssueDetails/AdminIssueDetails.css @@ -6,11 +6,8 @@ background-color: var(--background); color: var(--text); display: flex; - flex-direction: row; - justify-content: flex-start; margin: 0; padding-left: 30px; - position: relative; text-align: start; } @@ -29,7 +26,8 @@ .admin-issue .left-bar{ display: flex; flex-direction: column; - justify-content: space-evenly; + width: 100%; + height: 100%; } .admin-issue .right-bar{ @@ -37,7 +35,8 @@ flex-direction: column; margin-top: 20px; margin-left: 20px; - justify-content: space-between; + width: 100%; + height: 100%; } diff --git a/front-end/src/components/admin/AdminIssueDetails/AdminIssueDetails.js b/front-end/src/components/admin/AdminIssueDetails/AdminIssueDetails.js index de8b3be..430de02 100644 --- a/front-end/src/components/admin/AdminIssueDetails/AdminIssueDetails.js +++ b/front-end/src/components/admin/AdminIssueDetails/AdminIssueDetails.js @@ -1,3 +1,4 @@ +/* eslint-disable */ import UpdatesBox from '../UpdateBox/UpdatesBox.js'; import CommentBox from '../CommentBox/CommentBox.js'; import TagSidebar from '../TagSideBar/TagSidebar.js'; @@ -15,7 +16,7 @@ import axios from 'axios'; const AdminIssueDetails = () => { const { index } = useParams(); const [updateBoxes, setUpdateBoxes] = useState([]); - const [specificIssue, setSpecificIssue] = useState([]); + const [specificIssue, setSpecificIssue] = useState(); // const [commentBoxValue, setcommentBoxValue] = useState(''); const [loading, setLoading] = useState(false); const BASE_URL = process.env.REACT_APP_BACKEND_URL; @@ -50,9 +51,12 @@ const AdminIssueDetails = () => { async function fetchData() { try { - const response = await fetch('https://hasiburratul.github.io/mock-api/MOCK_DATA_ADMIN.json'); + const response = await fetch(`${BASE_URL}/api/issues/admin/IT/${index}`); + // const response = await fetch('https://hasiburratul.github.io/mock-api/MOCK_DATA_ADMIN.json'); const result = await response.json(); - setSpecificIssue(result); + setSpecificIssue(result[0]); + setUpdateBoxes(result[0].comments); + setLoading(true); } catch (error) { console.error(error); @@ -65,31 +69,31 @@ const AdminIssueDetails = () => {
{ loading -? ( + ? (
-

{specificIssue[index].title}

+

{specificIssue.title}

{/* Passses the issue fetched from the API */} - +

Issue History

- +
{ updateBoxes.map((item, index) => { - return ; + return ; }) } - +
- - - + + +
diff --git a/front-end/src/components/admin/AdminNavbar/AdminNavbar.js b/front-end/src/components/admin/AdminNavbar/AdminNavbar.js index 7636d25..86c28c2 100644 --- a/front-end/src/components/admin/AdminNavbar/AdminNavbar.js +++ b/front-end/src/components/admin/AdminNavbar/AdminNavbar.js @@ -3,7 +3,7 @@ import logoutImage from "../../../assets/images/logout-icon.png"; import "./AdminNavbar.css"; export default function AdminNavbar({ adminName, unresolvedIssues }) { - // const [showNotification, setShowNotification] = useState(false); + // const [showNotification, setShowNotification] = useState(false); const navigate = useNavigate(); const handleLogout = () => { @@ -16,7 +16,6 @@ export default function AdminNavbar({ adminName, unresolvedIssues }) {
Hello, {adminName} {unresolvedIssues} - Logout { }, []); const onClickIssueCard = async (event) => { - navigate('/admin/dashboard/' + (issue.index - 1)); + navigate('/admin/dashboard/' + (issue.index)); }; return (
diff --git a/front-end/src/components/admin/PriorityDropDown/PriorityDropdown.js b/front-end/src/components/admin/PriorityDropDown/PriorityDropdown.js index 362a9a0..8044297 100644 --- a/front-end/src/components/admin/PriorityDropDown/PriorityDropdown.js +++ b/front-end/src/components/admin/PriorityDropDown/PriorityDropdown.js @@ -1,4 +1,3 @@ -/* eslint-disable */ import { useState, useEffect } from 'react'; import axios from 'axios'; import Select from 'react-select'; @@ -13,7 +12,6 @@ const PriorityDropdown = ({ currentState }) => { { value: 'Reopened', label: 'Reopened', color: '#9d690235', textColor: '#9d6a02', isBold: 'true' } ]; const [selectedOption, setSelectedOption] = useState(options[0]); - const postPriorityUpdated = async (param) => { try { @@ -33,17 +31,18 @@ const PriorityDropdown = ({ currentState }) => { control: (base) => ({ ...base, backgroundColor: selectedOption.color, - color:'blue' + color: 'blue' }), option: (provided, state) => ({ ...provided, backgroundColor: state.data.color, color: state.data.textColor, fontWeight: state.data.isBold ? 'bold' : 'normal' - }), singleValue: provided => ({ + }), +singleValue: provided => ({ ...provided, color: selectedOption.textColor, - fontWeight : 'bold' + fontWeight: 'bold' }) }; const setDefaultValue = () => { diff --git a/front-end/src/components/admin/ProgressionDropdown/ProgressionDropdown.js b/front-end/src/components/admin/ProgressionDropdown/ProgressionDropdown.js index 977cbaa..ca9b8c8 100644 --- a/front-end/src/components/admin/ProgressionDropdown/ProgressionDropdown.js +++ b/front-end/src/components/admin/ProgressionDropdown/ProgressionDropdown.js @@ -1,21 +1,19 @@ -/* eslint-disable */ import { useState, useEffect } from 'react'; import './ProgressionDropdown.css'; import axios from 'axios'; import Select from 'react-select'; const ProgressionDropdown = ({ currentState }) => { - const options = [ - { value: 'Open', label: 'Not Started',color: '#b82c1c37',textColor: '#b82c1c',isBold: 'true'}, - { value: 'In Progress', label: 'In Progress',color: '#1f6deb37',textColor: '#1f6eeb',isBold: 'true'}, - { value: 'Action Required', label: 'Awaiting Response',color:'#9d690235',textColor: '#9d6a02',isBold: 'true'}, - { value: 'Resolved', label: 'Resolved',color: '#2386373a',textColor: '#238636',isBold: 'true'}, + { value: 'Open', label: 'Not Started', color: '#b82c1c37', textColor: '#b82c1c', isBold: 'true' }, + { value: 'In Progress', label: 'In Progress', color: '#1f6deb37', textColor: '#1f6eeb', isBold: 'true' }, + { value: 'Action Required', label: 'Awaiting Response', color: '#9d690235', textColor: '#9d6a02', isBold: 'true' }, + { value: 'Resolved', label: 'Resolved', color: '#2386373a', textColor: '#238636', isBold: 'true' } ]; const [selectedOption, setSelectedOption] = useState(options[0]); const BASE_URL = process.env.REACT_APP_BACKEND_URL; - + const dummyPostProgressionUpdated = async (param) => { try { await axios.post(`${BASE_URL}/dummyPostPriorityUpdated`, null); @@ -25,7 +23,7 @@ const ProgressionDropdown = ({ currentState }) => { }; const handleOptionChange = (newselectedOption) => { - setDefaultValue() + setDefaultValue(); setSelectedOption(newselectedOption); dummyPostProgressionUpdated(newselectedOption); }; @@ -34,41 +32,40 @@ const customStyles = { control: (base) => ({ ...base, backgroundColor: selectedOption.color, - color:'blue' + color: 'blue' }), option: (provided, state) => ({ ...provided, backgroundColor: state.data.color, color: state.data.textColor, fontWeight: state.data.isBold ? 'bold' : 'normal' - }), singleValue: provided => ({ + }), +singleValue: provided => ({ ...provided, color: selectedOption.textColor, - fontWeight : 'bold' + fontWeight: 'bold' }) }; const setDefaultValue = () => { - switch(currentState.currentStatus) - { + switch (currentState.currentStatus) { case "Open": - setSelectedOption(options[0]) + setSelectedOption(options[0]); break; case "In Progress": - setSelectedOption(options[1]) + setSelectedOption(options[1]); break; case "Action Required": - setSelectedOption(options[2]) + setSelectedOption(options[2]); break; case "Resolved": - setSelectedOption(options[3]) + setSelectedOption(options[3]); break; } -} - +}; useEffect(() => { - setDefaultValue() + setDefaultValue(); }, []); return ( diff --git a/front-end/src/components/admin/TagSideBar/TagSidebar.js b/front-end/src/components/admin/TagSideBar/TagSidebar.js index f0130b1..9272c09 100644 --- a/front-end/src/components/admin/TagSideBar/TagSidebar.js +++ b/front-end/src/components/admin/TagSideBar/TagSidebar.js @@ -56,11 +56,11 @@ function TagSidebar({ name, tags }) {
    - +
  • {inputVisible && } - - {departmentTags.map((tag, index) => ( +
  • + {departmentTags.filter(item => item != null).map((tag, index) => (
  • {tag} diff --git a/front-end/src/components/admin/UpdateBox/UpdatesBox.js b/front-end/src/components/admin/UpdateBox/UpdatesBox.js index 901ee3b..00a8087 100644 --- a/front-end/src/components/admin/UpdateBox/UpdatesBox.js +++ b/front-end/src/components/admin/UpdateBox/UpdatesBox.js @@ -1,8 +1,8 @@ import './UpdatesBox.css'; -function UpdatesBox({ index, description }) { +function UpdatesBox({ name, index, description }) { return (
    -

    Update 1{index}

    +

    {name} {index}

    {description}

    ); diff --git a/front-end/src/layouts/AdminDashboard/AdminDashboard.js b/front-end/src/layouts/AdminDashboard/AdminDashboard.js index 76e5152..27bdb7c 100644 --- a/front-end/src/layouts/AdminDashboard/AdminDashboard.js +++ b/front-end/src/layouts/AdminDashboard/AdminDashboard.js @@ -33,6 +33,7 @@ function AdminDashboard() { `${BASE_URL}/api/issues/admin/${currentDepartment}` ); setIssues(response.data); + console.log(response.data); } catch (error) { if (isMounted) { console.error('Error fetching data:', error);