102102 name =" allow_text_assignment"
103103 label =" "
104104 />
105+
106+ <BaseCheckbox
107+ id =" require_extension"
108+ v-model =" chkRequireExtension"
109+ :label =" t('Require specific file format')"
110+ name =" require_extension"
111+ />
112+
113+ <div v-if =" chkRequireExtension" >
114+ <BaseMultiSelect
115+ v-model =" assignment.allowedExtensions"
116+ :options =" predefinedExtensions"
117+ :label =" t('Select allowed file formats')"
118+ input-id =" allowed-file-extensions"
119+ />
120+
121+ <BaseInputText
122+ v-if =" assignment.allowedExtensions.includes('other')"
123+ id =" custom-extensions"
124+ v-model =" assignment.customExtensions"
125+ :label =" t('Custom extensions (separated by space)')"
126+ />
127+
128+ </div >
105129 </BaseAdvancedSettingsButton >
106130
107131 <div class =" flex justify-end space-x-2 mt-4" >
@@ -123,6 +147,7 @@ import BaseAdvancedSettingsButton from "../basecomponents/BaseAdvancedSettingsBu
123147import BaseButton from " ../basecomponents/BaseButton.vue"
124148import BaseCheckbox from " ../basecomponents/BaseCheckbox.vue"
125149import BaseSelect from " ../basecomponents/BaseSelect.vue"
150+ import BaseMultiSelect from " ../basecomponents/BaseMultiSelect.vue" ;
126151import BaseInputNumber from " ../basecomponents/BaseInputNumber.vue"
127152import BaseTinyEditor from " ../basecomponents/BaseTinyEditor.vue"
128153import useVuelidate from " @vuelidate/core"
@@ -162,6 +187,17 @@ const documentTypes = ref([
162187 { label: t (" Allow only files" ), value: 2 },
163188])
164189
190+ const chkRequireExtension = ref (false )
191+ const predefinedExtensions = ref ([
192+ {name: ' PDF' , id: ' pdf' },
193+ {name: ' DOCX' , id: ' docx' },
194+ {name: ' XLSX' , id: ' xlsx' },
195+ {name: ' ZIP' , id: ' zip' },
196+ {name: ' MP3' , id: ' mp3' },
197+ {name: ' MP4' , id: ' mp4' },
198+ {name: t (' Other extensions' ), id: ' other' },
199+ ])
200+
165201const assignment = reactive ({
166202 title: " " ,
167203 description: " " ,
@@ -172,6 +208,8 @@ const assignment = reactive({
172208 endsOn: new Date (),
173209 addToCalendar: false ,
174210 allowTextAssignment: 2 ,
211+ allowedExtensions: [],
212+ customExtensions: ' ' ,
175213})
176214
177215watchEffect (() => {
@@ -198,13 +236,41 @@ watchEffect(() => {
198236
199237 assignment .allowTextAssignment = def .allowTextAssignment
200238
239+
240+ if (def .extensions ) {
241+ const extensionsArray = def .extensions
242+ .split (' ' )
243+ .map (ext => ext .trim ())
244+ .filter (ext => ext .length > 0 )
245+
246+ if (extensionsArray .length > 0 ) {
247+ chkRequireExtension .value = true
248+
249+ const predefinedIds = predefinedExtensions .value
250+ .map (e => e .id )
251+ .filter (id => id !== ' other' )
252+
253+ const predefined = extensionsArray .filter (ext => predefinedIds .includes (ext))
254+ const custom = extensionsArray .filter (ext => ! predefinedIds .includes (ext))
255+ if (assignment .allowedExtensions .length === 0 ) {
256+ assignment .allowedExtensions = predefined
257+
258+ if (custom .length > 0 ) {
259+ assignment .allowedExtensions .push (' other' )
260+ assignment .customExtensions = custom .join (' ' )
261+ }
262+ }
263+ }
264+ }
265+
201266 if (
202267 def .qualification ||
203268 def .assignment .eventCalendarId ||
204269 def .weight ||
205270 def .assignment .expiresOn ||
206271 def .assignment .endsOn ||
207- def .allowTextAssignment !== undefined
272+ def .allowTextAssignment !== undefined ||
273+ (def .allowedExtensions )
208274 ) {
209275 showAdvancedSettings .value = true
210276 }
@@ -256,6 +322,26 @@ async function onSubmit() {
256322 if (chkEndsOn .value ) {
257323 payload .endsOn = assignment .endsOn .toISOString ()
258324 }
325+ if (chkRequireExtension .value && assignment .allowedExtensions .length > 0 ) {
326+ let extensions = []
327+
328+ assignment .allowedExtensions .forEach (ext => {
329+ if (ext !== ' other' ) {
330+ extensions .push (ext)
331+ }
332+ })
333+ if (assignment .allowedExtensions .includes (' other' ) && assignment .customExtensions ) {
334+ const customExts = assignment .customExtensions
335+ .split (' ' )
336+ .map (ext => ext .trim ().toLowerCase ().replace (' .' , ' ' ))
337+ .filter (ext => ext .length > 0 )
338+ extensions .push (... customExts)
339+ }
340+
341+ if (extensions .length > 0 ) {
342+ payload .extensions = extensions .join (' ' ) // "pdf docx rar ai"
343+ }
344+ }
259345 if (props .defaultAssignment ? .[" @id" ]) {
260346 payload[" @id" ] = props .defaultAssignment [" @id" ]
261347 }
0 commit comments