diff --git a/src/components/standalone/dashboard/HaStatusCard.vue b/src/components/standalone/dashboard/HaStatusCard.vue new file mode 100644 index 000000000..a400722a5 --- /dev/null +++ b/src/components/standalone/dashboard/HaStatusCard.vue @@ -0,0 +1,142 @@ + + + diff --git a/src/i18n/en/translation.json b/src/i18n/en/translation.json index 2f795b384..81c4b79e5 100644 --- a/src/i18n/en/translation.json +++ b/src/i18n/en/translation.json @@ -2409,6 +2409,24 @@ "max_detect_info": "Policy 'max-detect' is enabled.", "max_detect_description": "Please refer to the manual for more information.", "events_today": "event today | events today" + }, + "ha": { + "sidebar_title": "High Availability", + "state": "State", + "role": "Role", + "primary": "Primary", + "backup": "Backup", + "last_sync_status": "Last sync status", + "last_sync_time": "Last sync time", + "ssh_connection_failed": "SSH connection failed", + "rsync_detection_failed": "Rsync detection failed", + "rsync_transfer_failed": "Rsync transfer failed", + "successful": "Successful", + "up_to_date": "Up to date", + "master": "Active", + "enabled": "Enabled", + "disabled": "Disabled", + "backup_warning": "Read-only node" } }, "controller": { diff --git a/src/stores/standalone/haStatus.ts b/src/stores/standalone/haStatus.ts new file mode 100644 index 000000000..e8b07801c --- /dev/null +++ b/src/stores/standalone/haStatus.ts @@ -0,0 +1,55 @@ +import { defineStore } from 'pinia' +import { onMounted, ref } from 'vue' +import { ubusCall } from '@/lib/standalone/ubus' +import type { AxiosResponse } from 'axios' + +type HaStatus = AxiosResponse<{ + state: string + role: string + status: string + last_sync_status: string + last_sync_time: number +}> + +export const useHaStatusStore = defineStore('haStatus', () => { + const state = ref('') + const role = ref('') + const status = ref('') + const lastSyncStatus = ref('') + const lastSyncTime = ref(0) + + const loading = ref(true) + const error = ref() + + function fetchStatus() { + ubusCall('ns.ha', 'status', {}) + .then((response: HaStatus) => { + state.value = response.data.state + role.value = response.data.role + status.value = response.data.status + lastSyncStatus.value = response.data.last_sync_status.toLowerCase().replace(/ /g, '_') + lastSyncTime.value = response.data.last_sync_time + }) + .catch((reason: Error) => { + error.value = reason + }) + .finally(() => { + loading.value = false + }) + } + + onMounted(() => { + fetchStatus() + }) + + return { + state, + role, + status, + lastSyncStatus, + lastSyncTime, + loading, + error, + fetchStatus + } +}) diff --git a/src/views/standalone/StandaloneDashboardView.vue b/src/views/standalone/StandaloneDashboardView.vue index 3fd45954b..8757c5e98 100644 --- a/src/views/standalone/StandaloneDashboardView.vue +++ b/src/views/standalone/StandaloneDashboardView.vue @@ -17,6 +17,7 @@ import ThreatShieldIpCard from '@/components/standalone/dashboard/ThreatShieldIp import IpsServiceCard from '@/components/standalone/dashboard/IpsServiceCard.vue' import MacBindingStatusCard from '@/components/standalone/dashboard/MacBindingStatusCard.vue' import BackupStatusCard from '@/components/standalone/dashboard/BackupStatusCard.vue' +import HaStatusCard from '@/components/standalone/dashboard/HaStatusCard.vue' const { t } = useI18n() const route = useRoute() @@ -119,5 +120,6 @@ function goTo(path: string) { :icon="['fas', 'circle-info']" /> +