Merge pull request #1229 from Computroniks/#1209-Logout-button-in-navbar

Add #1209: logout button in navbar
This commit is contained in:
Louis Lam 2022-04-19 19:59:52 +08:00 committed by GitHub
commit 10f6a3c4f5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 127 additions and 20 deletions

View file

@ -87,5 +87,7 @@ module.exports.autoStart = async (token) => {
module.exports.stop = async () => { module.exports.stop = async () => {
console.log("Stop cloudflared"); console.log("Stop cloudflared");
if (cloudflared) {
cloudflared.stop(); cloudflared.stop();
}
}; };

View file

@ -4,7 +4,7 @@
<!-- Change Password --> <!-- Change Password -->
<template v-if="!settings.disableAuth"> <template v-if="!settings.disableAuth">
<p> <p>
{{ $t("Current User") }}: <strong>{{ username }}</strong> {{ $t("Current User") }}: <strong>{{ $root.username }}</strong>
<button v-if="! settings.disableAuth" id="logout-btn" class="btn btn-danger ms-4 me-2 mb-2" @click="$root.logout">{{ $t("Logout") }}</button> <button v-if="! settings.disableAuth" id="logout-btn" class="btn btn-danger ms-4 me-2 mb-2" @click="$root.logout">{{ $t("Logout") }}</button>
</p> </p>
@ -269,7 +269,6 @@ export default {
data() { data() {
return { return {
username: "",
invalidPassword: false, invalidPassword: false,
password: { password: {
currentPassword: "", currentPassword: "",
@ -297,10 +296,6 @@ export default {
}, },
}, },
mounted() {
this.loadUsername();
},
methods: { methods: {
savePassword() { savePassword() {
if (this.password.newPassword !== this.password.repeatNewPassword) { if (this.password.newPassword !== this.password.repeatNewPassword) {
@ -319,14 +314,6 @@ export default {
} }
}, },
loadUsername() {
const jwtPayload = this.$root.getJWTPayload();
if (jwtPayload) {
this.username = jwtPayload.username;
}
},
disableAuth() { disableAuth() {
this.settings.disableAuth = true; this.settings.disableAuth = true;

View file

@ -34,11 +34,13 @@ import {
faAward, faAward,
faLink, faLink,
faChevronDown, faChevronDown,
faSignOutAlt,
faPen, faPen,
faExternalLinkSquareAlt, faExternalLinkSquareAlt,
faSpinner, faSpinner,
faUndo, faUndo,
faPlusCircle, faPlusCircle,
faAngleDown,
} from "@fortawesome/free-solid-svg-icons"; } from "@fortawesome/free-solid-svg-icons";
library.add( library.add(
@ -72,11 +74,13 @@ library.add(
faAward, faAward,
faLink, faLink,
faChevronDown, faChevronDown,
faSignOutAlt,
faPen, faPen,
faExternalLinkSquareAlt, faExternalLinkSquareAlt,
faSpinner, faSpinner,
faUndo, faUndo,
faPlusCircle, faPlusCircle,
faAngleDown,
); );
export { FontAwesomeIcon }; export { FontAwesomeIcon };

View file

@ -32,10 +32,28 @@
</router-link> </router-link>
</li> </li>
<li v-if="$root.loggedIn" class="nav-item"> <li v-if="$root.loggedIn" class="nav-item">
<router-link to="/settings" class="nav-link" :class="{ active: $route.path.includes('settings') }"> <div class="dropdown dropdown-profile-pic">
<div type="button" 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><span class="dropdown-item-text">Signed in as <strong>{{ $root.username }}</strong></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") }} <font-awesome-icon icon="cog" /> {{ $t("Settings") }}
</router-link> </router-link>
</li> </li>
<li v-if="$root.loggedIn && $root.storage().token !== 'autoLogin'">
<button class="dropdown-item" @click="$root.logout">
<font-awesome-icon icon="sign-out-alt" />
{{ $t("Logout") }}
</button>
</li>
</ul>
</div>
</li>
</ul> </ul>
</header> </header>
@ -192,6 +210,79 @@ main {
z-index: 99999; 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;
margin-top: 8px !important;
border-radius: 20px;
.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 { .dark {
header { header {
background-color: $dark-header-bg; background-color: $dark-header-bg;

View file

@ -28,6 +28,7 @@ export default {
connectCount: 0, connectCount: 0,
initedSocketIO: false, initedSocketIO: false,
}, },
username: null,
remember: (localStorage.remember !== "0"), remember: (localStorage.remember !== "0"),
allowLoginDialog: false, // Allowed to show login dialog, but "loggedIn" have to be true too. This exists because prevent the login dialog show 0.1s in first before the socket server auth-ed. allowLoginDialog: false, // Allowed to show login dialog, but "loggedIn" have to be true too. This exists because prevent the login dialog show 0.1s in first before the socket server auth-ed.
loggedIn: false, loggedIn: false,
@ -102,6 +103,7 @@ export default {
socket.on("autoLogin", (monitorID, data) => { socket.on("autoLogin", (monitorID, data) => {
this.loggedIn = true; this.loggedIn = true;
this.username = "No Auth";
this.storage().token = "autoLogin"; this.storage().token = "autoLogin";
this.allowLoginDialog = false; this.allowLoginDialog = false;
}); });
@ -233,7 +235,6 @@ export default {
if (token !== "autoLogin") { if (token !== "autoLogin") {
this.loginByToken(token); this.loginByToken(token);
} else { } else {
// Timeout if it is not actually auto login // Timeout if it is not actually auto login
setTimeout(() => { setTimeout(() => {
if (! this.loggedIn) { if (! this.loggedIn) {
@ -241,7 +242,6 @@ export default {
this.$root.storage().removeItem("token"); this.$root.storage().removeItem("token");
} }
}, 5000); }, 5000);
} }
} else { } else {
this.allowLoginDialog = true; this.allowLoginDialog = true;
@ -305,6 +305,7 @@ export default {
this.storage().token = res.token; this.storage().token = res.token;
this.socket.token = res.token; this.socket.token = res.token;
this.loggedIn = true; this.loggedIn = true;
this.username = this.getJWTPayload()?.username;
// Trigger Chrome Save Password // Trigger Chrome Save Password
history.pushState({}, ""); history.pushState({}, "");
@ -322,6 +323,7 @@ export default {
this.logout(); this.logout();
} else { } else {
this.loggedIn = true; this.loggedIn = true;
this.username = this.getJWTPayload()?.username;
} }
}); });
}, },
@ -331,6 +333,7 @@ export default {
this.storage().removeItem("token"); this.storage().removeItem("token");
this.socket.token = null; this.socket.token = null;
this.loggedIn = false; this.loggedIn = false;
this.username = null;
this.clearData(); this.clearData();
}, },
@ -398,6 +401,14 @@ export default {
computed: { computed: {
usernameFirstChar() {
if (typeof this.username == "string" && this.username.length >= 1) {
return this.username.charAt(0).toUpperCase();
} else {
return "🐻";
}
},
lastHeartbeatList() { lastHeartbeatList() {
let result = {}; let result = {};

View file

@ -16,6 +16,14 @@
{{ item.title }} {{ item.title }}
</div> </div>
</router-link> </router-link>
<!-- Logout Button -->
<a v-if="$root.isMobile && $root.loggedIn && $root.storage().token !== 'autoLogin'" class="logout" @click.prevent="$root.logout">
<div class="menu-item">
<font-awesome-icon icon="sign-out-alt" />
{{ $t("Logout") }}
</div>
</a>
</div> </div>
<div class="settings-content col-lg-9 col-md-7"> <div class="settings-content col-lg-9 col-md-7">
<div v-if="currentPage" class="settings-content-header"> <div v-if="currentPage" class="settings-content-header">
@ -233,4 +241,8 @@ footer {
} }
} }
} }
.logout {
color: $danger !important;
}
</style> </style>