Skip to content

Commit d96cb92

Browse files
committed
feat: add status bar in case the synchronization fails
closes #43
1 parent 7395cfb commit d96cb92

File tree

16 files changed

+166
-14
lines changed

16 files changed

+166
-14
lines changed

src/app/components/base/button/Button.vue

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ const props = withDefaults(
3030
text?: string;
3131
tooltip?: string;
3232
type?: 'button' | 'reset' | 'submit';
33-
size?: 's' | 'm' | 'l';
33+
size?: 'xs' | 's' | 'm' | 'l';
3434
tooltipPosition?: Placement;
3535
color?: Color;
3636
textual?: boolean;
@@ -103,6 +103,14 @@ const classes = computed(() => [
103103
line-height: 1em;
104104
}
105105
106+
&.xs {
107+
padding: 4px 6px;
108+
109+
.text {
110+
font-size: var(--font-size-xs);
111+
}
112+
}
113+
106114
&.s {
107115
padding: 6px 8px;
108116

src/app/pages/Frame.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
</div>
3434

3535
<div ref="panes" :class="$style.panes">
36+
<StatusBar />
37+
3638
<!-- eslint-disable vue/no-template-shadow -->
3739
<RouterView v-slot="{ Component }">
3840
<ComponentTransition :is="Component" v-if="Component" />
@@ -49,6 +51,7 @@ import SettingsButton from './navigation/settings/SettingsButton.vue';
4951
import ThemeButton from './navigation/theme/ThemeButton.vue';
5052
import ToolsButton from './navigation/tools/ToolsButton.vue';
5153
import ChangeYearButton from './navigation/year/ChangeYearButton.vue';
54+
import StatusBar from './status-bar/StatusBar.vue';
5255
import Link from '@components/base/link/Link.vue';
5356
import ComponentTransition from '@components/misc/component-transition/ComponentTransition.vue';
5457
import { useMediaQuery } from '@composables';

src/app/pages/navigation/auth/CloudButton.vue

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import LoginDialog from './LoginDialog.vue';
88
import Button from '@components/base/button/Button.vue';
99
import { Color } from '@composables';
10-
import { RiCloudLine, RiCloudOffLine, RiRefreshLine } from '@remixicon/vue';
10+
import { RiCloudLine, RiCloudOffLine, RiRefreshLine, RiSignalWifiErrorLine } from '@remixicon/vue';
1111
import { useStorage } from '@storage/index';
1212
import { ClassNames } from '@utils';
1313
import { computed, ref } from 'vue';
@@ -25,9 +25,12 @@ const classes = computed(() => props.class);
2525
const icon = computed((): Component => {
2626
switch (status.value) {
2727
case 'syncing':
28+
case 'retrying':
2829
return RiRefreshLine;
2930
case 'idle':
3031
return RiCloudOffLine;
32+
case 'error':
33+
return RiSignalWifiErrorLine;
3134
}
3235
3336
return RiCloudLine;
@@ -40,6 +43,7 @@ const color = computed((): Color => {
4043
case 'loading':
4144
return 'warning';
4245
case 'idle':
46+
case 'error':
4347
return 'danger';
4448
case 'syncing':
4549
return 'primary';
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<template>
2+
<div v-if="status" :class="[$style.statusBar, classes]">
3+
<h1 :class="$style.title">{{ status.title }}</h1>
4+
<button v-if="status.button && status.action" type="button" :class="$style.button" @click="status.action">
5+
{{ status.button }}
6+
</button>
7+
</div>
8+
</template>
9+
10+
<script lang="ts" setup>
11+
import { useStorage } from '@storage/index.ts';
12+
import { ClassNames } from '@utils';
13+
import { computed } from 'vue';
14+
import { useI18n } from 'vue-i18n';
15+
16+
type Status = {
17+
title: string;
18+
button?: string;
19+
action?: () => unknown;
20+
};
21+
22+
const props = defineProps<{
23+
class?: ClassNames;
24+
}>();
25+
26+
const { t } = useI18n();
27+
const { status: storageStatus, retry: retrySync } = useStorage();
28+
29+
const classes = computed(() => props.class);
30+
31+
const status = computed((): Status | undefined => {
32+
switch (storageStatus.value) {
33+
case 'error':
34+
return {
35+
title: t('navigation.status.synchronizationFailedDueToNetworkError'),
36+
button: t('navigation.status.retrySynchronization'),
37+
action: retrySync
38+
};
39+
case 'retrying': {
40+
return {
41+
title: t('navigation.status.retryingPleaseWait')
42+
};
43+
}
44+
}
45+
46+
return undefined;
47+
});
48+
</script>
49+
50+
<style lang="scss" module>
51+
.statusBar {
52+
display: flex;
53+
align-items: center;
54+
justify-content: center;
55+
height: 24px;
56+
background: var(--c-danger);
57+
color: var(--c-danger-text);
58+
gap: 4px;
59+
}
60+
61+
.button {
62+
all: unset;
63+
text-decoration: underline;
64+
cursor: pointer;
65+
}
66+
67+
.title,
68+
.button {
69+
font-size: var(--font-size-xs);
70+
font-weight: var(--font-weight-l);
71+
}
72+
</style>

src/i18n/locales/cze.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@
8484
"language": "Jazyk",
8585
"currency": "Měna",
8686
"firstMonthOfYear": "První měsíc roku"
87+
},
88+
"status": {
89+
"synchronizationFailedDueToNetworkError": "Synchronizace selhala kvůli síťové chybě!",
90+
"retryingPleaseWait": "Znovu se pokoušíme, čekejte prosím...",
91+
"retrySynchronization": "Znovu synchronizovat"
8792
}
8893
},
8994
"shared": {

src/i18n/locales/de.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@
8484
"language": "Sprache",
8585
"currency": "Währung",
8686
"firstMonthOfYear": "Erster Monat des Jahres"
87+
},
88+
"status": {
89+
"synchronizationFailedDueToNetworkError": "Synchronisierung fehlgeschlagen, bitte überprüfen Sie Ihre Netzwerkverbindung!",
90+
"retryingPleaseWait": "Erneuter Versuch, bitte warten...",
91+
"retrySynchronization": "Erneut versuchen"
8792
}
8893
},
8994
"shared": {

src/i18n/locales/en.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@
8484
"language": "Language",
8585
"currency": "Currency",
8686
"firstMonthOfYear": "First month of the year"
87+
},
88+
"status": {
89+
"synchronizationFailedDueToNetworkError": "Synchronization failed due to network error!",
90+
"retryingPleaseWait": "Retrying, please wait...",
91+
"retrySynchronization": "Retry synchronization"
8792
}
8893
},
8994
"shared": {

src/i18n/locales/es.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@
8484
"language": "Idioma",
8585
"currency": "Moneda",
8686
"firstMonthOfYear": "Primer mes del año"
87+
},
88+
"status": {
89+
"synchronizationFailedDueToNetworkError": "¡La sincronización falló debido a un error de red!",
90+
"retryingPleaseWait": "Reintentando, por favor espera...",
91+
"retrySynchronization": "Reintentar sincronización"
8792
}
8893
},
8994
"shared": {

src/i18n/locales/hu.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@
8484
"language": "Nyelv",
8585
"currency": "Pénznem",
8686
"firstMonthOfYear": "Az év első hónapja"
87+
},
88+
"status": {
89+
"synchronizationFailedDueToNetworkError": "A szinkronizálás hálózati hiba miatt meghiúsult!",
90+
"retryingPleaseWait": "Újra próbálkozás, kérjük várjon...",
91+
"retrySynchronization": "Szinkronizálás újra"
8792
}
8893
},
8994
"shared": {

src/i18n/locales/it.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@
8484
"language": "Lingua",
8585
"currency": "Valuta",
8686
"firstMonthOfYear": "Primo mese dell'anno"
87+
},
88+
"status": {
89+
"synchronizationFailedDueToNetworkError": "Sincronizzazione fallita a causa di un errore di rete!",
90+
"retryingPleaseWait": "Riprova, attendere...",
91+
"retrySynchronization": "Riprova la sincronizzazione"
8792
}
8893
},
8994
"shared": {

0 commit comments

Comments
 (0)