Skip to content

Commit 8d1eb8f

Browse files
authored
Merge pull request #21 from bielchristo/draggable
Adding Drag and Drop Functionality to the Accessibility Portion of Spearmint
2 parents a15d5d8 + 2ac6dff commit 8d1eb8f

File tree

8 files changed

+282
-274
lines changed

8 files changed

+282
-274
lines changed

src/App.jsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@ import RightPanel from './pages/RightPanel/RightPanel';
88
import About from './pages/About/About';
99

1010
const App = () => {
11-
// useReducer takes a reducer and initial state as
12-
// args and return the current state paired with a dispatch method
13-
// distpatchTo method invokes associated reducer function
14-
1511
const [global, dispatchToGlobal] = useReducer(globalReducer, globalState);
1612

1713
if (!global.isProjectLoaded) {
Lines changed: 70 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,14 @@
1-
/* eslint-disable @typescript-eslint/no-unused-vars */
2-
/* eslint-disable linebreak-style */
3-
/* eslint-disable no-trailing-spaces */
4-
// import React object and destructure useRef and useEffect hooks
51
import React, { useRef, useEffect } from 'react';
6-
7-
// import It component
2+
import cn from 'classnames';
3+
import { Draggable, Droppable } from 'react-beautiful-dnd';
84
import ItRenderer from '../ItRenderer/ItRenderer';
9-
10-
// import Draggable for drag and drop functionality
11-
import { Draggable } from 'react-beautiful-dnd';
12-
13-
// import styling
145
import styles from './DescribeRenderer.module.scss';
15-
16-
// import action types
176
import { deleteDescribeBlock, addItStatement } from '../../../context/actions/accTestCaseActions';
187

19-
// import from accTypes - ### add after html structure is created?
20-
import { Assertion, AccObj, Header, Action, EventTarget } from '../../utils/accTypes';
21-
22-
import cn from 'classnames';
23-
// require in icons
24-
const closeIcon = require('../../../assets/images/close.png');
25-
// const dragIcon = require('../../assets/images/drag-vertical.png');
26-
// const minusIcon = require('../../assets/images/minus-box-outline.png');
27-
28-
298
const DescribeRenderer = ({
309
dispatcher,
3110
describeBlocks,
3211
itStatements,
33-
statements,
34-
draggableStatements,
3512
handleChangeDescribeText,
3613
handleChangeItStatementText,
3714
type,
@@ -53,52 +30,75 @@ const DescribeRenderer = ({
5330
dispatcher(addItStatement(describeId));
5431
};
5532

56-
return draggableStatements.map((id, i) => {
57-
return (
58-
<div id={styles.describeBlock} key={i}>
59-
<label htmlFor='describe-label' className={styles.describeLabel}>
60-
Describe Block
61-
</label>
62-
63-
<i
64-
onClick={deleteDescribeBlockHandleClick}
65-
id={id}
66-
className={cn('far fa-window-close', styles.describeClose)}
67-
></i>
68-
69-
<input
70-
ref={testDescription}
71-
id={id}
72-
className={styles.describeInput}
73-
name='describe-label'
74-
type='text'
75-
placeholder={'Component has basic accessibility'}
76-
value={describeBlocks.byId[id].text || ''}
77-
onChange={handleChangeDescribeText}
78-
/>
79-
80-
<div className={styles.separator}></div>
81-
<ItRenderer
82-
type={type}
83-
key={`it-${id}-${i}`}
84-
itStatements={itStatements}
85-
statements={statements}
86-
describeId={id}
87-
handleChangeItStatementText={handleChangeItStatementText}
88-
/>
89-
90-
{/* Implement Button For Stretch */}
91-
<div className={styles.buttonContainer}>
92-
<button className={styles.addIt} id={id} onClick={addItStatementHandleClick}>
93-
+It Statement
94-
</button>
33+
return describeBlocks.allIds.map((id, i) => (
34+
<Draggable
35+
key={id}
36+
draggableId={id}
37+
index={i}
38+
type="describe"
39+
>
40+
{(provided) => (
41+
<div
42+
ref={provided.innerRef}
43+
{...provided.draggableProps}
44+
{...provided.dragHandleProps}
45+
>
46+
<div id={styles.describeBlock} key={i}>
47+
<label htmlFor="describe-label" className={styles.describeLabel}>
48+
Describe Block
49+
</label>
50+
51+
<i
52+
onClick={deleteDescribeBlockHandleClick}
53+
id={id}
54+
className={cn('far fa-window-close', styles.describeClose)}
55+
/>
56+
57+
<input
58+
ref={testDescription}
59+
id={id}
60+
className={styles.describeInput}
61+
name="describe-label"
62+
type="text"
63+
placeholder="Component has basic accessibility"
64+
value={describeBlocks.byId[id].text || ''}
65+
onChange={handleChangeDescribeText}
66+
/>
67+
68+
<div className={styles.separator} />
69+
70+
<Droppable
71+
droppableId={"droppableAccIt" + id}
72+
type={id}
73+
>
74+
{(innerProvided) => (
75+
<div
76+
ref={innerProvided.innerRef}
77+
{...innerProvided.droppableProps}
78+
>
79+
<ItRenderer
80+
type={type}
81+
key={`it-${id}-${i}`}
82+
itStatements={itStatements}
83+
describeId={id}
84+
handleChangeItStatementText={handleChangeItStatementText}
85+
/>
86+
{innerProvided.placeholder}
87+
</div>
88+
)}
89+
</Droppable>
90+
91+
<div className={styles.buttonContainer}>
92+
<button className={styles.addIt} id={id} onClick={addItStatementHandleClick}>
93+
+It Statement
94+
</button>
95+
</div>
96+
97+
</div>
9598
</div>
96-
97-
</div>
98-
);
99-
});
99+
)}
100+
</Draggable>
101+
));
100102
};
101103

102104
export default DescribeRenderer;
103-
104-
Lines changed: 34 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
import React, { useContext } from 'react';
22
import cn from 'classnames';
3-
3+
import { Draggable } from 'react-beautiful-dnd';
44
import { AccTestCaseContext } from '../../../context/reducers/accTestCaseReducer';
55

6-
// test case statements are for action, assertion, and render options
7-
// import AccTestStatements from '../../TestCase/AccTestStatements';
8-
96
import {
107
deleteItStatement,
118
} from '../../../context/actions/accTestCaseActions';
@@ -18,55 +15,50 @@ const ItRenderer = ({
1815
type,
1916
itStatements,
2017
describeId,
21-
statements,
2218
handleChangeItStatementText,
2319
}) => {
2420

2521
const [, dispatchToAccTestCase] = useContext(AccTestCaseContext);
2622

27-
// filter out ids not belonging to the correct describe block
28-
// ### do we need this?
29-
const filteredIds = itStatements.allIds.filter((id) => {
30-
return itStatements.byId[id].describeId === describeId;
31-
});
32-
33-
3423
const deleteItStatementHandleClick = (e) => {
3524
const itId = e.target.id;
3625
dispatchToAccTestCase(deleteItStatement(describeId, itId));
3726
};
3827

39-
return filteredIds.map((id, i) => (
40-
<div id={styles.ItRenderer} key={i}>
41-
42-
<i
43-
onClick={deleteItStatementHandleClick}
44-
id={id}
45-
className={cn(styles.itClose, 'far fa-window-close')}
46-
></i>
47-
48-
<CustomInput
49-
key={`input-${id}-${i}`}
50-
id={id}
51-
label={'The element should...'}
52-
placeholder={'The tested element should...'}
53-
value={itStatements.byId[id].text}
54-
handleChange={handleChangeItStatementText}
55-
/>
56-
57-
<hr />
58-
59-
</div>
28+
return itStatements.allIds[describeId].map((id, i) => (
29+
<Draggable
30+
draggableId={id}
31+
index={i}
32+
>
33+
{(provided) => (
34+
<div
35+
ref={provided.innerRef}
36+
{...provided.draggableProps}
37+
{...provided.dragHandleProps}
38+
id={styles.ItRenderer}
39+
key={i}
40+
>
41+
42+
<i
43+
onClick={deleteItStatementHandleClick}
44+
id={id}
45+
className={cn(styles.itClose, 'far fa-window-close')}
46+
/>
47+
48+
<CustomInput
49+
key={`input-${id}-${i}`}
50+
id={id}
51+
label={'The element should...'}
52+
placeholder={'The tested element should...'}
53+
value={itStatements.byId[id].text}
54+
handleChange={handleChangeItStatementText}
55+
/>
56+
<hr />
57+
58+
</div>
59+
)}
60+
</Draggable>
6061
));
6162
};
6263

6364
export default ItRenderer;
64-
65-
66-
// ## stretch use?
67-
// <ReactTestStatements
68-
// key={`statement-${id}-${i}`}
69-
// statements={statements}
70-
// itId={id}
71-
// describeId={describeId}
72-
// />

src/components/ReactTestComponent/DescribeRenderer/DescribeRenderer.jsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@ const DescribeRenderer = ({
3333
dispatcher(addItstatement(describeId));
3434
};
3535

36-
return describeBlocks.allIds.map((id, i) => {
37-
return (
36+
return describeBlocks.allIds.map((id, i) => (
3837
<Draggable
3938
key={id}
4039
draggableId={id}
@@ -100,8 +99,7 @@ const DescribeRenderer = ({
10099

101100
)}
102101
</Draggable>
103-
);
104-
});
102+
));
105103
};
106104

107105
export default DescribeRenderer;

src/components/TestCase/AccTestCase.jsx

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import React, { useContext, useReducer } from 'react';
22
import cn from 'classnames';
3+
import { DragDropContext, Droppable } from 'react-beautiful-dnd';
34
import styles from './TestCase.module.scss';
45
import {
56
updateDescribeText,
67
updateItStatementText,
8+
updateDescribeOrder,
9+
updateItStatementOrder,
710
} from '../../context/actions/accTestCaseActions';
811
import { GlobalContext } from '../../context/reducers/globalReducer';
912
import SearchInput from '../SearchInput/SearchInput';
1013

11-
// ### this ties in with Sharon's code - did not create a file ### VERIFY PATH
1214
import AccTestMenu from '../TestMenu/AccTestMenu';
1315

1416
import DecribeRenderer from '../AccTestComponent/DescribeRenderer/DescribeRenderer';
@@ -24,10 +26,9 @@ const AccTestCase = () => {
2426
AccTestCaseContext,
2527
);
2628

27-
const { describeBlocks, itStatements, statements } = accTestCase;
29+
const { describeBlocks, itStatements } = accTestCase;
2830

2931
const [{ filePathMap }] = useContext(GlobalContext);
30-
const draggableStatements = describeBlocks.allIds;
3132

3233
const handleChangeDescribeText = (e) => {
3334
const text = e.target.value;
@@ -41,6 +42,26 @@ const AccTestCase = () => {
4142
dispatchToAccTestCase(updateItStatementText(text, itId));
4243
};
4344

45+
const reorder = (list, startIndex, endIndex) => {
46+
const result = Array.from(list);
47+
const [removed] = result.splice(startIndex, 1);
48+
result.splice(endIndex, 0, removed);
49+
return result;
50+
};
51+
52+
const onDragEnd = (result) => {
53+
// edge cases: dropped to a non-destination, or dropped where it was grabbed (no change)
54+
if (!result.destination) return;
55+
if (result.destination.index === result.source.index) return;
56+
57+
const list = result.draggableId.includes('describe') ? describeBlocks.allIds : itStatements.allIds[result.type];
58+
const func = result.draggableId.includes('describe') ? updateDescribeOrder : updateItStatementOrder;
59+
60+
const reorderedStatements = reorder(list, result.source.index, result.destination.index);
61+
62+
dispatchToAccTestCase(func(reorderedStatements, result.type));
63+
};
64+
4465
return (
4566
<div id={styles.AccTestCase}>
4667

@@ -59,16 +80,29 @@ const AccTestCase = () => {
5980
/>
6081
</div>
6182

62-
<DecribeRenderer
63-
dispatcher={dispatchToAccTestCase}
64-
draggableStatements={draggableStatements}
65-
describeBlocks={describeBlocks}
66-
itStatements={itStatements}
67-
statements={statements}
68-
handleChangeDescribeText={handleChangeDescribeText}
69-
handleChangeItStatementText={handleChangeItStatementText}
70-
type="acc"
71-
/>
83+
<DragDropContext onDragEnd={onDragEnd}>
84+
<Droppable
85+
droppableId="droppableAccDescribe"
86+
type="describe"
87+
>
88+
{(provided) => (
89+
<div
90+
ref={provided.innerRef}
91+
{...provided.droppableProps}
92+
>
93+
<DecribeRenderer
94+
dispatcher={dispatchToAccTestCase}
95+
describeBlocks={describeBlocks}
96+
itStatements={itStatements}
97+
handleChangeDescribeText={handleChangeDescribeText}
98+
handleChangeItStatementText={handleChangeItStatementText}
99+
type="acc"
100+
/>
101+
{provided.placeholder}
102+
</div>
103+
)}
104+
</Droppable>
105+
</DragDropContext>
72106
</section>
73107

74108
</div>

0 commit comments

Comments
 (0)