|
32 | 32 | @openSharing="openSharing" |
33 | 33 | @mobileCloseNavigation="mobileCloseNavigation" |
34 | 34 | @clone="onCloneForm" |
| 35 | + @download="onDownloadForm" |
35 | 36 | @delete="onDeleteForm" /> |
36 | 37 | </ul> |
37 | 38 | </template> |
|
51 | 52 | readOnly |
52 | 53 | @openSharing="openSharing" |
53 | 54 | @clone="onCloneForm" |
| 55 | + @download="onDownloadForm" |
54 | 56 | @mobileCloseNavigation="mobileCloseNavigation" /> |
55 | 57 | </ul> |
56 | 58 | </template> |
@@ -170,6 +172,7 @@ import AppNavigationForm from './components/AppNavigationForm.vue' |
170 | 172 | import ArchivedFormsModal from './components/ArchivedFormsModal.vue' |
171 | 173 | import Sidebar from './views/Sidebar.vue' |
172 | 174 | import FormsIcon from '../img/forms-dark.svg?raw' |
| 175 | +import { version } from '../package.json' |
173 | 176 | import PermissionTypes from './mixins/PermissionTypes.js' |
174 | 177 | import { FormState } from './models/Constants.ts' |
175 | 178 | import logger from './utils/Logger.js' |
@@ -440,6 +443,60 @@ export default { |
440 | 443 | } |
441 | 444 | } |
442 | 445 |
|
| 446 | + const onDownloadForm = async (id) => { |
| 447 | + const response = await axios.get( |
| 448 | + generateOcsUrl('apps/forms/api/v3/forms/{id}', { |
| 449 | + id, |
| 450 | + }), |
| 451 | + ) |
| 452 | + const form = OcsResponse2Data(response) |
| 453 | +
|
| 454 | + // download only required values |
| 455 | + const download = { |
| 456 | + appVersion: version, |
| 457 | + form: { |
| 458 | + title: form.title, |
| 459 | + description: form.description, |
| 460 | + isAnonymous: form.isAnonymous, |
| 461 | + submitMultiple: form.submitMultiple, |
| 462 | + allowEditSubmissions: form.allowEditSubmissions, |
| 463 | + showExpiration: form.showExpiration, |
| 464 | + submissionMessage: form.submissionMessage, |
| 465 | + maxSubmissions: form.maxSubmissions, |
| 466 | + confirmationEmailEnabled: form.confirmationEmailEnabled, |
| 467 | + confirmationEmailSubject: form.confirmationEmailSubject, |
| 468 | + confirmationEmailBody: form.confirmationEmailBody, |
| 469 | + confirmationEmailQuestionId: form.confirmationEmailQuestionId, |
| 470 | + allowComments: form.allowComments, |
| 471 | + questions: form.questions.map((question) => ({ |
| 472 | + type: question.type, |
| 473 | + order: question.order, |
| 474 | + isRequired: question.isRequired, |
| 475 | + text: question.text, |
| 476 | + name: question.name, |
| 477 | + description: question.description, |
| 478 | + extraSettings: question.extraSettings, |
| 479 | + options: question.options.map((option) => ({ |
| 480 | + order: option.order, |
| 481 | + text: option.text, |
| 482 | + optionType: option.optionType, |
| 483 | + })), |
| 484 | + accept: question.accept, |
| 485 | + })), |
| 486 | + }, |
| 487 | + } |
| 488 | + // create blob and download |
| 489 | + const blob = new Blob([JSON.stringify(download)]) |
| 490 | + const url = URL.createObjectURL(blob) |
| 491 | + const a = document.createElement('a') |
| 492 | + a.href = url |
| 493 | + const formTitle = form.title ? form.title : t('forms', 'New form') |
| 494 | + a.download = `${formTitle}.json` |
| 495 | + a.click() |
| 496 | + a.remove() |
| 497 | + URL.revokeObjectURL(url) |
| 498 | + } |
| 499 | +
|
443 | 500 | const onDeleteForm = async (id) => { |
444 | 501 | const formIndex = forms.value.findIndex((form) => form.id === id) |
445 | 502 | const deletedHash = forms.value[formIndex].hash |
@@ -513,6 +570,7 @@ export default { |
513 | 570 | fetchPartialForm, |
514 | 571 | onNewForm, |
515 | 572 | onCloneForm, |
| 573 | + onDownloadForm, |
516 | 574 | onDeleteForm, |
517 | 575 | onLastUpdatedByEventBus, |
518 | 576 | IconPlus, |
|
0 commit comments