From e369a90f9b7e5f718751a2812f5883d36f2b2dca Mon Sep 17 00:00:00 2001 From: Christian Dalton Date: Fri, 20 Nov 2020 20:54:05 -0600 Subject: [PATCH 01/17] stash --- client/src/api/api.js | 2 +- client/src/routes/admin/SelectTechnician.js | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/client/src/api/api.js b/client/src/api/api.js index cf8bd73..85c8536 100644 --- a/client/src/api/api.js +++ b/client/src/api/api.js @@ -1,5 +1,5 @@ import axios from "axios"; export default axios.create({ - baseURL: `http://localhost/`, + baseURL: `http://localhost:3000/api/`, }); diff --git a/client/src/routes/admin/SelectTechnician.js b/client/src/routes/admin/SelectTechnician.js index 42f0d54..910c4a9 100644 --- a/client/src/routes/admin/SelectTechnician.js +++ b/client/src/routes/admin/SelectTechnician.js @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import { EuiButton, @@ -24,13 +24,23 @@ import { fields, selectOptions, } from "../../components/form/ManageTechnicianForm/fields"; +import axios from "../../api/api.js"; var _ = require("lodash"); export const SelectTechnician = ({ setTechnician }, ...props) => { const [data, setData] = useState(fields); + const [options, setOptions] = useState(selectOptions); const [isFlyoutVisible, setIsFlyoutVisible] = useState(false); + useEffect(async () => { + const response = await axios.get("/tech"); + console.log(response.data); + + // const newOptions = options; + // newOptions[options] = _.forEach(response.data); + }); + const handleFormSubmit = (e, data) => { const errors = _.find(data, ["error", true]); if (errors === undefined) { From 63c3ba8d43a161ba05a7fed5229ef67f5628b405 Mon Sep 17 00:00:00 2001 From: Christian Dalton Date: Fri, 20 Nov 2020 22:07:23 -0600 Subject: [PATCH 02/17] reducers setup --- client/src/api/reducers.js | 25 +++++++++ client/src/components/callout/Callout.js | 15 +++++ .../form/ManageTicketForm/adminView.js | 2 +- .../{assignedTo.js => AssignedToTable.js} | 0 .../table/{openTickets.js => TicketsTable.js} | 56 ++++++++++++------- client/src/routes/admin/ManageTicket.js | 39 +++++-------- client/src/routes/admin/SelectTechnician.js | 28 +++++++--- client/src/routes/admin/Stats.js | 48 ++++++++++++++++ client/src/routes/admin/admin.js | 2 +- 9 files changed, 161 insertions(+), 54 deletions(-) create mode 100644 client/src/api/reducers.js create mode 100644 client/src/components/callout/Callout.js rename client/src/components/table/{assignedTo.js => AssignedToTable.js} (100%) rename client/src/components/table/{openTickets.js => TicketsTable.js} (66%) create mode 100644 client/src/routes/admin/Stats.js diff --git a/client/src/api/reducers.js b/client/src/api/reducers.js new file mode 100644 index 0000000..e652ac7 --- /dev/null +++ b/client/src/api/reducers.js @@ -0,0 +1,25 @@ +export const dataFetchReducer = (state, action) => { + switch (action.type) { + case "FETCH_INIT": + return { ...state, isLoading: true, isError: false }; + case "FETCH_SUCCESS": + return { + ...state, + isLoading: false, + isError: false, + data: action.payload, + }; + case "FETCH_FAILURE": + return { + ...state, + isLoading: false, + isError: true, + }; + case "UPDATE_DATA": + return { + ...state, + }; + default: + throw new Error(); + } +}; diff --git a/client/src/components/callout/Callout.js b/client/src/components/callout/Callout.js new file mode 100644 index 0000000..d1dd503 --- /dev/null +++ b/client/src/components/callout/Callout.js @@ -0,0 +1,15 @@ +import React from "react"; + +import { EuiCallOut, EuiLink } from "@elastic/eui"; + +export const ErrorCallout = ({ errMsg }, ...props) => { + return ( + +

{errMsg}

+
+ ); +}; diff --git a/client/src/components/form/ManageTicketForm/adminView.js b/client/src/components/form/ManageTicketForm/adminView.js index 7719a87..0ab79b9 100644 --- a/client/src/components/form/ManageTicketForm/adminView.js +++ b/client/src/components/form/ManageTicketForm/adminView.js @@ -23,7 +23,7 @@ import { } from "./handlers"; import { selectOptions } from "../selectOptions"; import { MyDatePicker } from "../MyDatePicker"; -import { TicketAssignmentTable } from "../../table/assignedTo"; +import { TicketAssignmentTable } from "../../table/AssignedToTable"; import { AddTechnicianPopover } from "../../popover/TechnicianPopover"; import { TimeLogTable } from "../../table/TimeLogTable"; diff --git a/client/src/components/table/assignedTo.js b/client/src/components/table/AssignedToTable.js similarity index 100% rename from client/src/components/table/assignedTo.js rename to client/src/components/table/AssignedToTable.js diff --git a/client/src/components/table/openTickets.js b/client/src/components/table/TicketsTable.js similarity index 66% rename from client/src/components/table/openTickets.js rename to client/src/components/table/TicketsTable.js index 5710389..70ca91d 100644 --- a/client/src/components/table/openTickets.js +++ b/client/src/components/table/TicketsTable.js @@ -1,7 +1,9 @@ -import React from "react"; - +import React, { useEffect, useState, useReducer } from "react"; +import axios from "../../api/api"; import { EuiBasicTable, EuiLink, EuiHealth, EuiButton } from "@elastic/eui"; import { AdminTicketFlyout } from "../flyout/flyout"; +import { dataFetchReducer } from "../../api/reducers"; +import { ErrorCallout } from "../callout/Callout"; const userTest = [ { @@ -14,21 +16,29 @@ const userTest = [ online: true, }, ]; -/* -Example user object: - +export const TicketsTable = ({ handleTicketSelection }, ...props) => { + const [state, dispatch] = useReducer(dataFetchReducer, { + isLoading: false, + isError: false, + data: null, + }); -Example country object: + useEffect(() => { + const fetchData = async () => { + dispatch({ type: "FETCH_INIT" }); + // TODO: ONCE BACKEND IS SET UP, FORMAT AND IMPLEMENT DATA FOR TABLE + try { + const result = await axios.get("ticket"); + dispatch({ type: "FETCH_SUCCESS", payload: result.data }); + } catch (error) { + dispatch({ type: "FETCH_FAILURE" }); + } + }; -{ - code: 'NL', - name: 'Netherlands', - flag: '🇳🇱' -} -*/ + fetchData(); + }, []); -export const TicketsTable = ({ handleTicketSelection }, ...props) => { const columns = [ { field: "firstName", @@ -103,12 +113,18 @@ export const TicketsTable = ({ handleTicketSelection }, ...props) => { }; return ( - +
+ {state.isError === true ? ( + + ) : ( + + )} +
); }; diff --git a/client/src/routes/admin/ManageTicket.js b/client/src/routes/admin/ManageTicket.js index d8b282c..ce796af 100644 --- a/client/src/routes/admin/ManageTicket.js +++ b/client/src/routes/admin/ManageTicket.js @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from "react"; +import React, { useState, useEffect, useReducer } from "react"; import { EuiPage, @@ -21,7 +21,7 @@ import { EuiCode, } from "@elastic/eui"; import { NavBar } from "../../components/navbar/navbar"; -import { TicketsTable } from "../../components/table/openTickets"; +import { TicketsTable } from "../../components/table/TicketsTable"; import { AdminTicketFlyout } from "../../components/flyout/flyout"; import { UserView } from "../../components/form/ManageTicketForm/userView"; import { handleFormSubmit } from "../../components/form/ManageTicketForm/handlers"; @@ -29,6 +29,9 @@ import { AdminView } from "../../components/form/ManageTicketForm/adminView"; import { Debug } from "../../components/debug/debug"; import axios from "../../api/api"; import { fields } from "../../components/form/ManageTicketForm/fields"; +import { dataFetchReducer } from "../../api/reducers"; +import { MyStat } from "./Stats"; + var _ = require("lodash"); const TicketForm = ({ data, setData }, ...props) => { @@ -58,6 +61,11 @@ const TicketForm = ({ data, setData }, ...props) => { }; export const ManageTicket = (props) => { + const [state, dispatch] = useReducer(dataFetchReducer, { + isLoading: false, + isError: false, + data: null, + }); const [isLoadingStat, setStatLoading] = useState(false); const [selectedTicket, setSelectedTicket] = useState(false); @@ -76,30 +84,12 @@ export const ManageTicket = (props) => {
- - - - - + {/*TODO : UPDATE ENDPOINT*/} + - - - - - + {/*TODO: UPDATE ENDPOINT*/} +
@@ -108,7 +98,6 @@ export const ManageTicket = (props) => {

All Tickets

- Temp Table until DB is setup diff --git a/client/src/routes/admin/SelectTechnician.js b/client/src/routes/admin/SelectTechnician.js index 910c4a9..992bc97 100644 --- a/client/src/routes/admin/SelectTechnician.js +++ b/client/src/routes/admin/SelectTechnician.js @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from "react"; +import React, { useState, useEffect, useReducer } from "react"; import { EuiButton, @@ -25,6 +25,7 @@ import { selectOptions, } from "../../components/form/ManageTechnicianForm/fields"; import axios from "../../api/api.js"; +import { dataFetchReducer } from "../../api/reducers"; var _ = require("lodash"); @@ -33,14 +34,27 @@ export const SelectTechnician = ({ setTechnician }, ...props) => { const [options, setOptions] = useState(selectOptions); const [isFlyoutVisible, setIsFlyoutVisible] = useState(false); - useEffect(async () => { - const response = await axios.get("/tech"); - console.log(response.data); - - // const newOptions = options; - // newOptions[options] = _.forEach(response.data); + const [state, dispatch] = useReducer(dataFetchReducer, { + isLoading: false, + isError: false, + data: null, }); + useEffect(() => { + const fetchData = async () => { + dispatch({ type: "FETCH_INIT" }); + // TODO: ONCE BACKEND IS SET UP, FORMAT AND IMPLEMENT DATA + try { + const result = await axios.get("ticket"); + dispatch({ type: "FETCH_SUCCESS", payload: result.data }); + } catch (error) { + dispatch({ type: "FETCH_FAILURE" }); + } + }; + + fetchData(); + }, []); + const handleFormSubmit = (e, data) => { const errors = _.find(data, ["error", true]); if (errors === undefined) { diff --git a/client/src/routes/admin/Stats.js b/client/src/routes/admin/Stats.js new file mode 100644 index 0000000..d2fffa6 --- /dev/null +++ b/client/src/routes/admin/Stats.js @@ -0,0 +1,48 @@ +import { EuiIcon, EuiPanel, EuiStat } from "@elastic/eui"; +import React, { useEffect, useReducer } from "react"; +import { dataFetchReducer } from "../../api/reducers"; +import axios from "../../api/api"; +import { ErrorCallout } from "../../components/callout/Callout"; + +export const MyStat = ({ endpoint, color, icon }, ...props) => { + const [state, dispatch] = useReducer(dataFetchReducer, { + isLoading: false, + isError: false, + data: null, + }); + + useEffect(() => { + const fetchData = async () => { + dispatch({ type: "FETCH_INIT" }); + // TODO: ONCE BACKEND IS SET UP, SEND TO COMPONENT + try { + const result = await axios.get(endpoint); + dispatch({ type: "FETCH_SUCCESS", payload: result.data }); + } catch (error) { + dispatch({ type: "FETCH_FAILURE" }); + } + }; + + fetchData(); + }, []); + + return ( + <> + {state.isError === true ? ( + + ) : ( + + + + + + )} + + ); +}; diff --git a/client/src/routes/admin/admin.js b/client/src/routes/admin/admin.js index 8976cea..99f6a1f 100644 --- a/client/src/routes/admin/admin.js +++ b/client/src/routes/admin/admin.js @@ -21,7 +21,7 @@ import { EuiCode, } from "@elastic/eui"; import { NavBar } from "../../components/navbar/navbar"; -import { TicketsTable } from "../../components/table/openTickets"; +import { TicketsTable } from "../../components/table/TicketsTable"; import { AdminTicketFlyout } from "../../components/flyout/flyout"; import { UserView } from "../../components/form/ManageTicketForm/userView"; import { fields } from "../../components/form/ManageTicketForm/fields"; From 580238b6c47d5959cb3a95b1be0365a731a2512d Mon Sep 17 00:00:00 2001 From: Christian Dalton Date: Fri, 20 Nov 2020 22:41:20 -0600 Subject: [PATCH 03/17] effects setup, partially broken until backend works --- client/src/api/reducers.js | 1 + .../ManageTechnicianForm/NewTechnicianForm.js | 26 ++++----- .../form/ManageTicketForm/adminView.js | 24 ++++----- .../form/ManageTicketForm/fields.js | 4 ++ .../form/ManageTicketForm/handlers.js | 14 +++-- .../form/ManageTicketForm/userView.js | 54 +++++++++---------- .../components/popover/TechnicianPopover.js | 33 ++++++++++-- client/src/routes/admin/ManageTicket.js | 26 ++++++--- .../src/routes/admin/NewTechnicianFlyout.js | 31 +++++++++-- client/src/routes/admin/SelectTechnician.js | 18 ++++--- 10 files changed, 145 insertions(+), 86 deletions(-) diff --git a/client/src/api/reducers.js b/client/src/api/reducers.js index e652ac7..8dad3bb 100644 --- a/client/src/api/reducers.js +++ b/client/src/api/reducers.js @@ -18,6 +18,7 @@ export const dataFetchReducer = (state, action) => { case "UPDATE_DATA": return { ...state, + data: action.payload, }; default: throw new Error(); diff --git a/client/src/components/form/ManageTechnicianForm/NewTechnicianForm.js b/client/src/components/form/ManageTechnicianForm/NewTechnicianForm.js index 69309e9..5e44498 100644 --- a/client/src/components/form/ManageTechnicianForm/NewTechnicianForm.js +++ b/client/src/components/form/ManageTechnicianForm/NewTechnicianForm.js @@ -18,55 +18,55 @@ import { var _ = require("lodash"); -export const NewTechnicianForm = ({ data, setData }, ...props) => { +export const NewTechnicianForm = ({ data, dispatch }, ...props) => { return ( <> handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> diff --git a/client/src/components/form/ManageTicketForm/adminView.js b/client/src/components/form/ManageTicketForm/adminView.js index 0ab79b9..20179a7 100644 --- a/client/src/components/form/ManageTicketForm/adminView.js +++ b/client/src/components/form/ManageTicketForm/adminView.js @@ -29,7 +29,7 @@ import { TimeLogTable } from "../../table/TimeLogTable"; var _ = require("lodash"); -export const AdminView = ({ data, setData }, ...props) => { +export const AdminView = ({ data, dispatch }, ...props) => { return ( <> @@ -42,8 +42,8 @@ export const AdminView = ({ data, setData }, ...props) => { data={data} name={"core_issue"} selectOptions={selectOptions} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} - handleChange={(e) => handleFormFieldChange(e, data, setData)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} /> @@ -51,8 +51,8 @@ export const AdminView = ({ data, setData }, ...props) => { data={data} name={"component"} selectOptions={selectOptions} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} - handleChange={(e) => handleFormFieldChange(e, data, setData)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} /> @@ -76,8 +76,8 @@ export const AdminView = ({ data, setData }, ...props) => { handleFormFieldChange(e, data, setData)} - onBlur={(e) => handleFormFieldBlur(e, data, setData)} + onChange={(e) => handleFormFieldChange(e, data, dispatch)} + onBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> @@ -117,7 +117,7 @@ export const AdminView = ({ data, setData }, ...props) => { data={data} name={"start_datetime"} handleChange={(date) => - handleDateChange(date, "start_datetime", data, setData) + handleDateChange(date, "start_datetime", data, dispatch) } /> @@ -127,9 +127,9 @@ export const AdminView = ({ data, setData }, ...props) => { handleFormFieldBlur(e, data, setData)} + // handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} handleChange={(e) => - handleDateChange(e, "end_datetime", data, setData) + handleDateChange(e, "end_datetime", data, dispatch) } /> @@ -144,8 +144,8 @@ export const AdminView = ({ data, setData }, ...props) => { handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} selectOptions={selectOptions} data={data} name={"status"} diff --git a/client/src/components/form/ManageTicketForm/fields.js b/client/src/components/form/ManageTicketForm/fields.js index 641ad83..2da1d74 100644 --- a/client/src/components/form/ManageTicketForm/fields.js +++ b/client/src/components/form/ManageTicketForm/fields.js @@ -1,6 +1,10 @@ import { personFields } from "../person/fields"; import { selectOptions } from "../selectOptions"; +export const required_field_props = { + error: false, + error_type: "none", +}; export const fields = [ ...personFields, { diff --git a/client/src/components/form/ManageTicketForm/handlers.js b/client/src/components/form/ManageTicketForm/handlers.js index 58e6641..9a3aaf1 100644 --- a/client/src/components/form/ManageTicketForm/handlers.js +++ b/client/src/components/form/ManageTicketForm/handlers.js @@ -17,7 +17,7 @@ export const handleFormSubmit = (e, data) => { } }; -export const handleFormFieldChange = (e, data, setData) => { +export const handleFormFieldChange = (e, data, dispatch) => { const target = e.target; const value = target.value; const name = target.name; @@ -26,20 +26,18 @@ export const handleFormFieldChange = (e, data, setData) => { const index = newData.findIndex((o) => o.name === name); newData[index].value = value; - - setData([...newData]); + dispatch({ type: "UPDATE_DATA", payload: newData }); }; -export const handleDateChange = (date, name, data, setData) => { +export const handleDateChange = (date, name, data, dispatch) => { const newData = data; const index = newData.findIndex((o) => o.name === name); newData[index].value = date.toJSON(); - - setData([...newData]); + dispatch({ type: "UPDATE_DATA", payload: newData }); }; -export const handleFormFieldBlur = (e, data, setData) => { +export const handleFormFieldBlur = (e, data, dispatch) => { const name = e.target.name; const value = e.target.value; @@ -53,5 +51,5 @@ export const handleFormFieldBlur = (e, data, setData) => { newData[index].error = false; } - setData([...newData]); + dispatch({ type: "UPDATE_DATA", payload: newData }); }; diff --git a/client/src/components/form/ManageTicketForm/userView.js b/client/src/components/form/ManageTicketForm/userView.js index 2cff176..1365eb2 100644 --- a/client/src/components/form/ManageTicketForm/userView.js +++ b/client/src/components/form/ManageTicketForm/userView.js @@ -20,7 +20,7 @@ import { selectOptions } from "../selectOptions"; var _ = require("lodash"); -export const UserView = ({ data, setData }, ...props) => { +export const UserView = ({ data, dispatch }, ...props) => { return ( <> @@ -28,32 +28,32 @@ export const UserView = ({ data, setData }, ...props) => { handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> @@ -62,16 +62,16 @@ export const UserView = ({ data, setData }, ...props) => { handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> @@ -85,8 +85,8 @@ export const UserView = ({ data, setData }, ...props) => { name={"priority"} data={data} selectOptions={selectOptions} - handleChange={(e) => handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> @@ -95,32 +95,32 @@ export const UserView = ({ data, setData }, ...props) => { handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> @@ -133,9 +133,9 @@ export const UserView = ({ data, setData }, ...props) => { handleFormFieldChange(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} selectOptions={selectOptions} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> @@ -154,8 +154,8 @@ export const UserView = ({ data, setData }, ...props) => { handleFormFieldChange(e, data, setData)} - onBlur={(e) => handleFormFieldBlur(e, data, setData)} + onChange={(e) => handleFormFieldChange(e, data, dispatch)} + onBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> diff --git a/client/src/components/popover/TechnicianPopover.js b/client/src/components/popover/TechnicianPopover.js index 5a34d9e..0994ce3 100644 --- a/client/src/components/popover/TechnicianPopover.js +++ b/client/src/components/popover/TechnicianPopover.js @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useEffect, useReducer, useState } from "react"; import { EuiButton, @@ -14,9 +14,30 @@ import { handleFormFieldBlur, handleFormFieldChange, } from "../form/ManageTicketForm/handlers"; +import { dataFetchReducer } from "../../api/reducers"; +import axios from "../../api/api"; export const AddTechnicianPopover = () => { - const [data, setData] = useState(fields); + const [state, dispatch] = useReducer(dataFetchReducer, { + isLoading: false, + isError: false, + data: null, + }); + + useEffect(() => { + const fetchData = async () => { + dispatch({ type: "FETCH_INIT" }); + // TODO: ONCE BACKEND IS SET UP, FORMAT AND IMPLEMENT DATA FOR TABLE + try { + const result = await axios.get("ticket"); + dispatch({ type: "FETCH_SUCCESS", payload: result.data }); + } catch (error) { + dispatch({ type: "FETCH_FAILURE" }); + } + }; + fetchData(); + }, []); + const [isPopoverOpen, setIsPopoverOpen] = useState(false); const onButtonClick = () => @@ -40,10 +61,12 @@ export const AddTechnicianPopover = () => { handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => + handleFormFieldChange(e, state.data, dispatch) + } + handleBlur={(e) => handleFormFieldBlur(e, state.data, dispatch)} /> diff --git a/client/src/routes/admin/ManageTicket.js b/client/src/routes/admin/ManageTicket.js index ce796af..c250fc5 100644 --- a/client/src/routes/admin/ManageTicket.js +++ b/client/src/routes/admin/ManageTicket.js @@ -64,17 +64,27 @@ export const ManageTicket = (props) => { const [state, dispatch] = useReducer(dataFetchReducer, { isLoading: false, isError: false, - data: null, + data: fields, }); - const [isLoadingStat, setStatLoading] = useState(false); + const [selectedTicket, setSelectedTicket] = useState(false); - const [data, setData] = useState(fields); + useEffect(() => { + const fetchData = async () => { + dispatch({ type: "FETCH_INIT" }); + // TODO: ONCE BACKEND IS SET UP, FORMAT AND IMPLEMENT DATA FOR TABLE + try { + const result = await axios.get("ticket"); + // TODO: CHANGE BACK! change payloud back to result.data once backend is setup + dispatch({ type: "FETCH_SUCCESS", payload: fields }); + } catch (error) { + dispatch({ type: "FETCH_FAILURE" }); + } + }; + + fetchData(); + }, []); - // TODO: get request for open and closed tickets. /api/ticket - // useEffect(async () => { - // const result = await axios.get(); - // }); const handleTicketSelection = (e, id) => { setSelectedTicket(id); }; @@ -109,7 +119,7 @@ export const ManageTicket = (props) => { - + ); diff --git a/client/src/routes/admin/NewTechnicianFlyout.js b/client/src/routes/admin/NewTechnicianFlyout.js index e8b5199..02e7bf5 100644 --- a/client/src/routes/admin/NewTechnicianFlyout.js +++ b/client/src/routes/admin/NewTechnicianFlyout.js @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useEffect, useReducer, useState } from "react"; import { EuiFlyout, @@ -16,13 +16,34 @@ import { NewTechnicianForm } from "../../components/form/ManageTechnicianForm/Ne import { personFields } from "../../components/form/person/fields"; import { handleFormSubmit } from "../../components/form/ManageTicketForm/handlers"; import { Debug } from "../../components/debug/debug"; +import { dataFetchReducer } from "../../api/reducers"; +import axios from "../../api/api"; export const NewTechnicianFlyout = ( { isFlyoutVisible, setIsFlyoutVisible }, ...props ) => { const closeFlyout = () => setIsFlyoutVisible(false); - const [data, setData] = useState(personFields); + const [state, dispatch] = useReducer(dataFetchReducer, { + isLoading: false, + isError: false, + data: null, + }); + + useEffect(() => { + const fetchData = async () => { + dispatch({ type: "FETCH_INIT" }); + // TODO: ONCE BACKEND IS SET UP, FORMAT AND IMPLEMENT DATA FOR TABLE + try { + const result = await axios.get("ticket"); + dispatch({ type: "FETCH_SUCCESS", payload: result.data }); + } catch (error) { + dispatch({ type: "FETCH_FAILURE" }); + } + }; + + fetchData(); + }, []); const showFlyout = () => setIsFlyoutVisible(true); @@ -41,17 +62,17 @@ export const NewTechnicianFlyout = ( - + handleFormSubmit(e, data)} + onClick={(e) => handleFormSubmit(e, state.data)} > Save - + diff --git a/client/src/routes/admin/SelectTechnician.js b/client/src/routes/admin/SelectTechnician.js index 992bc97..0115002 100644 --- a/client/src/routes/admin/SelectTechnician.js +++ b/client/src/routes/admin/SelectTechnician.js @@ -30,14 +30,13 @@ import { dataFetchReducer } from "../../api/reducers"; var _ = require("lodash"); export const SelectTechnician = ({ setTechnician }, ...props) => { - const [data, setData] = useState(fields); const [options, setOptions] = useState(selectOptions); const [isFlyoutVisible, setIsFlyoutVisible] = useState(false); const [state, dispatch] = useReducer(dataFetchReducer, { isLoading: false, isError: false, - data: null, + data: fields, }); useEffect(() => { @@ -46,7 +45,8 @@ export const SelectTechnician = ({ setTechnician }, ...props) => { // TODO: ONCE BACKEND IS SET UP, FORMAT AND IMPLEMENT DATA try { const result = await axios.get("ticket"); - dispatch({ type: "FETCH_SUCCESS", payload: result.data }); + // TODO: REMOVE! change back to result.data + dispatch({ type: "FETCH_SUCCESS", payload: fields }); } catch (error) { dispatch({ type: "FETCH_FAILURE" }); } @@ -77,10 +77,12 @@ export const SelectTechnician = ({ setTechnician }, ...props) => { handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => + handleFormFieldChange(e, state.data, dispatch) + } + handleBlur={(e) => handleFormFieldBlur(e, state.data, dispatch)} /> @@ -95,13 +97,13 @@ export const SelectTechnician = ({ setTechnician }, ...props) => { handleFormSubmit(e, data)} + onClick={(e) => handleFormSubmit(e, state.data)} > Select - + From 6a2fda0c9163a33c29f2c8420abb9dca5621855a Mon Sep 17 00:00:00 2001 From: Christian Dalton Date: Tue, 24 Nov 2020 20:04:25 -0600 Subject: [PATCH 04/17] submission date field --- .../form/ManageTicketForm/fields.js | 4 +- client/src/components/form/person/fields.js | 22 ++- schema.sql | 139 +++++++++++------- 3 files changed, 101 insertions(+), 64 deletions(-) diff --git a/client/src/components/form/ManageTicketForm/fields.js b/client/src/components/form/ManageTicketForm/fields.js index 2da1d74..4bf850b 100644 --- a/client/src/components/form/ManageTicketForm/fields.js +++ b/client/src/components/form/ManageTicketForm/fields.js @@ -81,8 +81,8 @@ export const fields = [ error_type: "none", }, { - name: "start_datetime", - label: "Start Datetime", + name: "submission_date", + label: "Submission Date", value: "", error: false, error_type: "none", diff --git a/client/src/components/form/person/fields.js b/client/src/components/form/person/fields.js index b35683b..b735de7 100644 --- a/client/src/components/form/person/fields.js +++ b/client/src/components/form/person/fields.js @@ -22,14 +22,6 @@ export const personFields = [ error: false, error_type: "required", }, - { - name: "department", - label: "Department/College", - value: selectOptions.find((o) => o.name === "department").options[0].value, - error: false, - error_type: "required", - }, - { name: "email", label: "Email Address", @@ -44,4 +36,18 @@ export const personFields = [ error: false, error_type: "required", }, + { + name: "department", + label: "Department/College", + value: selectOptions.find((o) => o.name === "department").options[0].value, + error: false, + error_type: "required", + }, + { + name: "admin", + label: "Admin", + value: false, + error: false, + error_type: "required", + }, ]; diff --git a/schema.sql b/schema.sql index 6e7038d..54be276 100644 --- a/schema.sql +++ b/schema.sql @@ -1,70 +1,101 @@ -/* -Schema for tables and fields for both API and CLIENT -Feel free to modify -*/ +create table "user" +( + lsu_id integer not null + constraint user_pkey + primary key, + first_name varchar(45) not null, + last_name varchar(45) not null, + email varchar(100) not null, + phone_number bigint not null, + department varchar(50) not null, + admin boolean default false not null +); +alter table "user" owner to brvuirrqqcjzsb; -CREATE TABLE student ( - lsu_id integer NOT NULL, - first_name varchar(45) NOT NULL, - last_name varchar(45) NOT NULL, - email varchar(100) NOT NULL, - phone_number BigInt NOT NULL, - department varchar(50) NOT NULL, - PRIMARY KEY (lsu_id) +create table ticket +( + ticket_id serial not null + constraint ticket_pk + primary key, + lsu_id integer + constraint ticket_user_lsu_id_fk + references "user" + on update cascade on delete cascade, + priority integer not null, + status varchar(20) not null, + problem_category varchar(50) not null, + description varchar(500), + core_issue varchar(50), + notes varchar(500), + submission_date timestamp not null ); -/* Is it okay for student and technician to share so many common fields? */ -CREATE TABLE technician ( - lsu_id integer NOT NULL, - first_name varchar(45) NOT NULL, - last_name varchar(45) NOT NULL, - email varchar(100) NOT NULL, - phone_number BigInt NOT NULL, - PRIMARY KEY (lsu_id) -); - -CREATE TABLE ticket ( - ticket_id SERIAL PRIMARY KEY, - priority integer NOT NULL, - status varchar(20) NOT NULL, - category varchar(50) NOT NULL, - problem varchar(500) NOT NULL, - description varchar(500) NOT NULL, - model varchar(50) NOT NULL, - os varchar(20) NOT NULL, - version varchar(50) NOT NULL -); +alter table ticket owner to brvuirrqqcjzsb; -/* -technician ---- work ---- ticket +create unique index ticket_ticket_id_uindex + on ticket (ticket_id); -one to many: 1 technician works many tickets? -*/ -CREATE TABLE work ( - issue varchar(50), +create table device +( + device_id serial not null + constraint device_pk + primary key, + ticket_id integer not null + constraint device_ticket_ticket_id_fk + references ticket + on update cascade on delete cascade, + model varchar(50) not null, component varchar(50), - description varchar(500), - starttime Date, - endtime Date, + manufacturer varchar(50) not null, + operating_system varchar(20) not null, + operating_system_version varchar(50) not null ); -/* -admin/technician ---- issue ---- technician - | - ticket -one to one to one: 1 admin/technician assigns 1 ticket to 1 technician? -*/ +alter table device owner to brvuirrqqcjzsb; + +create unique index device_device_id_uindex + on device (device_id); -CREATE TABLE issue ( - assignedby Foreign Key(technician.lsu_id); - assignedto Foreign Key(technician.lsu_id) - comment varchar(500) - assigndate Date; +create table assignment +( + assignment_id serial not null + constraint assignment_pk + primary key, + lsu_id integer not null + constraint assignment_user_lsu_id_fk + references "user" + on update cascade on delete cascade, + ticket_id integer not null + constraint assignment_ticket_ticket_id_fk + references ticket + on update cascade on delete cascade +); -) +alter table assignment owner to brvuirrqqcjzsb; +create unique index assignment_assignment_id_uindex + on assignment (assignment_id); +create table work +( + work_id serial not null + constraint work_pk + primary key, + ticket_id integer not null + constraint work_ticket_ticket_id_fk + references ticket + on update cascade on delete cascade, + lsu_id integer not null + constraint work_user_lsu_id_fk + references "user" + on update cascade on delete cascade, + start_datetime timestamp not null, + end_datetime timestamp not null +); +alter table work owner to brvuirrqqcjzsb; +create unique index work_work_id_uindex + on work (work_id); From 1584a291b959ed3075e20fd07fd056c5e83da8ab Mon Sep 17 00:00:00 2001 From: Christian Dalton Date: Tue, 24 Nov 2020 20:32:39 -0600 Subject: [PATCH 05/17] need backend...hopefully will finish by deadline --- api/src/tech/tech.service.ts | 2 ++ client/src/api/reducers.js | 14 ++++++++++- .../form/ManageTicketForm/adminView.js | 7 +++--- .../form/ManageTicketForm/fields.js | 24 +++++++++++++------ client/src/routes/admin/ManageTicket.js | 20 ++++++++++++---- client/src/routes/user/user.js | 7 ------ 6 files changed, 50 insertions(+), 24 deletions(-) diff --git a/api/src/tech/tech.service.ts b/api/src/tech/tech.service.ts index aea37b8..24ce1d6 100644 --- a/api/src/tech/tech.service.ts +++ b/api/src/tech/tech.service.ts @@ -19,6 +19,7 @@ export class TechService { - hash password */ async create(createTechDto: CreateTechDto) { + // TODO: CREATE USER WITH ADMIN FLAG == TRUE (FOR CREATE NEW TECH SIDEBAR ON TECH PAGE) const { firstname, lastname, lsuid, email, phone } = createTechDto; /* Query user by email or username */ @@ -51,6 +52,7 @@ export class TechService { } /* TODO */ findAll() { + // TODO: SELECT * FROM USER WHERE ADMIN = TRUE; (SELECT TECH PAGE) return `This action returns all user`; } /* TODO */ diff --git a/client/src/api/reducers.js b/client/src/api/reducers.js index 8dad3bb..9b5dc94 100644 --- a/client/src/api/reducers.js +++ b/client/src/api/reducers.js @@ -1,7 +1,14 @@ +import { workLogFields } from "../components/form/ManageTicketForm/fields"; + export const dataFetchReducer = (state, action) => { switch (action.type) { case "FETCH_INIT": - return { ...state, isLoading: true, isError: false }; + return { + ...state, + isLoading: true, + isError: false, + workLogData: { ...workLogFields }, + }; case "FETCH_SUCCESS": return { ...state, @@ -20,6 +27,11 @@ export const dataFetchReducer = (state, action) => { ...state, data: action.payload, }; + case "FETCH_WORK_LOG_SUCCESS": + return { + ...state, + workLogData: action.payload, + }; default: throw new Error(); } diff --git a/client/src/components/form/ManageTicketForm/adminView.js b/client/src/components/form/ManageTicketForm/adminView.js index 20179a7..4d421f1 100644 --- a/client/src/components/form/ManageTicketForm/adminView.js +++ b/client/src/components/form/ManageTicketForm/adminView.js @@ -29,7 +29,7 @@ import { TimeLogTable } from "../../table/TimeLogTable"; var _ = require("lodash"); -export const AdminView = ({ data, dispatch }, ...props) => { +export const AdminView = ({ data, dispatch, workLogData }, ...props) => { return ( <> @@ -114,7 +114,7 @@ export const AdminView = ({ data, dispatch }, ...props) => { handleDateChange(date, "start_datetime", data, dispatch) @@ -125,9 +125,8 @@ export const AdminView = ({ data, dispatch }, ...props) => { handleFormFieldBlur(e, data, dispatch)} handleChange={(e) => handleDateChange(e, "end_datetime", data, dispatch) } diff --git a/client/src/components/form/ManageTicketForm/fields.js b/client/src/components/form/ManageTicketForm/fields.js index 4bf850b..6713ab4 100644 --- a/client/src/components/form/ManageTicketForm/fields.js +++ b/client/src/components/form/ManageTicketForm/fields.js @@ -87,13 +87,6 @@ export const fields = [ error: false, error_type: "none", }, - { - name: "end_datetime", - label: "End Datetime", - value: "", - error: false, - error_type: "none", - }, { name: "status", label: "Status", @@ -107,3 +100,20 @@ export const errorMessages = [ { error_type: "required", error_message: "This field is required." }, { error_type: "none", error_message: "" }, ]; + +export const workLogFields = [ + { + name: "start_datetime", + label: "Start Datetime", + value: "", + error: false, + error_type: "none", + }, + { + name: "end_datetime", + label: "End Datetime", + value: "", + error: false, + error_type: "none", + }, +]; diff --git a/client/src/routes/admin/ManageTicket.js b/client/src/routes/admin/ManageTicket.js index c250fc5..22d6b3c 100644 --- a/client/src/routes/admin/ManageTicket.js +++ b/client/src/routes/admin/ManageTicket.js @@ -34,15 +34,15 @@ import { MyStat } from "./Stats"; var _ = require("lodash"); -const TicketForm = ({ data, setData }, ...props) => { +const TicketForm = ({ data, dispatch, workLogData }, ...props) => { return ( <>

Customer Information

- - + + @@ -75,8 +75,10 @@ export const ManageTicket = (props) => { // TODO: ONCE BACKEND IS SET UP, FORMAT AND IMPLEMENT DATA FOR TABLE try { const result = await axios.get("ticket"); - // TODO: CHANGE BACK! change payloud back to result.data once backend is setup + // TODO: CHANGE BACK! change payload back to result.data once backend is setup dispatch({ type: "FETCH_SUCCESS", payload: fields }); + const workLog = await axios.get("work"); + dispatch({ type: "FETCH_WORK_LOG_SUCCESS", payload: workLog }); } catch (error) { dispatch({ type: "FETCH_FAILURE" }); } @@ -119,7 +121,15 @@ export const ManageTicket = (props) => { - + {state.isLoading ? ( + "LOADING..." + ) : ( + + )} ); diff --git a/client/src/routes/user/user.js b/client/src/routes/user/user.js index e030eff..220b3a5 100644 --- a/client/src/routes/user/user.js +++ b/client/src/routes/user/user.js @@ -50,13 +50,6 @@ export const UserRoute = (props) => { - {/**/} - {/* */} - {/* */} - {/*

Submit Ticket

*/} - {/*
*/} - {/*
*/} - {/*
*/}

My Information

From 03a7b23ba6876a49f8139521528658ee5dbfe068 Mon Sep 17 00:00:00 2001 From: Christian Dalton Date: Fri, 27 Nov 2020 19:20:04 -0600 Subject: [PATCH 06/17] select techinican done --- client/src/api/reducers.js | 7 + .../form/ManageTechnicianForm/fields.js | 10 +- client/src/components/form/MySelectField.js | 3 +- .../components/popover/TechnicianPopover.js | 7 +- .../src/routes/admin/NewTechnicianFlyout.js | 2 +- client/src/routes/admin/SelectTechnician.js | 122 ++++++++++-------- 6 files changed, 86 insertions(+), 65 deletions(-) diff --git a/client/src/api/reducers.js b/client/src/api/reducers.js index 9b5dc94..2c2ef39 100644 --- a/client/src/api/reducers.js +++ b/client/src/api/reducers.js @@ -16,6 +16,13 @@ export const dataFetchReducer = (state, action) => { isError: false, data: action.payload, }; + case "FETCH_TECHNICIANS_SUCCESS": + return { + ...state, + isLoading: false, + isError: false, + selectTechnicianOptions: action.payload, + }; case "FETCH_FAILURE": return { ...state, diff --git a/client/src/components/form/ManageTechnicianForm/fields.js b/client/src/components/form/ManageTechnicianForm/fields.js index d8f8980..84f47c6 100644 --- a/client/src/components/form/ManageTechnicianForm/fields.js +++ b/client/src/components/form/ManageTechnicianForm/fields.js @@ -1,17 +1,15 @@ -export const selectOptions = [ +export const selectTechnicianOptions_default = [ { name: "technician", - options: [ - { value: "tech_a", text: "Tech A" }, - { value: "tech_b", text: "Tech B" }, - ], + options: [{ value: "", text: "" }], }, ]; export const fields = [ { name: "technician", label: "Technician", - value: selectOptions.find((o) => o.name === "technician").options[0].value, + value: selectTechnicianOptions_default.find((o) => o.name === "technician") + .options[0].value, error: false, error_type: "required", }, diff --git a/client/src/components/form/MySelectField.js b/client/src/components/form/MySelectField.js index 771d12b..96aa4af 100644 --- a/client/src/components/form/MySelectField.js +++ b/client/src/components/form/MySelectField.js @@ -13,10 +13,11 @@ export const MySelectField = ( o.name === name).options} + options={selectOptions.options} value={item.value} onChange={(e) => handleChange(e)} onBlur={(e) => handleBlur(e)} + hasNoInitialSelection={true} />
); diff --git a/client/src/components/popover/TechnicianPopover.js b/client/src/components/popover/TechnicianPopover.js index 0994ce3..0fb9e42 100644 --- a/client/src/components/popover/TechnicianPopover.js +++ b/client/src/components/popover/TechnicianPopover.js @@ -9,7 +9,10 @@ import { EuiFlexItem, } from "@elastic/eui"; import { MySelectField } from "../form/MySelectField"; -import { fields, selectOptions } from "../form/ManageTechnicianForm/fields"; +import { + fields, + selectTechnicianOptions_default, +} from "../form/ManageTechnicianForm/fields"; import { handleFormFieldBlur, handleFormFieldChange, @@ -62,7 +65,7 @@ export const AddTechnicianPopover = () => { handleFormFieldChange(e, state.data, dispatch) } diff --git a/client/src/routes/admin/NewTechnicianFlyout.js b/client/src/routes/admin/NewTechnicianFlyout.js index 02e7bf5..6d79aaa 100644 --- a/client/src/routes/admin/NewTechnicianFlyout.js +++ b/client/src/routes/admin/NewTechnicianFlyout.js @@ -24,6 +24,7 @@ export const NewTechnicianFlyout = ( ...props ) => { const closeFlyout = () => setIsFlyoutVisible(false); + const [state, dispatch] = useReducer(dataFetchReducer, { isLoading: false, isError: false, @@ -33,7 +34,6 @@ export const NewTechnicianFlyout = ( useEffect(() => { const fetchData = async () => { dispatch({ type: "FETCH_INIT" }); - // TODO: ONCE BACKEND IS SET UP, FORMAT AND IMPLEMENT DATA FOR TABLE try { const result = await axios.get("ticket"); dispatch({ type: "FETCH_SUCCESS", payload: result.data }); diff --git a/client/src/routes/admin/SelectTechnician.js b/client/src/routes/admin/SelectTechnician.js index 0115002..b441898 100644 --- a/client/src/routes/admin/SelectTechnician.js +++ b/client/src/routes/admin/SelectTechnician.js @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useReducer } from "react"; +import React, { useEffect, useReducer, useState } from "react"; import { EuiButton, @@ -22,7 +22,7 @@ import { NewTechnicianFlyout } from "./NewTechnicianFlyout"; import { Debug } from "../../components/debug/debug"; import { fields, - selectOptions, + selectTechnicianOptions_default, } from "../../components/form/ManageTechnicianForm/fields"; import axios from "../../api/api.js"; import { dataFetchReducer } from "../../api/reducers"; @@ -30,23 +30,29 @@ import { dataFetchReducer } from "../../api/reducers"; var _ = require("lodash"); export const SelectTechnician = ({ setTechnician }, ...props) => { - const [options, setOptions] = useState(selectOptions); const [isFlyoutVisible, setIsFlyoutVisible] = useState(false); const [state, dispatch] = useReducer(dataFetchReducer, { isLoading: false, isError: false, data: fields, + selectTechnicianOptions: selectTechnicianOptions_default, }); useEffect(() => { const fetchData = async () => { dispatch({ type: "FETCH_INIT" }); - // TODO: ONCE BACKEND IS SET UP, FORMAT AND IMPLEMENT DATA try { - const result = await axios.get("ticket"); - // TODO: REMOVE! change back to result.data - dispatch({ type: "FETCH_SUCCESS", payload: fields }); + const result = await axios.get("/user/admin"); + const final = { + name: "technician", + options: result.data.map((o) => ({ + ...o, + value: (o.first_name + "_" + o.last_name).toLowerCase(), + text: o.first_name + " " + o.last_name, + })), + }; + dispatch({ type: "FETCH_TECHNICIANS_SUCCESS", payload: final }); } catch (error) { dispatch({ type: "FETCH_FAILURE" }); } @@ -64,53 +70,59 @@ export const SelectTechnician = ({ setTechnician }, ...props) => { }; return ( - - - - - -

Choose Technician

-
-
-
- - - - handleFormFieldChange(e, state.data, dispatch) - } - handleBlur={(e) => handleFormFieldBlur(e, state.data, dispatch)} - /> - - - - setIsFlyoutVisible(true)} - > - New - - - - handleFormSubmit(e, state.data)} - > - Select - - - - - - -
- -
+ <> + {state.isLoading ? null : ( + + + + + +

Choose Technician

+
+
+
+ + + + handleFormFieldChange(e, state.data, dispatch) + } + handleBlur={(e) => + handleFormFieldBlur(e, state.data, dispatch) + } + /> + + + + setIsFlyoutVisible(true)} + > + New + + + + handleFormSubmit(e, state.data)} + > + Select + + + + + + +
+ +
+ )} + ); }; From 5a8348f7d849a9d367dfb56d779249d568bbfa6f Mon Sep 17 00:00:00 2001 From: Christian Dalton Date: Fri, 27 Nov 2020 19:59:30 -0600 Subject: [PATCH 07/17] create tech almost done. 500 server error on backend --- .../form/ManageTicketForm/handlers.js | 12 ++- .../src/routes/admin/NewTechnicianFlyout.js | 73 ++++++++++--------- 2 files changed, 50 insertions(+), 35 deletions(-) diff --git a/client/src/components/form/ManageTicketForm/handlers.js b/client/src/components/form/ManageTicketForm/handlers.js index 9a3aaf1..b4feda1 100644 --- a/client/src/components/form/ManageTicketForm/handlers.js +++ b/client/src/components/form/ManageTicketForm/handlers.js @@ -1,10 +1,20 @@ import { addToast } from "../../toast"; +import axios from "../../../api/api"; var _ = require("lodash"); +const postData = async (endpoint, data) => { + const response = await axios.post(endpoint, data); + console.log(response); +}; + export const handleFormSubmit = (e, data) => { const errors = _.find(data, ["error", true]); if (errors === undefined) { - console.log(data); + const d = data.map((o) => ({ [o.name]: o.value })); + console.log(d); + + postData("/tech", d); + addToast({ title: "Ticket Submitted!", color: "success", diff --git a/client/src/routes/admin/NewTechnicianFlyout.js b/client/src/routes/admin/NewTechnicianFlyout.js index 6d79aaa..7b65895 100644 --- a/client/src/routes/admin/NewTechnicianFlyout.js +++ b/client/src/routes/admin/NewTechnicianFlyout.js @@ -28,22 +28,21 @@ export const NewTechnicianFlyout = ( const [state, dispatch] = useReducer(dataFetchReducer, { isLoading: false, isError: false, - data: null, + data: personFields, }); - useEffect(() => { - const fetchData = async () => { - dispatch({ type: "FETCH_INIT" }); - try { - const result = await axios.get("ticket"); - dispatch({ type: "FETCH_SUCCESS", payload: result.data }); - } catch (error) { - dispatch({ type: "FETCH_FAILURE" }); - } - }; - - fetchData(); - }, []); + // useEffect(() => { + // const fetchData = async () => { + // dispatch({ type: "FETCH_INIT" }); + // try { + // dispatch({ type: "FETCH_SUCCESS", payload: result.data }); + // } catch (error) { + // dispatch({ type: "FETCH_FAILURE" }); + // } + // }; + // + // fetchData(); + // }, []); const showFlyout = () => setIsFlyoutVisible(true); @@ -55,26 +54,32 @@ export const NewTechnicianFlyout = ( ownFocus={true} aria-labelledby="flyoutSmallTitle" > - - -

New Technician

-
-
- - - - - - handleFormSubmit(e, state.data)} - > - Save - - - - - + {state.isLoading ? null : ( + <> + + +

New Technician

+
+
+ + + + + + { + handleFormSubmit(e, state.data); + }} + > + Save + + + + + + + )} ); } else { From 84bc359a6214c39b51184aa7255bab600e1cd641 Mon Sep 17 00:00:00 2001 From: Christian Dalton Date: Fri, 27 Nov 2020 20:46:05 -0600 Subject: [PATCH 08/17] stats working --- client/src/api/reducers.js | 13 +++++ client/src/routes/admin/ManageTicket.js | 65 ++++++++++++++++--------- client/src/routes/admin/Stats.js | 39 ++++++++------- 3 files changed, 74 insertions(+), 43 deletions(-) diff --git a/client/src/api/reducers.js b/client/src/api/reducers.js index 2c2ef39..4c73d1f 100644 --- a/client/src/api/reducers.js +++ b/client/src/api/reducers.js @@ -16,6 +16,19 @@ export const dataFetchReducer = (state, action) => { isError: false, data: action.payload, }; + case "FETCH_ALL_TICKETS_SUCCESS": + return { + ...state, + isTicketsLoading: false, + isError: false, + allTickets: action.payload, + closedTickets: action.payload.filter((o) => o.status === "CLOSE") + .length, + inProgressTickets: action.payload.filter( + (o) => o.status === "IN PROGRESS" + ).length, + openTickets: action.payload.filter((o) => o.status === "OPEN").length, + }; case "FETCH_TECHNICIANS_SUCCESS": return { ...state, diff --git a/client/src/routes/admin/ManageTicket.js b/client/src/routes/admin/ManageTicket.js index 22d6b3c..f798f08 100644 --- a/client/src/routes/admin/ManageTicket.js +++ b/client/src/routes/admin/ManageTicket.js @@ -62,9 +62,10 @@ const TicketForm = ({ data, dispatch, workLogData }, ...props) => { export const ManageTicket = (props) => { const [state, dispatch] = useReducer(dataFetchReducer, { - isLoading: false, + isTicketsLoading: false, isError: false, data: fields, + allTickets: {}, }); const [selectedTicket, setSelectedTicket] = useState(false); @@ -76,7 +77,7 @@ export const ManageTicket = (props) => { try { const result = await axios.get("ticket"); // TODO: CHANGE BACK! change payload back to result.data once backend is setup - dispatch({ type: "FETCH_SUCCESS", payload: fields }); + dispatch({ type: "FETCH_ALL_TICKETS_SUCCESS", payload: result.data }); const workLog = await axios.get("work"); dispatch({ type: "FETCH_WORK_LOG_SUCCESS", payload: workLog }); } catch (error) { @@ -94,16 +95,34 @@ export const ManageTicket = (props) => { return ( <>
- - - {/*TODO : UPDATE ENDPOINT*/} - - - - {/*TODO: UPDATE ENDPOINT*/} - - - + {state.isTicketsLoading === true ? null : ( + + + + + + + + + + + + )}
@@ -120,17 +139,17 @@ export const ManageTicket = (props) => { : "Edit ____'s Ticket"} - - {state.isLoading ? ( - "LOADING..." - ) : ( - - )} - + {/**/} + {/* {state.isLoading ? (*/} + {/* "LOADING..."*/} + {/* ) : (*/} + {/* */} + {/* )}*/} + {/**/} ); }; diff --git a/client/src/routes/admin/Stats.js b/client/src/routes/admin/Stats.js index d2fffa6..6a14d1a 100644 --- a/client/src/routes/admin/Stats.js +++ b/client/src/routes/admin/Stats.js @@ -4,37 +4,36 @@ import { dataFetchReducer } from "../../api/reducers"; import axios from "../../api/api"; import { ErrorCallout } from "../../components/callout/Callout"; -export const MyStat = ({ endpoint, color, icon }, ...props) => { +export const MyStat = ({ data, color, icon, description }, ...props) => { const [state, dispatch] = useReducer(dataFetchReducer, { isLoading: false, isError: false, data: null, }); - useEffect(() => { - const fetchData = async () => { - dispatch({ type: "FETCH_INIT" }); - // TODO: ONCE BACKEND IS SET UP, SEND TO COMPONENT - try { - const result = await axios.get(endpoint); - dispatch({ type: "FETCH_SUCCESS", payload: result.data }); - } catch (error) { - dispatch({ type: "FETCH_FAILURE" }); - } - }; - - fetchData(); - }, []); + // useEffect(() => { + // const fetchData = async () => { + // dispatch({ type: "FETCH_INIT" }); + // // TODO: ONCE BACKEND IS SET UP, SEND TO COMPONENT + // try { + // const result = await axios.get(endpoint); + // dispatch({ type: "FETCH_SUCCESS", payload: result.data }); + // } catch (error) { + // dispatch({ type: "FETCH_FAILURE" }); + // } + // }; + // + // fetchData(); + // }, []); return ( <> - {state.isError === true ? ( - - ) : ( + {state.isLoading === true ? null : ( + // Date: Fri, 27 Nov 2020 21:28:29 -0600 Subject: [PATCH 09/17] table started --- client/src/api/reducers.js | 1 + client/src/components/table/TicketsTable.js | 50 +++++++-------------- client/src/routes/admin/Stats.js | 1 - 3 files changed, 17 insertions(+), 35 deletions(-) diff --git a/client/src/api/reducers.js b/client/src/api/reducers.js index 4c73d1f..1f154a1 100644 --- a/client/src/api/reducers.js +++ b/client/src/api/reducers.js @@ -7,6 +7,7 @@ export const dataFetchReducer = (state, action) => { ...state, isLoading: true, isError: false, + allTickets: {}, workLogData: { ...workLogFields }, }; case "FETCH_SUCCESS": diff --git a/client/src/components/table/TicketsTable.js b/client/src/components/table/TicketsTable.js index 70ca91d..1f4c9f7 100644 --- a/client/src/components/table/TicketsTable.js +++ b/client/src/components/table/TicketsTable.js @@ -18,21 +18,17 @@ const userTest = [ ]; export const TicketsTable = ({ handleTicketSelection }, ...props) => { - const [state, dispatch] = useReducer(dataFetchReducer, { - isLoading: false, - isError: false, - data: null, - }); + const [items, setItems] = useState({}); + const [isLoading, setIsLoading] = useState(true); useEffect(() => { const fetchData = async () => { - dispatch({ type: "FETCH_INIT" }); - // TODO: ONCE BACKEND IS SET UP, FORMAT AND IMPLEMENT DATA FOR TABLE try { const result = await axios.get("ticket"); - dispatch({ type: "FETCH_SUCCESS", payload: result.data }); + setItems(result.data); + setIsLoading(false); } catch (error) { - dispatch({ type: "FETCH_FAILURE" }); + console.log(error); } }; @@ -41,7 +37,7 @@ export const TicketsTable = ({ handleTicketSelection }, ...props) => { const columns = [ { - field: "firstName", + field: "first_name", name: "First Name", sortable: true, "data-test-subj": "firstNameCell", @@ -64,33 +60,21 @@ export const TicketsTable = ({ handleTicketSelection }, ...props) => { field: "lastName", name: "Last Name", truncateText: true, - render: (name) => ( - - {name} - - ), - mobileOptions: { - show: false, - }, }, { - field: "github", - name: "Github", + field: "lsu_id", + name: "LSU ID", }, { - field: "online", - name: "Online", - dataType: "boolean", - render: (online) => { - const color = online ? "success" : "danger"; - const label = online ? "Online" : "Offline"; - return {label}; - }, + field: "problem_category", + name: "Problem Category", + }, + { + field: "status", + name: "Status", }, ]; - const items = userTest.filter((user, index) => index < 10); - const getRowProps = (item) => { const { id } = item; return { @@ -114,12 +98,10 @@ export const TicketsTable = ({ handleTicketSelection }, ...props) => { return (
- {state.isError === true ? ( - - ) : ( + {isLoading === true ? null : ( { return ( <> {state.isLoading === true ? null : ( - // Date: Fri, 27 Nov 2020 21:49:54 -0600 Subject: [PATCH 10/17] merge to backend --- client/src/api/reducers.js | 7 --- client/src/components/table/TicketsTable.js | 30 +++-------- client/src/routes/admin/ManageTicket.js | 45 ++++++++++++---- client/src/routes/admin/Stats.js | 57 +++++++++------------ 4 files changed, 65 insertions(+), 74 deletions(-) diff --git a/client/src/api/reducers.js b/client/src/api/reducers.js index 1f154a1..10d49e5 100644 --- a/client/src/api/reducers.js +++ b/client/src/api/reducers.js @@ -22,13 +22,6 @@ export const dataFetchReducer = (state, action) => { ...state, isTicketsLoading: false, isError: false, - allTickets: action.payload, - closedTickets: action.payload.filter((o) => o.status === "CLOSE") - .length, - inProgressTickets: action.payload.filter( - (o) => o.status === "IN PROGRESS" - ).length, - openTickets: action.payload.filter((o) => o.status === "OPEN").length, }; case "FETCH_TECHNICIANS_SUCCESS": return { diff --git a/client/src/components/table/TicketsTable.js b/client/src/components/table/TicketsTable.js index 1f4c9f7..a8bf7d7 100644 --- a/client/src/components/table/TicketsTable.js +++ b/client/src/components/table/TicketsTable.js @@ -17,24 +17,10 @@ const userTest = [ }, ]; -export const TicketsTable = ({ handleTicketSelection }, ...props) => { - const [items, setItems] = useState({}); - const [isLoading, setIsLoading] = useState(true); - - useEffect(() => { - const fetchData = async () => { - try { - const result = await axios.get("ticket"); - setItems(result.data); - setIsLoading(false); - } catch (error) { - console.log(error); - } - }; - - fetchData(); - }, []); - +export const TicketsTable = ( + { handleTicketSelection, tickets, isLoading }, + ...props +) => { const columns = [ { field: "first_name", @@ -76,12 +62,12 @@ export const TicketsTable = ({ handleTicketSelection }, ...props) => { ]; const getRowProps = (item) => { - const { id } = item; + const { lsu_id } = item; return { - "data-test-subj": `row-${id}`, + "data-test-subj": `row-${lsu_id}`, className: "customRowClass", onClick: (e) => { - handleTicketSelection(e, id); + handleTicketSelection(e, lsu_id); }, }; }; @@ -100,7 +86,7 @@ export const TicketsTable = ({ handleTicketSelection }, ...props) => {
{isLoading === true ? null : ( { allTickets: {}, }); - const [selectedTicket, setSelectedTicket] = useState(false); + const [selectedTicket, setSelectedTicket] = useState(null); useEffect(() => { const fetchData = async () => { dispatch({ type: "FETCH_INIT" }); - // TODO: ONCE BACKEND IS SET UP, FORMAT AND IMPLEMENT DATA FOR TABLE try { - const result = await axios.get("ticket"); - // TODO: CHANGE BACK! change payload back to result.data once backend is setup - dispatch({ type: "FETCH_ALL_TICKETS_SUCCESS", payload: result.data }); const workLog = await axios.get("work"); dispatch({ type: "FETCH_WORK_LOG_SUCCESS", payload: workLog }); } catch (error) { @@ -88,6 +84,23 @@ export const ManageTicket = (props) => { fetchData(); }, []); + const [tickets, setTickets] = useState(null); + const [isTicketsLoading, setIsTicketsLoading] = useState(true); + + useEffect(() => { + const fetchData = async () => { + try { + const result = await axios.get("ticket"); + setTickets(result.data); + setIsTicketsLoading(false); + } catch (error) { + console.log(error); + } + }; + + fetchData(); + }, []); + const handleTicketSelection = (e, id) => { setSelectedTicket(id); }; @@ -99,26 +112,32 @@ export const ManageTicket = (props) => { @@ -129,14 +148,18 @@ export const ManageTicket = (props) => {

All Tickets

- +

- {selectedTicket === false + {selectedTicket === null ? "Create New Ticket" - : "Edit ____'s Ticket"} + : "Edit " + selectedTicket + "'s Ticket"}

{/**/} diff --git a/client/src/routes/admin/Stats.js b/client/src/routes/admin/Stats.js index b276a87..ba77b54 100644 --- a/client/src/routes/admin/Stats.js +++ b/client/src/routes/admin/Stats.js @@ -1,46 +1,35 @@ import { EuiIcon, EuiPanel, EuiStat } from "@elastic/eui"; -import React, { useEffect, useReducer } from "react"; +import React, { useEffect, useState, useReducer } from "react"; import { dataFetchReducer } from "../../api/reducers"; import axios from "../../api/api"; import { ErrorCallout } from "../../components/callout/Callout"; -export const MyStat = ({ data, color, icon, description }, ...props) => { - const [state, dispatch] = useReducer(dataFetchReducer, { - isLoading: false, - isError: false, - data: null, - }); +export const MyStat = ( + { data, color, icon, description, filter, isLoading }, + ...props +) => { + const [items, setItems] = useState(null); - // useEffect(() => { - // const fetchData = async () => { - // dispatch({ type: "FETCH_INIT" }); - // // TODO: ONCE BACKEND IS SET UP, SEND TO COMPONENT - // try { - // const result = await axios.get(endpoint); - // dispatch({ type: "FETCH_SUCCESS", payload: result.data }); - // } catch (error) { - // dispatch({ type: "FETCH_FAILURE" }); - // } - // }; - // - // fetchData(); - // }, []); + useEffect(() => { + if (data != null) { + const i = data.filter((o) => o.status === filter).length; + setItems(i); + } + }, [data]); return ( <> - {state.isLoading === true ? null : ( - - - - - - )} + + + + + ); }; From b54fdc678e75881902a2b19f3b059b5cd2621c0b Mon Sep 17 00:00:00 2001 From: Christian Dalton Date: Fri, 27 Nov 2020 23:29:10 -0600 Subject: [PATCH 11/17] insert tech working --- api/src/tech/tech.service.ts | 70 --------------- .../form/ManageTicketForm/handlers.js | 13 +-- .../form/ManageTicketForm/userView.js | 54 ++++++------ client/src/components/table/TicketsTable.js | 2 +- client/src/routes/admin/ManageTicket.js | 87 +++++++++++-------- .../src/routes/admin/NewTechnicianFlyout.js | 22 ++--- 6 files changed, 92 insertions(+), 156 deletions(-) delete mode 100644 api/src/tech/tech.service.ts diff --git a/api/src/tech/tech.service.ts b/api/src/tech/tech.service.ts deleted file mode 100644 index 24ce1d6..0000000 --- a/api/src/tech/tech.service.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { HttpException, HttpStatus, Inject, Injectable } from '@nestjs/common'; -import { Pool } from 'pg'; -import { PG_CONNECTION } from 'src/connection'; -import { CreateTechDto } from './dto/create-tech.dto'; -import { UpdateTechDto } from './dto/update-tech.dto'; -import { Tech } from './entities/tech.entity'; - -/* TODO: - - Implement remaining methods - - Find solution to abstract SQL -*/ -@Injectable() -export class TechService { - constructor(@Inject(PG_CONNECTION) private connection: Pool) {} - - /* Working implementation - TODO: - - refactor table to match production table - - hash password - */ - async create(createTechDto: CreateTechDto) { - // TODO: CREATE USER WITH ADMIN FLAG == TRUE (FOR CREATE NEW TECH SIDEBAR ON TECH PAGE) - const { firstname, lastname, lsuid, email, phone } = createTechDto; - - /* Query user by email or username */ - const query = 'SELECT id FROM tech WHERE lsuid = $1'; - const queryRes = await this.connection.query(query, [lsuid]); - - /* Test to see if user exists */ - if (!!queryRes.rows[0]) { - throw new HttpException( - { status: HttpStatus.BAD_REQUEST, error: 'LSUID already in use' }, - HttpStatus.FORBIDDEN, - ); - } - - /* Insert new user into db - TODO: implement error handling for pg request - */ - const text = 'INSERT INTO tech VALUES ($1, $2, $3, $4, $5, $6) RETURNING *'; - const values = [firstname, lastname, lsuid, email, lsuid, phone]; - const res = (await this.connection.query(text, values)).rows[0]; - - /* Return user object without password */ - const tech = new Tech(); - tech.firstname = res.firstname; - tech.lastname = res.lastname; - tech.lsuid = res.lsuid; - tech.email = res.email; - tech.phone = res.phone; - return tech; - } - /* TODO */ - findAll() { - // TODO: SELECT * FROM USER WHERE ADMIN = TRUE; (SELECT TECH PAGE) - return `This action returns all user`; - } - /* TODO */ - findOne(id: number) { - return `This action returns a #${id} user`; - } - /* TODO */ - update(id: number, updateTechDto: UpdateTechDto) { - return `This action updates a #${id} user`; - } - /* TODO */ - remove(id: number) { - return `This action removes a #${id} user`; - } -} diff --git a/client/src/components/form/ManageTicketForm/handlers.js b/client/src/components/form/ManageTicketForm/handlers.js index b4feda1..be66444 100644 --- a/client/src/components/form/ManageTicketForm/handlers.js +++ b/client/src/components/form/ManageTicketForm/handlers.js @@ -3,27 +3,30 @@ import axios from "../../../api/api"; var _ = require("lodash"); const postData = async (endpoint, data) => { + console.log(data); const response = await axios.post(endpoint, data); - console.log(response); + return response; }; export const handleFormSubmit = (e, data) => { const errors = _.find(data, ["error", true]); if (errors === undefined) { - const d = data.map((o) => ({ [o.name]: o.value })); - console.log(d); - - postData("/tech", d); + let d = data.map((o) => ({ [o.name]: o.value })); + const dd = Object.assign({}, ...d); + const response = postData("/user", dd); addToast({ title: "Ticket Submitted!", color: "success", }); + return response; } else { addToast({ title: "Check Form for Errors", color: "danger", }); + + return null; } }; diff --git a/client/src/components/form/ManageTicketForm/userView.js b/client/src/components/form/ManageTicketForm/userView.js index 1365eb2..2cff176 100644 --- a/client/src/components/form/ManageTicketForm/userView.js +++ b/client/src/components/form/ManageTicketForm/userView.js @@ -20,7 +20,7 @@ import { selectOptions } from "../selectOptions"; var _ = require("lodash"); -export const UserView = ({ data, dispatch }, ...props) => { +export const UserView = ({ data, setData }, ...props) => { return ( <> @@ -28,32 +28,32 @@ export const UserView = ({ data, dispatch }, ...props) => { handleFormFieldChange(e, data, dispatch)} - handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} + handleChange={(e) => handleFormFieldChange(e, data, setData)} + handleBlur={(e) => handleFormFieldBlur(e, data, setData)} /> handleFormFieldChange(e, data, dispatch)} - handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} + handleChange={(e) => handleFormFieldChange(e, data, setData)} + handleBlur={(e) => handleFormFieldBlur(e, data, setData)} /> handleFormFieldChange(e, data, dispatch)} - handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} + handleChange={(e) => handleFormFieldChange(e, data, setData)} + handleBlur={(e) => handleFormFieldBlur(e, data, setData)} /> handleFormFieldChange(e, data, dispatch)} - handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} + handleChange={(e) => handleFormFieldChange(e, data, setData)} + handleBlur={(e) => handleFormFieldBlur(e, data, setData)} /> @@ -62,16 +62,16 @@ export const UserView = ({ data, dispatch }, ...props) => { handleFormFieldChange(e, data, dispatch)} - handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} + handleChange={(e) => handleFormFieldChange(e, data, setData)} + handleBlur={(e) => handleFormFieldBlur(e, data, setData)} /> handleFormFieldChange(e, data, dispatch)} - handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} + handleChange={(e) => handleFormFieldChange(e, data, setData)} + handleBlur={(e) => handleFormFieldBlur(e, data, setData)} /> @@ -85,8 +85,8 @@ export const UserView = ({ data, dispatch }, ...props) => { name={"priority"} data={data} selectOptions={selectOptions} - handleChange={(e) => handleFormFieldChange(e, data, dispatch)} - handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} + handleChange={(e) => handleFormFieldChange(e, data, setData)} + handleBlur={(e) => handleFormFieldBlur(e, data, setData)} /> @@ -95,32 +95,32 @@ export const UserView = ({ data, dispatch }, ...props) => { handleFormFieldChange(e, data, dispatch)} - handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} + handleChange={(e) => handleFormFieldChange(e, data, setData)} + handleBlur={(e) => handleFormFieldBlur(e, data, setData)} /> handleFormFieldChange(e, data, dispatch)} - handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} + handleChange={(e) => handleFormFieldChange(e, data, setData)} + handleBlur={(e) => handleFormFieldBlur(e, data, setData)} /> handleFormFieldChange(e, data, dispatch)} - handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} + handleChange={(e) => handleFormFieldChange(e, data, setData)} + handleBlur={(e) => handleFormFieldBlur(e, data, setData)} /> handleFormFieldChange(e, data, dispatch)} - handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} + handleChange={(e) => handleFormFieldChange(e, data, setData)} + handleBlur={(e) => handleFormFieldBlur(e, data, setData)} /> @@ -133,9 +133,9 @@ export const UserView = ({ data, dispatch }, ...props) => { handleFormFieldChange(e, data, dispatch)} + handleChange={(e) => handleFormFieldChange(e, data, setData)} selectOptions={selectOptions} - handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, setData)} /> @@ -154,8 +154,8 @@ export const UserView = ({ data, dispatch }, ...props) => { handleFormFieldChange(e, data, dispatch)} - onBlur={(e) => handleFormFieldBlur(e, data, dispatch)} + onChange={(e) => handleFormFieldChange(e, data, setData)} + onBlur={(e) => handleFormFieldBlur(e, data, setData)} /> diff --git a/client/src/components/table/TicketsTable.js b/client/src/components/table/TicketsTable.js index a8bf7d7..0106e33 100644 --- a/client/src/components/table/TicketsTable.js +++ b/client/src/components/table/TicketsTable.js @@ -67,7 +67,7 @@ export const TicketsTable = ( "data-test-subj": `row-${lsu_id}`, className: "customRowClass", onClick: (e) => { - handleTicketSelection(e, lsu_id); + handleTicketSelection(e, item); }, }; }; diff --git a/client/src/routes/admin/ManageTicket.js b/client/src/routes/admin/ManageTicket.js index ae941ab..a55cfcd 100644 --- a/client/src/routes/admin/ManageTicket.js +++ b/client/src/routes/admin/ManageTicket.js @@ -34,15 +34,52 @@ import { MyStat } from "./Stats"; var _ = require("lodash"); -const TicketForm = ({ data, dispatch, workLogData }, ...props) => { +const TicketForm = ({ selected, data, setData }, ...props) => { + const [workLogData, setWorkLogData] = useState(null); + const [workLogLoading, setWorkLogLoading] = useState(true); + + useEffect(() => { + const fetchWorkLog = async () => { + try { + const result = await axios.get("/work"); + setWorkLogData(result.data); + setWorkLogLoading(false); + } catch (error) { + console.log(error); + } + }; + + const fetchData = () => { + try { + const ticketFields = axios.get("/ticket/" + selected.id); + const userFields = axios.get("/user/" + selected.lsu_id); + } catch (error) { + console.log(error); + } + }; + fetchData(); + fetchWorkLog(); + }, []); + + useEffect(() => { + const d = []; + + let keys; + keys = Object.keys(data); + for (let x in keys) { + d.push({ label: x, value: keys[x] }); + } + setData(d); + }, [data]); + return ( <>

Customer Information

- - + + @@ -61,29 +98,7 @@ const TicketForm = ({ data, dispatch, workLogData }, ...props) => { }; export const ManageTicket = (props) => { - const [state, dispatch] = useReducer(dataFetchReducer, { - isTicketsLoading: false, - isError: false, - data: fields, - allTickets: {}, - }); - const [selectedTicket, setSelectedTicket] = useState(null); - - useEffect(() => { - const fetchData = async () => { - dispatch({ type: "FETCH_INIT" }); - try { - const workLog = await axios.get("work"); - dispatch({ type: "FETCH_WORK_LOG_SUCCESS", payload: workLog }); - } catch (error) { - dispatch({ type: "FETCH_FAILURE" }); - } - }; - - fetchData(); - }, []); - const [tickets, setTickets] = useState(null); const [isTicketsLoading, setIsTicketsLoading] = useState(true); @@ -108,7 +123,7 @@ export const ManageTicket = (props) => { return ( <>
- {state.isTicketsLoading === true ? null : ( + {isTicketsLoading === true ? null : ( {

{selectedTicket === null ? "Create New Ticket" - : "Edit " + selectedTicket + "'s Ticket"} + : "Edit " + selectedTicket.lsu_id + "'s Ticket"}

- {/**/} - {/* {state.isLoading ? (*/} - {/* "LOADING..."*/} - {/* ) : (*/} - {/* */} - {/* )}*/} - {/**/} + + {selectedTicket == null ? ( + "Please select ticket." + ) : ( + + )} + ); }; diff --git a/client/src/routes/admin/NewTechnicianFlyout.js b/client/src/routes/admin/NewTechnicianFlyout.js index 7b65895..eed746e 100644 --- a/client/src/routes/admin/NewTechnicianFlyout.js +++ b/client/src/routes/admin/NewTechnicianFlyout.js @@ -17,7 +17,6 @@ import { personFields } from "../../components/form/person/fields"; import { handleFormSubmit } from "../../components/form/ManageTicketForm/handlers"; import { Debug } from "../../components/debug/debug"; import { dataFetchReducer } from "../../api/reducers"; -import axios from "../../api/api"; export const NewTechnicianFlyout = ( { isFlyoutVisible, setIsFlyoutVisible }, @@ -31,21 +30,14 @@ export const NewTechnicianFlyout = ( data: personFields, }); - // useEffect(() => { - // const fetchData = async () => { - // dispatch({ type: "FETCH_INIT" }); - // try { - // dispatch({ type: "FETCH_SUCCESS", payload: result.data }); - // } catch (error) { - // dispatch({ type: "FETCH_FAILURE" }); - // } - // }; - // - // fetchData(); - // }, []); - const showFlyout = () => setIsFlyoutVisible(true); + const localFormSubmit = (e, data) => { + if (handleFormSubmit(e, data) != null) { + setIsFlyoutVisible(false); + } + }; + if (isFlyoutVisible) { return ( { - handleFormSubmit(e, state.data); + localFormSubmit(e, state.data); }} > Save From 6a186c20392a724df80383250e80a19ad45c7b4c Mon Sep 17 00:00:00 2001 From: Christian Dalton Date: Sat, 28 Nov 2020 11:16:23 -0600 Subject: [PATCH 12/17] tech --- .../ManageTechnicianForm/NewTechnicianForm.js | 5 +- .../form/ManageTicketForm/adminView.js | 58 ++--- .../form/ManageTicketForm/handlers.js | 41 ++- .../form/ManageTicketForm/userView.js | 9 +- client/src/components/form/selectOptions.js | 233 +++++++++++++++++- client/src/routes/admin/ManageTicket.js | 18 +- client/src/routes/admin/SelectTechnician.js | 26 +- client/src/routes/admin/admin.js | 5 +- 8 files changed, 335 insertions(+), 60 deletions(-) diff --git a/client/src/components/form/ManageTechnicianForm/NewTechnicianForm.js b/client/src/components/form/ManageTechnicianForm/NewTechnicianForm.js index 5e44498..1ec0e63 100644 --- a/client/src/components/form/ManageTechnicianForm/NewTechnicianForm.js +++ b/client/src/components/form/ManageTechnicianForm/NewTechnicianForm.js @@ -15,6 +15,8 @@ import { handleFormFieldBlur, handleFormFieldChange, } from "../ManageTicketForm/handlers"; +import { MySelectField } from "../MySelectField"; +import { selectOptions } from "../selectOptions"; var _ = require("lodash"); @@ -46,9 +48,10 @@ export const NewTechnicianForm = ({ data, dispatch }, ...props) => { />
- o.name === "department")} handleChange={(e) => handleFormFieldChange(e, data, dispatch)} handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> diff --git a/client/src/components/form/ManageTicketForm/adminView.js b/client/src/components/form/ManageTicketForm/adminView.js index 4d421f1..b28bda9 100644 --- a/client/src/components/form/ManageTicketForm/adminView.js +++ b/client/src/components/form/ManageTicketForm/adminView.js @@ -110,35 +110,35 @@ export const AdminView = ({ data, dispatch, workLogData }, ...props) => {
- - - - - handleDateChange(date, "start_datetime", data, dispatch) - } - /> - - - - - - handleDateChange(e, "end_datetime", data, dispatch) - } - /> - - - - - Add Time Entry - - - + {/**/} + {/* */} + {/* */} + {/* */} + {/* handleDateChange(date, "start_datetime", data, dispatch)*/} + {/* }*/} + {/* />*/} + {/* */} + {/* */} + {/* */} + {/* */} + {/* */} + {/* handleDateChange(e, "end_datetime", data, dispatch)*/} + {/* }*/} + {/* />*/} + {/* */} + {/* */} + {/* */} + {/* */} + {/* Add Time Entry*/} + {/* */} + {/* */} + {/**/} diff --git a/client/src/components/form/ManageTicketForm/handlers.js b/client/src/components/form/ManageTicketForm/handlers.js index be66444..5765f2d 100644 --- a/client/src/components/form/ManageTicketForm/handlers.js +++ b/client/src/components/form/ManageTicketForm/handlers.js @@ -30,7 +30,19 @@ export const handleFormSubmit = (e, data) => { } }; -export const handleFormFieldChange = (e, data, dispatch) => { +export const handleFormFieldChange = (e, data, setData) => { + const target = e.target; + const value = target.value; + const name = target.name; + + const newData = data; + const index = newData.findIndex((o) => o.name === name); + + newData[index].value = value; + setData(newData); +}; + +export const handleFormFieldChangeDispatch = (e, data, dispatch) => { const target = e.target; const value = target.value; const name = target.name; @@ -50,7 +62,15 @@ export const handleDateChange = (date, name, data, dispatch) => { dispatch({ type: "UPDATE_DATA", payload: newData }); }; -export const handleFormFieldBlur = (e, data, dispatch) => { +export const handleDateChangeDispatch = (date, name, data, setData) => { + const newData = data; + const index = newData.findIndex((o) => o.name === name); + + newData[index].value = date.toJSON(); + setData(newData); +}; + +export const handleFormFieldBlurDispatch = (e, data, dispatch) => { const name = e.target.name; const value = e.target.value; @@ -66,3 +86,20 @@ export const handleFormFieldBlur = (e, data, dispatch) => { dispatch({ type: "UPDATE_DATA", payload: newData }); }; + +export const handleFormFieldBlur = (e, data, setData) => { + const name = e.target.name; + const value = e.target.value; + + const newData = data; + const index = newData.findIndex((o) => o.name === name); + + if (value === "") { + newData[index].error = true; + newData[index].error_msg = "required"; + } else { + newData[index].error = false; + } + + setData(newData); +}; diff --git a/client/src/components/form/ManageTicketForm/userView.js b/client/src/components/form/ManageTicketForm/userView.js index 2cff176..4dd45e1 100644 --- a/client/src/components/form/ManageTicketForm/userView.js +++ b/client/src/components/form/ManageTicketForm/userView.js @@ -49,9 +49,10 @@ export const UserView = ({ data, setData }, ...props) => { /> - o.name === "department")} handleChange={(e) => handleFormFieldChange(e, data, setData)} handleBlur={(e) => handleFormFieldBlur(e, data, setData)} /> @@ -84,7 +85,7 @@ export const UserView = ({ data, setData }, ...props) => { o.name === "priority")} handleChange={(e) => handleFormFieldChange(e, data, setData)} handleBlur={(e) => handleFormFieldBlur(e, data, setData)} /> @@ -134,7 +135,9 @@ export const UserView = ({ data, setData }, ...props) => { name={"problem_category"} data={data} handleChange={(e) => handleFormFieldChange(e, data, setData)} - selectOptions={selectOptions} + selectOptions={selectOptions.find( + (o) => o.name === "problem_category" + )} handleBlur={(e) => handleFormFieldBlur(e, data, setData)} /> diff --git a/client/src/components/form/selectOptions.js b/client/src/components/form/selectOptions.js index 1179135..f26e365 100644 --- a/client/src/components/form/selectOptions.js +++ b/client/src/components/form/selectOptions.js @@ -17,9 +17,236 @@ export const selectOptions = [ { name: "department", options: [ - { value: "computer_science", text: "Computer Science" }, - { value: "petroleum_engineering", text: "Petroleum Engineering" }, - { value: "chemical_engineering", text: "Chemical Engineering" }, + { value: "accounting", text: "Accounting" }, + { + value: "administrative_foundation_se", + text: "Administrative_Foundation_Se", + }, + { value: "aerospace_studies", text: "Aerospace_Studies" }, + { + value: "african_african-american_stu", + text: "African_African-American_Stu", + }, + { value: "agric_education", text: "Agric_Education" }, + { + value: "agric_extension_ed_evaluat", + text: "Agric_Extension_Ed_Evaluat", + }, + { value: "agricultural_economics", text: "Agricultural_Economics" }, + { + value: "agricultural_economics_agrib", + text: "Agricultural_Economics_Agrib", + }, + { value: "agriculture", text: "Agriculture" }, + { + value: "agri,_extension_adult_educat", + text: "Agri,_Extension_Adult_Educat", + }, + { value: "agronomy", text: "Agronomy" }, + { value: "animal_sciences", text: "Animal_Sciences" }, + { value: "anthropology", text: "Anthropology" }, + { value: "arabic", text: "Arabic" }, + { value: "architecture", text: "Architecture" }, + { value: "art", text: "Art" }, + { value: "art_history", text: "Art_History" }, + { value: "astronomy", text: "Astronomy" }, + { value: "athletic_training", text: "Athletic_Training" }, + { value: "audio-visual_arts", text: "Audio-Visual_Arts" }, + { value: "basic_sciences", text: "Basic_Sciences" }, + { value: "biological_engineering", text: "Biological_Engineering" }, + { value: "biological_sciences", text: "Biological_Sciences" }, + { value: "business_administration", text: "Business_Administration" }, + { value: "business_education", text: "Business_Education" }, + { value: "business_law", text: "Business_Law" }, + { value: "chemical_engineering", text: "Chemical_Engineering" }, + { value: "chemistry", text: "Chemistry" }, + { value: "child_and_family_studies", text: "Child_And_Family_Studies" }, + { value: "chinese", text: "Chinese" }, + { value: "civil_engineering", text: "Civil_Engineering" }, + { + value: "civil_environmental_engineer", + text: "Civil_Environmental_Engineer", + }, + { value: "classical_studies", text: "Classical_Studies" }, + { value: "communication_disorders", text: "Communication_Disorders" }, + { value: "communication_studies", text: "Communication_Studies" }, + { + value: "comparative_biomedical_science", + text: "Comparative_Biomedical_Science", + }, + { value: "comparative_literature", text: "Comparative_Literature" }, + { value: "computer_science", text: "Computer_Science" }, + { value: "construction_management", text: "Construction_Management" }, + { value: "curriculum_instruction", text: "Curriculum_Instruction" }, + { value: "dairy_science", text: "Dairy_Science" }, + { + value: "digital_media_arts_engineeri", + text: "Digital_Media_Arts_Engineeri", + }, + { + value: "disaster_science_management", + text: "Disaster_Science_Management", + }, + { value: "doctor_of_design", text: "Doctor_Of_Design" }, + { value: "economics", text: "Economics" }, + { + value: "educ_leadership_research_couns", + text: "Educ_Leadership_Research_Couns", + }, + { value: "education", text: "Education" }, + { value: "electrical_engineering", text: "Electrical_Engineering" }, + { value: "engineering", text: "Engineering" }, + { value: "english", text: "English" }, + { value: "entomology", text: "Entomology" }, + { value: "entrepreneurship", text: "Entrepreneurship" }, + { value: "environmental_engineering", text: "Environmental_Engineering" }, + { + value: "environmental_management_systems", + text: "Environmental_Management_Systems", + }, + { value: "environmental_sciences", text: "Environmental_Sciences" }, + { value: "environmental_studies", text: "Environmental_Studies" }, + { + value: "epidemiology_community_health", + text: "Epidemiology_Community_Health", + }, + { value: "experimental_statistics", text: "Experimental_Statistics" }, + { value: "extension_education", text: "Extension_Education" }, + { value: "film_media_arts", text: "Film_Media_Arts" }, + { value: "finance", text: "Finance" }, + { value: "fisheries", text: "Fisheries" }, + { value: "food_science", text: "Food_Science" }, + { value: "forestry", text: "Forestry" }, + { value: "french", text: "French" }, + { value: "french_studies", text: "French_Studies" }, + { value: "freshman_forum", text: "Freshman_Forum" }, + { value: "freshman_seminar", text: "Freshman_Seminar" }, + { value: "general_business", text: "General_Business" }, + { value: "geography", text: "Geography" }, + { value: "geology", text: "Geology" }, + { value: "german", text: "German" }, + { value: "greek", text: "Greek" }, + { value: "hebrew", text: "Hebrew" }, + { value: "history", text: "History" }, + { value: "home_econ_educ", text: "Home_Econ_Educ" }, + { value: "honors", text: "Honors" }, + { value: "horticulture", text: "Horticulture" }, + { value: "how_to_do_lsu", text: "How_To_Do_Lsu" }, + { value: "human_ecology", text: "Human_Ecology" }, + { value: "human_resource_education", text: "Human_Resource_Education" }, + { value: "human_sciences_education", text: "Human_Sciences_Education" }, + { value: "humanities", text: "Humanities" }, + { + value: "humanities_and_social_sciences", + text: "Humanities_And_Social_Sciences", + }, + { value: "industrial_education", text: "Industrial_Education" }, + { value: "industrial_engineering", text: "Industrial_Engineering" }, + { value: "industrial_technology", text: "Industrial_Technology" }, + { + value: "industrial_manufacture_engineering", + text: "Industrial_Manufacture_Engineering", + }, + { + value: "info_systems_and_decision_science", + text: "Info_Systems_And_Decision_Science", + }, + { value: "interior_design", text: "Interior_Design" }, + { value: "international_studies", text: "International_Studies" }, + { value: "italian", text: "Italian" }, + { value: "japanese", text: "Japanese" }, + { value: "junior_division", text: "Junior_Division" }, + { value: "kinesiology", text: "Kinesiology" }, + { value: "landscape_architecture", text: "Landscape_Architecture" }, + { value: "latin", text: "Latin" }, + { + value: "leadership_human_resources_d", + text: "Leadership_Human_Resources_D", + }, + { value: "liberal_arts", text: "Liberal_Arts" }, + { + value: "library_information_science", + text: "Library_Information_Science", + }, + { value: "life_course_and_aging", text: "Life_Course_And_Aging" }, + { value: "life_course_in_aging", text: "Life_Course_In_Aging" }, + { value: "linguistics", text: "Linguistics" }, + { value: "management", text: "Management" }, + { value: "marketing", text: "Marketing" }, + { value: "mass_communication", text: "Mass_Communication" }, + { value: "mathematics", text: "Mathematics" }, + { value: "mechanical_engineering", text: "Mechanical_Engineering" }, + { value: "medical_physics", text: "Medical_Physics" }, + { value: "military_science", text: "Military_Science" }, + { value: "music", text: "Music" }, + { value: "music_education", text: "Music_Education" }, + { value: "nuclear_science", text: "Nuclear_Science" }, + { value: "nutrition_food_sciences", text: "Nutrition_Food_Sciences" }, + { + value: "oceanography_coastal_science", + text: "Oceanography_Coastal_Science", + }, + { value: "pathobiological_sciences", text: "Pathobiological_Sciences" }, + { value: "petroleum_engineering", text: "Petroleum_Engineering" }, + { value: "philosophy", text: "Philosophy" }, + { + value: "philosophy_religious_studies", + text: "Philosophy_Religious_Studies", + }, + { value: "physical_science", text: "Physical_Science" }, + { value: "physics", text: "Physics" }, + { value: "plant_health", text: "Plant_Health" }, + { value: "political_science", text: "Political_Science" }, + { value: "portuguese", text: "Portuguese" }, + { value: "poultry_science", text: "Poultry_Science" }, + { value: "psychology", text: "Psychology" }, + { value: "public_administration", text: "Public_Administration" }, + { value: "religious_studies", text: "Religious_Studies" }, + { + value: "renewable_natural_resources", + text: "Renewable_Natural_Resources", + }, + { value: "russian", text: "Russian" }, + { value: "science", text: "Science" }, + { value: "screen_arts", text: "Screen_Arts" }, + { value: "social_work", text: "Social_Work" }, + { value: "sociology", text: "Sociology" }, + { value: "spanish", text: "Spanish" }, + { value: "speech_communication", text: "Speech_Communication" }, + { value: "student_support_services", text: "Student_Support_Services" }, + { value: "swahili", text: "Swahili" }, + { value: "systems_science", text: "Systems_Science" }, + { + value: "textiles,apparel_merchandise", + text: "Textiles,Apparel_Merchandise", + }, + { value: "theatre", text: "Theatre" }, + { value: "university", text: "University" }, + { value: "university_college", text: "University_College" }, + { value: "university_studies", text: "University_Studies" }, + { value: "veterinary_anatomy", text: "Veterinary_Anatomy" }, + { + value: "veterinary_clinical_sciences", + text: "Veterinary_Clinical_Sciences", + }, + { value: "veterinary_medicine", text: "Veterinary_Medicine" }, + { + value: "veterinary_microbiol_parasit", + text: "Veterinary_Microbiol_Parasit", + }, + { value: "veterinary_pathology", text: "Veterinary_Pathology" }, + { + value: "veterinary_physiol,_pharmacy", + text: "VeterinaryPhysiol Pharmacy", + }, + { value: "veterinary_science", text: "Veterinary Science" }, + { value: "vocational_education", text: "Vocational Education" }, + { value: "vocational_trade_ind_ed", text: "Vocational Trade Ind Ed" }, + { value: "wildlife", text: "Wildlife" }, + { + value: "women's_and_gender_studies", + text: "Women'S_And_Gender_Studies", + }, ], }, { diff --git a/client/src/routes/admin/ManageTicket.js b/client/src/routes/admin/ManageTicket.js index a55cfcd..43a9611 100644 --- a/client/src/routes/admin/ManageTicket.js +++ b/client/src/routes/admin/ManageTicket.js @@ -34,14 +34,15 @@ import { MyStat } from "./Stats"; var _ = require("lodash"); -const TicketForm = ({ selected, data, setData }, ...props) => { +const TicketForm = ({ selected }, ...props) => { const [workLogData, setWorkLogData] = useState(null); const [workLogLoading, setWorkLogLoading] = useState(true); + const [data, setData] = useState(fields); useEffect(() => { const fetchWorkLog = async () => { try { - const result = await axios.get("/work"); + const result = await axios.get("/ticket/work/" + selected.id); setWorkLogData(result.data); setWorkLogLoading(false); } catch (error) { @@ -59,18 +60,7 @@ const TicketForm = ({ selected, data, setData }, ...props) => { }; fetchData(); fetchWorkLog(); - }, []); - - useEffect(() => { - const d = []; - - let keys; - keys = Object.keys(data); - for (let x in keys) { - d.push({ label: x, value: keys[x] }); - } - setData(d); - }, [data]); + }, [selected]); return ( <> diff --git a/client/src/routes/admin/SelectTechnician.js b/client/src/routes/admin/SelectTechnician.js index b441898..9cf44ef 100644 --- a/client/src/routes/admin/SelectTechnician.js +++ b/client/src/routes/admin/SelectTechnician.js @@ -15,8 +15,11 @@ import { } from "@elastic/eui"; import { MySelectField } from "../../components/form/MySelectField"; import { + handleDateChangeDispatch, handleFormFieldBlur, + handleFormFieldBlurDispatch, handleFormFieldChange, + handleFormFieldChangeDispatch, } from "../../components/form/ManageTicketForm/handlers"; import { NewTechnicianFlyout } from "./NewTechnicianFlyout"; import { Debug } from "../../components/debug/debug"; @@ -26,10 +29,11 @@ import { } from "../../components/form/ManageTechnicianForm/fields"; import axios from "../../api/api.js"; import { dataFetchReducer } from "../../api/reducers"; +import { addToast } from "../../components/toast"; var _ = require("lodash"); -export const SelectTechnician = ({ setTechnician }, ...props) => { +export const SelectTechnician = ({ technician, setTechnician }, ...props) => { const [isFlyoutVisible, setIsFlyoutVisible] = useState(false); const [state, dispatch] = useReducer(dataFetchReducer, { @@ -62,10 +66,18 @@ export const SelectTechnician = ({ setTechnician }, ...props) => { }, []); const handleFormSubmit = (e, data) => { + e.preventDefault(); const errors = _.find(data, ["error", true]); if (errors === undefined) { - console.log(data); - setTechnician(data); + if (data[0].value === "") { + addToast({ + title: "Select technician to continue", + color: "danger", + }); + } else { + console.log(data); + setTechnician(data); + } } }; @@ -87,11 +99,11 @@ export const SelectTechnician = ({ setTechnician }, ...props) => { name={"technician"} data={state.data} selectOptions={state.selectTechnicianOptions} - handleChange={(e) => - handleFormFieldChange(e, state.data, dispatch) - } + handleChange={(e) => { + handleFormFieldChangeDispatch(e, state.data, dispatch); + }} handleBlur={(e) => - handleFormFieldBlur(e, state.data, dispatch) + handleFormFieldBlurDispatch(e, state.data, dispatch) } /> diff --git a/client/src/routes/admin/admin.js b/client/src/routes/admin/admin.js index 99f6a1f..c46b9cb 100644 --- a/client/src/routes/admin/admin.js +++ b/client/src/routes/admin/admin.js @@ -43,7 +43,10 @@ export const AdminRoute = (props) => {
{technician === false ? ( - + ) : ( )} From d5b31c548959c1fc5aa9a889b5de7df4a608a53a Mon Sep 17 00:00:00 2001 From: Christian Dalton Date: Sat, 28 Nov 2020 11:24:30 -0600 Subject: [PATCH 13/17] ticket table updated --- client/src/components/table/TicketsTable.js | 17 ++++++++++++++++- client/src/routes/admin/ManageTicket.js | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/client/src/components/table/TicketsTable.js b/client/src/components/table/TicketsTable.js index 0106e33..b5c78cd 100644 --- a/client/src/components/table/TicketsTable.js +++ b/client/src/components/table/TicketsTable.js @@ -43,7 +43,7 @@ export const TicketsTable = ( }, }, { - field: "lastName", + field: "last_name", name: "Last Name", truncateText: true, }, @@ -58,6 +58,21 @@ export const TicketsTable = ( { field: "status", name: "Status", + render: (status) => { + const color = + status === "OPEN" + ? "danger" + : status === "IN PROGRESS" + ? "primary" + : "success"; + const label = + status === "OPEN" + ? "Open" + : status === "IN PROGRESS" + ? "In Progress" + : "Closed"; + return {label}; + }, }, ]; diff --git a/client/src/routes/admin/ManageTicket.js b/client/src/routes/admin/ManageTicket.js index 43a9611..df92c8e 100644 --- a/client/src/routes/admin/ManageTicket.js +++ b/client/src/routes/admin/ManageTicket.js @@ -164,7 +164,7 @@ export const ManageTicket = (props) => {

{selectedTicket === null ? "Create New Ticket" - : "Edit " + selectedTicket.lsu_id + "'s Ticket"} + : "Edit " + selectedTicket.first_name + "'s Ticket"}

From 8057b85b118dbf044657dc2db9f6efd0badb8488 Mon Sep 17 00:00:00 2001 From: Christian Dalton Date: Sat, 28 Nov 2020 12:41:57 -0600 Subject: [PATCH 14/17] back to reducers... user ticket post working --- client/src/api/reducers.js | 14 ++++- .../form/ManageTicketForm/handlers.js | 48 +++-------------- .../form/ManageTicketForm/userView.js | 54 +++++++++---------- client/src/components/form/selectOptions.js | 9 ++-- .../src/routes/admin/NewTechnicianFlyout.js | 2 +- client/src/routes/admin/SelectTechnician.js | 8 ++- client/src/routes/user/user.js | 22 ++++++-- 7 files changed, 72 insertions(+), 85 deletions(-) diff --git a/client/src/api/reducers.js b/client/src/api/reducers.js index 10d49e5..0f9d8ea 100644 --- a/client/src/api/reducers.js +++ b/client/src/api/reducers.js @@ -1,14 +1,24 @@ -import { workLogFields } from "../components/form/ManageTicketForm/fields"; +import { + fields, + workLogFields, +} from "../components/form/ManageTicketForm/fields"; export const dataFetchReducer = (state, action) => { switch (action.type) { + case "CLEAR_FORM": + const newData = state.data; + newData.map((o) => (o.value = "")); + return { + ...state, + data: newData, + }; case "FETCH_INIT": return { ...state, isLoading: true, isError: false, allTickets: {}, - workLogData: { ...workLogFields }, + data: fields, }; case "FETCH_SUCCESS": return { diff --git a/client/src/components/form/ManageTicketForm/handlers.js b/client/src/components/form/ManageTicketForm/handlers.js index 5765f2d..49aa420 100644 --- a/client/src/components/form/ManageTicketForm/handlers.js +++ b/client/src/components/form/ManageTicketForm/handlers.js @@ -8,17 +8,18 @@ const postData = async (endpoint, data) => { return response; }; -export const handleFormSubmit = (e, data) => { +export const handleFormSubmit = async (e, data, endpoint) => { const errors = _.find(data, ["error", true]); if (errors === undefined) { let d = data.map((o) => ({ [o.name]: o.value })); const dd = Object.assign({}, ...d); - const response = postData("/user", dd); + const response = await postData(endpoint, dd); addToast({ title: "Ticket Submitted!", color: "success", }); + return response; } else { addToast({ @@ -30,19 +31,7 @@ export const handleFormSubmit = (e, data) => { } }; -export const handleFormFieldChange = (e, data, setData) => { - const target = e.target; - const value = target.value; - const name = target.name; - - const newData = data; - const index = newData.findIndex((o) => o.name === name); - - newData[index].value = value; - setData(newData); -}; - -export const handleFormFieldChangeDispatch = (e, data, dispatch) => { +export const handleFormFieldChange = (e, data, dispatch) => { const target = e.target; const value = target.value; const name = target.name; @@ -54,15 +43,7 @@ export const handleFormFieldChangeDispatch = (e, data, dispatch) => { dispatch({ type: "UPDATE_DATA", payload: newData }); }; -export const handleDateChange = (date, name, data, dispatch) => { - const newData = data; - const index = newData.findIndex((o) => o.name === name); - - newData[index].value = date.toJSON(); - dispatch({ type: "UPDATE_DATA", payload: newData }); -}; - -export const handleDateChangeDispatch = (date, name, data, setData) => { +export const handleDateChange = (date, name, data, setData) => { const newData = data; const index = newData.findIndex((o) => o.name === name); @@ -70,7 +51,7 @@ export const handleDateChangeDispatch = (date, name, data, setData) => { setData(newData); }; -export const handleFormFieldBlurDispatch = (e, data, dispatch) => { +export const handleFormFieldBlur = (e, data, dispatch) => { const name = e.target.name; const value = e.target.value; @@ -86,20 +67,3 @@ export const handleFormFieldBlurDispatch = (e, data, dispatch) => { dispatch({ type: "UPDATE_DATA", payload: newData }); }; - -export const handleFormFieldBlur = (e, data, setData) => { - const name = e.target.name; - const value = e.target.value; - - const newData = data; - const index = newData.findIndex((o) => o.name === name); - - if (value === "") { - newData[index].error = true; - newData[index].error_msg = "required"; - } else { - newData[index].error = false; - } - - setData(newData); -}; diff --git a/client/src/components/form/ManageTicketForm/userView.js b/client/src/components/form/ManageTicketForm/userView.js index 4dd45e1..f424f45 100644 --- a/client/src/components/form/ManageTicketForm/userView.js +++ b/client/src/components/form/ManageTicketForm/userView.js @@ -20,7 +20,7 @@ import { selectOptions } from "../selectOptions"; var _ = require("lodash"); -export const UserView = ({ data, setData }, ...props) => { +export const UserView = ({ data, dispatch }, ...props) => { return ( <> @@ -28,24 +28,24 @@ export const UserView = ({ data, setData }, ...props) => { handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> @@ -53,8 +53,8 @@ export const UserView = ({ data, setData }, ...props) => { name={"department"} data={data} selectOptions={selectOptions.find((o) => o.name === "department")} - handleChange={(e) => handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> @@ -63,16 +63,16 @@ export const UserView = ({ data, setData }, ...props) => { handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> @@ -86,8 +86,8 @@ export const UserView = ({ data, setData }, ...props) => { name={"priority"} data={data} selectOptions={selectOptions.find((o) => o.name === "priority")} - handleChange={(e) => handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> @@ -96,32 +96,32 @@ export const UserView = ({ data, setData }, ...props) => { handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> handleFormFieldChange(e, data, setData)} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> @@ -134,11 +134,11 @@ export const UserView = ({ data, setData }, ...props) => { handleFormFieldChange(e, data, setData)} + handleChange={(e) => handleFormFieldChange(e, data, dispatch)} selectOptions={selectOptions.find( (o) => o.name === "problem_category" )} - handleBlur={(e) => handleFormFieldBlur(e, data, setData)} + handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> @@ -157,8 +157,8 @@ export const UserView = ({ data, setData }, ...props) => { handleFormFieldChange(e, data, setData)} - onBlur={(e) => handleFormFieldBlur(e, data, setData)} + onChange={(e) => handleFormFieldChange(e, data, dispatch)} + onBlur={(e) => handleFormFieldBlur(e, data, dispatch)} /> diff --git a/client/src/components/form/selectOptions.js b/client/src/components/form/selectOptions.js index f26e365..172bce9 100644 --- a/client/src/components/form/selectOptions.js +++ b/client/src/components/form/selectOptions.js @@ -2,14 +2,16 @@ export const selectOptions = [ { name: "priority", options: [ - { value: "low", text: "Low" }, - { value: "medium", text: "Medium" }, - { value: "high", text: "High" }, + { value: "", text: "" }, + { value: "1", text: "Low" }, + { value: "2", text: "Medium" }, + { value: "3", text: "High" }, ], }, { name: "problem_category", options: [ + { value: "", text: "" }, { value: "general_help", text: "General Help" }, { value: "problem_2", text: "Problem 2" }, ], @@ -17,6 +19,7 @@ export const selectOptions = [ { name: "department", options: [ + { value: "", text: "" }, { value: "accounting", text: "Accounting" }, { value: "administrative_foundation_se", diff --git a/client/src/routes/admin/NewTechnicianFlyout.js b/client/src/routes/admin/NewTechnicianFlyout.js index eed746e..72e0b8d 100644 --- a/client/src/routes/admin/NewTechnicianFlyout.js +++ b/client/src/routes/admin/NewTechnicianFlyout.js @@ -33,7 +33,7 @@ export const NewTechnicianFlyout = ( const showFlyout = () => setIsFlyoutVisible(true); const localFormSubmit = (e, data) => { - if (handleFormSubmit(e, data) != null) { + if (handleFormSubmit(e, data, "/user") != null) { setIsFlyoutVisible(false); } }; diff --git a/client/src/routes/admin/SelectTechnician.js b/client/src/routes/admin/SelectTechnician.js index 9cf44ef..a7e8ac7 100644 --- a/client/src/routes/admin/SelectTechnician.js +++ b/client/src/routes/admin/SelectTechnician.js @@ -15,11 +15,9 @@ import { } from "@elastic/eui"; import { MySelectField } from "../../components/form/MySelectField"; import { - handleDateChangeDispatch, + handleDateChange, handleFormFieldBlur, - handleFormFieldBlurDispatch, handleFormFieldChange, - handleFormFieldChangeDispatch, } from "../../components/form/ManageTicketForm/handlers"; import { NewTechnicianFlyout } from "./NewTechnicianFlyout"; import { Debug } from "../../components/debug/debug"; @@ -100,10 +98,10 @@ export const SelectTechnician = ({ technician, setTechnician }, ...props) => { data={state.data} selectOptions={state.selectTechnicianOptions} handleChange={(e) => { - handleFormFieldChangeDispatch(e, state.data, dispatch); + handleFormFieldChange(e, state.data, dispatch); }} handleBlur={(e) => - handleFormFieldBlurDispatch(e, state.data, dispatch) + handleFormFieldBlur(e, state.data, dispatch) } /> diff --git a/client/src/routes/user/user.js b/client/src/routes/user/user.js index 220b3a5..f7b6a65 100644 --- a/client/src/routes/user/user.js +++ b/client/src/routes/user/user.js @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useEffect, useReducer, useState } from "react"; import { EuiPage, @@ -31,12 +31,24 @@ import { UserView } from "../../components/form/ManageTicketForm/userView"; import { fields } from "../../components/form/ManageTicketForm/fields"; import { handleFormSubmit } from "../../components/form/ManageTicketForm/handlers"; import { Debug } from "../../components/debug/debug"; +import { dataFetchReducer } from "../../api/reducers"; +import { selectTechnicianOptions_default } from "../../components/form/ManageTechnicianForm/fields"; var _ = require("lodash"); export const UserRoute = (props) => { - const [data, setData] = useState(fields); + const [state, dispatch] = useReducer(dataFetchReducer, { + isLoading: false, + isError: false, + data: fields, + }); + const internalFormSubmit = async (e, data) => { + const response = await handleFormSubmit(e, data, "/ticket"); + if (response.status === 201) { + dispatch({ type: "CLEAR_FORM" }); + } + }; return ( <> @@ -55,20 +67,20 @@ export const UserRoute = (props) => {

My Information

- + handleFormSubmit(e, data)} + onClick={(e) => internalFormSubmit(e, state.data)} > Submit - + From ba875547dbb683e44db88b673da32d903b0f9c07 Mon Sep 17 00:00:00 2001 From: Christian Dalton Date: Sat, 28 Nov 2020 14:07:31 -0600 Subject: [PATCH 15/17] admin view retrieving data. no put request yet --- client/src/api/reducers.js | 17 ++- .../form/ManageTicketForm/adminView.js | 14 ++- .../form/ManageTicketForm/handlers.js | 16 ++- client/src/components/form/MyTextField.js | 1 + client/src/components/form/selectOptions.js | 19 ++- client/src/routes/admin/ManageTicket.js | 112 +++++++++++++++--- client/src/routes/admin/SelectTechnician.js | 1 - client/src/routes/admin/admin.js | 6 - 8 files changed, 143 insertions(+), 43 deletions(-) diff --git a/client/src/api/reducers.js b/client/src/api/reducers.js index 0f9d8ea..1ce533d 100644 --- a/client/src/api/reducers.js +++ b/client/src/api/reducers.js @@ -17,22 +17,14 @@ export const dataFetchReducer = (state, action) => { ...state, isLoading: true, isError: false, - allTickets: {}, - data: fields, }; - case "FETCH_SUCCESS": + case "FETCH_TICKET_SUCCESS": return { ...state, isLoading: false, isError: false, data: action.payload, }; - case "FETCH_ALL_TICKETS_SUCCESS": - return { - ...state, - isTicketsLoading: false, - isError: false, - }; case "FETCH_TECHNICIANS_SUCCESS": return { ...state, @@ -55,6 +47,13 @@ export const dataFetchReducer = (state, action) => { return { ...state, workLogData: action.payload, + workLogLoading: false, + }; + case "FETCH_ASSIGN_LOG_SUCCESS": + return { + ...state, + assignLog: action.payload, + assignLogLoading: false, }; default: throw new Error(); diff --git a/client/src/components/form/ManageTicketForm/adminView.js b/client/src/components/form/ManageTicketForm/adminView.js index b28bda9..5fa7f01 100644 --- a/client/src/components/form/ManageTicketForm/adminView.js +++ b/client/src/components/form/ManageTicketForm/adminView.js @@ -29,7 +29,10 @@ import { TimeLogTable } from "../../table/TimeLogTable"; var _ = require("lodash"); -export const AdminView = ({ data, dispatch, workLogData }, ...props) => { +export const AdminView = ( + { data, dispatch, workLogData, assignLogData }, + ...props +) => { return ( <> @@ -93,9 +96,10 @@ export const AdminView = ({ data, dispatch, workLogData }, ...props) => { <> - - - + {/* TODO: WAITING ON BACKEND*/} + {/**/} + {/**/} + {/**/} @@ -109,7 +113,7 @@ export const AdminView = ({ data, dispatch, workLogData }, ...props) => { - + {/* TODO: WAITING ON BACKEND*/} {/**/} {/* */} {/* */} diff --git a/client/src/components/form/ManageTicketForm/handlers.js b/client/src/components/form/ManageTicketForm/handlers.js index 49aa420..141d7f8 100644 --- a/client/src/components/form/ManageTicketForm/handlers.js +++ b/client/src/components/form/ManageTicketForm/handlers.js @@ -8,13 +8,25 @@ const postData = async (endpoint, data) => { return response; }; -export const handleFormSubmit = async (e, data, endpoint) => { +const putData = async (endpoint, data) => { + console.log(data); + const response = await axios.put(endpoint, data); + return response; +}; + +export const handleFormSubmit = async (e, data, endpoint, put) => { const errors = _.find(data, ["error", true]); if (errors === undefined) { let d = data.map((o) => ({ [o.name]: o.value })); const dd = Object.assign({}, ...d); - const response = await postData(endpoint, dd); + let response; + if (put === true) { + response = await putData(endpoint, dd); + } else { + response = await postData(endpoint, dd); + } + addToast({ title: "Ticket Submitted!", color: "success", diff --git a/client/src/components/form/MyTextField.js b/client/src/components/form/MyTextField.js index c4f2e32..497ee27 100644 --- a/client/src/components/form/MyTextField.js +++ b/client/src/components/form/MyTextField.js @@ -20,6 +20,7 @@ export const MyTextField = ( name={item.name} onChange={(e) => handleChange(e)} onBlur={(e) => handleBlur(e)} + value={item.value} /> ); diff --git a/client/src/components/form/selectOptions.js b/client/src/components/form/selectOptions.js index 172bce9..2ffe608 100644 --- a/client/src/components/form/selectOptions.js +++ b/client/src/components/form/selectOptions.js @@ -12,8 +12,16 @@ export const selectOptions = [ name: "problem_category", options: [ { value: "", text: "" }, + { value: "general_help", text: "General Help" }, - { value: "problem_2", text: "Problem 2" }, + { value: "login_help", text: "Login Help" }, + { value: "missing_documents", text: "Missing Documents" }, + { value: "class_access", text: "Can't access your class?" }, + { value: "view_grades_help", text: "Can't see your grades?" }, + { value: "upload_help", text: "Upload Help" }, + { value: "download_help", text: "Download Help" }, + { value: "tigerware_support", text: "Tigerware support" }, + { value: "hardware_support", text: "Hardware support" }, ], }, { @@ -258,6 +266,11 @@ export const selectOptions = [ { value: "broken_screen", text: "Broken Screen" }, { value: "expanded_battery", text: "Expanded Battery" }, { value: "faulty_ram", text: "Faulty RAM" }, + { value: "network_problem", text: "Network Problem" }, + { value: "post_error", text: "Post Error" }, + { value: "virus_infection", text: "Malware or Spyware Infection" }, + { value: "system_overheat", text: "System overheating" }, + { value: "system_crash", text: "System Crash" }, ], }, { @@ -269,6 +282,10 @@ export const selectOptions = [ { value: "storage_device", text: "Storage Device" }, { value: "power_supply", text: "Power Supply" }, { value: "gpu", text: "GPU" }, + { value: "motherboard", text: "Motherboard" }, + { value: "heatsink", text: "Heatsink" }, + { value: "case_fans", text: "Case Fans" }, + { value: "usb_port", text: "USB Port" }, ], }, { diff --git a/client/src/routes/admin/ManageTicket.js b/client/src/routes/admin/ManageTicket.js index df92c8e..e64818a 100644 --- a/client/src/routes/admin/ManageTicket.js +++ b/client/src/routes/admin/ManageTicket.js @@ -31,58 +31,129 @@ import axios from "../../api/api"; import { fields } from "../../components/form/ManageTicketForm/fields"; import { dataFetchReducer } from "../../api/reducers"; import { MyStat } from "./Stats"; +import { personFields } from "../../components/form/person/fields"; var _ = require("lodash"); -const TicketForm = ({ selected }, ...props) => { - const [workLogData, setWorkLogData] = useState(null); - const [workLogLoading, setWorkLogLoading] = useState(true); - const [data, setData] = useState(fields); +const TicketForm = ({ setSelectedTicket, selectedTicket }, ...props) => { + const [state, dispatch] = useReducer(dataFetchReducer, { + isLoading: false, + isError: false, + data: fields, + workLogData: null, + workLogLoading: true, + assignLog: null, + assignLogLoading: true, + }); useEffect(() => { - const fetchWorkLog = async () => { + const fetchWorkLog = async (selectedTicket) => { try { - const result = await axios.get("/ticket/work/" + selected.id); - setWorkLogData(result.data); - setWorkLogLoading(false); + const result = await axios.get( + "/ticket/work/" + selectedTicket.ticket_id + ); + dispatch({ type: "FETCH_WORK_LOG_SUCCESS", payload: result.data }); } catch (error) { console.log(error); } }; - const fetchData = () => { + const fetchAssignLog = async (selectedTicket) => { try { - const ticketFields = axios.get("/ticket/" + selected.id); - const userFields = axios.get("/user/" + selected.lsu_id); + const result = await axios.get( + "/ticket/assign/" + selectedTicket.ticket_id + ); + dispatch({ type: "FETCH_ASSIGN_LOG_SUCCESS", payload: result.data }); } catch (error) { console.log(error); } }; - fetchData(); - fetchWorkLog(); - }, [selected]); + const fetchData = async (selectedTicket) => { + String.prototype.toProperCase = function () { + return this.replace(/\w\S*/g, function (txt) { + return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); + }); + }; + + try { + const result = await axios.get("/ticket/" + selectedTicket.ticket_id); + const userResult = await axios.get("/user/" + selectedTicket.lsu_id); + let final = []; + for (const [key, value] of Object.entries(result.data)) { + console.log(`${key}: ${value}`); + final.push({ + name: key, + value: value, + error: false, + error_type: "none", + label: key.replace("_", " ").toProperCase(), + }); + } + + for (const [key, value] of Object.entries(userResult.data)) { + console.log(`${key}: ${value}`); + final.push({ + name: key, + value: value, + error: false, + error_type: "none", + label: key.replace("_", " ").toProperCase(), + }); + } + const union = _.unionBy(final, fields, "name"); + dispatch({ + type: "FETCH_TICKET_SUCCESS", + payload: union, + }); + } catch (error) { + console.log(error); + } + }; + if (selectedTicket != null) { + fetchData(selectedTicket); + fetchWorkLog(selectedTicket); + fetchAssignLog(selectedTicket); + } + }, [selectedTicket]); + + const internalFormSubmit = async (e, data) => { + const response = await handleFormSubmit(e, data, "/ticket"); + if (response.status === 201) { + dispatch({ type: "CLEAR_FORM" }); + } + }; return ( <>

Customer Information

- - + {state.isLoading ? null : ( + <> + + + + )} + handleFormSubmit(e, data)} + onClick={(e) => internalFormSubmit(e, state.data)} > Submit
- + ); }; @@ -171,7 +242,10 @@ export const ManageTicket = (props) => { {selectedTicket == null ? ( "Please select ticket." ) : ( - + )}
diff --git a/client/src/routes/admin/SelectTechnician.js b/client/src/routes/admin/SelectTechnician.js index a7e8ac7..9182dd4 100644 --- a/client/src/routes/admin/SelectTechnician.js +++ b/client/src/routes/admin/SelectTechnician.js @@ -43,7 +43,6 @@ export const SelectTechnician = ({ technician, setTechnician }, ...props) => { useEffect(() => { const fetchData = async () => { - dispatch({ type: "FETCH_INIT" }); try { const result = await axios.get("/user/admin"); const final = { diff --git a/client/src/routes/admin/admin.js b/client/src/routes/admin/admin.js index c46b9cb..0388ff7 100644 --- a/client/src/routes/admin/admin.js +++ b/client/src/routes/admin/admin.js @@ -21,12 +21,6 @@ import { EuiCode, } from "@elastic/eui"; import { NavBar } from "../../components/navbar/navbar"; -import { TicketsTable } from "../../components/table/TicketsTable"; -import { AdminTicketFlyout } from "../../components/flyout/flyout"; -import { UserView } from "../../components/form/ManageTicketForm/userView"; -import { fields } from "../../components/form/ManageTicketForm/fields"; -import { handleFormSubmit } from "../../components/form/ManageTicketForm/handlers"; -import { AdminView } from "../../components/form/ManageTicketForm/adminView"; import { SelectTechnician } from "./SelectTechnician"; import { ManageTicket } from "./ManageTicket"; From e4086a8e856ac17d7a148687b9c7b34ba26930ca Mon Sep 17 00:00:00 2001 From: Christian Dalton Date: Sat, 28 Nov 2020 20:31:43 -0600 Subject: [PATCH 16/17] post from admin setup. assignment/work all that left --- .../form/ManageTicketForm/adminView.js | 19 +++++++---------- .../form/ManageTicketForm/userView.js | 1 + client/src/components/table/TicketsTable.js | 21 ++++++++----------- client/src/routes/admin/ManageTicket.js | 12 +---------- 4 files changed, 18 insertions(+), 35 deletions(-) diff --git a/client/src/components/form/ManageTicketForm/adminView.js b/client/src/components/form/ManageTicketForm/adminView.js index 5fa7f01..d6d8b24 100644 --- a/client/src/components/form/ManageTicketForm/adminView.js +++ b/client/src/components/form/ManageTicketForm/adminView.js @@ -11,10 +11,7 @@ import { EuiTitle, } from "@elastic/eui"; import React, { useState } from "react"; -import { MyTextField } from "../MyTextField"; import { MySelectField } from "../MySelectField"; -import { addToast } from "../../toast"; -import { DEBUG } from "../../app/app"; import { errorMessages } from "./fields"; import { handleDateChange, @@ -22,9 +19,6 @@ import { handleFormFieldChange, } from "./handlers"; import { selectOptions } from "../selectOptions"; -import { MyDatePicker } from "../MyDatePicker"; -import { TicketAssignmentTable } from "../../table/AssignedToTable"; -import { AddTechnicianPopover } from "../../popover/TechnicianPopover"; import { TimeLogTable } from "../../table/TimeLogTable"; var _ = require("lodash"); @@ -44,7 +38,7 @@ export const AdminView = ( o.name === "core_issue")} handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} handleChange={(e) => handleFormFieldChange(e, data, dispatch)} /> @@ -53,7 +47,7 @@ export const AdminView = ( o.name === "component")} handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} handleChange={(e) => handleFormFieldChange(e, data, dispatch)} /> @@ -67,20 +61,21 @@ export const AdminView = ( handleFormFieldChange(e, data, dispatch)} onBlur={(e) => handleFormFieldBlur(e, data, dispatch)} + value={_.find(data, ["name", "description"]).value} /> @@ -149,7 +144,7 @@ export const AdminView = ( handleFormFieldChange(e, data, dispatch)} handleBlur={(e) => handleFormFieldBlur(e, data, dispatch)} - selectOptions={selectOptions} + selectOptions={selectOptions.find((o) => o.name === "status")} data={data} name={"status"} /> diff --git a/client/src/components/form/ManageTicketForm/userView.js b/client/src/components/form/ManageTicketForm/userView.js index f424f45..9a5e884 100644 --- a/client/src/components/form/ManageTicketForm/userView.js +++ b/client/src/components/form/ManageTicketForm/userView.js @@ -159,6 +159,7 @@ export const UserView = ({ data, dispatch }, ...props) => { name={_.find(data, ["name", "description"]).name} onChange={(e) => handleFormFieldChange(e, data, dispatch)} onBlur={(e) => handleFormFieldBlur(e, data, dispatch)} + value={_.find(data, ["name", "description"]).value} /> diff --git a/client/src/components/table/TicketsTable.js b/client/src/components/table/TicketsTable.js index b5c78cd..f698741 100644 --- a/client/src/components/table/TicketsTable.js +++ b/client/src/components/table/TicketsTable.js @@ -5,18 +5,6 @@ import { AdminTicketFlyout } from "../flyout/flyout"; import { dataFetchReducer } from "../../api/reducers"; import { ErrorCallout } from "../callout/Callout"; -const userTest = [ - { - id: "1", - firstName: "john", - lastName: "doe", - github: "johndoe", - dateOfBirth: Date.now(), - nationality: "NL", - online: true, - }, -]; - export const TicketsTable = ( { handleTicketSelection, tickets, isLoading }, ...props @@ -54,6 +42,15 @@ export const TicketsTable = ( { field: "problem_category", name: "Problem Category", + render: (problem_category) => { + String.prototype.toProperCase = function () { + return this.replace(/\w\S*/g, function (txt) { + return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); + }); + }; + + return problem_category.replace("_", " ").toProperCase(); + }, }, { field: "status", diff --git a/client/src/routes/admin/ManageTicket.js b/client/src/routes/admin/ManageTicket.js index e64818a..bc9637b 100644 --- a/client/src/routes/admin/ManageTicket.js +++ b/client/src/routes/admin/ManageTicket.js @@ -77,8 +77,8 @@ const TicketForm = ({ setSelectedTicket, selectedTicket }, ...props) => { }; try { + dispatch({ type: "CLEAR_FORM" }); const result = await axios.get("/ticket/" + selectedTicket.ticket_id); - const userResult = await axios.get("/user/" + selectedTicket.lsu_id); let final = []; for (const [key, value] of Object.entries(result.data)) { console.log(`${key}: ${value}`); @@ -91,16 +91,6 @@ const TicketForm = ({ setSelectedTicket, selectedTicket }, ...props) => { }); } - for (const [key, value] of Object.entries(userResult.data)) { - console.log(`${key}: ${value}`); - final.push({ - name: key, - value: value, - error: false, - error_type: "none", - label: key.replace("_", " ").toProperCase(), - }); - } const union = _.unionBy(final, fields, "name"); dispatch({ type: "FETCH_TICKET_SUCCESS", From f8ca3dc81537ad8e8bb76351fb6abcc18c7f2303 Mon Sep 17 00:00:00 2001 From: Christian Dalton Date: Sun, 29 Nov 2020 13:09:25 -0600 Subject: [PATCH 17/17] mostly done --- client/src/api/reducers.js | 2 +- client/src/components/app/app.js | 2 +- .../form/ManageTechnicianForm/fields.js | 1 + .../form/ManageTicketForm/adminView.js | 122 ++++++++++++------ .../form/ManageTicketForm/handlers.js | 2 +- client/src/components/form/MySelectField.js | 2 +- .../components/popover/TechnicianPopover.js | 98 +++++++++----- ...nedToTable.js => TicketAssignmentTable.js} | 60 +++------ client/src/components/table/TicketsTable.js | 1 + .../{TimeLogTable.js => WorkLogTable.js} | 69 +++++----- client/src/routes/admin/ManageTicket.js | 64 +++++++-- .../src/routes/admin/NewTechnicianFlyout.js | 4 +- client/src/routes/admin/SelectTechnician.js | 2 +- client/src/routes/admin/Stats.js | 20 +-- client/src/routes/admin/admin.js | 2 +- client/src/routes/user/user.js | 3 +- 16 files changed, 272 insertions(+), 182 deletions(-) rename client/src/components/table/{AssignedToTable.js => TicketAssignmentTable.js} (55%) rename client/src/components/table/{TimeLogTable.js => WorkLogTable.js} (56%) diff --git a/client/src/api/reducers.js b/client/src/api/reducers.js index 1ce533d..410d99d 100644 --- a/client/src/api/reducers.js +++ b/client/src/api/reducers.js @@ -52,7 +52,7 @@ export const dataFetchReducer = (state, action) => { case "FETCH_ASSIGN_LOG_SUCCESS": return { ...state, - assignLog: action.payload, + assignLogData: action.payload, assignLogLoading: false, }; default: diff --git a/client/src/components/app/app.js b/client/src/components/app/app.js index 23685f5..8920956 100644 --- a/client/src/components/app/app.js +++ b/client/src/components/app/app.js @@ -10,4 +10,4 @@ export const App = () => { ); }; -export const DEBUG_ON = true; +export const DEBUG_ON = false; diff --git a/client/src/components/form/ManageTechnicianForm/fields.js b/client/src/components/form/ManageTechnicianForm/fields.js index 84f47c6..e810d15 100644 --- a/client/src/components/form/ManageTechnicianForm/fields.js +++ b/client/src/components/form/ManageTechnicianForm/fields.js @@ -4,6 +4,7 @@ export const selectTechnicianOptions_default = [ options: [{ value: "", text: "" }], }, ]; + export const fields = [ { name: "technician", diff --git a/client/src/components/form/ManageTicketForm/adminView.js b/client/src/components/form/ManageTicketForm/adminView.js index d6d8b24..ebbd4a8 100644 --- a/client/src/components/form/ManageTicketForm/adminView.js +++ b/client/src/components/form/ManageTicketForm/adminView.js @@ -12,21 +12,52 @@ import { } from "@elastic/eui"; import React, { useState } from "react"; import { MySelectField } from "../MySelectField"; -import { errorMessages } from "./fields"; +import { errorMessages, workLogFields } from "./fields"; import { handleDateChange, handleFormFieldBlur, handleFormFieldChange, + handleFormSubmit, } from "./handlers"; import { selectOptions } from "../selectOptions"; -import { TimeLogTable } from "../../table/TimeLogTable"; +import { WorkLogTable } from "../../table/WorkLogTable"; +import { TicketAssignmentTable } from "../../table/TicketAssignmentTable"; +import { AddTechnicianPopover } from "../../popover/TechnicianPopover"; +import { MyDatePicker } from "../MyDatePicker"; var _ = require("lodash"); export const AdminView = ( - { data, dispatch, workLogData, assignLogData }, + { + technician, + selectedTicket, + data, + dispatch, + workLogData, + workLogLoading, + assignLogData, + assignLogLoading, + assignmentRefresh, + setAssignmentRefresh, + workRefresh, + setWorkRefresh, + }, ...props ) => { + const internalFormSubmit = async (e, data) => { + const d = []; + d.push({ name: "start_datetime", value: data[0].value }); + d.push({ name: "end_datetime", value: data[1].value }); + d.push({ name: "ticket_id", value: selectedTicket.ticket_id }); + d.push({ name: "lsu_id", value: technician[0].value }); + + const response = await handleFormSubmit(e, d, "/work"); + if (response != null) { + const w = !workRefresh; + setWorkRefresh(w); + } + }; + const [timeData, setTimeData] = useState(workLogFields); return ( <> @@ -91,10 +122,20 @@ export const AdminView = ( <> - {/* TODO: WAITING ON BACKEND*/} - {/**/} - {/**/} - {/**/} + {assignLogLoading === true ? null : ( + <> + + + + + )} @@ -104,40 +145,43 @@ export const AdminView = (

Work Log

- - + + {workLogLoading === true ? null : ( + + )} + + + + + + + handleDateChange(date, "start_datetime", timeData, setTimeData) + } + /> + + + + + + handleDateChange(e, "end_datetime", timeData, setTimeData) + } + /> + + + + + internalFormSubmit(e, timeData)}> + Add Time Entry + + - {/* TODO: WAITING ON BACKEND*/} - {/**/} - {/* */} - {/* */} - {/* */} - {/* handleDateChange(date, "start_datetime", data, dispatch)*/} - {/* }*/} - {/* />*/} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* handleDateChange(e, "end_datetime", data, dispatch)*/} - {/* }*/} - {/* />*/} - {/* */} - {/* */} - {/* */} - {/* */} - {/* Add Time Entry*/} - {/* */} - {/* */} - {/**/} diff --git a/client/src/components/form/ManageTicketForm/handlers.js b/client/src/components/form/ManageTicketForm/handlers.js index 141d7f8..fa07521 100644 --- a/client/src/components/form/ManageTicketForm/handlers.js +++ b/client/src/components/form/ManageTicketForm/handlers.js @@ -28,7 +28,7 @@ export const handleFormSubmit = async (e, data, endpoint, put) => { } addToast({ - title: "Ticket Submitted!", + title: "Saved!", color: "success", }); diff --git a/client/src/components/form/MySelectField.js b/client/src/components/form/MySelectField.js index 96aa4af..0fc85e9 100644 --- a/client/src/components/form/MySelectField.js +++ b/client/src/components/form/MySelectField.js @@ -14,7 +14,7 @@ export const MySelectField = ( name={item.name} id={item.name} options={selectOptions.options} - value={item.value} + value={item.value === null ? "" : item.value} onChange={(e) => handleChange(e)} onBlur={(e) => handleBlur(e)} hasNoInitialSelection={true} diff --git a/client/src/components/popover/TechnicianPopover.js b/client/src/components/popover/TechnicianPopover.js index 0fb9e42..820b794 100644 --- a/client/src/components/popover/TechnicianPopover.js +++ b/client/src/components/popover/TechnicianPopover.js @@ -16,24 +16,37 @@ import { import { handleFormFieldBlur, handleFormFieldChange, + handleFormSubmit, } from "../form/ManageTicketForm/handlers"; import { dataFetchReducer } from "../../api/reducers"; import axios from "../../api/api"; +import { personFields } from "../form/person/fields"; -export const AddTechnicianPopover = () => { +export const AddTechnicianPopover = ( + { selectedTicket, assignmentRefresh, setAssignmentRefresh }, + ...props +) => { const [state, dispatch] = useReducer(dataFetchReducer, { isLoading: false, isError: false, - data: null, + data: fields, + selectTechnicianOptions: selectTechnicianOptions_default, }); - + const [isPopoverOpen, setIsPopoverOpen] = useState(false); useEffect(() => { const fetchData = async () => { dispatch({ type: "FETCH_INIT" }); - // TODO: ONCE BACKEND IS SET UP, FORMAT AND IMPLEMENT DATA FOR TABLE try { - const result = await axios.get("ticket"); - dispatch({ type: "FETCH_SUCCESS", payload: result.data }); + const result = await axios.get("/user/admin"); + const final = { + name: "technician", + options: result.data.map((o) => ({ + ...o, + value: o.lsu_id, + text: o.first_name + " " + o.last_name, + })), + }; + dispatch({ type: "FETCH_TECHNICIANS_SUCCESS", payload: final }); } catch (error) { dispatch({ type: "FETCH_FAILURE" }); } @@ -41,12 +54,21 @@ export const AddTechnicianPopover = () => { fetchData(); }, []); - const [isPopoverOpen, setIsPopoverOpen] = useState(false); - const onButtonClick = () => setIsPopoverOpen((isPopoverOpen) => !isPopoverOpen); const closePopover = () => setIsPopoverOpen(false); + const internalFormSubmit = async (e, data) => { + const d = []; + d.push({ name: "lsu_id", value: data[0].value }); + d.push({ name: "ticket_id", value: selectedTicket.ticket_id }); + + const response = await handleFormSubmit(e, d, "/assign"); + if (response != null) { + setIsPopoverOpen(false); + setAssignmentRefresh(!assignmentRefresh); + } + }; const button = ( Add @@ -54,31 +76,39 @@ export const AddTechnicianPopover = () => { ); return ( - -
- - - - handleFormFieldChange(e, state.data, dispatch) - } - handleBlur={(e) => handleFormFieldBlur(e, state.data, dispatch)} - /> - - - - Add - - - -
-
+ <> + {state.isLoading === true ? null : ( + + + + + { + handleFormFieldChange(e, state.data, dispatch); + }} + handleBlur={(e) => + handleFormFieldBlur(e, state.data, dispatch) + } + /> + + + + internalFormSubmit(e, state.data)}> + Add + + + + + + + )} + ); }; diff --git a/client/src/components/table/AssignedToTable.js b/client/src/components/table/TicketAssignmentTable.js similarity index 55% rename from client/src/components/table/AssignedToTable.js rename to client/src/components/table/TicketAssignmentTable.js index 48af5cb..cd5b103 100644 --- a/client/src/components/table/AssignedToTable.js +++ b/client/src/components/table/TicketAssignmentTable.js @@ -3,28 +3,7 @@ import React from "react"; import { EuiBasicTable, EuiLink, EuiHealth, EuiButton } from "@elastic/eui"; import { AdminTicketFlyout } from "../flyout/flyout"; -const userTest = [ - { - id: "1", - firstName: "john", - lastName: "doe", - }, -]; -/* -Example user object: - - - -Example country object: - -{ - code: 'NL', - name: 'Netherlands', - flag: '🇳🇱' -} -*/ - -export const TicketAssignmentTable = ({ handleTicketSelection }, ...props) => { +export const TicketAssignmentTable = ({ items, isLoading }, ...props) => { const deleteUser = (user) => {}; const actions = [ @@ -41,18 +20,12 @@ export const TicketAssignmentTable = ({ handleTicketSelection }, ...props) => { const columns = [ { - field: "firstName", + field: "first_name", name: "First Name", - sortable: true, - "data-test-subj": "firstNameCell", }, { - field: "lastName", + field: "last_name", name: "Last Name", - truncateText: true, - mobileOptions: { - show: false, - }, }, { name: "Actions", @@ -60,16 +33,14 @@ export const TicketAssignmentTable = ({ handleTicketSelection }, ...props) => { }, ]; - const items = userTest.filter((user, index) => index < 10); - const getRowProps = (item) => { const { id } = item; return { "data-test-subj": `row-${id}`, className: "customRowClass", - onClick: (e) => { - handleTicketSelection(e, id); - }, + // onClick: (e) => { + // handleTicketSelection(e, id); + // }, }; }; @@ -84,12 +55,17 @@ export const TicketAssignmentTable = ({ handleTicketSelection }, ...props) => { }; return ( - +
+ {isLoading === true ? null : ( + + )} +
); }; diff --git a/client/src/components/table/TicketsTable.js b/client/src/components/table/TicketsTable.js index f698741..35aa608 100644 --- a/client/src/components/table/TicketsTable.js +++ b/client/src/components/table/TicketsTable.js @@ -103,6 +103,7 @@ export const TicketsTable = ( columns={columns} rowProps={getRowProps} cellProps={getCellProps} + tableLayout={"auto"} /> )}
diff --git a/client/src/components/table/TimeLogTable.js b/client/src/components/table/WorkLogTable.js similarity index 56% rename from client/src/components/table/TimeLogTable.js rename to client/src/components/table/WorkLogTable.js index 71d6e97..8114742 100644 --- a/client/src/components/table/TimeLogTable.js +++ b/client/src/components/table/WorkLogTable.js @@ -2,29 +2,9 @@ import React from "react"; import { EuiBasicTable, EuiLink, EuiHealth, EuiButton } from "@elastic/eui"; import { AdminTicketFlyout } from "../flyout/flyout"; +import moment from "moment"; -const userTest = [ - { - id: "1", - start_datetime: "john", - end_datetime: "doe", - }, -]; -/* -Example user object: - - - -Example country object: - -{ - code: 'NL', - name: 'Netherlands', - flag: '🇳🇱' -} -*/ - -export const TimeLogTable = ({ handleTicketSelection }, ...props) => { +export const WorkLogTable = ({ items, isLoading }, ...props) => { const deleteUser = (user) => {}; const actions = [ @@ -40,18 +20,26 @@ export const TimeLogTable = ({ handleTicketSelection }, ...props) => { ]; const columns = [ + { + field: "first_name", + name: "First Name", + }, + { + field: "last_name", + name: "Last Name", + }, { field: "start_datetime", name: "Start Datetime", - sortable: true, - "data-test-subj": "firstNameCell", + render: (start_datetime) => { + return moment(start_datetime).format("MMMM Do YYYY, h:mm a"); + }, }, { field: "end_datetime", name: "End Datetime", - truncateText: true, - mobileOptions: { - show: false, + render: (end_datetime) => { + return moment(end_datetime).format("MMMM Do YYYY, h:mm a"); }, }, { @@ -60,16 +48,14 @@ export const TimeLogTable = ({ handleTicketSelection }, ...props) => { }, ]; - const items = userTest.filter((user, index) => index < 10); - const getRowProps = (item) => { const { id } = item; return { "data-test-subj": `row-${id}`, className: "customRowClass", - onClick: (e) => { - handleTicketSelection(e, id); - }, + // onClick: (e) => { + // handleTicketSelection(e, id); + // }, }; }; @@ -84,12 +70,17 @@ export const TimeLogTable = ({ handleTicketSelection }, ...props) => { }; return ( - +
+ {isLoading === true ? null : ( + + )} +
); }; diff --git a/client/src/routes/admin/ManageTicket.js b/client/src/routes/admin/ManageTicket.js index bc9637b..40b09f0 100644 --- a/client/src/routes/admin/ManageTicket.js +++ b/client/src/routes/admin/ManageTicket.js @@ -28,14 +28,20 @@ import { handleFormSubmit } from "../../components/form/ManageTicketForm/handler import { AdminView } from "../../components/form/ManageTicketForm/adminView"; import { Debug } from "../../components/debug/debug"; import axios from "../../api/api"; -import { fields } from "../../components/form/ManageTicketForm/fields"; +import { + fields, + workLogFields, +} from "../../components/form/ManageTicketForm/fields"; import { dataFetchReducer } from "../../api/reducers"; import { MyStat } from "./Stats"; import { personFields } from "../../components/form/person/fields"; var _ = require("lodash"); -const TicketForm = ({ setSelectedTicket, selectedTicket }, ...props) => { +const TicketForm = ( + { technician, setSelectedTicket, selectedTicket }, + ...props +) => { const [state, dispatch] = useReducer(dataFetchReducer, { isLoading: false, isError: false, @@ -46,29 +52,60 @@ const TicketForm = ({ setSelectedTicket, selectedTicket }, ...props) => { assignLogLoading: true, }); + const [workRefresh, setWorkRefresh] = useState(false); + const [assignmentRefresh, setAssignmentRefresh] = useState(false); + const [dataRefresh, setDataRefresh] = useState(false); + useEffect(() => { const fetchWorkLog = async (selectedTicket) => { try { const result = await axios.get( - "/ticket/work/" + selectedTicket.ticket_id + "/work/ticket/" + selectedTicket.ticket_id ); - dispatch({ type: "FETCH_WORK_LOG_SUCCESS", payload: result.data }); + const userResult = await axios.get("/user/admin"); + let final = []; + + for (let i = 0; i < result.data.length; i++) { + final.push({ + ...result.data[i], + ...userResult.data.find( + (itmInner) => itmInner.lsu_id === result.data[i].lsu_id + ), + }); + } + dispatch({ type: "FETCH_WORK_LOG_SUCCESS", payload: final }); } catch (error) { console.log(error); } }; + if (selectedTicket != null) { + fetchWorkLog(selectedTicket); + } + }, [workRefresh, selectedTicket]); + useEffect(() => { const fetchAssignLog = async (selectedTicket) => { try { const result = await axios.get( - "/ticket/assign/" + selectedTicket.ticket_id + "/assign/ticket/" + selectedTicket.ticket_id + ); + + const userResult = await axios.get("/user/admin"); + const final = userResult.data.filter((o) => + result.data.find(({ lsu_id }) => o.lsu_id === lsu_id) ); - dispatch({ type: "FETCH_ASSIGN_LOG_SUCCESS", payload: result.data }); + + dispatch({ type: "FETCH_ASSIGN_LOG_SUCCESS", payload: final }); } catch (error) { console.log(error); } }; + if (selectedTicket != null) { + fetchAssignLog(selectedTicket); + } + }, [assignmentRefresh, selectedTicket]); + useEffect(() => { const fetchData = async (selectedTicket) => { String.prototype.toProperCase = function () { return this.replace(/\w\S*/g, function (txt) { @@ -102,10 +139,8 @@ const TicketForm = ({ setSelectedTicket, selectedTicket }, ...props) => { }; if (selectedTicket != null) { fetchData(selectedTicket); - fetchWorkLog(selectedTicket); - fetchAssignLog(selectedTicket); } - }, [selectedTicket]); + }, [dataRefresh, selectedTicket]); const internalFormSubmit = async (e, data) => { const response = await handleFormSubmit(e, data, "/ticket"); @@ -123,10 +158,18 @@ const TicketForm = ({ setSelectedTicket, selectedTicket }, ...props) => { <> )} @@ -148,7 +191,7 @@ const TicketForm = ({ setSelectedTicket, selectedTicket }, ...props) => { ); }; -export const ManageTicket = (props) => { +export const ManageTicket = ({ technician }, ...props) => { const [selectedTicket, setSelectedTicket] = useState(null); const [tickets, setTickets] = useState(null); const [isTicketsLoading, setIsTicketsLoading] = useState(true); @@ -233,6 +276,7 @@ export const ManageTicket = (props) => { "Please select ticket." ) : ( diff --git a/client/src/routes/admin/NewTechnicianFlyout.js b/client/src/routes/admin/NewTechnicianFlyout.js index 72e0b8d..5232360 100644 --- a/client/src/routes/admin/NewTechnicianFlyout.js +++ b/client/src/routes/admin/NewTechnicianFlyout.js @@ -32,7 +32,7 @@ export const NewTechnicianFlyout = ( const showFlyout = () => setIsFlyoutVisible(true); - const localFormSubmit = (e, data) => { + const internalFormSubmit = (e, data) => { if (handleFormSubmit(e, data, "/user") != null) { setIsFlyoutVisible(false); } @@ -61,7 +61,7 @@ export const NewTechnicianFlyout = ( { - localFormSubmit(e, state.data); + internalFormSubmit(e, state.data); }} > Save diff --git a/client/src/routes/admin/SelectTechnician.js b/client/src/routes/admin/SelectTechnician.js index 9182dd4..cef0910 100644 --- a/client/src/routes/admin/SelectTechnician.js +++ b/client/src/routes/admin/SelectTechnician.js @@ -49,7 +49,7 @@ export const SelectTechnician = ({ technician, setTechnician }, ...props) => { name: "technician", options: result.data.map((o) => ({ ...o, - value: (o.first_name + "_" + o.last_name).toLowerCase(), + value: o.lsu_id, text: o.first_name + " " + o.last_name, })), }; diff --git a/client/src/routes/admin/Stats.js b/client/src/routes/admin/Stats.js index ba77b54..53f4599 100644 --- a/client/src/routes/admin/Stats.js +++ b/client/src/routes/admin/Stats.js @@ -20,15 +20,17 @@ export const MyStat = ( return ( <> - - - + {isLoading ? null : ( + + + + )} ); diff --git a/client/src/routes/admin/admin.js b/client/src/routes/admin/admin.js index 0388ff7..fc86871 100644 --- a/client/src/routes/admin/admin.js +++ b/client/src/routes/admin/admin.js @@ -42,7 +42,7 @@ export const AdminRoute = (props) => { setTechnician={setTechnician} /> ) : ( - + )}
diff --git a/client/src/routes/user/user.js b/client/src/routes/user/user.js index f7b6a65..4b42475 100644 --- a/client/src/routes/user/user.js +++ b/client/src/routes/user/user.js @@ -44,9 +44,10 @@ export const UserRoute = (props) => { }); const internalFormSubmit = async (e, data) => { + data.find((o) => o.name === "component").value = "N/A"; const response = await handleFormSubmit(e, data, "/ticket"); if (response.status === 201) { - dispatch({ type: "CLEAR_FORM" }); + // dispatch({ type: "CLEAR_FORM" }); } }; return (