feat(web-ui): add logout (#5121)
This commit is contained in:
@@ -1755,6 +1755,7 @@ namespace confighttp {
|
|||||||
server.resource["^/clients/?$"]["GET"] = page_handler("clients.html");
|
server.resource["^/clients/?$"]["GET"] = page_handler("clients.html");
|
||||||
server.resource["^/config/?$"]["GET"] = page_handler("config.html");
|
server.resource["^/config/?$"]["GET"] = page_handler("config.html");
|
||||||
server.resource["^/featured/?$"]["GET"] = page_handler("featured.html");
|
server.resource["^/featured/?$"]["GET"] = page_handler("featured.html");
|
||||||
|
server.resource["^/logout/?$"]["GET"] = page_handler("logout.html", false);
|
||||||
server.resource["^/password/?$"]["GET"] = page_handler("password.html");
|
server.resource["^/password/?$"]["GET"] = page_handler("password.html");
|
||||||
server.resource["^/pin/?$"]["GET"] = page_handler("pin.html");
|
server.resource["^/pin/?$"]["GET"] = page_handler("pin.html");
|
||||||
server.resource["^/troubleshooting/?$"]["GET"] = page_handler("troubleshooting.html");
|
server.resource["^/troubleshooting/?$"]["GET"] = page_handler("troubleshooting.html");
|
||||||
|
|||||||
@@ -41,21 +41,38 @@
|
|||||||
{{ $t('navbar.configuration') }}
|
{{ $t('navbar.configuration') }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="./password">
|
|
||||||
<Shield :size="18" class="icon"></Shield>
|
|
||||||
{{ $t('navbar.password') }}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="./troubleshooting">
|
<a class="nav-link" href="./troubleshooting">
|
||||||
<Info :size="18" class="icon"></Info>
|
<Info :size="18" class="icon"></Info>
|
||||||
{{ $t('navbar.troubleshoot') }}
|
{{ $t('navbar.troubleshoot') }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="navbar-nav ms-auto mb-2 mb-lg-0">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<ThemeToggle/>
|
<ThemeToggle/>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item dropdown">
|
||||||
|
<button class="nav-link dropdown-toggle" type="button" id="navbarUserMenu"
|
||||||
|
data-bs-toggle="dropdown" aria-expanded="false" aria-label="User menu" title="User menu">
|
||||||
|
<CircleUserRound :size="18" class="icon"></CircleUserRound>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarUserMenu">
|
||||||
|
<li>
|
||||||
|
<a class="dropdown-item d-flex align-items-center" href="./password">
|
||||||
|
<Shield :size="18" class="icon"></Shield>
|
||||||
|
{{ $t('navbar.password') }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li><hr class="dropdown-divider"></li>
|
||||||
|
<li>
|
||||||
|
<button type="button" class="dropdown-item d-flex align-items-center" @click="logout">
|
||||||
|
<LogOut :size="18" class="icon"></LogOut>
|
||||||
|
{{ $t('navbar.logout') }}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -65,7 +82,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { Home, Lock, Layers, Star, Settings, Shield, Info } from 'lucide-vue-next'
|
import { CircleUserRound, Home, Info, Layers, Lock, LogOut, Settings, Shield, Star } from 'lucide-vue-next'
|
||||||
import ThemeToggle from './ThemeToggle.vue'
|
import ThemeToggle from './ThemeToggle.vue'
|
||||||
import Notification from './Notification.vue'
|
import Notification from './Notification.vue'
|
||||||
|
|
||||||
@@ -79,14 +96,48 @@ export default {
|
|||||||
Star,
|
Star,
|
||||||
Settings,
|
Settings,
|
||||||
Shield,
|
Shield,
|
||||||
Info
|
Info,
|
||||||
|
CircleUserRound,
|
||||||
|
LogOut
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
console.log("Header mounted!")
|
console.log("Header mounted!")
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
let el = document.querySelector("a[href='" + document.location.pathname + "']");
|
const currentPath = globalThis.location.pathname.replace(/\/$/, '') || '/'
|
||||||
if (el) el.classList.add("active")
|
const links = document.querySelectorAll('.navbar-sunshine a[href]')
|
||||||
|
|
||||||
|
for (const link of links) {
|
||||||
|
const href = link.getAttribute('href')
|
||||||
|
if (!href || href === '#') {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const linkPath = new URL(href, globalThis.location.href).pathname.replace(/\/$/, '') || '/'
|
||||||
|
if (linkPath !== currentPath) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
link.classList.add('active')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
logout() {
|
||||||
|
const cacheBuster = Date.now().toString()
|
||||||
|
const logoutPageUrl = new URL('/logout', globalThis.location.href)
|
||||||
|
const request = new XMLHttpRequest()
|
||||||
|
const finish = () => {
|
||||||
|
globalThis.location.replace(logoutPageUrl.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
request.open('GET', '/', true, 'sunshine-logout', cacheBuster)
|
||||||
|
request.setRequestHeader('Cache-Control', 'no-store')
|
||||||
|
request.onload = finish
|
||||||
|
request.onerror = finish
|
||||||
|
request.ontimeout = finish
|
||||||
|
request.timeout = 5000
|
||||||
|
request.send()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
41
src_assets/common/assets/web/logout.html
Normal file
41
src_assets/common/assets/web/logout.html
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" data-bs-theme="auto">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<%- header %>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body id="app" v-cloak>
|
||||||
|
<div class="container py-5">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-8 col-lg-6">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body text-center">
|
||||||
|
<img src="/images/logo-sunshine-45.png" height="45" alt="Sunshine" class="mb-3">
|
||||||
|
<h1 class="h3 mb-3">{{ $t('logout.logged_out') }}</h1>
|
||||||
|
<p class="text-muted mb-4">{{ $t('logout.logged_out_desc') }}</p>
|
||||||
|
<a class="btn btn-primary" href="./">
|
||||||
|
<log-in :size="18" class="icon"></log-in>
|
||||||
|
{{ $t('logout.login') }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
<script type="module">
|
||||||
|
import { createApp } from 'vue'
|
||||||
|
import { initApp } from './init'
|
||||||
|
import { LogIn } from 'lucide-vue-next'
|
||||||
|
|
||||||
|
const app = createApp({
|
||||||
|
components: {
|
||||||
|
LogIn,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
initApp(app);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -802,6 +802,7 @@ body {
|
|||||||
color: var(--navbar-text-muted) !important;
|
color: var(--navbar-text-muted) !important;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
padding: 0.5rem 1rem !important;
|
padding: 0.5rem 1rem !important;
|
||||||
|
min-height: calc(1.5em + 1rem);
|
||||||
border-radius: var(--radius-md);
|
border-radius: var(--radius-md);
|
||||||
transition: all var(--transition-fast);
|
transition: all var(--transition-fast);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -426,6 +426,7 @@
|
|||||||
"configuration": "Configuration",
|
"configuration": "Configuration",
|
||||||
"featured": "Featured Apps",
|
"featured": "Featured Apps",
|
||||||
"home": "Home",
|
"home": "Home",
|
||||||
|
"logout": "Log Out",
|
||||||
"password": "Change Password",
|
"password": "Change Password",
|
||||||
"pin": "PIN",
|
"pin": "PIN",
|
||||||
"theme_auto": "Auto",
|
"theme_auto": "Auto",
|
||||||
@@ -446,6 +447,11 @@
|
|||||||
"toggle_theme": "Theme",
|
"toggle_theme": "Theme",
|
||||||
"troubleshoot": "Troubleshooting"
|
"troubleshoot": "Troubleshooting"
|
||||||
},
|
},
|
||||||
|
"logout": {
|
||||||
|
"logged_out": "Logged Out",
|
||||||
|
"logged_out_desc": "You have successfully logged out.",
|
||||||
|
"login": "Log In"
|
||||||
|
},
|
||||||
"password": {
|
"password": {
|
||||||
"confirm_password": "Confirm Password",
|
"confirm_password": "Confirm Password",
|
||||||
"current_creds": "Current Credentials",
|
"current_creds": "Current Credentials",
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ export default defineConfig({
|
|||||||
config: resolve(assetsSrcPath, 'config.html'),
|
config: resolve(assetsSrcPath, 'config.html'),
|
||||||
featured: resolve(assetsSrcPath, 'featured.html'),
|
featured: resolve(assetsSrcPath, 'featured.html'),
|
||||||
index: resolve(assetsSrcPath, 'index.html'),
|
index: resolve(assetsSrcPath, 'index.html'),
|
||||||
|
logout: resolve(assetsSrcPath, 'logout.html'),
|
||||||
password: resolve(assetsSrcPath, 'password.html'),
|
password: resolve(assetsSrcPath, 'password.html'),
|
||||||
pin: resolve(assetsSrcPath, 'pin.html'),
|
pin: resolve(assetsSrcPath, 'pin.html'),
|
||||||
troubleshooting: resolve(assetsSrcPath, 'troubleshooting.html'),
|
troubleshooting: resolve(assetsSrcPath, 'troubleshooting.html'),
|
||||||
|
|||||||
Reference in New Issue
Block a user