Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
0f642bc
added some comments to code
williamzhu17 Jun 24, 2021
beb1899
Merge branch 'issue-11-add-functionality-to-create-new-shapes' of htt…
williamzhu17 Jun 24, 2021
bb648f7
feat: Form now resets when modal is closed
williamzhu17 Jun 24, 2021
4491c94
feat: fixed issue with clip-path type not switching
williamzhu17 Jun 24, 2021
76c86c9
feat: fixed issue where deleting entire clip-path crashes app
williamzhu17 Jun 24, 2021
076094b
feat: no longer able to add vertices when shape is not a polygon
williamzhu17 Jun 24, 2021
c9e4622
feat: fixed issue with x button on modal not resetting form values to…
williamzhu17 Jun 24, 2021
f48c2c2
added comments to increase readibility and cleaned up some code
williamzhu17 Jun 24, 2021
9024f24
feat: fixed issue where DraggableVertices do not reset when switching…
williamzhu17 Jun 24, 2021
ffc32aa
feat: made close button a bit less wonky
williamzhu17 Jun 24, 2021
dea6337
feat: No need to pass the entire object as create operation update
atapas Jun 24, 2021
e48761f
feat: form now fully resets after the creation of a shape
williamzhu17 Jun 24, 2021
2c9a131
feat: fixed issue with deleting entirety of clip-path formula and add…
williamzhu17 Jun 24, 2021
9e46af9
feat: name now remains the same when switching clip-path types
williamzhu17 Jun 24, 2021
f2d6c29
feat: fixed issue with clip-paths breaking when deleting all of the v…
williamzhu17 Jun 24, 2021
fa8d0bb
feat: fixed issue where cannot create new vertices when there are no …
williamzhu17 Jun 24, 2021
3ac9e43
feat: switched dropdown menu to a ToggleButton in ShapeForm for consi…
williamzhu17 Jun 25, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
252 changes: 145 additions & 107 deletions components/core/CreateShape.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
import React, { useState } from "react";

// Bootstrap
import Container from "react-bootstrap/Container";
import Row from "react-bootstrap/Row";
import Col from "react-bootstrap/Col";
import Modal from "react-bootstrap/Modal";
import Button from "react-bootstrap/Button";

// ShapeForm and ShapePreview Components
import { ShapeForm, ShapePreview } from "..";

// Toast
import toast from "react-hot-toast";

// harperDb fetch call
import { harperFetch } from "../../utils/HarperFetch";

import { ShapeForm, ShapePreview } from "..";

