Skip to content

Commit 87bfc7c

Browse files
committed
feat: downloading forms
Signed-off-by: TimedIn <git@timedin.net>
1 parent a138698 commit 87bfc7c

3 files changed

Lines changed: 77 additions & 2 deletions

File tree

src/Forms.vue

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
@openSharing="openSharing"
3333
@mobileCloseNavigation="mobileCloseNavigation"
3434
@clone="onCloneForm"
35+
@download="onDownloadForm"
3536
@delete="onDeleteForm" />
3637
</ul>
3738
</template>
@@ -51,6 +52,7 @@
5152
readOnly
5253
@openSharing="openSharing"
5354
@clone="onCloneForm"
55+
@download="onDownloadForm"
5456
@mobileCloseNavigation="mobileCloseNavigation" />
5557
</ul>
5658
</template>
@@ -170,6 +172,7 @@ import AppNavigationForm from './components/AppNavigationForm.vue'
170172
import ArchivedFormsModal from './components/ArchivedFormsModal.vue'
171173
import Sidebar from './views/Sidebar.vue'
172174
import FormsIcon from '../img/forms-dark.svg?raw'
175+
import { version } from '../package.json'
173176
import PermissionTypes from './mixins/PermissionTypes.js'
174177
import { FormState } from './models/Constants.ts'
175178
import logger from './utils/Logger.js'
@@ -440,6 +443,60 @@ export default {
440443
}
441444
}
442445
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+
443500
const onDeleteForm = async (id) => {
444501
const formIndex = forms.value.findIndex((form) => form.id === id)
445502
const deletedHash = forms.value[formIndex].hash
@@ -513,6 +570,7 @@ export default {
513570
fetchPartialForm,
514571
onNewForm,
515572
onCloneForm,
573+
onDownloadForm,
516574
onDeleteForm,
517575
onLastUpdatedByEventBus,
518576
IconPlus,

src/components/AppNavigationForm.vue

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@
6464
</template>
6565
{{ t('forms', 'Copy form') }}
6666
</NcActionButton>
67+
<NcActionButton v-if="canEdit" closeAfterClick @click="onDownloadForm">
68+
<template #icon>
69+
<NcIconSvgWrapper :svg="IconDownload" />
70+
</template>
71+
{{ t('forms', 'Download form') }}
72+
</NcActionButton>
6773
<NcActionSeparator v-if="canEdit && !readOnly" />
6874
<NcActionButton
6975
v-if="canEdit && !readOnly"
@@ -103,6 +109,7 @@ import IconPoll from '@material-symbols/svg-400/outlined/bar_chart.svg?raw'
103109
import IconCheck from '@material-symbols/svg-400/outlined/check.svg?raw'
104110
import IconContentCopy from '@material-symbols/svg-400/outlined/content_copy.svg?raw'
105111
import IconDelete from '@material-symbols/svg-400/outlined/delete.svg?raw'
112+
import IconDownload from '@material-symbols/svg-400/outlined/download.svg?raw'
106113
import IconPencil from '@material-symbols/svg-400/outlined/edit.svg?raw'
107114
import IconShareVariant from '@material-symbols/svg-400/outlined/share.svg?raw'
108115
import IconArchiveOff from '@material-symbols/svg-400/outlined/unarchive.svg?raw'
@@ -154,7 +161,7 @@ export default {
154161
},
155162
},
156163
157-
emits: ['mobileCloseNavigation', 'openSharing', 'clone', 'delete'],
164+
emits: ['mobileCloseNavigation', 'openSharing', 'clone', 'delete', 'download'],
158165
159166
setup() {
160167
return {
@@ -164,6 +171,7 @@ export default {
164171
IconCheck,
165172
IconContentCopy,
166173
IconDelete,
174+
IconDownload,
167175
IconPencil,
168176
IconPoll,
169177
IconShareVariant,
@@ -292,6 +300,10 @@ export default {
292300
this.$emit('clone', this.form.id)
293301
},
294302
303+
onDownloadForm() {
304+
this.$emit('download', this.form.id)
305+
},
306+
295307
async onConfirmDelete() {
296308
const shouldDelete = await showConfirmation({
297309
name: t('forms', 'Delete form'),

src/components/ArchivedFormsModal.vue

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
:form="form"
1818
forceDisplayActions
1919
@clone="onCloneForm(form.id)"
20+
@download="onDownloadForm(form.id)"
2021
@delete="onDelete(form)"
2122
@mobileCloseNavigation="$emit('update:open', false)" />
2223
</ul>
@@ -49,7 +50,7 @@ export default defineComponent({
4950
},
5051
},
5152
52-
emits: ['update:open', 'clone'],
53+
emits: ['update:open', 'clone', 'download'],
5354
5455
data() {
5556
return {
@@ -74,6 +75,10 @@ export default defineComponent({
7475
this.$emit('update:open', false)
7576
},
7677
78+
onDownloadForm(formId) {
79+
this.$emit('download', formId)
80+
},
81+
7782
onDelete(form) {
7883
this.shownForms = this.shownForms.filter(({ id }) => id !== form.id)
7984
},

0 commit comments

Comments
 (0)