Files
dougal-software/lib/www/client/source/src/components/footer.vue
2025-08-12 00:22:09 +02:00

99 lines
2.8 KiB
Vue

<!-- kate: replace-tabs on; indent-width 2; -->
<template>
<v-footer app>
<dougal-help-dialog></dougal-help-dialog>
<v-spacer></v-spacer>
<small class="d-none d-sm-inline">&copy; {{year}} <a href="https://aaltronav.eu/" target="_blank" class="brand">Aaltronav</a></small>
<v-spacer></v-spacer>
<template v-if="isFrontendRemote">
<template v-if="serverConnected">
<v-icon v-if="isGatewayReliable" class="mr-6" title="Connected to server via gateway">mdi-cloud-outline</v-icon>
<v-icon v-else class="mr-6" color="orange" title="Gateway connection is unreliable. Expect outages.">mdi-cloud-off</v-icon>
</template>
<v-icon v-else class="mr-6" color="red" :title="`Server connection lost: the gateway cannot reach the remote server.\nWe will reconnect automatically when the link with the remote server is restored.`">mdi-cloud-off</v-icon>
</template>
<template v-else>
<v-icon v-if="serverConnected" class="mr-6" small title="Connected to server">mdi-lan-connect</v-icon>
<v-icon v-else class="mr-6" small color="red" :title="`Server connection lost.\nWe will reconnect automatically when the server comes back.`">mdi-lan-disconnect</v-icon>
</template>
<dougal-notifications-control class="mr-6"></dougal-notifications-control>
<div title="Night mode">
<v-switch
class="ma-auto"
flat
hide-details
v-model="$vuetify.theme.dark"
append-icon="mdi-weather-night"
></v-switch>
</div>
</v-footer>
</template>
<style>
@font-face {
font-family: "Bank Gothic Medium";
src: local("Bank Gothic Medium"), url("/public/fonts/bank-gothic-medium.woff");
}
.brand {
font-family: "Bank Gothic Medium";
}
</style>
<script>
import { mapState } from 'vuex';
import DougalHelpDialog from '@/components/help-dialog';
import DougalNotificationsControl from '@/components/notifications-control';
export default {
name: 'DougalFooter',
components: {
DougalHelpDialog,
DougalNotificationsControl
},
data () {
return {
lastGatewayErrorTimestamp: 0,
gatewayErrorSilencePeriod: 60000,
}
},
computed: {
year () {
const date = new Date();
return date.getUTCFullYear();
},
...mapState({
serverConnected: state => state.notify.serverConnected,
isFrontendRemote: state => state.api.serverInfo?.["remote-frontend"] ?? false,
isGatewayReliable: state => state.api.isGatewayReliable
})
},
watch: {
isGatewayReliable (val) {
if (val === false) {
const elapsed = Date.now() - this.lastGatewayErrorTimestamp;
const lastGatewayErrorTimestamp = Date.now();
if (elapsed > this.gatewayErrorSilencePeriod) {
this.$root.showSnack("Gateway error", "warning");
}
}
}
}
};
</script>