Skip to content

Commit bdf0b1a

Browse files
committed
Store form fields in a separate table
1 parent a114e30 commit bdf0b1a

File tree

4 files changed

+68
-65
lines changed

4 files changed

+68
-65
lines changed

src/main/java/net/discordjug/javabot/systems/staff_commands/forms/commands/AddFieldFormSubcommand.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public void execute(SlashCommandInteractionEvent event) {
6666
return;
6767
}
6868

69-
formsRepo.addField(form, createFormFieldFromEvent(event), index);
69+
formsRepo.addField(form, createFormFieldFromEvent(event));
7070
event.getHook().sendMessage("Added a new field to the form.").queue();
7171
}
7272

@@ -98,6 +98,6 @@ private static FormField createFormFieldFromEvent(SlashCommandInteractionEvent e
9898
});
9999
String value = e.getOption("value", OptionMapping::getAsString);
100100

101-
return new FormField(label, max, min, placeholder, required, style.name(), value);
101+
return new FormField(label, max, min, placeholder, required, style, value, 0);
102102
}
103103
}

src/main/java/net/discordjug/javabot/systems/staff_commands/forms/dao/FormsRepository.java

Lines changed: 30 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import java.sql.PreparedStatement;
55
import java.sql.ResultSet;
66
import java.sql.SQLException;
7-
import java.util.ArrayList;
87
import java.util.Collections;
98
import java.util.HashMap;
109
import java.util.List;
@@ -18,10 +17,6 @@
1817
import org.springframework.jdbc.core.RowMapper;
1918
import org.springframework.stereotype.Repository;
2019

21-
import com.google.gson.Gson;
22-
import com.google.gson.JsonElement;
23-
import com.google.gson.JsonParser;
24-
2520
import lombok.NonNull;
2621
import lombok.RequiredArgsConstructor;
2722
import net.discordjug.javabot.systems.staff_commands.forms.model.FormData;
@@ -30,32 +25,28 @@
3025
import net.dv8tion.jda.api.entities.Message;
3126
import net.dv8tion.jda.api.entities.User;
3227
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
28+
import net.dv8tion.jda.api.interactions.components.text.TextInputStyle;
3329

