forked from rowyio/rowy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSettings.tsx
221 lines (209 loc) · 6.97 KB
/
Settings.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
import { useState, useRef } from "react";
import { ISettingsProps } from "@src/components/fields/types";
import {
InputLabel,
TextField,
Grid,
IconButton,
Typography,
Divider,
FormControlLabel,
Checkbox,
FormHelperText,
} from "@mui/material";
import AddIcon from "@mui/icons-material/AddCircle";
import RemoveIcon from "@mui/icons-material/CancelRounded";
import ColorSelect, {
SelectColorThemeOptions,
} from "@src/components/SelectColors";
import {
DragDropContext,
Draggable,
DraggingStyle,
Droppable,
NotDraggingStyle,
} from "react-beautiful-dnd";
import DragIndicatorOutlinedIcon from "@mui/icons-material/DragIndicatorOutlined";
const getItemStyle = (
isDragging: boolean,
draggableStyle: DraggingStyle | NotDraggingStyle | undefined
) => ({
backgroundColor: isDragging ? "rgba(255, 255, 255, 0.08)" : "",
borderRadius: "4px",
...draggableStyle,
});
export default function Settings({ onChange, config }: ISettingsProps) {
const listEndRef: any = useRef(null);
let options = config.options ?? [];
const [newOption, setNewOption] = useState("");
/* State for holding Chip Colors for Select and MultiSelect */
const colors = config.colors ?? {};
const handleAdd = () => {
if (newOption.trim() !== "") {
if (options.includes(newOption)) {
window.alert(`"${newOption}" is already an option`);
} else {
onChange("options")([...options, newOption.trim()]);
setNewOption("");
listEndRef.current.scrollIntoView({ behavior: "smooth", block: "end" });
}
}
};
const handleChipColorChange = (
type: "save" | "delete",
key: string,
color?: SelectColorThemeOptions
) => {
const _key = key.toLocaleLowerCase();
if (type === "save") colors[_key] = color;
else if (type === "delete") delete colors[_key];
onChange("colors")(colors);
};
const handleItemDelete = async (option: string) => {
onChange("options")(options.filter((o: string) => o !== option));
};
const handleOnDragEnd = (result: any) => {
if (!result.destination) return;
const [removed] = options.splice(result.source.index, 1);
options.splice(result.destination.index, 0, removed);
onChange("options")([...options]);
};
return (
<div>
<InputLabel>Options</InputLabel>
<div
style={{
maxHeight: 180,
overflowY: "scroll",
overflowX: "hidden",
marginBottom: 5,
}}
>
<DragDropContext onDragEnd={handleOnDragEnd}>
<Droppable droppableId="options_manager" direction="vertical">
{(provided) => (
<div ref={provided.innerRef} {...provided.droppableProps}>
{options?.map((option: string, index: number) => (
<Draggable key={option} draggableId={option} index={index}>
{(provided, snapshot) => (
<>
<Grid
ref={provided.innerRef}
{...provided.draggableProps}
style={getItemStyle(
snapshot.isDragging,
provided.draggableProps.style
)}
container
direction="row"
key={`option-${option}`}
justifyContent="space-between"
alignItems="center"
>
<Grid
{...provided.dragHandleProps}
item
sx={{ display: "flex" }}
alignItems="center"
>
<DragIndicatorOutlinedIcon
color="disabled"
sx={[
{
marginRight: "6px",
},
]}
/>
<Grid
container
direction="row"
alignItems="center"
gap={2}
>
<ColorSelect
initialValue={
colors[option.toLocaleLowerCase()]
}
handleChange={(color) =>
handleChipColorChange("save", option, color)
}
/>
<Typography>{option}</Typography>
</Grid>
</Grid>
<Grid item>
<IconButton
aria-label="Remove"
onClick={() =>
handleItemDelete(option).then(() => {
handleChipColorChange("delete", option);
console.log(options, colors); // Here for debugging purposes
})
}
>
{<RemoveIcon />}
</IconButton>
</Grid>
</Grid>
<Divider />
</>
)}
</Draggable>
))}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
<div ref={listEndRef} style={{ height: 40 }} />
</div>
<Grid container direction="row" alignItems="center">
<Grid item>
<IconButton
aria-label="Add new"
onClick={() => {
handleAdd();
}}
>
{<AddIcon />}
</IconButton>
</Grid>
<Grid item xs={10} md={11}>
<TextField
value={newOption}
fullWidth
label="New option"
id="new-option"
onChange={(e) => {
setNewOption(e.target.value);
}}
onKeyPress={(e: any) => {
if (e.key === "Enter") {
handleAdd();
}
}}
helperText=" "
/>
</Grid>
</Grid>
<FormControlLabel
control={
<Checkbox
checked={config.freeText}
onChange={(e) => onChange("freeText")(e.target.checked)}
/>
}
label={
<>
Users can add custom options
<FormHelperText>
Custom options will only appear in the row it was added to. They
will not appear in the list of options above.
</FormHelperText>
</>
}
style={{ marginLeft: -10 }}
/>
</div>
);
}