rework message store

This commit is contained in:
Axolotle 2020-10-12 15:18:57 +02:00
parent e2a13f4c35
commit 23aa8bba64
3 changed files with 125 additions and 15 deletions

View file

@ -4,15 +4,37 @@
no-center
:show="waiting"
>
<slot name="default" />
<template v-slot:overlay>
<b-card>
<div class="d-flex justify-content-center m-3">
<b-spinner />
<b-card no-body>
<div class="d-flex justify-content-center">
<!-- <b-spinner /> -->
<img class="pacman" src="@/assets/ajax-loader.gif">
</div>
<b-card-title class="text-center" v-t="'api_waiting'" />
<b-card-body class="pb-4">
<b-card-title class="text-center m-0" v-t="'api_waiting'" />
<!-- PROGRESS BAR -->
<b-progress
v-if="progress" class="mt-4"
:max="progress.max" height=".5rem"
>
<b-progress-bar variant="success" :value="progress.values[0]" />
<b-progress-bar variant="warning" :value="progress.values[1]" animated />
<b-progress-bar variant="secondary" :value="progress.values[2]" striped />
</b-progress>
</b-card-body>
<!-- MESSAGES -->
<b-list-group v-if="messages" flush>
<b-list-group-item
v-for="({ text, type }, i) in messages" :key="i"
:variant="type"
>
{{ text }}
</b-list-group-item>
</b-list-group>
</b-card>
</template>
</b-overlay>
@ -25,7 +47,20 @@ export default {
name: 'ApiWaitOverlay',
computed: {
...mapGetters(['waiting'])
...mapGetters(['waiting', 'lastAction']),
progress () {
const progress = this.lastAction.progress
if (!progress) return null
return {
values: progress, max: progress.reduce((sum, value) => (sum + value), 0)
}
},
messages () {
const messages = this.lastAction.messages
return messages.length > 0 ? this.lastAction.messages : null
}
}
}
</script>
@ -35,6 +70,7 @@ export default {
position: sticky;
top: 5vh;
margin: 0 5%;
padding: 3rem 0;
@include media-breakpoint-up(md) {
margin: 0 10%;
@ -43,4 +79,33 @@ export default {
margin: 0 20%;
}
}
.card-body {
padding-bottom: 2rem;
}
.progress {
margin-top: 2rem;
}
.list-group {
max-height: 50vh;
overflow-y: auto;
// Hide all message except the last one if the mouse isn't hovering the list group.
&:not(:hover) .list-group-item:not(:last-of-type) {
display: none;
}
}
.pacman {
animation: back-and-forth 4s linear infinite;
@keyframes back-and-forth {
0%, 100% { transform: translateX(-50vw) scale(1); }
49% { transform: translateX(50vw) scale(1); }
50% { transform: translateX(50vw) scale(-1); }
99% { transform: translateX(-50vw) scale(-1); }
}
}
</style>

View file

@ -52,7 +52,7 @@ export function objectToParams (object, { addLocale = false } = {}) {
* @return {DigestedResponse} Parsed response's json, response's text or an error.
*/
export async function handleResponse (response) {
store.commit('UPDATE_WAITING', false)
store.dispatch('SERVER_RESPONDED')
if (!response.ok) return handleErrors(response)
// FIXME the api should always return json objects
const responseText = await response.text()
@ -174,7 +174,7 @@ export default {
* @return {Promise<module:api~DigestedResponse>} Promise that resolve the api responses as an array.
*/
post (uri, data = {}) {
store.commit('UPDATE_WAITING', true)
store.dispatch('WAITING_FOR_RESPONSE', [uri, 'POST'])
return this.fetch('POST', uri, data).then(handleResponse)
},
@ -186,7 +186,7 @@ export default {
* @return {Promise<module:api~DigestedResponse>} Promise that resolve the api responses as an array.
*/
put (uri, data = {}) {
store.commit('UPDATE_WAITING', true)
store.dispatch('WAITING_FOR_RESPONSE', [uri, 'PUT'])
return this.fetch('PUT', uri, data).then(handleResponse)
},
@ -198,9 +198,9 @@ export default {
* @return {Promise<('ok'|Error)>} Promise that resolve the api responses as an array.
*/
delete (uri, data = {}) {
store.commit('UPDATE_WAITING', true)
store.dispatch('WAITING_FOR_RESPONSE', [uri, 'DELETE'])
return this.fetch('DELETE', uri, data).then(response => {
store.commit('UPDATE_WAITING', false)
store.dispatch('SERVER_RESPONDED')
return response.ok ? 'ok' : handleErrors(response)
})
}

View file

@ -1,12 +1,14 @@
import Vue from 'vue'
import api, { timeout } from '@/helpers/api'
import router from '@/router'
export default {
state: {
host: window.location.host,
connected: localStorage.getItem('connected') === 'true',
yunohost: null, // yunohost app infos: Object {version, repo}
waiting: false,
host: window.location.host
history: []
},
mutations: {
@ -21,6 +23,18 @@ export default {
'UPDATE_WAITING' (state, boolean) {
state.waiting = boolean
},
'ADD_HISTORY_ENTRY' (state, [uri, method, date]) {
state.history.push({ uri, method, date, messages: [] })
},
'ADD_MESSAGE' (state, message) {
state.history[state.history.length - 1].messages.push(message)
},
'UPDATE_PROGRESS' (state, progress) {
Vue.set(state.history[state.history.length - 1], 'progress', progress)
}
},
@ -80,15 +94,46 @@ export default {
})
},
'DISPATCH_MESSAGE' (store, message) {
console.log(message)
'WAITING_FOR_RESPONSE' ({ commit }, [uri, method]) {
commit('UPDATE_WAITING', true)
commit('ADD_HISTORY_ENTRY', [uri, method, Date.now()])
},
'SERVER_RESPONDED' ({ state, dispatch, commit }) {
if (!state.waiting) return
commit('UPDATE_WAITING', false)
},
'DISPATCH_MESSAGE' ({ commit }, messages) {
const typeToColor = { error: 'danger' }
for (const type in messages) {
const message = {
text: messages[type],
type: type in typeToColor ? typeToColor[type] : type
}
let progressBar = message.text.match(/^\[#*\+*\.*\] > /)
if (progressBar) {
progressBar = progressBar[0]
message.text = message.text.replace(progressBar, '')
const progress = { '#': 0, '+': 0, '.': 0 }
for (const char of progressBar) {
if (char in progress) progress[char] += 1
}
commit('UPDATE_PROGRESS', Object.values(progress))
}
if (message.text) {
commit('ADD_MESSAGE', message)
}
}
}
},
getters: {
host: state => state.host,
connected: state => (state.connected),
yunohost: state => (state.yunohost),
waiting: state => state.waiting,
host: state => state.host
history: state => state.history,
lastAction: state => state.history[state.history.length - 1]
}
}