Skip to content

Commit d3959f6

Browse files
Improve partial form submission validation and synchronization
1 parent 52c5812 commit d3959f6

File tree

4 files changed

+43
-6
lines changed

4 files changed

+43
-6
lines changed

api/app/Http/Controllers/Forms/PublicFormController.php

+15
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Illuminate\Support\Facades\Auth;
1717
use Illuminate\Support\Facades\Storage;
1818
use Vinkla\Hashids\Facades\Hashids;
19+
use Illuminate\Support\Str;
1920

2021
class PublicFormController extends Controller
2122
{
@@ -98,6 +99,20 @@ private function handlePartialSubmissions(Request $request)
9899
// Process submission data to extract submission ID
99100
$submissionData = $this->processSubmissionIdentifiers($request, $request->all());
100101

102+
// Validate that at least one field has a value
103+
$hasValue = false;
104+
foreach ($submissionData as $key => $value) {
105+
if (Str::isUuid($key) && !empty($value)) {
106+
$hasValue = true;
107+
break;
108+
}
109+
}
110+
if (!$hasValue) {
111+
return $this->error([
112+
'message' => 'At least one field must have a value for partial submissions.'
113+
], 422);
114+
}
115+
101116
// Explicitly mark this as a partial submission
102117
$submissionData['is_partial'] = true;
103118

client/components/open/forms/OpenCompleteForm.vue

+8-4
Original file line numberDiff line numberDiff line change
@@ -303,16 +303,16 @@ export default {
303303
if (form.busy) return
304304
this.loading = true
305305
306+
if (this.form?.enable_partial_submissions) {
307+
this.partialSubmission.stopSync()
308+
}
309+
306310
form.post('/forms/' + this.form.slug + '/answer').then((data) => {
307311
this.submittedData = form.data()
308312
useAmplitude().logEvent('form_submission', {
309313
workspace_id: this.form.workspace_id,
310314
form_id: this.form.id
311315
})
312-
313-
if (this.form?.enable_partial_submissions) {
314-
this.partialSubmission.stopSync()
315-
}
316316
317317
const payload = clonedeep({
318318
type: 'form-submitted',
@@ -351,6 +351,10 @@ export default {
351351
this.confetti.play()
352352
}
353353
}).catch((error) => {
354+
if (this.form?.enable_partial_submissions) {
355+
this.partialSubmission.startSync()
356+
}
357+
354358
console.error(error)
355359
if (error.response && error.data && error.data.message) {
356360
useAlert().error(error.data.message)

client/composables/forms/pendingSubmission.js

+13
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,17 @@ export const pendingSubmission = (form) => {
3131
return pendingSubmission ? JSON.parse(pendingSubmission) : defaultValue
3232
}
3333

34+
const setSubmissionHash = (hash) => {
35+
set({
36+
...get(),
37+
submission_hash: hash
38+
})
39+
}
40+
41+
const getSubmissionHash = () => {
42+
return get()?.submission_hash ?? null
43+
}
44+
3445
const setTimer = (value) => {
3546
if (import.meta.server) return
3647
useStorage(formPendingSubmissionTimerKey.value).value = value
@@ -51,6 +62,8 @@ export const pendingSubmission = (form) => {
5162
set,
5263
get,
5364
remove,
65+
setSubmissionHash,
66+
getSubmissionHash,
5467
setTimer,
5568
removeTimer,
5669
getTimer,

client/composables/forms/usePartialSubmission.js

+7-2
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@ export const usePartialSubmission = (form, formData = {}) => {
1212
let dataWatcher = null
1313

1414
const getSubmissionHash = () => {
15-
return submissionHashes.value.get(pendingSubmission.formPendingSubmissionKey.value)
15+
return pendingSubmission.getSubmissionHash() ?? submissionHashes.value.get(pendingSubmission.formPendingSubmissionKey.value)
1616
}
1717

1818
const setSubmissionHash = (hash) => {
1919
submissionHashes.value.set(pendingSubmission.formPendingSubmissionKey.value, hash)
20+
pendingSubmission.setSubmissionHash(hash)
2021
}
2122

2223
const debouncedSync = () => {
@@ -92,6 +93,8 @@ export const usePartialSubmission = (form, formData = {}) => {
9293
}
9394

9495
const stopSync = () => {
96+
submissionHashes.value = new Map()
97+
9598
if (dataWatcher) {
9699
dataWatcher()
97100
dataWatcher = null
@@ -113,7 +116,9 @@ export const usePartialSubmission = (form, formData = {}) => {
113116
stopSync()
114117

115118
// Final sync attempt before unmounting
116-
syncToServer()
119+
if(getSubmissionHash()) {
120+
syncToServer()
121+
}
117122
})
118123

119124
return {

0 commit comments

Comments
 (0)