Skip to content

Commit 5ea74ab

Browse files
authored
Merge pull request #37 from TryShape/issue-13-add-ability-to-edit-a-private-shape
Issue 13 add ability to edit a private shape
2 parents 520fbe4 + 0215c3c commit 5ea74ab

12 files changed

Lines changed: 443 additions & 110 deletions

File tree

components/core/App.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,15 @@ const App = (props) => {
112112
width={300}
113113
/>
114114
) : (
115-
<ShapeList {...props} data={ data } searchTerm={searchTerm} sort={sort} />
115+
<ShapeList
116+
{...props}
117+
data={ data }
118+
setSearchTerm = { setSearchTerm }
119+
searchTerm={searchTerm}
120+
sort={sort}
121+
shapeAction={shapeAction}
122+
setShapeAction={setShapeAction}
123+
/>
116124
)}
117125
</>
118126
);

components/core/CopyShapeSource.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ const CopyShapeSource = ({ show, setShow, shape }) => {
212212
</Modal.Body>
213213

214214
<Modal.Footer>
215-
<Button variant="outline-info" onClick={() => setShow(false)}>
215+
<Button variant="outline-dark" onClick={() => setShow(false)}>
216216
Close
217217
</Button>
218218
</Modal.Footer>

components/core/CreateShape.js

Lines changed: 135 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState } from "react";
1+
import React, { useState, useEffect } from "react";
22

33
// Bootstrap
44
import Container from "react-bootstrap/Container";
@@ -54,6 +54,37 @@ const CreateShape = (props) => {
5454
...initialState,
5555
});
5656

