Skip to content

Commit 55ccee5

Browse files
committed
Setup pollers
1 parent b7773cc commit 55ccee5

6 files changed

Lines changed: 122 additions & 3 deletions

File tree

api/pkg/handlers/heartbeat_handler.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func NewHeartbeatHandler(
3838

3939
// RegisterRoutes registers the routes for the MessageHandler
4040
func (h *HeartbeatHandler) RegisterRoutes(router fiber.Router) {
41-
router.Get("/heartbeat", h.Index)
41+
router.Get("/heartbeats", h.Index)
4242
}
4343

4444
// Index returns the heartbeats of a phone number

web/components/MessageThreadHeader.vue

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,37 @@
88
<nuxt-link to="/" class="text-decoration-none text--primary">
99
<v-toolbar-title>
1010
{{ $store.getters.getOwner | phoneNumber }}
11+
<v-progress-circular
12+
v-if="$store.getters.getPolling"
13+
indeterminate
14+
:size="14"
15+
:width="1"
16+
class="mt-n1"
17+
color="success"
18+
></v-progress-circular>
1119
</v-toolbar-title>
1220
</nuxt-link>
13-
<p class="text--secondary mb-n1">Estonia</p>
21+
<div class="d-flex">
22+
<p class="text--secondary mb-n1">
23+
{{ $store.getters.getOwner | phoneCountry }}
24+
</p>
25+
<v-tooltip v-if="$store.getters.getHeartbeat" right>
26+
<template #activator="{ on, attrs }">
27+
<v-btn
28+
x-small
29+
v-bind="attrs"
30+
color="success"
31+
class="ml-2 mt-1 mb-n1"
32+
icon
33+
v-on="on"
34+
>
35+
<v-icon x-small>mdi-circle</v-icon>
36+
</v-btn>
37+
</template>
38+
<h4>Last Heartbeat</h4>
39+
{{ $store.getters.getHeartbeat.timestamp | timestamp }}
40+
</v-tooltip>
41+
</div>
1442
</div>
1543
<v-spacer></v-spacer>
1644
<v-tooltip bottom>

web/layouts/default.vue

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,39 @@ import { Vue, Component } from 'vue-property-decorator'
2929
@Component
3030
export default class DefaultLayout extends Vue {
3131
mounted() {
32-
this.$store.dispatch('loadThreads')
32+
Promise.all([
33+
this.$store.dispatch('loadThreads'),
34+
this.$store.dispatch('getHeartbeat'),
35+
])
36+
this.startPoller()
37+
}
38+
39+
startPoller() {
40+
setInterval(async () => {
41+
await this.$store.dispatch('setPolling', true)
42+
43+
const promises = []
44+
if (this.$store.getters.getOwner) {
45+
promises.push(
46+
this.$store.dispatch('loadThreads'),
47+
this.$store.dispatch('getHeartbeat')
48+
)
49+
}
50+
51+
if (this.$store.getters.hasThread) {
52+
promises.push(
53+
this.$store.dispatch(
54+
'loadThreadMessages',
55+
this.$store.getters.getThread.id
56+
)
57+
)
58+
}
59+
await Promise.all(promises)
60+
61+
setTimeout(() => {
62+
this.$store.dispatch('setPolling', false)
63+
}, 1000)
64+
}, 10000)
3365
}
3466
}
3567
</script>

web/models/heartbeat.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export interface Heartbeat {
2+
id: string
3+
owner: string
4+
timestamp: string
5+
quantity: string
6+
}

web/plugins/filters.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,16 @@ Vue.filter('phoneNumber', (value: string): string => {
88
}
99
return value
1010
})
11+
12+
Vue.filter('phoneCountry', (value: string): string => {
13+
const phoneNumber = parsePhoneNumber(value)
14+
if (phoneNumber && phoneNumber.country) {
15+
const regionNames = new Intl.DisplayNames(undefined, { type: 'region' })
16+
return regionNames.of(phoneNumber.country) ?? 'earth'
17+
}
18+
return 'Earth'
19+
})
20+
21+
Vue.filter('timestamp', (value: string): string => {
22+
return new Date(value).toLocaleString()
23+
})

web/store/index.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,23 @@ import { ActionContext } from 'vuex'
22
import axios from '~/plugins/axios'
33
import { MessageThread } from '~/models/message-thread'
44
import { Message } from '~/models/message'
5+
import { Heartbeat } from '~/models/heartbeat'
6+
import { compile } from 'vue-template-compiler'
57

68
type State = {
79
owner: string
810
threads: Array<MessageThread>
911
threadId: string | null
12+
heartbeat: null | Heartbeat
13+
pooling: boolean
1014
threadMessages: Array<Message>
1115
}
1216

1317
export const state = (): State => ({
1418
threads: [],
1519
threadId: null,
20+
heartbeat: null,
21+
pooling: false,
1622
threadMessages: [],
1723
owner: '+37259139660',
1824
})
@@ -40,6 +46,14 @@ export const getters = {
4046
}
4147
return thread
4248
},
49+
50+
getHeartbeat(state: State): Heartbeat | null {
51+
return state.heartbeat
52+
},
53+
54+
getPolling(state: State): boolean {
55+
return state.pooling
56+
},
4357
}
4458

4559
export const mutations = {
@@ -52,6 +66,12 @@ export const mutations = {
5266
setThreadMessages(state: State, payload: Array<Message>) {
5367
state.threadMessages = payload
5468
},
69+
setHeartbeat(state: State, payload: Heartbeat | null) {
70+
state.heartbeat = payload
71+
},
72+
setPooling(state: State, payload: boolean) {
73+
state.pooling = payload
74+
},
5575
}
5676

5777
export type SendMessageRequest = {
@@ -70,6 +90,26 @@ export const actions = {
7090
context.commit('setThreads', response.data.data)
7191
},
7292

93+
async getHeartbeat(context: ActionContext<State, State>) {
94+
const response = await axios.get('/v1/heartbeats', {
95+
params: {
96+
limit: 1,
97+
owner: context.getters.getOwner,
98+
},
99+
})
100+
101+
if (response.data.data.length > 0) {
102+
context.commit('setHeartbeat', response.data.data[0])
103+
return
104+
}
105+
106+
context.commit('setHeartbeat', null)
107+
},
108+
109+
setPolling(context: ActionContext<State, State>, status: boolean) {
110+
context.commit('setPooling', status)
111+
},
112+
73113
async sendMessage(
74114
context: ActionContext<State, State>,
75115
request: SendMessageRequest

0 commit comments

Comments
 (0)