diff --git a/app/Http/Controllers/Forms/FormController.php b/app/Http/Controllers/Forms/FormController.php
index 8b29d6e0..9c268c5f 100644
--- a/app/Http/Controllers/Forms/FormController.php
+++ b/app/Http/Controllers/Forms/FormController.php
@@ -218,4 +218,24 @@ class FormController extends Controller
return redirect()->to(Storage::temporaryUrl($path, now()->addMinutes(5)));
}
+
+ /**
+ * Updates a form's workspace
+ */
+ public function updateWorkspace($id, $workspace_id)
+ {
+ $form = Form::findOrFail($id);
+ $workspace = Workspace::findOrFail($workspace_id);
+
+ $this->authorize('update', $form);
+ $this->authorize('view', $workspace);
+
+ $form->workspace_id = $workspace_id;
+ $form->creator_id = auth()->user()->id;
+ $form->save();
+
+ return $this->success([
+ 'message' => 'Form workspace updated successfully.',
+ ]);
+ }
}
diff --git a/app/Http/Requests/AnswerFormRequest.php b/app/Http/Requests/AnswerFormRequest.php
index 8e381f74..c1f8f9c1 100644
--- a/app/Http/Requests/AnswerFormRequest.php
+++ b/app/Http/Requests/AnswerFormRequest.php
@@ -27,6 +27,12 @@ class AnswerFormRequest extends FormRequest
$this->maxFileSize = $this->form->workspace->max_file_size;
}
+ private function getFieldMaxFileSize($fieldProps)
+ {
+ return array_key_exists('max_file_size', $fieldProps) ?
+ min($fieldProps['max_file_size'] * 1000000, $this->maxFileSize) : $this->maxFileSize;
+ }
+
/**
* Validate form before use it
*
@@ -180,7 +186,7 @@ class AnswerFormRequest extends FormRequest
if (! empty($property['allowed_file_types'])) {
$allowedFileTypes = explode(',', $property['allowed_file_types']);
}
- $this->requestRules[$property['id'].'.*'] = [new StorageFile($this->maxFileSize, $allowedFileTypes, $this->form)];
+ $this->requestRules[$property['id'] . '.*'] = [new StorageFile($this->getFieldMaxFileSize($property), $allowedFileTypes, $this->form)];
return ['array'];
case 'email':
diff --git a/app/Http/Requests/UserFormRequest.php b/app/Http/Requests/UserFormRequest.php
index 7444b525..74660646 100644
--- a/app/Http/Requests/UserFormRequest.php
+++ b/app/Http/Requests/UserFormRequest.php
@@ -118,6 +118,9 @@ abstract class UserFormRequest extends \Illuminate\Foundation\Http\FormRequest
'properties.*.generates_uuid' => 'boolean|nullable',
'properties.*.generates_auto_increment_id' => 'boolean|nullable',
+ // For file (min and max)
+ 'properties.*.max_file_size' => 'min:1|numeric',
+
// Security & Privacy
'can_be_indexed' => 'boolean',
'password' => 'sometimes|nullable',
diff --git a/client/components/forms/CodeInput.client.vue b/client/components/forms/CodeInput.client.vue
index 4d4a0090..50704574 100644
--- a/client/components/forms/CodeInput.client.vue
+++ b/client/components/forms/CodeInput.client.vue
@@ -11,7 +11,7 @@
diff --git a/client/components/forms/RichTextAreaInput.client.vue b/client/components/forms/RichTextAreaInput.client.vue
index ccd1d0c0..e3b609c4 100644
--- a/client/components/forms/RichTextAreaInput.client.vue
+++ b/client/components/forms/RichTextAreaInput.client.vue
@@ -7,7 +7,7 @@
diff --git a/client/components/forms/SignatureInput.vue b/client/components/forms/SignatureInput.vue
index c213a9dd..cda0ca9d 100644
--- a/client/components/forms/SignatureInput.vue
+++ b/client/components/forms/SignatureInput.vue
@@ -7,7 +7,7 @@
diff --git a/client/components/open/forms/fields/components/FieldOptions.vue b/client/components/open/forms/fields/components/FieldOptions.vue
index f65153c2..88d1db59 100644
--- a/client/components/open/forms/fields/components/FieldOptions.vue
+++ b/client/components/open/forms/fields/components/FieldOptions.vue
@@ -60,6 +60,13 @@
label="Allowed file types" placeholder="jpg,jpeg,png,gif"
help="Comma separated values, leave blank to allow all file types"
/>
+
+
@@ -428,6 +435,9 @@ export default {
required: false
}
},
+ setup() {
+ return { currentWorkspace: computed(() => useWorkspacesStore().getCurrent), }
+ },
data () {
return {
typesWithoutPlaceholder: ['date', 'checkbox', 'files'],
@@ -442,6 +452,9 @@ export default {
hasPlaceholder () {
return !this.typesWithoutPlaceholder.includes(this.field.type)
},
+ mbLimit() {
+ return this.form?.max_file_size ?? this.currentWorkspace?.max_file_size
+ },
prefillSelectsOptions () {
if (!['select', 'multi_select'].includes(this.field.type)) return {}
@@ -504,6 +517,9 @@ export default {
if (['text', 'number', 'url', 'email'].includes(this.field?.type) && !this.field?.max_char_limit) {
this.field.max_char_limit = 2000
}
+ if (this.field.type == 'files') {
+ this.field.max_file_size = Math.min((this.field.max_file_size ?? this.mbLimit), this.mbLimit)
+ }
},
methods: {
diff --git a/client/components/pages/forms/show/ExtraMenu.vue b/client/components/pages/forms/show/ExtraMenu.vue
index f6aca7fc..9e6b10c3 100644
--- a/client/components/pages/forms/show/ExtraMenu.vue
+++ b/client/components/pages/forms/show/ExtraMenu.vue
@@ -107,6 +107,17 @@
Create Template
+
+
+
+
+ Change workspace
+
+
+
@@ -159,6 +172,7 @@
import { ref, defineProps, computed } from 'vue'
import Dropdown from '~/components/global/Dropdown.vue'
import FormTemplateModal from '../../../open/forms/components/templates/FormTemplateModal.vue'
+import FormWorkspaceModal from '../../../open/forms/components/FormWorkspaceModal.vue'
const { copy } = useClipboard()
const router = useRouter()
@@ -177,6 +191,7 @@ let loadingDuplicate = ref(false)
let loadingDelete = ref(false)
let showDeleteFormModal = ref(false)
let showFormTemplateModal = ref(false)
+let showFormWorkspaceModal = ref(false)
const copyLink = () => {
copy(props.form.share_url)
diff --git a/routes/api.php b/routes/api.php
index bb27a16c..33885bb6 100644
--- a/routes/api.php
+++ b/routes/api.php
@@ -89,6 +89,7 @@ Route::group(['middleware' => 'auth:api'], function () {
Route::prefix('forms')->name('forms.')->group(function () {
Route::post('/', [FormController::class, 'store'])->name('store');
+ Route::post('/{id}/workspace/{workspace_id}', [FormController::class, 'updateWorkspace'])->name('workspace.update');
Route::put('/{id}', [FormController::class, 'update'])->name('update');
Route::delete('/{id}', [FormController::class, 'destroy'])->name('destroy');