Skip to content

Commit

Permalink
Ask for restarting submission if form was changed
Browse files Browse the repository at this point in the history
Signed-off-by: Kostiantyn Miakshyn <[email protected]>
  • Loading branch information
Koc committed Sep 22, 2024
1 parent 13b1f00 commit ffc0ad6
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 48 deletions.
12 changes: 4 additions & 8 deletions src/components/Questions/QuestionDate.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
v-on="commonListeners">
<div class="question__content">
<NcDateTimePicker
v-model="time"
:value="time"
:disabled="!readOnly"
:formatter="formatter"
:placeholder="datetimePickerPlaceholder"
Expand Down Expand Up @@ -57,7 +57,6 @@ export default {
data() {
return {
time: null,
formatter: {
stringify: this.stringify,
parse: this.parse,
Expand All @@ -84,13 +83,10 @@ export default {
name: this.name || undefined,
}
},
},
mounted() {
// Init time from values prop
if (this.values) {
this.time = this.parse(this.values[0])
}
time() {
return this.values ? this.parse(this.values[0]) : null
},
},
methods: {
Expand Down
17 changes: 9 additions & 8 deletions src/components/Questions/QuestionDropdown.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
</template>
<NcSelect
v-if="readOnly"
v-model="selectedOption"
:value="selectedOption"
:name="name || undefined"
:placeholder="selectOptionPlaceholder"
:multiple="isMultiple"
Expand Down Expand Up @@ -133,7 +133,6 @@ export default {
data() {
return {
selectedOption: null,
inputValue: '',
isOptionDialogShown: false,
isLoading: false,
Expand Down Expand Up @@ -173,16 +172,18 @@ export default {
shiftDragHandle() {
return !this.readOnly && this.options.length !== 0 && !this.isLastEmpty
},
},
mounted() {
// Init selected options from values prop
if (this.values) {
selectedOption() {
if (!this.values) {
return null
}
const selected = this.values.map((id) =>
this.options.find((option) => option.id === id),
)
this.selectedOption = this.isMultiple ? selected : selected[0]
}
return this.isMultiple ? selected : selected[0]
},
},
methods: {
Expand Down
19 changes: 14 additions & 5 deletions src/components/Questions/QuestionLong.vue
Original file line number Diff line number Diff line change
Expand Up @@ -71,25 +71,34 @@ export default {
},
},
mounted() {
this.autoSizeText()
},
methods: {
onInput() {
const textarea = this.$refs.textarea
this.$emit('update:values', [textarea.value])
this.autoSizeText()
},
autoSizeText() {
const textarea = this.$refs.textarea
if (!textarea) {
return
}
textarea.style.cssText = 'height:auto; padding:0'
textarea.style.cssText = `height: ${textarea.scrollHeight + 28}px`
},
onKeydownCtrlEnter(event) {
this.$emit('keydown', event)
},
},
watch: {

Check warning on line 92 in src/components/Questions/QuestionLong.vue

View workflow job for this annotation

GitHub Actions / NPM lint

The "watch" property should be above the "methods" property on line 74
values: {
handler() {
this.$nextTick(() => {
this.autoSizeText()
})
},
immediate: true,
},
},
}
</script>

Expand Down
130 changes: 103 additions & 27 deletions src/views/Submit.vue
Original file line number Diff line number Diff line change
Expand Up @@ -145,17 +145,31 @@
@keydown.ctrl.enter="onKeydownCtrlEnter"
@update:values="(values) => onUpdate(question, values)" />
</ul>
<NcButton
alignment="center-reverse"
class="submit-button"
:disabled="loading"
native-type="submit"
type="primary">
<template #icon>
<NcIconSvgWrapper :svg="IconSendSvg" />
</template>
{{ t('forms', 'Submit') }}
</NcButton>
<div class="form-buttons">
<NcButton
alignment="center-reverse"
class="submit-button"
:disabled="!hasAnswers"
native-type="reset"
type="tertiary-no-background"
@click.prevent="showRestartSubmissionDialog = true">
<template #icon>
<NcIconSvgWrapper :svg="IconRefreshSvg" />
</template>
{{ t('forms', 'Restart submission') }}
</NcButton>
<NcButton
alignment="center-reverse"
class="submit-button"
:disabled="loading"
native-type="submit"
type="primary">
<template #icon>
<NcIconSvgWrapper :svg="IconSendSvg" />
</template>
{{ t('forms', 'Submit') }}
</NcButton>
</div>
</form>
<!-- Confirmation dialog if form is empty submitted -->
Expand All @@ -179,6 +193,27 @@
:buttons="confirmLeaveFormButtons"
:can-close="false"
:close-on-click-outside="false" />
<!-- Confirmation dialog for restart submission -->
<NcDialog
:open.sync="showRestartSubmissionDialog"
:name="t('forms', 'Clear form')"
:message="t('forms', 'Do you want to clear all answers?')"
:buttons="confirmRestartSubmissionButtons"
:can-close="false"
:close-on-click-outside="false" />
<!-- Confirmation dialog if form was changed -->
<NcDialog
:open.sync="showRestartSubmissionDueToChangeDialog"
:name="t('forms', 'Clear form')"
:message="
t(
'forms',
'The form has changed since your last visit. Do you want to clear all answers?',
)
"
:buttons="confirmRestartSubmissionButtons"
:can-close="false"
:close-on-click-outside="false" />
</template>
</NcAppContent>
</template>
Expand All @@ -201,6 +236,7 @@ import NcNoteCard from '@nextcloud/vue/dist/Components/NcNoteCard.js'
import IconCancelSvg from '@mdi/svg/svg/cancel.svg?raw'
import IconCheckSvg from '@mdi/svg/svg/check.svg?raw'
import IconRefreshSvg from '@mdi/svg/svg/refresh.svg?raw'
import IconSendSvg from '@mdi/svg/svg/send.svg?raw'
import { FormState } from '../models/FormStates.ts'
Expand Down Expand Up @@ -277,6 +313,7 @@ export default {
// Non reactive properties
return {
IconCheckSvg,
IconRefreshSvg,
IconSendSvg,
maxStringLengths: loadState('forms', 'maxStringLengths'),
Expand All @@ -297,6 +334,8 @@ export default {
submitForm: false,
showConfirmEmptyModal: false,
showConfirmLeaveDialog: false,
showRestartSubmissionDialog: false,
showRestartSubmissionDueToChangeDialog: false,
}
},
Expand All @@ -316,6 +355,10 @@ export default {
})
},
validQuestionsIds() {
return new Set(this.validQuestions.map((question) => question.id))
},
isRequiredUsed() {
return this.form.questions.reduce(
(isUsed, question) => isUsed || question.isRequired,
Expand Down Expand Up @@ -413,13 +456,36 @@ export default {
},
]
},
/**
* Buttons for the "confirm restart submission" dialog
*/
confirmRestartSubmissionButtons() {
return [
{
label: t('forms', 'Abort'),
icon: IconCancelSvg,
callback: () => {},
},
{
label: t('forms', 'Restart'),
icon: IconCheckSvg,
type: 'primary',
callback: () => this.onResetSubmission(),
},
]
},
hasAnswers() {
return Object.keys(this.answers).length > 0
},
},
watch: {
hash() {
// If public view, abort. Should normally not occur.
if (this.publicView) {
logger.error('Hash changed on public View. Aborting.')
logger.error('Hash changsed on public View. Aborting.')
return
}
this.resetData()
Expand All @@ -437,17 +503,19 @@ export default {
window.addEventListener('beforeunload', this.beforeWindowUnload)
},
beforeMount() {
async beforeMount() {
// Public Views get their form by initial-state from parent. No fetch necessary.
if (this.publicView) {
this.isLoadingForm = false
} else {
this.fetchFullForm(this.form.id)
await this.fetchFullForm(this.form.id)
}
SetWindowTitle(this.formTitle)
if (this.isLoggedIn) {
this.initFromLocalStorage()
}
SetWindowTitle(this.formTitle)
},
methods: {
Expand All @@ -473,8 +541,16 @@ export default {
if (!savedState) {
return
}
const answers = {}
for (const [questionId, answer] of Object.entries(savedState)) {
// Clean up answers for questions that do not exist anymore
if (!this.validQuestionsIds.has(parseInt(questionId))) {
this.showRestartSubmissionDueToChangeDialog = true
logger.debug('Question does not exist anymore', { questionId })
continue
}
answers[questionId] =
answer.type === 'QuestionMultiple'
? answer.value.map(String)
Expand Down Expand Up @@ -585,17 +661,6 @@ export default {
async (question) => await question.validate(),
)
// Clean up answers for questions that do not exist anymore
const questionIds = new Map(
this.validQuestions.map((question) => [question.id, true]),
)
for (const questionId of Object.keys(this.answers)) {
if (!questionIds.has(parseInt(questionId))) {
logger.debug('Question does not exist anymore', { questionId })
delete this.answers[questionId]
}
}
try {
// wait for all to be validated
const result = await Promise.all(validation)
Expand Down Expand Up @@ -654,13 +719,20 @@ export default {
}
},
onResetSubmission() {
this.deleteFormFieldFromLocalStorage()
this.resetData()
},
/**
* Reset View-Data
*/
resetData() {
this.answers = {}
this.loading = false
this.showConfirmLeaveDialog = false
this.showRestartSubmissionDialog = false
this.showRestartSubmissionDueToChangeDialog = false
this.success = false
this.submitForm = false
},
Expand Down Expand Up @@ -749,8 +821,12 @@ export default {
padding-inline-start: var(--default-clickable-area);
}
.form-buttons {
display: flex;
justify-content: flex-end;
}
.submit-button {
align-self: flex-end;
margin: 5px;
margin-block-end: 160px;
padding-inline-start: 20px;
Expand Down

0 comments on commit ffc0ad6

Please sign in to comment.