refactor(components): move status indicator from topbar to sidebar
Relocate the online status indicator component from the top navigation bar to the sidebar for better layout organization. Remove unused code and update styling to match sidebar theme.
This commit is contained in:
@@ -12,6 +12,12 @@
|
|||||||
<span class="menu-text">{{ item.title }}</span>
|
<span class="menu-text">{{ item.title }}</span>
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="status-info">
|
||||||
|
<div class="status-item">
|
||||||
|
<span :class="['status-dot', { online: isOnline }]"></span>
|
||||||
|
<span class="status-text">{{ isOnline ? 'Online' : 'Offline' }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="theme-toggle">
|
<div class="theme-toggle">
|
||||||
<button @click="toggleTheme" class="theme-button">
|
<button @click="toggleTheme" class="theme-button">
|
||||||
<span class="theme-icon"><i :class="isDarkMode ? 'fas fa-sun' : 'fas fa-moon'" aria-hidden="true"></i></span>
|
<span class="theme-icon"><i :class="isDarkMode ? 'fas fa-sun' : 'fas fa-moon'" aria-hidden="true"></i></span>
|
||||||
@@ -22,8 +28,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { computed, inject } from 'vue';
|
import { ref, computed, inject, onMounted, onBeforeUnmount } from 'vue';
|
||||||
import { getCookie } from '../utils/functions.js';
|
import { getCookie } from '../utils/functions.js';
|
||||||
|
import { systemApi } from '../api/index.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'SideBar',
|
name: 'SideBar',
|
||||||
@@ -31,6 +38,8 @@ export default {
|
|||||||
const userType = getCookie('user-type') || 'visitor';
|
const userType = getCookie('user-type') || 'visitor';
|
||||||
const isDarkMode = inject('isDarkMode');
|
const isDarkMode = inject('isDarkMode');
|
||||||
const toggleTheme = inject('toggleTheme');
|
const toggleTheme = inject('toggleTheme');
|
||||||
|
const isOnline = ref(false);
|
||||||
|
let statusInterval;
|
||||||
|
|
||||||
const allMenuItems = [
|
const allMenuItems = [
|
||||||
{ path: '/instances', title: 'Instance Management', icon: 'fas fa-box', permission: ['superuser', 'admin', 'visitor'] },
|
{ path: '/instances', title: 'Instance Management', icon: 'fas fa-box', permission: ['superuser', 'admin', 'visitor'] },
|
||||||
@@ -45,10 +54,31 @@ export default {
|
|||||||
return allMenuItems.filter(item => item.permission.includes(userType));
|
return allMenuItems.filter(item => item.permission.includes(userType));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const checkStatus = async () => {
|
||||||
|
try {
|
||||||
|
const result = await systemApi.getStatus();
|
||||||
|
isOnline.value = result.data.Status === 'Online';
|
||||||
|
} catch (error) {
|
||||||
|
isOnline.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
checkStatus();
|
||||||
|
statusInterval = setInterval(checkStatus, 60000);
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
if (statusInterval) {
|
||||||
|
clearInterval(statusInterval);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
menuItems,
|
menuItems,
|
||||||
isDarkMode,
|
isDarkMode,
|
||||||
toggleTheme
|
toggleTheme,
|
||||||
|
isOnline
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -156,4 +186,32 @@ export default {
|
|||||||
.theme-text {
|
.theme-text {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.status-info {
|
||||||
|
padding: 16px;
|
||||||
|
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-dot {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #ff4d4f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-dot.online {
|
||||||
|
background: #52c41a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--sidebar-text);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -15,10 +15,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="topbar-right">
|
<div class="topbar-right">
|
||||||
<div class="status-info">
|
|
||||||
<span :class="['status-dot', { online: isOnline }]"></span>
|
|
||||||
<span class="status-text">{{ isOnline ? 'Online' : 'Offline' }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="version-info" v-if="softwareInfo">
|
<div class="version-info" v-if="softwareInfo">
|
||||||
<span>v{{ softwareInfo.Version }}</span>
|
<span>v{{ softwareInfo.Version }}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -88,7 +84,6 @@ export default {
|
|||||||
emits: ['search'],
|
emits: ['search'],
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const searchQuery = ref('');
|
const searchQuery = ref('');
|
||||||
const isOnline = ref(false);
|
|
||||||
const softwareInfo = ref(null);
|
const softwareInfo = ref(null);
|
||||||
const username = ref(getCookie('username') || 'User');
|
const username = ref(getCookie('username') || 'User');
|
||||||
const menuVisible = ref(false);
|
const menuVisible = ref(false);
|
||||||
@@ -103,15 +98,6 @@ export default {
|
|||||||
});
|
});
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const checkStatus = async () => {
|
|
||||||
try {
|
|
||||||
const result = await systemApi.getStatus();
|
|
||||||
isOnline.value = result.data.Status === 'Online';
|
|
||||||
} catch (error) {
|
|
||||||
isOnline.value = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getSoftwareInfo = async () => {
|
const getSoftwareInfo = async () => {
|
||||||
try {
|
try {
|
||||||
const result = await systemApi.getSoftwareInfo();
|
const result = await systemApi.getSoftwareInfo();
|
||||||
@@ -207,9 +193,7 @@ export default {
|
|||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
checkStatus();
|
|
||||||
getSoftwareInfo();
|
getSoftwareInfo();
|
||||||
setInterval(checkStatus, 60000);
|
|
||||||
document.addEventListener('click', closeMenu);
|
document.addEventListener('click', closeMenu);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -219,7 +203,6 @@ export default {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
searchQuery,
|
searchQuery,
|
||||||
isOnline,
|
|
||||||
softwareInfo,
|
softwareInfo,
|
||||||
username,
|
username,
|
||||||
handleSearch,
|
handleSearch,
|
||||||
@@ -312,27 +295,7 @@ export default {
|
|||||||
gap: 24px;
|
gap: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-info {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-dot {
|
|
||||||
width: 8px;
|
|
||||||
height: 8px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: #ff4d4f;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-dot.online {
|
|
||||||
background: #52c41a;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-text {
|
|
||||||
font-size: 14px;
|
|
||||||
color: var(--text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.version-info {
|
.version-info {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|||||||
Reference in New Issue
Block a user