1
0

fix: bubble changes from the editor immediately and move the delay to callers

This gives the callers more control over when to save data and show/hide additional controls based on the input text
This commit is contained in:
kolaente 2023-06-02 12:40:21 +02:00
parent 68fd4698ac
commit f4a7943680
No known key found for this signature in database
GPG Key ID: F40E70337AB24C9B
3 changed files with 64 additions and 33 deletions

View File

@ -4,7 +4,7 @@
<vue-easymde <vue-easymde
:configs="config" :configs="config"
@change="() => bubble()" @change="() => bubbleNow()"
@update:modelValue="handleInput" @update:modelValue="handleInput"
class="content" class="content"
v-if="isEditActive" v-if="isEditActive"
@ -35,7 +35,7 @@
</BaseButton> </BaseButton>
<BaseButton <BaseButton
v-else-if="isEditActive" v-else-if="isEditActive"
@click="toggleEdit" @click="bubbleSaveClick"
class="done-edit"> class="done-edit">
{{ $t('misc.save') }} {{ $t('misc.save') }}
</BaseButton> </BaseButton>
@ -56,7 +56,7 @@
</ul> </ul>
<x-button <x-button
v-else-if="isEditActive" v-else-if="isEditActive"
@click="toggleEdit" @click="bubbleSaveClick"
variant="secondary" variant="secondary"
:shadow="false" :shadow="false"
v-cy="'saveEditor'"> v-cy="'saveEditor'">
@ -84,8 +84,8 @@ import {createRandomID} from '@/helpers/randomId'
import BaseButton from '@/components/base/BaseButton.vue' import BaseButton from '@/components/base/BaseButton.vue'
import ButtonLink from '@/components/misc/ButtonLink.vue' import ButtonLink from '@/components/misc/ButtonLink.vue'
import type { IAttachment } from '@/modelTypes/IAttachment' import type {IAttachment} from '@/modelTypes/IAttachment'
import type { ITask } from '@/modelTypes/ITask' import type {ITask} from '@/modelTypes/ITask'
const props = defineProps({ const props = defineProps({
modelValue: { modelValue: {
@ -115,7 +115,7 @@ const props = defineProps({
default: true, default: true,
}, },
bottomActions: { bottomActions: {
type: Array, type: Array,
default: () => [], default: () => [],
}, },
emptyText: { emptyText: {
@ -134,10 +134,9 @@ const props = defineProps({
}, },
}) })
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue', 'save'])
const text = ref('') const text = ref('')
const changeTimeout = ref<ReturnType<typeof setTimeout> | null>(null)
const isEditActive = ref(false) const isEditActive = ref(false)
const isPreviewActive = ref(true) const isPreviewActive = ref(true)
@ -148,7 +147,7 @@ const preview = ref('')
const attachmentService = new AttachmentService() const attachmentService = new AttachmentService()
type CacheKey = `${ITask['id']}-${IAttachment['id']}` type CacheKey = `${ITask['id']}-${IAttachment['id']}`
const loadedAttachments = ref<{[key: CacheKey]: string}>({}) const loadedAttachments = ref<{ [key: CacheKey]: string }>({})
const config = ref(createEasyMDEConfig({ const config = ref(createEasyMDEConfig({
placeholder: props.placeholder, placeholder: props.placeholder,
uploadImage: props.uploadEnabled, uploadImage: props.uploadEnabled,
@ -175,7 +174,7 @@ watch(
if (oldVal === '' && text.value === modelValue.value) { if (oldVal === '' && text.value === modelValue.value) {
return return
} }
bubble() bubbleNow()
}, },
) )
@ -208,17 +207,11 @@ function handleInput(val: string) {
} }
text.value = val text.value = val
bubble(1000) bubbleNow()
} }
function bubble(timeout = 5000) { function bubbleNow() {
if (changeTimeout.value !== null) { emit('update:modelValue', text.value)
clearTimeout(changeTimeout.value)
}
changeTimeout.value = setTimeout(() => {
emit('update:modelValue', text.value)
}, timeout)
} }
function replaceAt(str: string, index: number, replacement: string) { function replaceAt(str: string, index: number, replacement: string) {
@ -287,24 +280,26 @@ function handleCheckboxClick(e: Event) {
return return
} }
const projectPrefix = text.value.substring(index, index + 1) const projectPrefix = text.value.substring(index, index + 1)
console.debug({index, projectPrefix, checked, text: text.value}) console.debug({index, projectPrefix, checked, text: text.value})
text.value = replaceAt(text.value, index, `${projectPrefix} ${checked ? '[x]' : '[ ]'} `) text.value = replaceAt(text.value, index, `${projectPrefix} ${checked ? '[x]' : '[ ]'} `)
bubble() bubbleNow()
emit('save', text.value)
renderPreview() renderPreview()
} }
function toggleEdit() { function toggleEdit() {
if (isEditActive.value) { isPreviewActive.value = false
isPreviewActive.value = true isEditActive.value = true
isEditActive.value = false }
renderPreview()
bubble(0) // save instantly function bubbleSaveClick() {
} else { isPreviewActive.value = true
isPreviewActive.value = false isEditActive.value = false
isEditActive.value = true renderPreview()
} bubbleNow()
emit('save', text.value)
} }
</script> </script>

View File

@ -74,9 +74,13 @@
@update:model-value=" @update:model-value="
() => { () => {
toggleEdit(c) toggleEdit(c)
editComment() editCommentWithDelay()
} }
" "
@save="() => {
toggleEdit(c)
editComment()
}"
:bottom-actions="actions[c.id]" :bottom-actions="actions[c.id]"
:show-save="true" :show-save="true"
/> />
@ -279,10 +283,26 @@ function toggleDelete(commentId: ITaskComment['id']) {
commentToDelete.id = commentId commentToDelete.id = commentId
} }
const changeTimeout = ref<ReturnType<typeof setTimeout> | null>(null)
async function editCommentWithDelay() {
if (changeTimeout.value !== null) {
clearTimeout(changeTimeout.value)
}
changeTimeout.value = setTimeout(async () => {
await editComment()
}, 5000)
}
async function editComment() { async function editComment() {
if (commentEdit.comment === '') { if (commentEdit.comment === '') {
return return
} }
if (changeTimeout.value !== null) {
clearTimeout(changeTimeout.value)
}
saving.value = commentEdit.id saving.value = commentEdit.id

View File

@ -25,7 +25,8 @@
:show-save="true" :show-save="true"
edit-shortcut="e" edit-shortcut="e"
v-model="task.description" v-model="task.description"
@update:model-value="save" @update:model-value="saveWithDelay"
@save="save"
/> />
</div> </div>
</template> </template>
@ -40,7 +41,6 @@ import type {ITask} from '@/modelTypes/ITask'
import {useTaskStore} from '@/stores/tasks' import {useTaskStore} from '@/stores/tasks'
import TaskModel from '@/models/task' import TaskModel from '@/models/task'
const props = defineProps({ const props = defineProps({
modelValue: { modelValue: {
type: Object as PropType<ITask>, type: Object as PropType<ITask>,
@ -74,7 +74,23 @@ watch(
{immediate: true}, {immediate: true},
) )
const changeTimeout = ref<ReturnType<typeof setTimeout> | null>(null)
async function saveWithDelay() {
if (changeTimeout.value !== null) {
clearTimeout(changeTimeout.value)
}
changeTimeout.value = setTimeout(async () => {
await save()
}, 5000)
}
async function save() { async function save() {
if (changeTimeout.value !== null) {
clearTimeout(changeTimeout.value)
}
saving.value = true saving.value = true
try { try {