<template> <div :class="classes"> <div v-if="! $root.socket.connected && ! $root.socket.firstConnect" class="lost-connection"> <div class="container-fluid"> {{ $root.connectionErrorMsg }} <div v-if="$root.showReverseProxyGuide"> {{ $t("Using a Reverse Proxy?") }} <a href="https://github.com/louislam/uptime-kuma/wiki/Reverse-Proxy" target="_blank">{{ $t("Check how to config it for WebSocket") }}</a> </div> </div> </div> <!-- Desktop header --> <header v-if="! $root.isMobile" class="d-flex flex-wrap justify-content-center py-3 mb-3 border-bottom"> <router-link to="/dashboard" class="d-flex align-items-center mb-3 mb-md-0 me-md-auto text-dark text-decoration-none"> <object class="bi me-2 ms-4" width="40" height="40" data="/icon.svg" /> <span class="fs-4 title">{{ $t("Uptime Kuma") }}</span> </router-link> <a v-if="hasNewVersion" target="_blank" href="https://github.com/louislam/uptime-kuma/releases" class="btn btn-info me-3"> <font-awesome-icon icon="arrow-alt-circle-up" /> {{ $t("New Update") }} </a> <ul class="nav nav-pills"> <li v-if="$root.loggedIn" class="nav-item me-2"> <router-link to="/manage-status-page" class="nav-link"> <font-awesome-icon icon="stream" /> {{ $t("Status Pages") }} </router-link> </li> <li v-if="$root.loggedIn" class="nav-item me-2"> <router-link to="/dashboard" class="nav-link"> <font-awesome-icon icon="tachometer-alt" /> {{ $t("Dashboard") }} </router-link> </li> <li v-if="$root.loggedIn" class="nav-item"> <div class="dropdown dropdown-profile-pic"> <div class="nav-link" data-bs-toggle="dropdown"> <div class="profile-pic">{{ $root.usernameFirstChar }}</div> <font-awesome-icon icon="angle-down" /> </div> <ul class="dropdown-menu"> <li> <i18n-t v-if="$root.username != null" tag="span" keypath="signedInDisp" class="dropdown-item-text"> <strong>{{ $root.username }}</strong> </i18n-t> <span v-if="$root.username == null" class="dropdown-item-text">{{ $t("signedInDispDisabled") }}</span> </li> <li><hr class="dropdown-divider"></li> <li> <router-link to="/settings" class="dropdown-item" :class="{ active: $route.path.includes('settings') }"> <font-awesome-icon icon="cog" /> {{ $t("Settings") }} </router-link> </li> <li v-if="$root.loggedIn && $root.socket.token !== 'autoLogin'"> <button class="dropdown-item" @click="$root.logout"> <font-awesome-icon icon="sign-out-alt" /> {{ $t("Logout") }} </button> </li> </ul> </div> </li> </ul> </header> <!-- Mobile header --> <header v-else class="d-flex flex-wrap justify-content-center pt-2 pb-2 mb-3"> <router-link to="/dashboard" class="d-flex align-items-center text-dark text-decoration-none"> <object class="bi" width="40" height="40" data="/icon.svg" /> <span class="fs-4 title ms-2">Uptime Kuma</span> </router-link> </header> <main> <router-view v-if="$root.loggedIn" /> <Login v-if="! $root.loggedIn && $root.allowLoginDialog" /> </main> <!-- Mobile Only --> <div v-if="$root.isMobile" style="width: 100%; height: 60px;" /> <nav v-if="$root.isMobile" class="bottom-nav"> <router-link to="/dashboard" class="nav-link"> <div><font-awesome-icon icon="tachometer-alt" /></div> {{ $t("Dashboard") }} </router-link> <router-link to="/list" class="nav-link"> <div><font-awesome-icon icon="list" /></div> {{ $t("List") }} </router-link> <router-link to="/add" class="nav-link"> <div><font-awesome-icon icon="plus" /></div> {{ $t("Add") }} </router-link> <router-link to="/settings" class="nav-link"> <div><font-awesome-icon icon="cog" /></div> {{ $t("Settings") }} </router-link> </nav> </div> </template> <script> import Login from "../components/Login.vue"; import compareVersions from "compare-versions"; export default { components: { Login, }, data() { return {}; }, computed: { // Theme or Mobile classes() { const classes = {}; classes[this.$root.theme] = true; classes["mobile"] = this.$root.isMobile; return classes; }, hasNewVersion() { if (this.$root.info.latestVersion && this.$root.info.version) { return compareVersions(this.$root.info.latestVersion, this.$root.info.version) >= 1; } else { return false; } }, }, watch: { }, mounted() { }, methods: { }, }; </script> <style lang="scss" scoped> @import "../assets/vars.scss"; .nav-link { &.status-page { background-color: rgba(255, 255, 255, 0.1); } } .bottom-nav { z-index: 1000; position: fixed; bottom: 0; height: 60px; width: 100%; left: 0; background-color: #fff; box-shadow: 0 15px 47px 0 rgba(0, 0, 0, 0.05), 0 5px 14px 0 rgba(0, 0, 0, 0.05); text-align: center; white-space: nowrap; padding: 0 10px; a { text-align: center; width: 25%; display: inline-block; height: 100%; padding: 8px 10px 0; font-size: 13px; color: #c1c1c1; overflow: hidden; text-decoration: none; &.router-link-exact-active, &.active { color: $primary; font-weight: bold; } div { font-size: 20px; } } } main { min-height: calc(100vh - 160px); } .title { font-weight: bold; } .nav { margin-right: 25px; } .lost-connection { padding: 5px; background-color: crimson; color: white; position: fixed; width: 100%; z-index: 99999; } // Profile Pic Button with Dropdown .dropdown-profile-pic { user-select: none; .nav-link { cursor: pointer; display: flex; gap: 6px; align-items: center; background-color: rgba(200, 200, 200, 0.2); padding: 0.5rem 0.8rem; &:hover { background-color: rgba(255, 255, 255, 0.2); } } .dropdown-menu { transition: all 0.2s; padding-left: 0; padding-bottom: 0; margin-top: 8px !important; border-radius: 16px; overflow: hidden; .dropdown-divider { margin: 0; border-top: 1px solid rgba(0, 0, 0, 0.4); background-color: transparent; } .dropdown-item-text { font-size: 14px; padding-bottom: 0.7rem; } .dropdown-item { padding: 0.7rem 1rem; } .dark & { background-color: $dark-bg; color: $dark-font-color; border-color: $dark-border-color; .dropdown-item { color: $dark-font-color; &.active { color: $dark-font-color2; background-color: $highlight !important; } &:hover { background-color: $dark-bg2; } } } } .profile-pic { display: flex; align-items: center; justify-content: center; color: white; background-color: $primary; width: 24px; height: 24px; margin-right: 5px; border-radius: 50rem; font-weight: bold; font-size: 10px; } } .dark { header { background-color: $dark-header-bg; border-bottom-color: $dark-header-bg !important; span { color: #f0f6fc; } } .bottom-nav { background-color: $dark-bg; } } </style>