const CreateShape = (props) => {
const [shapeInformation, setShapeInformation] = useState({
"name": "Tilted Square",

// Store the default state as a variable so resetting form is easier
const initialState = {
"name": "",
"formula": "polygon(10% 10%, 90% 10%, 90% 90%, 10% 80%)",
"vertices": 4,
"private": false,
Expand All @@ -42,30 +47,38 @@ const CreateShape = (props) => {
"y": "80%",
},
]
}

// shapeInformation holds all information about the shape
const [shapeInformation, setShapeInformation] = useState({
...initialState,
});

function handleChange(event, data, number) {
// Changes shapeInformation when something in ShapeForm or ShapePreview is altered
const handleChange = (event, data, number) => {

// console.log(event, data);

const name = event.target.name || event.type;
const value = event.target.type === "checkbox" ? event.target.checked : event.target.value;

// console.log(event, data);

// If Clip-Path formula value is changed, it makes sure that the parentheses stay there and also alters the verticeCoordinates value
if (name === "name") {
setShapeInformation({
...shapeInformation,
"name": value,
});
} else if (name === 'private') {
setShapeInformation({
...shapeInformation,
"private": !shapeInformation.private,

});
} else if (name === "formula") {
const edgeVerticeNumber = shapeInformation.clipPathType === "polygon" ? value.split(",").length: 0;
return;
}

// If formula value is changed, alter formula value and verticeCoordinates value depending on clipPathType
if (name === "formula") {

const edgeVerticeNumber = shapeInformation.clipPathType === "polygon" && value !== "" ? value.split(",").length: 0;

// If user deletes all, set formula to the Clip-Path type with an empty set of parentheses
if (value === "") {
handleFormulaChange(shapeInformation.clipPathType + "()", edgeVerticeNumber)
handleFormulaChange(shapeInformation.clipPathType + "()", edgeVerticeNumber);
} else if (value.includes("polygon")) {
handleFormulaChange(value, edgeVerticeNumber, "polygon");
} else if (value.includes("circle")) {
Expand All @@ -75,7 +88,50 @@ const CreateShape = (props) => {
} else {
handleFormulaChange(value, edgeVerticeNumber);
}
} else if (name === "mousemove") {
return;

}

// If Clip-Path Type is changed, change the value of the clipPathType
if (name === "clipPathType") {

if (value === "polygon") {
setShapeInformation({
...initialState,
});
}

if (value === "circle") {
setShapeInformation({
...shapeInformation,
"type": "circle",
"formula": "circle(50% at 50% 50%)",
});
}

if (value === "ellipse") {
setShapeInformation({
...shapeInformation,
"type": "ellipse",
"formula": "ellipse(25% 40% at 50% 50%)",
});
}

setShapeInformation(prevState => {
return {
...prevState,
"clipPathType": value,
"edges": value === "polygon" ? 4 : 0,
"vertices": value === "polygon" ? 4 : 0,
"notes": "",
}
});
return;
}

// If DraggableVertice is moved, adjust verticeCoordinates and formula
if (name === "mousemove") {

const newVerticeCoordinates = addNewVerticeCoordinates(data.x, data.y, number);
const newFormula = generateNewFormula(newVerticeCoordinates);

Expand All @@ -84,7 +140,12 @@ const CreateShape = (props) => {
"verticeCoordinates": newVerticeCoordinates,
"formula": newFormula,
});
} else if (name === "click" && event.target.id === "shapeShadow") {
return;
}

// If preview is clicked and the clipPathType is a polygon, add a verticeCoordinate value at its location and adjust formula
if ((event.target.id === "shapeShadow" || event.target.id === "clippedShape") && name === "click" && shapeInformation.clipPathType === "polygon") {

const newVerticeCoordinates = addNewVerticeCoordinates(event.nativeEvent.offsetX, event.nativeEvent.offsetY, shapeInformation.verticeCoordinates.length);
const newFormula = generateNewFormula(newVerticeCoordinates);

Expand All @@ -95,7 +156,11 @@ const CreateShape = (props) => {
"verticeCoordinates": newVerticeCoordinates,
"formula": newFormula,
});
} else if ((event.target.id.includes("deleteButton") || event.target.localName === "line") && number !== undefined) {
return;
}

// If delete button is pressed and passes a number that corresponds to the vertice, remove the corresponding verticeCoordinate and adjust formula
if (event.target.id.includes("deleteButton") && number !== undefined) {

let newVerticeCoordinates = [];

Expand All @@ -114,44 +179,20 @@ const CreateShape = (props) => {
"verticeCoordinates": newVerticeCoordinates,
"formula": newFormula,
});

} else if (name === "clipPathType") {
handleClipPathChange(value);
} else {
setShapeInformation({
...shapeInformation,
[name]: value,
});
return;
}
}

function addNewVerticeCoordinates(x ,y, number) {
const xPercentage = Math.round((x / 280.0) * 100.0);
const yPercentage = Math.round((y / 280.0) * 100.0);

let newVerticeCoordinates = shapeInformation.verticeCoordinates;
newVerticeCoordinates[number] = {
"x": xPercentage + "%",
"y": yPercentage + "%"
}

return newVerticeCoordinates;
}

function generateNewFormula(newVerticeCoordinates) {
let newFormula = shapeInformation.clipPathType + "(";

for (let i = 0; i < newVerticeCoordinates.length; i++) {
let newX = newVerticeCoordinates[i].x;
let newY = newVerticeCoordinates[i].y;

i === newVerticeCoordinates.length - 1 ? newFormula = newFormula + newX + " " + newY + ")" : newFormula = newFormula + newX + " " + newY + ", ";
}

return newFormula;

// Handles all other ShapeForm and ShapePreview Changes
setShapeInformation({
...shapeInformation,
[name]: value,
});
}

function handleFormulaChange(formula, edgeVerticeNumber, clipPathType) {
// Called when there is a change in the textbox for formula in the form
// Adjusts verticeCoordinates, vertices, and edges accordingly
// Ensures that the parentheses remain
const handleFormulaChange = (formula, edgeVerticeNumber, clipPathType) => {
let newVerticeCoordinates = [];

if (clipPathType === "polygon") {
Expand All @@ -176,44 +217,42 @@ const CreateShape = (props) => {
"verticeCoordinates": newVerticeCoordinates,
}
});
}
}

