diff --git a/client/src/components/CSVParser.js b/client/src/components/CSVParser.js
index 6d7af2e..8f1b77c 100644
--- a/client/src/components/CSVParser.js
+++ b/client/src/components/CSVParser.js
@@ -34,7 +34,7 @@ function CSVParser({
setVisiblity,
CSVFlowVisible,
setCSVFlowVisible,
- forceNewGroup
+ forceNewGroup,
}) {
const { CSVReader } = useCSVReader();
const { CSVDownloader, Type } = useCSVDownloader();
@@ -45,7 +45,7 @@ function CSVParser({
const [createCSVGroup, setCreateCSVGroup] = useState(false); // tracks if group creation from csv is toggled
React.useEffect(async () => {
- if(group) {
+ if (group) {
await fetch(`${process.env.REACT_APP_BACKEND_URI}/rows?group=` + group.id).then(
async (response) => {
if (response.ok) {
@@ -146,7 +146,7 @@ function CSVParser({
onUploadAccepted={async (results) => {
// if we create group from CSV
setCSVData(results.data);
-
+
let headers = Object.keys(results.data[0]);
headers = headers.map((value) => {
return { name: value, type: "Text" };
@@ -196,7 +196,7 @@ function CSVParser({
) : null}
- {forceNewGroup ?
+ {forceNewGroup ? (
- :
+ ) : (
setCreateCSVGroup(!createCSVGroup)}
/>
- }
+ )}
-
+
);
}
diff --git a/client/src/components/CreateGroup.js b/client/src/components/CreateGroup.js
index 861cbb7..496d697 100644
--- a/client/src/components/CreateGroup.js
+++ b/client/src/components/CreateGroup.js
@@ -65,7 +65,6 @@ function CreateGroup({ onConfirm, onCancel, editGroup, onDelete, CSVFields }) {
const [groupNameInvalid, setGroupNameInvalid] = useState(false);
const fieldsListDiv = useRef(null);
-
/**
* `fields` is an array of objects representing the group's fields. Each object has a `name` and
* a `type`, both strings. Each object may also have a boolean `invalid` field, denoting whether
@@ -174,7 +173,7 @@ function CreateGroup({ onConfirm, onCancel, editGroup, onDelete, CSVFields }) {
/>
))}
- {!CSVFields ?
+ {!CSVFields ? (
Add new field
- :
+ ) : (
- }
+ )}
{editGroup ? "Save" : "Create"}
diff --git a/client/src/components/CreateGroupFieldRow.js b/client/src/components/CreateGroupFieldRow.js
index 9514e58..e7bce70 100644
--- a/client/src/components/CreateGroupFieldRow.js
+++ b/client/src/components/CreateGroupFieldRow.js
@@ -38,7 +38,7 @@ function CreateGroupFieldRow({ index, fieldName, fieldType, invalid, changeDispa
- {(index !== 0 && !CSVFields) && (
+ {index !== 0 && !CSVFields && (
{
+ if (event.key === "Enter") {
+ event.preventDefault();
+ event.stopPropagation();
+ setDropdownItems((items) => [...items, event.target.value]);
+ setTypeField(false);
+ setTypeFieldValue("");
+ }
+ };
+ const deleteType = (option) => {
+ setDropdownItems(
+ dropdownItems.filter((item) => {
+ return item !== option;
+ })
+ );
+ };
+ return (
+
+
+
setTypeField(true)}
+ >
+
+ Add Type
+
+ {dropdownItems.map((item) => (
+
+ ))}
+ {typeField ? (
+
+ setTypeFieldValue(event.target.value)}
+ autoFocus="autofocus"
+ />
+
+ ) : null}
+
+
+ );
+}
+
+export default TypeDropdown;
diff --git a/client/src/components/TypeDropdownOption.js b/client/src/components/TypeDropdownOption.js
new file mode 100644
index 0000000..a9b5f61
--- /dev/null
+++ b/client/src/components/TypeDropdownOption.js
@@ -0,0 +1,79 @@
+/**
+ * Components representing rows in the TypeDropdown menu.
+ *
+ * @summary Table display for dashboard page.
+ * @author Alex Zhang
+ */
+
+import React, { useState, useRef, useEffect } from "react";
+import Pencil from "../images/Pencil";
+import TrashCan from "../images/TrashCan.svg";
+
+/**
+ * Renders the dropdown option for the custom type menu.
+ * @param {string} value The string value of the type option
+ * @param {function} deleteType Function to remove the type option from the dropdown.
+ * @returns
+ */
+function TypeDropdownOption({ value, deleteType }) {
+ const [fieldValue, setFieldValue] = useState(value);
+ const [editOption, setEditOption] = useState(false);
+ const [editFieldValue, setEditFieldValue] = useState(value);
+ // This useEffect hook manages clicks outside the menu and minimizes the window.
+ const editOptionRef = useRef(null);
+ useEffect(() => {
+ const handleClickOutside = (event) => {
+ if (editOption && editOptionRef.current && !editOptionRef.current.contains(event.target)) {
+ setEditFieldValue(fieldValue);
+ setEditOption(false);
+ }
+ };
+ document.addEventListener("mousedown", handleClickOutside);
+ return () => {
+ document.removeEventListener("mousedown", handleClickOutside);
+ };
+ });
+
+ const onKeyDown = (event) => {
+ // 'keypress' event misbehaves on mobile so we track 'Enter' key via 'keydown' event
+ if (event.key === "Enter") {
+ event.preventDefault();
+ event.stopPropagation();
+ setFieldValue(editFieldValue);
+ setEditOption(false);
+ }
+ };
+ return (
+
+
{fieldValue}
+
{
+ setEditOption(true);
+ setEditFieldValue(fieldValue);
+ }}
+ >
+
+
+ {editOption ? (
+
+
Edit Option
+
+
setEditFieldValue(event.target.value)}
+ autoFocus="autofocus"
+ />
+
deleteType(value)}>
+
+ Delete Option
+
+
+ ) : null}
+
+ );
+}
+
+export default TypeDropdownOption;
diff --git a/client/src/css/CSVParser.css b/client/src/css/CSVParser.css
index bc9c88e..7eb5899 100644
--- a/client/src/css/CSVParser.css
+++ b/client/src/css/CSVParser.css
@@ -165,4 +165,4 @@
width: max-content;
margin-bottom: -20px;
margin-top: 10px;
-}
\ No newline at end of file
+}
diff --git a/client/src/css/Dashboard.css b/client/src/css/Dashboard.css
index 8cbb492..a2e19fa 100644
--- a/client/src/css/Dashboard.css
+++ b/client/src/css/Dashboard.css
@@ -182,4 +182,4 @@
.no-groups-info-wrapper {
text-align: center;
-}
\ No newline at end of file
+}
diff --git a/client/src/css/TypeDropdown.css b/client/src/css/TypeDropdown.css
new file mode 100644
index 0000000..6862906
--- /dev/null
+++ b/client/src/css/TypeDropdown.css
@@ -0,0 +1,140 @@
+.type-dropdown-div-wrapper {
+ position: relative;
+ left: 50%;
+}
+
+.type-dropdown-div {
+ display: flex;
+ flex-flow: wrap;
+ width: 200px;
+ background: #fafafa;
+ border: 0.2px solid #05204a;
+ box-shadow: 0px 1.5px 12px rgba(0, 0, 0, 0.25);
+ border-radius: 3.5px;
+ justify-content: center;
+ max-height: 200px;
+ overflow-x: hidden;
+ overflow-y: auto;
+}
+
+.add-type-dropdown-button {
+ display: table-cell;
+ margin-top: 14px;
+ margin-bottom: 12px;
+ width: 170px;
+ height: 35px;
+ font-weight: 400;
+ font-size: 14px;
+ line-height: 35px;
+ border-radius: 5px;
+ border: none;
+ background: #05204a;
+ color: #ffffff;
+ cursor: pointer;
+}
+
+.type-dropdown-add-icon-svg {
+ position: relative;
+ top: 3px;
+ padding-right: 8px;
+ width: 15px;
+ justify-self: auto;
+}
+
+.type-dropdown-field {
+ height: 35px;
+ width: 135px;
+ margin-bottom: 12px;
+ text-align: center;
+ border: 0px;
+ background: #f3f3f3;
+ border-radius: 5px;
+ color: #404040;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: clip;
+}
+
+.type-dropdown-field.empty {
+ width: 170px;
+}
+
+.type-dropdown-option {
+ position: static;
+ width: 170px;
+}
+
+.type-dropdown-pencil {
+ float: right;
+ margin-top: 9px;
+ cursor: pointer;
+}
+
+.type-dropdown-edit-div {
+ position: absolute;
+ left: 13%;
+ z-index: 10;
+ background: #000000;
+ width: 190px;
+ height: 135px;
+ background: #fafafa;
+ border: 0.2px solid #05204a;
+ box-shadow: 0px 1.5px 12px rgba(0, 0, 0, 0.25);
+ border-radius: 3.5px;
+}
+
+.type-dropdown-edit-header {
+ margin-left: 12px;
+ margin-top: 7px;
+ margin-bottom: 7px;
+ font-weight: 500;
+ font-size: 16px;
+ line-height: 24px;
+ color: #05204a;
+}
+
+.type-dropdown-edit-divider {
+ width: 160px;
+ border: 0.75px solid #e0dddd;
+ margin: 0px;
+ margin-left: 12px;
+}
+
+.type-dropdown-edit-field {
+ height: 35px;
+ width: 150px;
+ margin: 12px;
+ padding-left: 10px;
+ border: 1px solid #c5c5c5;
+ background: #f3f3f3;
+ border-radius: 5px;
+ color: #404040;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: clip;
+}
+
+.type-dropdown-delete-option {
+ display: inline-block;
+ padding: 0px;
+ background: none;
+ border: none;
+ height: 21px;
+ width: 150px;
+ margin-left: 17px;
+ font-weight: 400;
+ font-size: 14px;
+ color: #c4c4c4;
+ cursor: pointer;
+}
+
+.type-dropdown-trash-can-svg {
+ float: left;
+ margin-right: 9px;
+}
+
+.type-dropdown-delete-option-text {
+ float: left;
+ line-height: 21px;
+ margin: 0px;
+}
diff --git a/client/src/pages/Dashboard.js b/client/src/pages/Dashboard.js
index 5ecbf6f..942c846 100644
--- a/client/src/pages/Dashboard.js
+++ b/client/src/pages/Dashboard.js
@@ -62,7 +62,6 @@ function Dashboard() {
const [CSVFields, setCSVFields] = useState(null); // stores fields from uploaded csv
const [CSVData, setCSVData] = useState(null); // tracks if csv for group creation was uploaded
-
/**
* Fetches the list of groups and populates the options in the group selection dropdown.
* @returns The new list of options
@@ -420,11 +419,11 @@ function Dashboard() {
/**
* Hide csv dropdown when click outside of it
- */
- document.addEventListener('mouseup', function(e) {
- var dropdown = document.getElementById('csv-parser-dropdown');
+ */
+ document.addEventListener("mouseup", function (e) {
+ var dropdown = document.getElementById("csv-parser-dropdown");
if (!dropdown.contains(e.target)) {
- setVisibility(false)
+ setVisibility(false);
}
});
@@ -460,35 +459,46 @@ function Dashboard() {
-
+
+
Start building your dashboard!
-
Click "Create new" to begin adding data to your table.
- Have previous databases? No worries! You can upload your CSV file as well.
+
+ Click "Create new" to begin adding data to your table.
+
+ Have previous databases? No worries! You can upload your CSV file as well.
+
{
- setGroupCreationVisible(true);
- }}
+ className="create-group clickable"
+ type="button"
+ onClick={() => {
+ setGroupCreationVisible(true);
+ }}
>
-
+
Create new
{
- setCSVFlowVisible(true);
- }}
+ className="csv-create-group clickable"
+ type="button"
+ onClick={() => {
+ setCSVFlowVisible(true);
+ }}
>
Create from CSV
- {(groupCreationVisible && !CSVFields) && (
-
setGroupCreationVisible(false)} />
+ {groupCreationVisible && !CSVFields && (
+ setGroupCreationVisible(false)}
+ />
)}
-
- {(groupCreationVisible && CSVFields) && (
+
+ {groupCreationVisible && CSVFields && (
{
@@ -499,7 +509,7 @@ function Dashboard() {
CSVFields={CSVFields}
/>
)}
-
+
>
);
@@ -510,26 +520,30 @@ function Dashboard() {
{orgInfo ? orgInfo.name : userInfo.orgName}
-
- {selectedGroup && (
-
setAddingRow(!addingRow)}
- >
-
- Add row
-
- )}
+
+ {selectedGroup && (
+
setAddingRow(!addingRow)}
+ >
+
+ Add row
+
+ )}
-
-
setSearch(event.target.value)}
- />
-
+
+
setSearch(event.target.value)}
+ />
+
+
+ {dataLoading ? (
+
+
+
+ ) : (
+
+ )}
- {dataLoading ? (
-
-
-
- ) : (
-
{
+ setGroupCreationVisible(false);
+ setCSVFields(null);
+ setCSVData(null);
+ }}
+ CSVFields={CSVFields}
/>
)}
-
- {groupCreationVisible && (
- {
- setGroupCreationVisible(false);
- setCSVFields(null);
- setCSVData(null);
- }}
- CSVFields={CSVFields}
- />
- )}
- {groupEditVisible && (
- setGroupEditVisible(false)}
- CSVFields={null}
- />
- )}
-
-
+ {groupEditVisible && (
+ setGroupEditVisible(false)}
+ CSVFields={null}
+ />
+ )}
+