3430
/**
3531
* Dao class that represents the FORMS database.
3632
*/
3733
@RequiredArgsConstructor
3834
@Repository
3935
public class FormsRepository {
40-
private final Gson gson;
4136
private final JdbcTemplate jdbcTemplate;
4237

4338
/**
4439
* Add a field to a form.
4540
*
4641
* @param form form to add field to
4742
* @param field field to add
48-
* @param index insertion index, or -1 to append
4943
*/
50-
public void addField(FormData form, FormField field, int index) {
51-
Objects.requireNonNull(field);
52-
List<FormField> fields = new ArrayList<>(form.getFields());
53-
if (index != -1) {
54-
fields.add(index, field);
55-
} else {
56-
fields.add(field);
57-
}
58-
updateFormData(form, fields);
44+
public void addField(FormData form, FormField field) {
45+
jdbcTemplate.update(
46+
"INSERT INTO FORM_FIELDS (FORM_ID, LABEL, MIN, MAX, PLACEHOLDER, REQUIRED, \"style\", INITIAL) "
47+
+ "VALUES(?, ?, ?, ?, ?, ?, ?, ?)",
48+
form.getId(), field.getLabel(), field.getMin(), field.getMax(), field.getPlaceholder(),
49+
field.isRequired(), field.getStyle().name(), field.getValue());
5950
}
6051

6152
/**
@@ -133,7 +124,7 @@ public void detachForm(FormData form) {
133124
* @return A list of forms
134125
*/
135126
public List<FormData> getAllForms() {
136-
return jdbcTemplate.query("select * from `forms`", (rs, rowNum) -> read(rs));
127+
return jdbcTemplate.query("select * from `forms`", (rs, rowNum) -> read(rs, readFormFields(rowNum)));
137128
}
138129

139130
/**
@@ -147,7 +138,7 @@ public List<FormData> getAllForms(boolean closed) {
147138
PreparedStatement statement = con.prepareStatement("select * from `forms` where `closed` = ?");
148139
statement.setBoolean(1, closed);
149140
return statement;
150-
}, (rs, rowNum) -> read(rs));
141+
}, (rs, rowNum) -> read(rs, readFormFields(rowNum)));
151142
}
152143

153144
/**
@@ -176,7 +167,7 @@ public Map<FormUser, Integer> getAllSubmissions(FormData form) {
176167
public Optional<FormData> getForm(long formId) {
177168
try {
178169
return Optional.of(jdbcTemplate.queryForObject("select * from `forms` where `form_id` = ?",
179-
(RowMapper<FormData>) (rs, rowNum) -> read(rs), formId));
170+
(RowMapper<FormData>) (rs, rowNum) -> read(rs, readFormFields(formId)), formId));
180171
} catch (EmptyResultDataAccessException e) {
181172
return Optional.empty();
182173
}
@@ -224,16 +215,14 @@ public void insertForm(@NonNull FormData data) {
224215
@Override
225216
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
226217
PreparedStatement statement = con.prepareStatement(
227-
"merge into `forms` (form_id, form_data, title, submit_message, submit_channel, message_id, message_channel, expiration, onetime) values (?, ?, ?, ?, ?, ?, ? ,?, ?)");
228-
statement.setLong(1, data.getId());
229-
statement.setString(2, gson.toJson(data.getFields()));
230-
statement.setString(3, data.getTitle());
231-
statement.setString(4, data.getSubmitMessage());
232-
statement.setString(5, data.getSubmitChannel());
233-
statement.setString(6, data.getMessageId());
234-
statement.setString(7, data.getMessageChannel());
235-
statement.setLong(8, data.getExpiration());
236-
statement.setBoolean(9, data.isOnetime());
218+
"insert into `forms` (title, submit_message, submit_channel, message_id, message_channel, expiration, onetime) values (?, ?, ?, ?, ?, ?, ?)");
219+
statement.setString(1, data.getTitle());
220+
statement.setString(2, data.getSubmitMessage());
221+
statement.setString(3, data.getSubmitChannel());
222+
statement.setString(4, data.getMessageId());
223+
statement.setString(5, data.getMessageChannel());
224+
statement.setLong(6, data.getExpiration());
225+
statement.setBoolean(7, data.isOnetime());
237226
return statement;
238227
}
239228
});
@@ -266,10 +255,9 @@ public void logSubmission(User user, FormData form) {
266255
* @param index index of the field to remove
267256
*/
268257
public void removeField(FormData form, int index) {
269-
List<FormField> fields = new ArrayList<>(form.getFields());
258+
List<FormField> fields = form.getFields();
270259
if (index < 0 || index >= fields.size()) return;
271-
fields.remove(index);
272-
updateFormData(form, fields);
260+
jdbcTemplate.update("delete from `form_fields` where `id` = ?", fields.get(index).getId());
273261
}
274262

275263
/**
@@ -302,26 +290,20 @@ public void updateForm(FormData newData) {
302290
});
303291
}
304292

305-
private FormData read(ResultSet rs) throws SQLException {
306-
List<FormField> fields = new ArrayList<>();
307-
for (JsonElement element : JsonParser.parseString(rs.getString("form_data")).getAsJsonArray()) {
308-
fields.add(gson.fromJson(element, FormField.class));
309-
}
293+
private List<FormField> readFormFields(long formId) {
294+
return jdbcTemplate.query("select * from `form_fields` where `form_id` = ?", (rs, rowNum) -> readField(rs),
295+
formId);
296+
}
297+
298+
private static FormData read(ResultSet rs, List<FormField> fields) throws SQLException {
310299
return new FormData(rs.getLong("form_id"), fields, rs.getString("title"), rs.getString("submit_channel"),
311300
rs.getString("submit_message"), rs.getString("message_id"), rs.getString("message_channel"),
312301
rs.getLong("expiration"), rs.getBoolean("closed"), rs.getBoolean("onetime"));
313302
}
314303

315-
private void updateFormData(FormData form, List<FormField> fields) {
316-
Objects.requireNonNull(form);
317-
Objects.requireNonNull(fields);
318-
String json = gson.toJson(fields);
319-
jdbcTemplate.update(con -> {
320-
PreparedStatement statement = con
321-
.prepareStatement("update `forms` set `form_data` = ? where `form_id` = ?");
322-
statement.setString(1, json);
323-
statement.setLong(2, form.getId());
324-
return statement;
325-
});
304+
private static FormField readField(ResultSet rs) throws SQLException {
305+
return new FormField(rs.getString("label"), rs.getInt("max"), rs.getInt("min"), rs.getString("placeholder"),
306+
rs.getBoolean("required"), TextInputStyle.valueOf(rs.getString("style").toUpperCase()),
307+
rs.getString("initial"), rs.getInt("id"));
326308
}
327309
}

src/main/java/net/discordjug/javabot/systems/staff_commands/forms/model/FormField.java

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@
77
* Represents a form field.
88
*/
99
public class FormField {
10+
private final long id;
1011
private final String label;
1112
private final int max;
1213
private final int min;
1314
private final String placeholder;
1415
private final boolean required;
15-
private final String style;
16+
private final TextInputStyle style;
1617
private final String value;
1718

1819
/**
@@ -26,8 +27,11 @@ public class FormField {
2627
* @param style text field style. One of {@link TextInputStyle} values.
2728
* Case insensitive.
2829
* @param value initial value of this text field.
30+
* @param id unique ID of this field.
2931
*/
30-
public FormField(String label, int max, int min, String placeholder, boolean required, String style, String value) {
32+
public FormField(String label, int max, int min, String placeholder, boolean required, TextInputStyle style,
33+
String value, long id) {
34+
this.id = id;
3135
this.label = label;
3236
this.max = max;
3337
this.min = min;
@@ -48,6 +52,15 @@ public TextInput createTextInput(String id) {
4852
.setPlaceholder(getPlaceholder()).setRequired(isRequired()).setValue(getValue()).build();
4953
}
5054

55+
/**
56+
* Get this field's unique ID.
57+
*
58+
* @return unique ID of the field.
59+
*/
60+
public long getId() {
61+
return id;
62+
}
63+
5164
public String getLabel() {
5265
return label;
5366
}
@@ -65,17 +78,12 @@ public String getPlaceholder() {
6578
}
6679

6780
/**
68-
* Get a parsed style of this field's text input.
69-
*
70-
* @return one of {@link TextInputStyle} values. Defaults to
71-
* {@link TextInputStyle#SHORT} if the stored value is invalid.
81+
* Get the style of this field's text input.
82+
*
83+
* @return one of {@link TextInputStyle} values.
7284
*/
7385
public TextInputStyle getStyle() {
74-
try {
75-
return style == null ? TextInputStyle.SHORT : TextInputStyle.valueOf(style.toUpperCase());
76-
} catch (IllegalArgumentException e) {
77-
return TextInputStyle.SHORT;
78-
}
86+
return style;
7987
}
8088

8189
public String getValue() {

src/main/resources/database/migrations/09-08-2025_forms.sql

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,30 @@
11
CREATE TABLE forms (
2-
form_id BIGINT NOT NULL,
3-
form_data VARCHAR NOT NULL,
2+
form_id BIGINT NOT NULL AUTO_INCREMENT,
43
title VARCHAR NOT NULL,
54
submit_message VARCHAR,
65
submit_channel VARCHAR NOT NULL,
76
message_id VARCHAR,
87
message_channel VARCHAR,
9-
expiration BIGINT NOT NULL,
8+
expiration BIGINT NOT NULL DEFAULT -1,
109
closed BOOLEAN NOT NULL DEFAULT FALSE,
11-
onetime BOOLEAN NOT NULL,
10+
onetime BOOLEAN NOT NULL DEFAULT FALSE,
1211
PRIMARY KEY (form_id)
1312
);
1413

14+
CREATE TABLE FORM_FIELDS (
15+
ID BIGINT NOT NULL AUTO_INCREMENT,
16+
FORM_ID BIGINT NOT NULL,
17+
LABEL CHARACTER VARYING NOT NULL,
18+
MIN INTEGER DEFAULT 0 NOT NULL,
19+
MAX INTEGER DEFAULT 16 NOT NULL,
20+
PLACEHOLDER CHARACTER VARYING,
21+
REQUIRED BOOLEAN DEFAULT FALSE NOT NULL,
22+
"style" ENUM('SHORT', 'PARAGRAPH') DEFAULT 'SHORT' NOT NULL,
23+
INITIAL CHARACTER VARYING,
24+
PRIMARY KEY (ID),
25+
FOREIGN KEY (FORM_ID) REFERENCES FORMS(FORM_ID) ON DELETE CASCADE ON UPDATE RESTRICT
26+
);
27+
1528
CREATE TABLE form_submissions (
1629
"timestamp" BIGINT NOT NULL,
1730
user_id VARCHAR NOT NULL,

0 commit comments

Comments
 (0)