Refactor cards in Nodes
This commit is contained in:
parent
3d13a05c0f
commit
b367d4086e
@ -44,7 +44,7 @@
|
|||||||
<!-- Toggle button for expanded section -->
|
<!-- Toggle button for expanded section -->
|
||||||
<div v-show="sections.info" class="section-content-wrapper">
|
<div v-show="sections.info" class="section-content-wrapper">
|
||||||
<div class="section-content">
|
<div class="section-content">
|
||||||
<div class="metrics-row">
|
<div class="info-row">
|
||||||
<!-- Card 1: Daemon State -->
|
<!-- Card 1: Daemon State -->
|
||||||
<ValueCard
|
<ValueCard
|
||||||
title="Daemon State"
|
title="Daemon State"
|
||||||
@ -63,34 +63,22 @@
|
|||||||
:value="selectedNodeData.domain_state || 'Unknown'"
|
:value="selectedNodeData.domain_state || 'Unknown'"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- Card 4: Domains Count -->
|
<!-- Card 4: PVC Version -->
|
||||||
<ValueCard
|
|
||||||
title="Domains Count"
|
|
||||||
:value="selectedNodeData.domains_count || 0"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- Card 5: PVC Version -->
|
|
||||||
<ValueCard
|
<ValueCard
|
||||||
title="PVC Version"
|
title="PVC Version"
|
||||||
:value="selectedNodeData.pvc_version || 'Unknown'"
|
:value="selectedNodeData.pvc_version || 'Unknown'"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- Card 6: Kernel Version -->
|
<!-- Card 5: Kernel Version -->
|
||||||
<ValueCard
|
<ValueCard
|
||||||
title="Kernel Version"
|
title="Kernel Version"
|
||||||
:value="selectedNodeData.kernel || 'Unknown'"
|
:value="selectedNodeData.kernel || 'Unknown'"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- Card 7: Host CPU Count -->
|
<!-- Card 6: VM Count -->
|
||||||
<ValueCard
|
<ValueCard
|
||||||
title="Host CPU Count"
|
title="VM Count"
|
||||||
:value="selectedNodeData.cpu_count || 0"
|
:value="selectedNodeData.domains_count || 0"
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- Card 8: Guest CPU Count -->
|
|
||||||
<ValueCard
|
|
||||||
title="Guest CPU Count"
|
|
||||||
:value="selectedNodeData.vcpu?.allocated || 0"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -158,6 +146,52 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- CPU Resources Section -->
|
||||||
|
<div class="section-container" :class="{ 'collapsed': !sections.cpu }">
|
||||||
|
<!-- Collapsed section indicator -->
|
||||||
|
<div v-if="!sections.cpu" class="section-content-wrapper">
|
||||||
|
<div class="section-content">
|
||||||
|
<div class="collapsed-section-header">
|
||||||
|
<h6 class="card-title mb-0 metric-label">CPU Resources</h6>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="toggle-column">
|
||||||
|
<button class="section-toggle" @click="toggleSection('cpu')">
|
||||||
|
<i class="fas fa-chevron-down"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Toggle button for expanded section -->
|
||||||
|
<div v-show="sections.cpu" class="section-content-wrapper">
|
||||||
|
<div class="section-content">
|
||||||
|
<div class="resources-row-cpu">
|
||||||
|
<!-- Card 1: Host CPUs -->
|
||||||
|
<ValueCard
|
||||||
|
title="Host CPUs"
|
||||||
|
:value="selectedNodeData.cpu_count || 0"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- Card 2: Guest CPUs -->
|
||||||
|
<ValueCard
|
||||||
|
title="Guest CPUs"
|
||||||
|
:value="selectedNodeData.vcpu?.allocated || 0"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- Card 3: Load -->
|
||||||
|
<ValueCard
|
||||||
|
title="Load"
|
||||||
|
:value="selectedNodeData.load || 0"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="toggle-column expanded">
|
||||||
|
<button class="section-toggle" @click="toggleSection('cpu')">
|
||||||
|
<i class="fas fa-chevron-up"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Memory Resources Section -->
|
<!-- Memory Resources Section -->
|
||||||
<div class="section-container" :class="{ 'collapsed': !sections.resources }">
|
<div class="section-container" :class="{ 'collapsed': !sections.resources }">
|
||||||
<!-- Collapsed section indicator -->
|
<!-- Collapsed section indicator -->
|
||||||
@ -176,66 +210,36 @@
|
|||||||
<!-- Toggle button for expanded section -->
|
<!-- Toggle button for expanded section -->
|
||||||
<div v-show="sections.resources" class="section-content-wrapper">
|
<div v-show="sections.resources" class="section-content-wrapper">
|
||||||
<div class="section-content">
|
<div class="section-content">
|
||||||
<div class="resources-row">
|
<div class="resources-row-memory">
|
||||||
<!-- Total Memory -->
|
<!-- Total Memory -->
|
||||||
<div class="metric-card">
|
<ValueCard
|
||||||
<div class="card-header">
|
title="Total Memory"
|
||||||
<h6 class="card-title mb-0">
|
:value="formatMemory(selectedNodeData.memory?.total)"
|
||||||
<span class="metric-label">Total Memory</span>
|
/>
|
||||||
</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<h4 class="metric-value">{{ formatMemory(selectedNodeData.memory?.total) }}</h4>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Used Memory -->
|
<!-- Used Memory -->
|
||||||
<div class="metric-card">
|
<ValueCard
|
||||||
<div class="card-header">
|
title="Used Memory"
|
||||||
<h6 class="card-title mb-0">
|
:value="formatMemory(selectedNodeData.memory?.used)"
|
||||||
<span class="metric-label">Used Memory</span>
|
/>
|
||||||
</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<h4 class="metric-value">{{ formatMemory(selectedNodeData.memory?.used) }}</h4>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Free Memory -->
|
<!-- Free Memory -->
|
||||||
<div class="metric-card">
|
<ValueCard
|
||||||
<div class="card-header">
|
title="Free Memory"
|
||||||
<h6 class="card-title mb-0">
|
:value="formatMemory(selectedNodeData.memory?.free)"
|
||||||
<span class="metric-label">Free Memory</span>
|
/>
|
||||||
</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<h4 class="metric-value">{{ formatMemory(selectedNodeData.memory?.free) }}</h4>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Allocated Memory -->
|
<!-- Allocated Memory -->
|
||||||
<div class="metric-card">
|
<ValueCard
|
||||||
<div class="card-header">
|
title="Allocated Memory"
|
||||||
<h6 class="card-title mb-0">
|
:value="formatMemory(selectedNodeData.memory?.allocated)"
|
||||||
<span class="metric-label">Allocated Memory</span>
|
/>
|
||||||
</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<h4 class="metric-value">{{ formatMemory(selectedNodeData.memory?.allocated) }}</h4>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Provisioned Memory -->
|
<!-- Provisioned Memory -->
|
||||||
<div class="metric-card">
|
<ValueCard
|
||||||
<div class="card-header">
|
title="Provisioned Memory"
|
||||||
<h6 class="card-title mb-0">
|
:value="formatMemory(selectedNodeData.memory?.provisioned)"
|
||||||
<span class="metric-label">Provisioned Memory</span>
|
/>
|
||||||
</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<h4 class="metric-value">{{ formatMemory(selectedNodeData.memory?.provisioned) }}</h4>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="toggle-column expanded">
|
<div class="toggle-column expanded">
|
||||||
@ -257,10 +261,10 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted, watch, nextTick, onUnmounted } from 'vue';
|
import { ref, computed, onMounted, watch, nextTick, onUnmounted } from 'vue';
|
||||||
import PageTitle from '../components/PageTitle.vue';
|
import PageTitle from '../components/PageTitle.vue';
|
||||||
import HealthChart from '../components/charts/HealthChart.vue';
|
|
||||||
import CPUChart from '../components/charts/CPUChart.vue';
|
import CPUChart from '../components/charts/CPUChart.vue';
|
||||||
import MemoryChart from '../components/charts/MemoryChart.vue';
|
import MemoryChart from '../components/charts/MemoryChart.vue';
|
||||||
import StorageChart from '../components/charts/StorageChart.vue';
|
import StorageChart from '../components/charts/StorageChart.vue';
|
||||||
|
import HealthChart from '../components/charts/HealthChart.vue';
|
||||||
import ValueCard from '../components/ValueCard.vue';
|
import ValueCard from '../components/ValueCard.vue';
|
||||||
|
|
||||||
// Implement formatBytes function directly
|
// Implement formatBytes function directly
|
||||||
@ -277,15 +281,12 @@ function formatBytes(bytes, decimals = 2) {
|
|||||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format memory values (similar to formatBytes but with GB as default unit)
|
// Format memory values
|
||||||
function formatMemory(bytes) {
|
const formatMemory = (memoryMB) => {
|
||||||
if (bytes === undefined || bytes === null) return 'N/A';
|
if (!memoryMB) return '0 GB';
|
||||||
if (bytes === 0) return '0 GB';
|
// The values are already in MB, so we just need to convert to GB
|
||||||
|
return Math.round(memoryMB / 1024) + ' GB';
|
||||||
// Convert to GB with 2 decimal places
|
};
|
||||||
const gbValue = (bytes / (1024 * 1024 * 1024)).toFixed(2);
|
|
||||||
return `${gbValue} GB`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
nodeData: {
|
nodeData: {
|
||||||
@ -309,11 +310,17 @@ const props = defineProps({
|
|||||||
const sections = ref({
|
const sections = ref({
|
||||||
info: true,
|
info: true,
|
||||||
graphs: true,
|
graphs: true,
|
||||||
|
cpu: true,
|
||||||
resources: true
|
resources: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Toggle section visibility
|
||||||
|
const toggleSection = (section) => {
|
||||||
|
sections.value[section] = !sections.value[section];
|
||||||
|
};
|
||||||
|
|
||||||
// State for selected node and tab scrolling
|
// State for selected node and tab scrolling
|
||||||
const selectedNode = ref(localStorage.getItem('selectedNodeTab') || '');
|
const selectedNode = ref('');
|
||||||
const tabsContainer = ref(null);
|
const tabsContainer = ref(null);
|
||||||
const showLeftScroll = ref(false);
|
const showLeftScroll = ref(false);
|
||||||
const showRightScroll = ref(false);
|
const showRightScroll = ref(false);
|
||||||
@ -327,53 +334,61 @@ const selectedNodeData = computed(() => {
|
|||||||
// Select a node
|
// Select a node
|
||||||
const selectNode = (nodeName) => {
|
const selectNode = (nodeName) => {
|
||||||
selectedNode.value = nodeName;
|
selectedNode.value = nodeName;
|
||||||
// Save to localStorage
|
|
||||||
localStorage.setItem('selectedNodeTab', nodeName);
|
|
||||||
|
|
||||||
// Scroll the selected tab into view
|
// Scroll the selected tab into view
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
const activeTab = document.querySelector('.node-tab.active');
|
const activeTab = tabsContainer.value?.querySelector('.node-tab.active');
|
||||||
if (activeTab) {
|
if (activeTab) {
|
||||||
activeTab.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' });
|
activeTab.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if scroll buttons should be shown
|
||||||
|
checkScrollButtons();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Toggle section visibility
|
|
||||||
const toggleSection = (section) => {
|
|
||||||
sections.value[section] = !sections.value[section];
|
|
||||||
};
|
|
||||||
|
|
||||||
// Scroll the tabs
|
|
||||||
const scrollTabs = (direction) => {
|
|
||||||
if (!tabsContainer.value) return;
|
|
||||||
|
|
||||||
const container = tabsContainer.value;
|
|
||||||
const scrollAmount = 200; // Adjust as needed
|
|
||||||
|
|
||||||
if (direction === 'left') {
|
|
||||||
container.scrollLeft -= scrollAmount;
|
|
||||||
} else {
|
|
||||||
container.scrollLeft += scrollAmount;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update scroll button visibility after scrolling
|
|
||||||
checkScrollButtons();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check if scroll buttons should be shown
|
// Check if scroll buttons should be shown
|
||||||
const checkScrollButtons = () => {
|
const checkScrollButtons = () => {
|
||||||
if (!tabsContainer.value) return;
|
if (!tabsContainer.value) return;
|
||||||
|
|
||||||
const container = tabsContainer.value;
|
const { scrollLeft, scrollWidth, clientWidth } = tabsContainer.value;
|
||||||
showLeftScroll.value = container.scrollLeft > 0;
|
|
||||||
showRightScroll.value = container.scrollLeft < (container.scrollWidth - container.clientWidth - 5); // 5px buffer
|
// Show left scroll button if not at the beginning
|
||||||
|
showLeftScroll.value = scrollLeft > 0;
|
||||||
|
|
||||||
|
// Show right scroll button if not at the end
|
||||||
|
showRightScroll.value = scrollLeft + clientWidth < scrollWidth - 1; // -1 for rounding errors
|
||||||
};
|
};
|
||||||
|
|
||||||
// Calculate CPU utilization
|
// Scroll tabs left or right
|
||||||
const calculateCpuUtilization = (node) => {
|
const scrollTabs = (direction) => {
|
||||||
if (!node || !node.load || !node.cpu_count) return 0;
|
if (!tabsContainer.value) return;
|
||||||
return Math.round((node.load / node.cpu_count) * 100);
|
|
||||||
|
const scrollAmount = tabsContainer.value.clientWidth / 2;
|
||||||
|
const currentScroll = tabsContainer.value.scrollLeft;
|
||||||
|
|
||||||
|
if (direction === 'left') {
|
||||||
|
tabsContainer.value.scrollTo({
|
||||||
|
left: Math.max(0, currentScroll - scrollAmount),
|
||||||
|
behavior: 'smooth'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
tabsContainer.value.scrollTo({
|
||||||
|
left: currentScroll + scrollAmount,
|
||||||
|
behavior: 'smooth'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check scroll buttons after scrolling
|
||||||
|
setTimeout(checkScrollButtons, 300);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Calculate CPU utilization (load / cpu_count * 100)
|
||||||
|
const calculateCpuUtilization = (nodeData) => {
|
||||||
|
if (!nodeData || !nodeData.load || !nodeData.cpu_count) return 0;
|
||||||
|
|
||||||
|
const utilization = (nodeData.load / nodeData.cpu_count) * 100;
|
||||||
|
return Math.round(utilization);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Calculate memory utilization
|
// Calculate memory utilization
|
||||||
@ -382,7 +397,7 @@ const calculateMemoryUtilization = (node) => {
|
|||||||
const used = node.memory.used || 0;
|
const used = node.memory.used || 0;
|
||||||
const total = node.memory.total || 1; // Avoid division by zero
|
const total = node.memory.total || 1; // Avoid division by zero
|
||||||
if (total === 0) return 0;
|
if (total === 0) return 0;
|
||||||
return Math.round((node.memory.used / node.memory.total) * 100);
|
return Math.round((used / total) * 100);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Calculate allocated memory
|
// Calculate allocated memory
|
||||||
@ -391,31 +406,31 @@ const calculateAllocatedMemory = (node) => {
|
|||||||
const allocated = node.memory.allocated || 0;
|
const allocated = node.memory.allocated || 0;
|
||||||
const total = node.memory.total || 1; // Avoid division by zero
|
const total = node.memory.total || 1; // Avoid division by zero
|
||||||
if (total === 0) return 0;
|
if (total === 0) return 0;
|
||||||
return Math.round((node.memory.allocated / node.memory.total) * 100);
|
return Math.round((allocated / total) * 100);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Prepare chart data for the node
|
// Prepare chart data for the node
|
||||||
const nodeHealthChartData = computed(() => {
|
const nodeHealthChartData = computed(() => {
|
||||||
// Get node metrics history if available
|
// Get node metrics history if available
|
||||||
const nodeMetrics = props.metricsData.nodes?.[selectedNodeData.value?.name];
|
const nodeMetrics = props.metricsData.nodes?.[selectedNodeData.value.name];
|
||||||
|
|
||||||
if (nodeMetrics && nodeMetrics.health && nodeMetrics.health.data.length > 0) {
|
if (nodeMetrics && nodeMetrics.health && nodeMetrics.health.data.length > 0) {
|
||||||
return {
|
return {
|
||||||
labels: nodeMetrics.health.labels,
|
labels: nodeMetrics.health.labels,
|
||||||
data: nodeMetrics.health.data
|
data: nodeMetrics.health.data
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback to current value only
|
// Fallback to current value only
|
||||||
return {
|
return {
|
||||||
labels: ['Health'],
|
labels: ['Health'],
|
||||||
data: [selectedNodeData.value?.health || 0]
|
data: [selectedNodeData.value.health || 0]
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const nodeCpuChartData = computed(() => {
|
const nodeCpuChartData = computed(() => {
|
||||||
// Get node metrics history if available
|
// Get node metrics history if available
|
||||||
const nodeMetrics = props.metricsData.nodes?.[selectedNodeData.value?.name];
|
const nodeMetrics = props.metricsData.nodes?.[selectedNodeData.value.name];
|
||||||
|
|
||||||
if (nodeMetrics && nodeMetrics.cpu && nodeMetrics.cpu.data.length > 0) {
|
if (nodeMetrics && nodeMetrics.cpu && nodeMetrics.cpu.data.length > 0) {
|
||||||
return {
|
return {
|
||||||
@ -473,15 +488,8 @@ const nodeAllocatedMemoryChartData = computed(() => {
|
|||||||
|
|
||||||
// Initialize the component
|
// Initialize the component
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// Check if the saved node exists in the current node data
|
// Select the first node by default if available
|
||||||
const savedNode = localStorage.getItem('selectedNodeTab');
|
if (props.nodeData && props.nodeData.length > 0) {
|
||||||
const nodeExists = props.nodeData.some(node => node.name === savedNode);
|
|
||||||
|
|
||||||
if (savedNode && nodeExists) {
|
|
||||||
// Use the saved node
|
|
||||||
selectedNode.value = savedNode;
|
|
||||||
} else if (props.nodeData && props.nodeData.length > 0) {
|
|
||||||
// Default to the first node if saved node doesn't exist
|
|
||||||
selectNode(props.nodeData[0].name);
|
selectNode(props.nodeData[0].name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -491,10 +499,9 @@ onMounted(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Watch for changes in the nodes data
|
// Watch for changes in the nodes data
|
||||||
watch(() => props.nodeData, (newNodes) => {
|
watch(() => props.nodeData, () => {
|
||||||
// If the currently selected node no longer exists, select the first available node
|
// If the currently selected node no longer exists, select the first available node
|
||||||
const nodeExists = newNodes.some(node => node.name === selectedNode.value);
|
if (props.nodeData && props.nodeData.length > 0 && !props.nodeData.find(node => node.name === selectedNode.value)) {
|
||||||
if (newNodes && newNodes.length > 0 && !nodeExists) {
|
|
||||||
selectNode(props.nodeData[0].name);
|
selectNode(props.nodeData[0].name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -669,7 +676,7 @@ onUnmounted(() => {
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.metrics-row, .graphs-row, .resources-row {
|
.metrics-row, .graphs-row, .resources-row-cpu, .resources-row-memory, .info-row {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -680,12 +687,20 @@ onUnmounted(() => {
|
|||||||
.metrics-row {
|
.metrics-row {
|
||||||
grid-template-columns: repeat(4, 1fr);
|
grid-template-columns: repeat(4, 1fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.info-row {
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
.graphs-row {
|
.graphs-row {
|
||||||
grid-template-columns: repeat(4, 1fr);
|
grid-template-columns: repeat(4, 1fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
.resources-row {
|
.resources-row-cpu {
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.resources-row-memory {
|
||||||
grid-template-columns: repeat(5, 1fr);
|
grid-template-columns: repeat(5, 1fr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -694,18 +709,30 @@ onUnmounted(() => {
|
|||||||
.metrics-row {
|
.metrics-row {
|
||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: repeat(2, 1fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.info-row {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
.graphs-row {
|
.graphs-row {
|
||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: repeat(2, 1fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
.resources-row {
|
.resources-row-cpu {
|
||||||
grid-template-columns: repeat(5, 1fr);
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.resources-row-memory {
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 800px) {
|
@media (max-width: 800px) {
|
||||||
.metrics-row, .graphs-row, .resources-row {
|
.metrics-row,
|
||||||
|
.info-row,
|
||||||
|
.graphs-row,
|
||||||
|
.resources-row-cpu,
|
||||||
|
.resources-row-memory {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user