diff --git a/web/pages/search-messages/index.vue b/web/pages/search-messages/index.vue index 67062625..f5eda862 100644 --- a/web/pages/search-messages/index.vue +++ b/web/pages/search-messages/index.vue @@ -95,8 +95,11 @@ class="py-5" @click="fetchMessages(true)" > - {{ mdiMagnify }} - Search Messages + {{ + mdiMagnify + }} + SEARCH + Search Messages @@ -120,8 +123,11 @@ v-bind="attrs" v-on="on" > - {{ mdiDelete }} - Delete messages + {{ + mdiDelete + }} + DELETE + Delete messages @@ -139,7 +145,6 @@ :loading="loading" @click="deleteMessages" > - {{ mdiDelete }} Yes Delete Messages @@ -147,6 +152,46 @@ + + + + + Are you sure you want to resend the + {{ selectedMessages.length }} selected messages? + + + The selected messages will be queued for sending again using + the original sender, recipient, and content. + + + + Yes Resend Messages + + + Close + + + - {{ mdiExport }} - Export to CSV + {{ + mdiExport + }} + EXPORT + Export to CSV @@ -280,11 +328,13 @@ import { mdiCallReceived, mdiCallMade, mdiExport, + mdiRefresh, mdiProgressCheck, mdiAlert, } from '@mdi/js' import { AxiosError } from 'axios' import { DataOptions } from 'vuetify' +import axios from '~/plugins/axios' import { ErrorMessages, getErrorMessages } from '~/plugins/errors' import capitalize from '~/plugins/capitalize' import { @@ -317,6 +367,7 @@ export default Vue.extend({ mdiMagnify, mdiArrowLeft, mdiExport, + mdiRefresh, mdiAlert, mdiCheck, mdiCheckAll, @@ -328,6 +379,7 @@ export default Vue.extend({ initialLoadComplete: false, errorTitle: '', showDeleteDialog: false, + showResendDialog: false, selectedMessages: [] as EntitiesMessage[], errorMessages: new ErrorMessages(), formOwners: [], @@ -360,6 +412,16 @@ export default Vue.extend({ } }, computed: { + canResendSelected(): boolean { + return ( + this.selectedMessages.length > 0 && + this.selectedMessages.every( + (message: EntitiesMessage) => + message.type === 'mobile-terminated' && + (message.status === 'expired' || message.status === 'failed'), + ) + ) + }, phoneNumberSelectItems() { return this.$store.getters.getPhones.map((phone: EntitiesPhone) => { return { @@ -495,6 +557,49 @@ export default Vue.extend({ }) }, + resendMessages() { + this.loading = true + Promise.allSettled( + this.selectedMessages.map((message) => + axios.post('/v1/messages/send', { + from: message.owner, + to: message.contact, + content: message.content, + sim: message.sim, + request_id: message.request_id, + }), + ), + ) + .then((results) => { + const failed = results.filter((r) => r.status === 'rejected') + if (failed.length === 0) { + this.$store.dispatch('addNotification', { + message: 'The selected messages have been queued for resending', + type: 'success', + }) + this.selectedMessages = [] + } else if (failed.length === results.length) { + this.$store.dispatch('addNotification', { + message: 'Error while resending the selected messages', + type: 'error', + }) + } else { + this.$store.dispatch('addNotification', { + message: `${results.length - failed.length} messages resent, ${ + failed.length + } failed`, + type: 'warning', + }) + this.selectedMessages = [] + } + }) + .finally(() => { + this.loading = false + this.showResendDialog = false + this.fetchMessages() + }) + }, + fetchMessages(reset = false) { this.loading = true this.errorMessages = new ErrorMessages() diff --git a/web/store/index.ts b/web/store/index.ts index 9077ccf6..4e9e9482 100644 --- a/web/store/index.ts +++ b/web/store/index.ts @@ -294,6 +294,7 @@ export type SendMessageRequest = { to: string content: string sim: SIM + request_id?: string } export const actions = {