57+
// Checks if edit is true and will provide different initial values
58+
useEffect(() => {
59+
60+
if (props.edit) {
61+
let formula = props.shape.formula;
62+
let slicedFormula = formula.slice(formula.indexOf("(") + 1, formula.indexOf(")"));
63+
let newVerticeCoordinates = slicedFormula.split(", ");
64+
newVerticeCoordinates = newVerticeCoordinates.map((value) => {
65+
let coordinates = value.split(" ");
66+
return {
67+
"x": coordinates[0],
68+
"y": coordinates[1],
69+
}
70+
});
71+
72+
setShapeInformation({
73+
...shapeInformation,
74+
"name": props.shape.name,
75+
"formula": props.shape.formula,
76+
"vertices": props.shape.vertices,
77+
"private": true,
78+
"edges": props.shape.edges,
79+
"notes": props.shape.notes,
80+
"clipPathType": props.shape.type,
81+
"backgroundColor": props.shape.backgroundColor,
82+
"verticeCoordinates" : newVerticeCoordinates,
83+
});
84+
}
85+
86+
}, [props.show]);
87+
5788
// Changes shapeInformation when something in ShapeForm or ShapePreview is altered
5889
const handleChange = (event, data, number) => {
5990

@@ -97,33 +128,35 @@ const CreateShape = (props) => {
97128

98129
if (value === "polygon") {
99130
setShapeInformation({
100-
...initialState,
131+
...shapeInformation,
132+
"formula": "polygon(10% 10%, 90% 10%, 90% 90%, 10% 80%)",
133+
"vertices": 4,
134+
"edges": 4,
101135
});
102136
}
103137

104138
if (value === "circle") {
105139
setShapeInformation({
106-
...shapeInformation,
107-
"type": "circle",
108-
"formula": "circle(50% at 50% 50%)",
140+
...shapeInformation,
141+
"type": "circle",
142+
"formula": "circle(50% at 50% 50%)",
109143
});
110144
}
111145

112146
if (value === "ellipse") {
113147
setShapeInformation({
114-
...shapeInformation,
115-
"type": "ellipse",
116-
"formula": "ellipse(25% 40% at 50% 50%)",
148+
...shapeInformation,
149+
"type": "ellipse",
150+
"formula": "ellipse(25% 40% at 50% 50%)",
117151
});
118152
}
119153

120154
setShapeInformation(prevState => {
121155
return {
122-
...prevState,
123-
"clipPathType": value,
124-
"edges": value === "polygon" ? 4 : 0,
125-
"vertices": value === "polygon" ? 4 : 0,
126-
"notes": "",
156+
...prevState,
157+
"clipPathType": value,
158+
"edges": value === "polygon" ? 4 : 0,
159+
"vertices": value === "polygon" ? 4 : 0,
127160
}
128161
});
129162
return;
@@ -265,56 +298,101 @@ const CreateShape = (props) => {
265298
setValidated(true);
266299

267300
console.log(shapeInformation);
301+
302+
// Editing Shape
303+
if (props.edit) {
304+
305+
const editShape = await harperFetch({
306+
operation: "sql",
307+
sql: `
308+
UPDATE tryshape.shapes
309+
SET
310+
name = '${shapeInformation.name}',
311+
formula = '${shapeInformation.formula}',
312+
vertices = '${shapeInformation.vertices}',
313+
private = '${shapeInformation.private}',
314+
edges = '${shapeInformation.edges}',
315+
notes = '${shapeInformation.notes}',
316+
type = '${shapeInformation.clipPathType}',
317+
backgroundColor = '${shapeInformation.backgroundColor}'
318+
WHERE
319+
shape_id === '${props.shape.shape_id}'
320+
`
321+
});
268322

269-
// Create the shape in the DB
270-
const insertShape = await harperFetch({
271-
operation: "sql",
272-
sql: `INSERT into tryshape.shapes(backgroundColor, createdAt, createdBy, edges, email, formula, likes, name, notes, private, type, vertices)
273-
values('${shapeInformation.backgroundColor}', null, '${props.user.email}', ${shapeInformation.edges}, null, '${shapeInformation.formula}', 0, '${shapeInformation.name}', '${shapeInformation.notes}', ${shapeInformation.private}, '${shapeInformation.clipPathType}', ${shapeInformation.vertices})`,
274-
});
323+
console.log(editShape);
324+
325+
if (editShape["update_hashes"].length > 0) {
326+
props.handleClose();
327+
toast.success(`Shape ${shapeInformation.name} edited successfully.`);
328+
props.setShapeAction({
329+
...props.shapeAction,
330+
"action": "edit",
331+
"payload": {
332+
"shape_id": editShape['update_hashes']
333+
}
334+
});
335+
} else {
336+
toast.error('OOPS!! We hit a bummer. Please try again.');
337+
}
275338

276-
console.log(insertShape);
277-
278-
// Create the user in the db
279-
if (insertShape['inserted_hashes'].length > 0) {
280-
// First check if the user exist
281-
const result = await harperFetch({
339+
// Creating Shape
340+
} else {
341+
342+
// Create the shape in the DB
343+
const insertShape = await harperFetch({
282344
operation: "sql",
283-
sql: `SELECT count(*) from tryshape.users WHERE email='${props.user.email}'`,
345+
sql: `INSERT into tryshape.shapes(backgroundColor, createdAt, createdBy, edges, email, formula, likes, name, notes, private, type, vertices)
346+
values('${shapeInformation.backgroundColor}', null, '${props.user.email}', ${shapeInformation.edges}, null, '${shapeInformation.formula}', 0, '${shapeInformation.name}', '${shapeInformation.notes}', ${shapeInformation.private}, '${shapeInformation.clipPathType}', ${shapeInformation.vertices})`,
284347
});
285-
const count = (result[0]['COUNT(*)']);
286-
console.log({count});
287-
// If doesn't exist, create in db
288-
if (count === 0) {
289-
const insertUser = await harperFetch({
348+
349+
console.log(insertShape);
350+
351+
// Create the user in the db
352+
if (insertShape['inserted_hashes'].length > 0) {
353+
// First check if the user exist
354+
const result = await harperFetch({
290355
operation: "sql",
291-
sql: `INSERT into tryshape.users(email, name, photoURL)
292-
values('${props.user.email}', '${props.user.displayName}', '${props.user.photoURL}')`,
356+
sql: `SELECT count(*) from tryshape.users WHERE email='${props.user.email}'`,
293357
});
358+
const count = (result[0]['COUNT(*)']);
359+
console.log({count});
360+
// If doesn't exist, create in db
361+
if (count === 0) {
362+
const insertUser = await harperFetch({
363+
operation: "sql",
364+
sql: `INSERT into tryshape.users(email, name, photoURL)
365+
values('${props.user.email}', '${props.user.displayName}', '${props.user.photoURL}')`,
366+
});
367+
} else {
368+
console.log(`The user ${props.user.email} present in DB`);
369+
}
370+
371+
// Finally, close the modal and update the shape in UI
372+
props.handleClose();
373+
if (props.setSearchTerm) {
374+
props.setSearchTerm('');
375+
}
376+
toast.success(`Shape ${shapeInformation.name} created successfully.`);
377+
props.setShapeAction({
378+
...props.shapeAction,
379+
"action": "add",
380+
"payload": {
381+
"shape_id": insertShape['inserted_hashes']
382+
}
383+
});
384+
294385
} else {
295-
console.log(`The user ${props.user.email} present in DB`);
386+
toast.error('OOPS!! We hit a bummer. Please try again.');
296387
}
297388

298-
// Finally, close the modal and update the shape in UI
299-
props.handleClose();
300-
toast.success(`Shape ${shapeInformation.name} created successfully.`);
301-
props.setShapeAction({
302-
...props.shapeAction,
303-
"action": "add",
304-
"payload": {
305-
"shape_id": insertShape['inserted_hashes']
306-
}
307-
});
308-
309-
setShapeInformation({
310-
...initialState,
311-
});
389+
}
312390

313-
setValidated(false);
391+
setShapeInformation({
392+
...initialState,
393+
});
314394

315-
} else {
316-
toast.error('OOPS!! We hit a bummer. Please try again.');
317-
}
395+
setValidated(false);
318396

319397
}
320398

@@ -328,7 +406,7 @@ const CreateShape = (props) => {
328406
backdrop="static"
329407
>
330408
<Modal.Header closeButton>
331-
<Modal.Title>Create a Shape</Modal.Title>
409+
<Modal.Title>{props.edit ? "Edit Shape" : "Create Shape"}</Modal.Title>
332410
</Modal.Header>
333411
<Modal.Body>
334412
<Container fluid>
@@ -352,11 +430,11 @@ const CreateShape = (props) => {
352430
</Container>
353431
</Modal.Body>
354432
<Modal.Footer>
355-
<Button onClick={() => { setShapeInformation({ ...initialState }); props.handleClose(); }} variant="outline-info">
356-
Close
357-
</Button>
358433
<Button variant="secondary" type="submit" form="createShapeForm" disabled={!shapeInformation.name}>
359-
Create
434+
{props.edit ? "Save Changes" : "Create"}
435+
</Button>
436+
<Button onClick={() => { setShapeInformation({ ...initialState }); props.handleClose(); }} variant="outline-dark">
437+
Cancel
360438
</Button>
361439
</Modal.Footer>
362440
</Modal>

components/core/DeleteShape.js

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import React from "react";
2+
3+
import Modal from "react-bootstrap/Modal";
4+
import Button from "react-bootstrap/Button";
5+
6+
import toast from "react-hot-toast";
7+
8+
import { harperFetch } from "../../utils/HarperFetch";
9+
10+
// Styled Component
11+
import styled from "styled-components";
12+
13+
// icons
14+
import { FiTrash2 } from 'react-icons/fi';
15+
16+
17+
const ModalHeader = styled.div`
18+
display: flex;
19+
align-items: center;
20+
grid-gap: 0.4rem;
21+
`;
22+
23+
const ModalContent = styled.div`
24+
display: flex;
25+
align-items: flex-start;
26+
grid-gap: 1rem;
27+
padding: 1rem 0 0 0.6rem;
28+
`;
29+
30+
const IconWrapper = styled.div`
31+
padding: 1.2rem 1rem 1rem 1rem;
32+
33+
34+
`;
35+
36+
const ContentWrapper = styled.div`
37+
padding: 1rem 0;
38+
39+
.modal-title {
40+
margin-left: 0;
41+
}
42+
`;
43+
44+
45+
46+
const DeleteShape = ({ show, setShow, shape, shapeAction, setShapeAction }) => {
47+
48+
const handleDelete = async() => {
49+
const deleteShape = await harperFetch({
50+
operation: "sql",
51+
sql: `
52+
DELETE FROM tryshape.shapes
53+
WHERE
54+
shape_id === '${shape.shape_id}'
55+
`
56+
});
57+
58+
console.log(deleteShape);
59+
60+
if (deleteShape["deleted_hashes"].length > 0) {
61+
setShow(false);
62+
toast.success(`Shape ${shape.name} deleted successfully.`);
63+
setShapeAction({
64+
...shapeAction,
65+
"action": "delete",
66+
"payload": {
67+
"shape_id": deleteShape["deleted_hashes"]
68+
}
69+
});
70+
} else {
71+
toast.error('OOPS!! We hit a bummer. Please try again.');
72+
}
73+
}
74+
75+
return(
76+
<Modal
77+
size="md"
78+
show={ show }
79+
onHide={() => setShow(false)}
80+
centered
81+
>
82+
<Modal.Body>
83+
<ModalContent>
84+
<IconWrapper>
85+
<FiTrash2 size="48px" color='var(--color-primary-pink)' />
86+
</IconWrapper>
87+
<ContentWrapper>
88+
<Modal.Title>Delete Shape</Modal.Title>
89+
<p>Are you sure you want to delete this shape? </p>
90+
</ContentWrapper>
91+
</ModalContent>
92+
</Modal.Body>
93+
<Modal.Footer>
94+
<Button onClick={() => handleDelete()} variant="danger">
95+
Yes
96+
</Button>
97+
<Button onClick={() => setShow(false)} variant="outline-dark">
98+
No
99+
</Button>
100+
</Modal.Footer>
101+
</Modal>
102+
);
103+
}
104+
105+
export default DeleteShape;

0 commit comments

Comments
 (0)