Skip to content

Commit

Permalink
Added Text Input, Edit and Delete Functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
Shubhrajyoti-Dey-FrosTiK committed Jul 19, 2022
1 parent 99e8dfd commit 5470b31
Show file tree
Hide file tree
Showing 9 changed files with 296 additions and 23 deletions.
1 change: 0 additions & 1 deletion src/components/Canvas/Canvas.jsx
Expand Up @@ -10,7 +10,6 @@ import Group from "../Group/Group";

function Canvas() {
const [formData] = useContext(FormData);

return (
<div className={styles.Canvas}>
<Group
Expand Down
7 changes: 5 additions & 2 deletions src/components/FormBuilderTool/index.jsx
Expand Up @@ -6,8 +6,11 @@ import Canvas from "../Canvas/Canvas";
// Styles
import styles from "./FormBuilderTool.module.css";

// Constants
import { getUserSideFormTypes } from "../../constants/formTypes";

function FormBuilderTool() {
const formTools = ["Tool 1", "Tool 2", "Tool 3", "Tool 4", "Tool 5"];
const formTools = getUserSideFormTypes();
return (
<div className={styles.FomBuilderContainer}>
<div className={styles.FormCanvas}>
Expand All @@ -16,7 +19,7 @@ function FormBuilderTool() {
<div className={styles.FormToolsContainer}>
{formTools.map((tool, index) => (
<div key={`Tool_${index}`}>
<Tool toolName={tool} />
<Tool toolName={tool.value} />
</div>
))}
</div>
Expand Down
71 changes: 71 additions & 0 deletions src/components/FormComponent/FormComponent.jsx
@@ -0,0 +1,71 @@
import React, { useContext } from "react";

// ContextAPI
import { FormData, PopupContext } from "../../App";

// Icons
import EditIcon from "@mui/icons-material/Edit";
import DeleteIcon from "@mui/icons-material/Delete";

// Constants
import { FORM_TYPES, getUserSideFormTypeById } from "../../constants/formTypes";
import { POPUP_TYPES } from "../../constants/popupTypes";

// Services
import GraphStructureService from "../../services/graph.structurer.service";

function FormComponent({ element, groupId }) {
const gs = new GraphStructureService();
const [, setPopupContext] = useContext(PopupContext);
const [formDataContext, setFormDataContext] = useContext(FormData);

const handleEdit = () => {
setPopupContext({
data: {
id: groupId,
formData: element,
type: FORM_TYPES.TEXT_INPUT,
},
show: true,
edit: true,
type: POPUP_TYPES.ADD_FORM_ELEMENT,
});
};

const handleDelete = () => {
setFormDataContext(
gs.deleteFormElement(groupId, element.id, formDataContext)
);
};

return (
<div
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
}}
>
<div>
<p style={{ margin: "0px" }}>
<strong>Label: </strong>
{element.label}
</p>
<p style={{ margin: "0px" }}>
<strong>Form Type: </strong>
{getUserSideFormTypeById(element.type)}
</p>
</div>
<div style={{ display: "flex" }}>
<div style={{ cursor: "pointer", marginRight: "10px" }}>
<EditIcon onClick={handleEdit} />
</div>
<div style={{ cursor: "pointer" }}>
<DeleteIcon onClick={handleDelete} />
</div>
</div>
</div>
);
}

export default FormComponent;
20 changes: 16 additions & 4 deletions src/components/GroupElement/GroupElement.jsx
@@ -1,18 +1,23 @@
import { Button } from "@material-ui/core";
import React, { useContext } from "react";
import { useState } from "react";
import { useDrop } from "react-dnd";

// ContextAPI
import { PopupContext } from "../../App";
import { FormData, PopupContext } from "../../App";
import { getFormType } from "../../constants/formTypes";

// Constants
import { POPUP_TYPES } from "../../constants/popupTypes";
import FormComponent from "../FormComponent/FormComponent";

// Styles
import styles from "./GroupElement.module.css";

function GroupElement({ groupId, data }) {
function GroupElement({ groupId }) {
const [popupContext, setPopupContext] = useContext(PopupContext);
const [formDataContext] = useContext(FormData);
const [data] = useState(formDataContext.schema[groupId]);
const [, drop] = useDrop({
accept: "tool",
drop: (item) => {
Expand All @@ -37,7 +42,10 @@ function GroupElement({ groupId, data }) {
setPopupContext({
show: true,
type: POPUP_TYPES.ADD_FORM_ELEMENT,
data: { element: item.toolName, id: groupId },
data: {
id: groupId,
type: getFormType(item.toolName),
},
});
};

Expand All @@ -49,7 +57,11 @@ function GroupElement({ groupId, data }) {
</div>
<div style={{ marginTop: "10px" }}>
{data.formElements.map((element, index) => {
return <div key={`FormElement_${index}`}>{element}</div>;
return (
<div key={`FormElement_${index}`}>
<FormComponent element={element} groupId={groupId} />
</div>
);
})}
</div>
<div style={{ margin: "10px", textAlign: "center" }}>
Expand Down
47 changes: 31 additions & 16 deletions src/components/Popup/types/AddFormElement/AddFormElement.jsx
@@ -1,34 +1,49 @@
import { FormControl, InputLabel, MenuItem, Select } from "@material-ui/core";
import Button from "@material-ui/core/Button";
import React, { useContext } from "react";
import React, { useContext, useState } from "react";

// ContextAPI
import { FormData, PopupContext } from "../../../../App";

// Constants
import {
FORM_TYPES,
getFormType,
getUserSideFormTypes,
} from "../../../../constants/formTypes";

// Components
import TextInput from "../formTypes/TextInput/TextInput";

// Styles
import styles from "./AddFormElement.module.css";

function AddFormElement() {
const [popupContext, setPopupContext] = useContext(PopupContext);
const [formData, setFormData] = useContext(FormData);
const [formType, setFormType] = useState(popupContext.data.type);
const [formTypesArray] = useState(getUserSideFormTypes());

const handleAddFormElement = async () => {
const updatedFormData = { ...formData };
updatedFormData.schema[popupContext.data.id].formElements.push(
popupContext.data.element
);
setFormData(updatedFormData);
setPopupContext({ ...popupContext, show: false });
};
return (
<div>
AddFormElement {popupContext.data.element}
<Button
<p>Select the form type</p>
<Select
variant="outlined"
className={styles.SubmitButton}
onClick={handleAddFormElement}
placeholder="Form Type"
value={formType}
style={{ width: "100%" }}
onChange={(e) => {
setFormType(e.target.value);
}}
>
ADD
</Button>
{formTypesArray.map((ft, index) => (
<MenuItem key={`FormType_${index}`} value={ft.key}>
{ft.value}
</MenuItem>
))}
</Select>
{formType === FORM_TYPES.TEXT_INPUT && (
<TextInput edit={popupContext.edit} />
)}
</div>
);
}
Expand Down
123 changes: 123 additions & 0 deletions src/components/Popup/types/formTypes/TextInput/TextInput.jsx
@@ -0,0 +1,123 @@
// ContextAPI
import { FormData, PopupContext } from "../../../../../App";

// Libraries
import React, { Fragment, useContext } from "react";
import { useFormik } from "formik";
import * as yup from "yup";
import { v4 as uuidv4 } from "uuid";

// Components
import Button from "@material-ui/core/Button";
import TextField from "@material-ui/core/TextField";

// styles
import styles from "./TextInput.module.css";
import { Checkbox, FormControlLabel } from "@material-ui/core";
import { FORM_TYPES } from "../../../../../constants/formTypes";

const initialValidationSchema = yup.object({
label: yup
.string("Enter the form label")
.required("This field must be specified"),
});

function TextInput({ edit }) {
// ContextAPI
const [formData] = useContext(FormData);
const [popupContext, setPopupContext] = useContext(PopupContext);

const initialFormValues = () => {
let value = {};
value = popupContext.data.formData || { label: "", isRequired: false };
return value;
};

// handleSubmit
const handleFormSubmit = async (values) => {
values.type = FORM_TYPES.TEXT_INPUT;
const updatedFormData = formData;
if (!edit) {
values.id = uuidv4();
updatedFormData.schema[popupContext.data.id].formElements.push(values);
setPopupContext({ ...popupContext, show: false });
} else {
const formElements = formData.schema[popupContext.data.id].formElements;
for (let i = 0; i < formElements.length; i++) {
if (formElements[i].id === popupContext.data.formData.id) {
values.id = formElements[i].id;
formElements[i] = values;
}
}
updatedFormData.schema[popupContext.data.id].formElements = formElements;
setPopupContext({ ...popupContext, show: false });
}
};

const handleClose = async () => {
setPopupContext({ ...popupContext, show: false });
};

// Formik
const formik = useFormik({
initialValues: initialFormValues(),
validationSchema: initialValidationSchema,
onSubmit: (values) => {
handleFormSubmit(values);
},
});

return (
<Fragment>
<div className={styles.InitialFormScreen} onSubmit={handleFormSubmit}>
<h2>Text Input</h2>
<p>Add a text Input</p>
<form onSubmit={formik.handleSubmit} className={styles.InitialForm}>
<TextField
variant="outlined"
className={styles.FormField}
id="label"
name="label"
label="Label"
value={formik.values["label"]}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={formik.touched["label"] && Boolean(formik.errors["label"])}
helperText={formik.touched["label"] && formik.errors["label"]}
/>
<FormControlLabel
control={
<Checkbox
id="isRequired"
name="isRequired"
checked={formik.values["isRequired"]}
onChange={formik.handleChange}
/>
}
label="Is Required"
/>
<div
style={{
marginTop: "20px",
display: "flex",
justifyContent: "space-between",
}}
>
<div style={{ cursor: "pointer" }} onClick={handleClose}>
<p>CANCEL</p>
</div>
<Button
variant="contained"
type="submit"
className={styles.SubmitButton}
>
{edit ? "SAVE" : "CREATE"}
</Button>
</div>
</form>
</div>
</Fragment>
);
}

export default TextInput;
@@ -0,0 +1,14 @@
.SubmitButton {
width: 100px;
background-color: rgb(0, 213, 255) !important;
margin-top: 10px;
}

.FormFieldContainer {
margin-top: 10px;
margin-bottom: 10px;
}

.FormField {
width: 100%;
}
26 changes: 26 additions & 0 deletions src/constants/formTypes.js
@@ -0,0 +1,26 @@
export const FORM_TYPES = {
TEXT_INPUT: "TEXT_INPUT",
PARAGRAPH_INPUT: "PARAGRAPH_INPUT",
};

export const USER_SIDE_FORM_TYPES = {
"Text Input": "TEXT_INPUT",
"Paragraph Input": "PARAGRAPH_INPUT",
};

export const getFormType = (type) => {
return USER_SIDE_FORM_TYPES[type];
};

export const getUserSideFormTypeById = (id) => {
for (let key in USER_SIDE_FORM_TYPES) {
if (USER_SIDE_FORM_TYPES[key] === id) return key;
}
};

export const getUserSideFormTypes = () => {
const formTypes = [];
for (let key in USER_SIDE_FORM_TYPES)
formTypes.push({ value: key, key: USER_SIDE_FORM_TYPES[key] });
return formTypes;
};
10 changes: 10 additions & 0 deletions src/services/graph.structurer.service.js
Expand Up @@ -83,4 +83,14 @@ export default class GraphStructureService {
getGraphStepConnections(data.schema, currentStep, connectionsArray);
return connectionsArray;
};

deleteFormElement = (groupId, formId, data) => {
const updatedForms = [];
data.schema[groupId].formElements.forEach((form) => {
if (form.id !== formId) updatedForms.push(form);
});
data.schema[groupId].formElements = updatedForms;
console.log(data);
return { ...data };
};
}

0 comments on commit 5470b31

Please sign in to comment.