feat: simplify heading blur logic #727
No reviewers
Labels
No Label
area/internal-code
changes requested
confirmed
dependencies
duplicate
good first issue
help wanted
hosting
invalid
kind/bug
kind/feature
question
wontfix
No Milestone
No project
No Assignees
2 Participants
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: vikunja/frontend#727
Loading…
Reference in New Issue
No description provided.
Delete Branch "dpschen/frontend:feature/simplify-heading-blur-logic"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
I saw the recent change with the the blur in the heading and remembered I had something like that recently. With this trick there is always just one call.
@ -66,4 +60,1 @@
// Pull the task title from the contenteditable
let taskTitle = this.$refs.taskTitle.textContent
this.task.title = taskTitle
By assigning
taskTitle
tothis.task.title
thetask
is getting modified.I guess this is the only reason why a local copy of the task existed. By getting the value as a parameter from the
save
function there is no need to modify the task directly.I'm pretty sure there's a few cases like this in other places.
Yes! Those are the ones that give me headache with vue3 :)
@ -12,2 +10,3 @@
@blur="save($event.target.textContent)"
@keydown.enter.prevent.stop="$event.target.blur()"
:contenteditable="canWrite ? 'true' : 'false'"
ref="taskTitle">{{ task.title.trim() }}</h1>
By trimming the title on saving (see in
save
function) there should never be a title with whitespace around.Maybe there are old ones in the database but they should disappear :)
I agree in principle, but remember the api can theoretically be used with other clients as well. Therefore we cannot be sure there won't be any spaces around the task title without the
trim()
. Unless we add a trim on task create/update in the api. That might actually be a good idea.How about keeping both?
You mean on update/create and when displaying it? Sounds great. But then the trim on create/update should go into the TaskService.
Good point.
Not sure where exactly to put this then in the TaskService.
I had already problems with the
processModel
method, because it modifies the original task in the store instead of creating a new one. I guess it would be something like:Okay, I put this now in the TaskService
processModel
method.I'm just a bit confused because it seems to me that almost the same stuff is done in the constructor of the TaskModel, so I added it there aswell.
Shouldn't those two operation be identical / happen just once?
Or what is the difference?
It's almost the same, but not quite.
processModel
is called before a model is sent to the api, the task constructor is called when a model is returned from the api. They are mostly used to convert js date objects to iso dates and create releated models and such.I'm sure there are better ways to do this.
Oh and by the way, check your email 🙂
So checking if I understood this right:
processModel
functions in the services are some kind of validation / formatting so that the data has the right format for the api.If that's correct I don't understand why
new XYModel
(aka calling the model constructor) is called in so many places where there is no data coming from the api.Can you point me to an example where the constructor is called when e.g. the task model is returned from the api?
Checking!
The services have a
modelFactory
function which receives data from the api and returns anew XYZModel(data)
. The other cases where a new model is created is when creating these things, for example a new task. That might be a bit redundant though. Again, I'm sure there are better way to do this.I created the whole Services / Model implementation based on some things I did in other languages or that I've seen with not much experience.
Sure, just want to make sure that I understand the imagined role of the parts :)
@ -17,3 +18,3 @@
{{ $t('misc.saving') }}
</span>
<span class="has-text-success is-inline-flex is-align-content-center" v-if="!loading && saved">
<span class="has-text-success is-inline-flex is-align-content-center" v-if="!loading && showSavedMessage">
I renamed this variable to make the meaning more clear.
@ -25,22 +26,25 @@
</template>
<script>
import {LOADING} from '@/store/mutation-types'
Since
LOADING
is used here to get a state viamapState
and (and not mutation-type viamapMutation
) this seemed like a mistake.@ -10,2 +10,2 @@
@focusout="save()"
@keydown.enter.prevent.stop="save()"
@blur="save($event.target.textContent)"
@keydown.enter.prevent.stop="$event.target.blur()"
Wow, that's as elegant as it is obvious.
Thanks :) Was also new to me. Google helped :D
Before that i always used something like _.throttle ; but that seemed too overpowered here.
I've used good ol'
setTimeout
in the past but that never felt good. It didn't even work all the time...Yes :D
When you use setTimeout it's almost (!) always a hint that you are creating a workaround for something and not using the "right" ™️ way.
@ -92,3 +73,1 @@
.then(() => {
this.$emit('input', this.task)
this.saved = true
const newTask = {
We created a new task to prevent unwanted mutations
@ -62,4 +57,1 @@
},
methods: {
save() {
this.$refs.taskTitle.spellcheck = false
I was not sure why spellcheck is set to
false
here.Also it's never set to
undefined
/false
later.I removed the direct element access and added a default value. Maybe wrong assumptions?
Probably because I wanted to disable it before saving. What does the commit message on that line say?
It was from the original commit of that component.
I see. I think it makes sense to just always disable spellcheck, but I'm pretty sure I tried to do that back then and got bitten by it somehow.
Okay, so shall I just set
spellcheck="false"
in the template?Yeah I think that would work.
Done ✅
887ef74a66
to42f89e16ad
42f89e16ad
to88f773745d
88f773745d
to7c8f411ba4
Thanks!