Add navigation and fix layouts
This commit is contained in:
		| @@ -1,5 +1,5 @@ | ||||
| <template> | ||||
|   <div class="d-flex"> | ||||
|   <div class="app-container"> | ||||
|     <!-- Sidebar --> | ||||
|     <div class="sidebar bg-dark" :class="{ 'collapsed': sidebarCollapsed }"> | ||||
|       <div class="sidebar-header"> | ||||
| @@ -9,7 +9,12 @@ | ||||
|         </button> | ||||
|       </div> | ||||
|       <div class="sidebar-content"> | ||||
|         <!-- Future navigation items can go here --> | ||||
|         <nav class="nav-menu"> | ||||
|           <router-link to="/" class="nav-item active"> | ||||
|             <i class="fas fa-home"></i> | ||||
|             <span class="nav-text">Overview</span> | ||||
|           </router-link> | ||||
|         </nav> | ||||
|       </div> | ||||
|       <div class="sidebar-footer"> | ||||
|         <button class="btn btn-outline-light w-100" @click="toggleConfig"> | ||||
| @@ -171,32 +176,78 @@ onUnmounted(() => { | ||||
| @import 'bootstrap/dist/css/bootstrap.min.css'; | ||||
| @import '@fortawesome/fontawesome-free/css/all.min.css'; | ||||
|  | ||||
| .app-container { | ||||
|   display: flex; | ||||
|   min-height: 100vh; | ||||
|   width: 100%; | ||||
| } | ||||
|  | ||||
| .sidebar { | ||||
|   width: 250px; | ||||
|   height: 100vh; | ||||
|   position: fixed; | ||||
|   left: 0; | ||||
|   top: 0; | ||||
|   padding: 1rem; | ||||
|   padding: 0.75rem 0.5rem; | ||||
|   transition: all 0.3s ease; | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|   z-index: 1000; | ||||
| } | ||||
|  | ||||
| .sidebar.collapsed { | ||||
|   width: 60px; | ||||
| } | ||||
|  | ||||
| /* Collapsed sidebar styles */ | ||||
| .sidebar.collapsed .sidebar-header h5, | ||||
| .sidebar.collapsed .sidebar-content, | ||||
| .sidebar.collapsed .config-text { | ||||
| .sidebar.collapsed .config-text, | ||||
| .sidebar.collapsed .nav-text { | ||||
|   display: none; | ||||
| } | ||||
|  | ||||
| .sidebar.collapsed .nav-menu { | ||||
|   padding: 0.5rem 0; | ||||
| } | ||||
|  | ||||
| .sidebar.collapsed .nav-item { | ||||
|   padding: 0.75rem 0.25rem; | ||||
|   justify-content: center; | ||||
| } | ||||
|  | ||||
| .sidebar.collapsed .nav-item i { | ||||
|   margin-right: 0; | ||||
|   font-size: 1.1rem; | ||||
| } | ||||
|  | ||||
| .sidebar.collapsed .sidebar-footer .btn { | ||||
|   padding: 0.375rem; | ||||
|   display: flex; | ||||
|   justify-content: center; | ||||
| } | ||||
|  | ||||
| .main-content { | ||||
|   flex: 1; | ||||
|   padding-left: 262px; | ||||
|   padding-right: 0.5rem; | ||||
|   padding-top: 0.5rem; | ||||
|   padding-bottom: 0.5rem; | ||||
|   transition: padding-left 0.3s ease; | ||||
|   min-height: 100vh; | ||||
|   width: 100%; | ||||
|   box-sizing: border-box; | ||||
| } | ||||
|  | ||||
| .main-content.expanded { | ||||
|   padding-left: 72px; | ||||
| } | ||||
|  | ||||
| .sidebar-header { | ||||
|   padding-bottom: 1rem; | ||||
|   padding-left: 0.25rem; | ||||
|   padding-right: 0.25rem; | ||||
|   padding-bottom: 0.75rem; | ||||
|   border-bottom: 1px solid rgba(255,255,255,0.1); | ||||
|   margin-bottom: 1rem; | ||||
|   margin-bottom: 0.75rem; | ||||
|   display: flex; | ||||
|   justify-content: space-between; | ||||
|   align-items: center; | ||||
| @@ -217,29 +268,18 @@ onUnmounted(() => { | ||||
|  | ||||
| .sidebar-footer { | ||||
|   margin-top: auto; | ||||
|   padding-top: 1rem; | ||||
|   padding-left: 0.25rem; | ||||
|   padding-right: 0.25rem; | ||||
|   padding-top: 0.75rem; | ||||
|   border-top: 1px solid rgba(255,255,255,0.1); | ||||
| } | ||||
|  | ||||
| .sidebar.collapsed .sidebar-footer .btn { | ||||
|   padding: 0.375rem; | ||||
|   padding: 0.375rem 0.5rem; | ||||
|   display: flex; | ||||
|   justify-content: center; | ||||
| } | ||||
|  | ||||
| .main-content { | ||||
|   margin-left: 250px; | ||||
|   padding: 0.5rem; | ||||
|   width: calc(100% - 250px); | ||||
|   min-height: 100vh; | ||||
|   transition: all 0.3s ease; | ||||
| } | ||||
|  | ||||
| .main-content.expanded { | ||||
|   margin-left: 60px; | ||||
|   width: calc(100% - 60px); | ||||
| } | ||||
|  | ||||
| .content-grid { | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
| @@ -253,4 +293,60 @@ onUnmounted(() => { | ||||
| .status-healthy { color: #28a745; } | ||||
| .status-warning { color: #ffc107; } | ||||
| .status-error { color: #dc3545; } | ||||
|  | ||||
| .nav-menu { | ||||
|   padding: 0.5rem 0; | ||||
| } | ||||
|  | ||||
| .nav-item { | ||||
|   display: flex; | ||||
|   align-items: center; | ||||
|   padding: 0.75rem 0.5rem; | ||||
|   color: rgba(255, 255, 255, 0.8); | ||||
|   text-decoration: none; | ||||
|   transition: all 0.2s; | ||||
|   border-left: 3px solid transparent; | ||||
| } | ||||
|  | ||||
| .nav-item:hover { | ||||
|   color: white; | ||||
|   background: rgba(255, 255, 255, 0.1); | ||||
| } | ||||
|  | ||||
| .nav-item.active { | ||||
|   color: white; | ||||
|   background: rgba(255, 255, 255, 0.05); | ||||
|   border-left-color: #0d6efd; | ||||
| } | ||||
|  | ||||
| .nav-item i { | ||||
|   width: 1.25rem; | ||||
|   text-align: center; | ||||
|   margin-right: 1rem; | ||||
| } | ||||
|  | ||||
| .nav-text { | ||||
|   white-space: nowrap; | ||||
|   overflow: hidden; | ||||
|   text-overflow: ellipsis; | ||||
| } | ||||
|  | ||||
| .sidebar.collapsed .nav-text { | ||||
|   display: none; | ||||
| } | ||||
|  | ||||
| .sidebar.collapsed .nav-item { | ||||
|   padding: 0.75rem 0.25rem; | ||||
|   justify-content: center; | ||||
| } | ||||
|  | ||||
| .sidebar.collapsed .nav-item i { | ||||
|   margin-right: 0; | ||||
| } | ||||
|  | ||||
| .sidebar.collapsed .sidebar-footer .btn { | ||||
|   padding: 0.375rem 0.5rem; | ||||
|   display: flex; | ||||
|   justify-content: center; | ||||
| } | ||||
| </style> | ||||
|   | ||||
| @@ -163,7 +163,9 @@ | ||||
|                   {{ metricsData.cpu.data[metricsData.cpu.data.length - 1] || 0 }}% | ||||
|                 </h4> | ||||
|               </div> | ||||
|               <Line :data="cpuChartData" :options="chartOptions" /> | ||||
|               <div class="chart-wrapper"> | ||||
|                 <Line :data="cpuChartData" :options="chartOptions" /> | ||||
|               </div> | ||||
|             </div> | ||||
|           </div> | ||||
|           <!-- Memory Chart --> | ||||
| @@ -359,6 +361,8 @@ const healthChartOptions = { | ||||
|   responsive: true, | ||||
|   maintainAspectRatio: false, | ||||
|   clip: false, | ||||
|   resizeDelay: 0, | ||||
|   responsiveAnimationDuration: 0,  /* Disable resize animation */ | ||||
|   plugins: { | ||||
|     legend: { | ||||
|       display: false | ||||
| @@ -408,6 +412,9 @@ const healthChartOptions = { | ||||
|     enabled: true, | ||||
|     mode: 'nearest', | ||||
|     intersect: false | ||||
|   }, | ||||
|   onResize: (chart, size) => { | ||||
|     chart.resize();  /* Force resize on container change */ | ||||
|   } | ||||
| }; | ||||
|  | ||||
| @@ -469,6 +476,8 @@ const chartOptions = { | ||||
|   responsive: true, | ||||
|   maintainAspectRatio: false, | ||||
|   clip: false, | ||||
|   resizeDelay: 0, | ||||
|   responsiveAnimationDuration: 0,  /* Disable resize animation */ | ||||
|   plugins: { | ||||
|     legend: { | ||||
|       display: false | ||||
| @@ -500,6 +509,9 @@ const chartOptions = { | ||||
|     enabled: true, | ||||
|     mode: 'nearest', | ||||
|     intersect: false | ||||
|   }, | ||||
|   onResize: (chart, size) => { | ||||
|     chart.resize();  /* Force resize on container change */ | ||||
|   } | ||||
| }; | ||||
| </script> | ||||
| @@ -509,18 +521,21 @@ const chartOptions = { | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|   gap: 0.5rem; | ||||
|   width: 100%; | ||||
| } | ||||
|  | ||||
| .graphs-row { | ||||
|   display: grid; | ||||
|   grid-template-columns: repeat(4, 1fr); | ||||
|   gap: 0.5rem; | ||||
|   width: 100%; | ||||
| } | ||||
|  | ||||
| .metrics-row { | ||||
|   display: grid; | ||||
|   grid-template-columns: repeat(8, 1fr); | ||||
|   grid-template-columns: 1fr minmax(auto, 1.2fr) repeat(6, 1fr);  /* Version card (2nd) gets more space */ | ||||
|   gap: 0.5rem; | ||||
|   width: 100%; | ||||
| } | ||||
|  | ||||
| .health-card { | ||||
| @@ -528,6 +543,7 @@ const chartOptions = { | ||||
|   border: 1px solid rgba(0,0,0,0.125); | ||||
|   border-radius: 0.25rem; | ||||
|   height: 100%; | ||||
|   width: 100%; | ||||
| } | ||||
|  | ||||
| .health-content-wrapper { | ||||
| @@ -544,6 +560,8 @@ const chartOptions = { | ||||
|   min-height: 0; | ||||
|   display: flex; | ||||
|   align-items: center; | ||||
|   width: 100%; | ||||
|   overflow: hidden;  /* Ensure graph doesn't overflow */ | ||||
| } | ||||
|  | ||||
| .health-percentage { | ||||
| @@ -692,22 +710,12 @@ const chartOptions = { | ||||
|   height: 100%; | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|   min-width: 0; | ||||
|   width: 100%;  /* Take full width of grid cell */ | ||||
| } | ||||
|  | ||||
| .metric-card .card-body { | ||||
|   flex: 1; | ||||
|   padding: 0.5rem; | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|   position: relative; | ||||
| } | ||||
|  | ||||
| .metric-card .metric-value { | ||||
|   font-size: 1.25rem;  /* Return to original size for metric cards */ | ||||
|   font-weight: bold; | ||||
|   color: #333; | ||||
|   line-height: 1; | ||||
|   margin: 0; | ||||
| .metric-card .card-header { | ||||
|   text-align: left; | ||||
| } | ||||
|  | ||||
| .card-header h6 { | ||||
| @@ -718,6 +726,29 @@ const chartOptions = { | ||||
|   align-items: center; | ||||
| } | ||||
|  | ||||
| .metric-card .card-body { | ||||
|   flex: 1; | ||||
|   padding: 0.5rem; | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|   position: relative; | ||||
|   width: 100%; | ||||
|   overflow: visible; | ||||
|   justify-content: center; | ||||
|   align-items: center; | ||||
| } | ||||
|  | ||||
| .metric-card .metric-value { | ||||
|   font-size: 1.25rem; | ||||
|   font-weight: bold; | ||||
|   color: #333; | ||||
|   line-height: 1; | ||||
|   margin: 0; | ||||
|   text-align: center; | ||||
|   white-space: nowrap;  /* Prevent text wrapping */ | ||||
|   min-width: fit-content;  /* Allow text to determine minimum width */ | ||||
| } | ||||
|  | ||||
| .metric-label { | ||||
|   color: #666; | ||||
| } | ||||
| @@ -745,26 +776,20 @@ const chartOptions = { | ||||
| } | ||||
|  | ||||
| @media (max-width: 1400px) { | ||||
|   .graphs-row { | ||||
|     grid-template-columns: 1fr 1fr; | ||||
|   } | ||||
|   .metrics-row { | ||||
|     grid-template-columns: repeat(4, 1fr); | ||||
|     grid-template-columns: 1fr minmax(auto, 1.2fr) repeat(2, 1fr); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @media (max-width: 992px) { | ||||
|   .metrics-row { | ||||
|     grid-template-columns: repeat(3, 1fr); | ||||
|     grid-template-columns: 1fr minmax(auto, 1.2fr) 1fr; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @media (max-width: 576px) { | ||||
|   .graphs-row { | ||||
|     grid-template-columns: 1fr; | ||||
|   } | ||||
|   .metrics-row { | ||||
|     grid-template-columns: repeat(2, 1fr); | ||||
|     grid-template-columns: 1fr minmax(auto, 1.2fr); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -802,4 +827,12 @@ const chartOptions = { | ||||
|   outline: none; | ||||
|   box-shadow: none; | ||||
| } | ||||
|  | ||||
| /* Add a wrapper for the chart to ensure proper sizing */ | ||||
| .chart-wrapper { | ||||
|   position: relative; | ||||
|   width: 100%; | ||||
|   height: 100%; | ||||
|   min-width: 0; | ||||
| } | ||||
| </style> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user