use an 'AsyncButton' that waits for completion of an async onClick handler for mail replies and comments in tickets

This commit is contained in:
j3d1 2024-11-05 23:32:53 +01:00
parent 3a8fa8cdcf
commit 6e38ff7ac7
2 changed files with 58 additions and 13 deletions

View file

@ -40,10 +40,10 @@
<div class="">
<textarea placeholder="add comment..." v-model="newComment" class="form-control">
</textarea>
<button class="btn btn-primary float-right" @click="addCommentAndClear">
<AsyncButton class="btn btn-primary float-right" :task="addCommentAndClear">
<font-awesome-icon icon="comment"/>
Save Comment
</button>
</AsyncButton>
</div>
</div>
</li>
@ -58,10 +58,10 @@
<div>
<textarea placeholder="reply mail..." v-model="newMail" class="form-control">
</textarea>
<button class="btn btn-primary float-right" @click="sendMailAndClear">
<AsyncButton class="btn btn-primary float-right" :task="sendMailAndClear">
<font-awesome-icon icon="envelope"/>
Send Mail
</button>
</AsyncButton>
</div>
</div>
</li>
@ -77,11 +77,12 @@ import {mapActions, mapGetters} from "vuex";
import TimelineAssignment from "@/components/TimelineAssignment.vue";
import TimelineRelatedItem from "@/components/TimelineRelatedItem.vue";
import TimelineShippingVoucher from "@/components/TimelineShippingVoucher.vue";
import AsyncButton from "@/components/inputs/AsyncButton.vue";
export default {
name: 'Timeline',
components: {
TimelineShippingVoucher,
TimelineShippingVoucher, AsyncButton,
TimelineRelatedItem, TimelineAssignment, TimelineStateChange, TimelineComment, TimelineMail
},
props: {
@ -103,18 +104,15 @@ export default {
},
},
methods: {
...mapActions(['fetchShippingVouchers']),
sendMailAndClear: function () {
this.$emit('sendMail', this.newMail);
...mapActions(['sendMail', 'postComment']),
sendMailAndClear: async function () {
await this.sendMail(this.newMail);
this.newMail = "";
},
addCommentAndClear: function () {
this.$emit('addComment', this.newComment);
addCommentAndClear: async function () {
await this.postComment(this.newComment);
this.newComment = "";
}
},
mounted() {
this.fetchShippingVouchers();
}
};
</script>

View file

@ -0,0 +1,47 @@
<template>
<button @click.stop="handleClick" :disabled="disabled">
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"
:class="{'d-none': !disabled}"></span>
<span class="ml-2" :class="{'d-none': !disabled}">In Progress...</span>
<span :class="{'d-none': disabled}"><slot></slot></span>
</button>
</template>
<script>
export default {
name: 'AsyncButton',
data() {
return {
disabled: false,
};
},
props: {
task: {
type: Function,
required: true,
},
},
methods: {
async handleClick() {
console.log("AsyncButton.handleClick() called");
if (this.task && typeof this.task === 'function') {
this.disabled = true;
try {
await this.task();
} catch (e) {
console.error(e);
} finally {
this.disabled = false;
}
}
},
}
};
</script>
<style scoped>
.spinner-border {
vertical-align: -0.125em;
}
</style>