function handleClipPathChange(clipPathType) {
if (clipPathType === "polygon") {
setShapeInformation({
...shapeInformation,
"name": "Tilted Square",
"formula": "polygon(10% 10%, 90% 10%, 90% 90%, 10% 80%)",
});
// Returns an array that has a new verticeCoordinate
const addNewVerticeCoordinates = (x ,y, number) => {
const xPercentage = Math.round((x / 280.0) * 100.0);
const yPercentage = Math.round((y / 280.0) * 100.0);

let newVerticeCoordinates = shapeInformation.verticeCoordinates;
newVerticeCoordinates[number] = {
"x": xPercentage + "%",
"y": yPercentage + "%"
}

if (clipPathType === "circle") {
setShapeInformation({
...shapeInformation,
"name": "Circle",
"formula": "circle(50% at 50% 50%)",
});
return newVerticeCoordinates;
}

// Returns a generated formula string from a verticeCoordinate array
const generateNewFormula = (newVerticeCoordinates) => {

let newFormula = shapeInformation.clipPathType + "(";

if (newVerticeCoordinates.length === 0) {
return newFormula + ")";
}

if (clipPathType === "ellipse") {
setShapeInformation({
...shapeInformation,
"name": "Ellipse",
"formula": "ellipse(25% 40% at 50% 50%)",
});
for (let i = 0; i < newVerticeCoordinates.length; i++) {
let newX = newVerticeCoordinates[i].x;
let newY = newVerticeCoordinates[i].y;

i === newVerticeCoordinates.length - 1 ? newFormula = newFormula + newX + " " + newY + ")" : newFormula = newFormula + newX + " " + newY + ", ";
}

setShapeInformation(prevState => {
return {
...prevState,
"clipPathType": clipPathType,
"edges": clipPathType === "polygon" ? 4 : 0,
"vertices": clipPathType === "polygon" ? 4 : 0,
"notes": "",
}
})
return newFormula;
}

// Form Validation
const [validated, setValidated] = useState(false);

const handleSubmit = async(event) => {
Expand Down Expand Up @@ -255,29 +294,28 @@ const CreateShape = (props) => {
} else {
console.log(`The user ${props.user.email} present in DB`);
}

// Finally, close the modal and update the shape in UI
props.handleClose();
toast.success(`Shape ${shapeInformation.name} created successfully.`);
props.setShapeAction({
...props.shapeAction,
"action": "add",
"payload": {
"shape_id": insertShape['inserted_hashes']
}
});

setShapeInformation({
...initialState,
});

setValidated(false);

} else {
toast.error('OOPS!! We hit a bummer. Please try again.');
}
props.handleClose();
toast.success(`Shape ${shapeInformation.name} created successfully.`);
props.setShapeAction({
...props.shapeAction,
"action": "add",
"payload": {
"backgroundColor": shapeInformation.backgroundColor,
"createdAt": null,
"createdBy": props.user.email,
"edges": shapeInformation.edges,
"email": null,
"email1": props.user.email,
"formula": shapeInformation.formula,
"likes": 0,
"name": shapeInformation.name,
"name1": props.user.displayName,
"notes": shapeInformation.notes,
"photoURL": props.user.photoURL,
"private": shapeInformation.private,
"type": shapeInformation.clipPathType
}
});

}

return(
Expand All @@ -286,7 +324,7 @@ const CreateShape = (props) => {
show={props.show}
centered
size="lg"
onHide={props.handleClose}
onHide={() => {setShapeInformation({ ...initialState }); props.handleClose(); }}
backdrop="static"
>
<Modal.Header closeButton>
Expand All @@ -313,7 +351,7 @@ const CreateShape = (props) => {
</Container>
</Modal.Body>
<Modal.Footer>
<Button onClick={() => props.handleClose()} variant="outline-info">
<Button onClick={() => { setShapeInformation({ ...initialState }); props.handleClose(); }} variant="outline-info">
Close
</Button>
<Button variant="secondary" type="submit" form="createShapeForm" disabled={!shapeInformation.name}>
Expand Down
Loading