Files
eapim-admin/WebContent/jsp/dashboard-modern/components/dashboard-servers.jsp
T
2025-12-08 19:35:27 +09:00

980 lines
33 KiB
Plaintext

<%@ page language="java" contentType="text/html; charset=utf-8"%>
<%@ page import="java.util.*" %>
<%@ page import="com.eactive.eai.rms.common.datasource.*" %>
<%@ page import="java.util.stream.Collectors" %>
<div class="dashboard-servers">
<div class="dashboard-header">
<h2 class="section-title">서버 상태</h2>
<div class="server-filters">
<div class="filter-group">
<button class="filter-btn active" data-type="all">전체</button>
<%
// serverTypeMap 변수를 가져오기
Map<String, List<DataSourceType>> serverTypeMap =
(Map<String, List<DataSourceType>>)request.getAttribute("serverTypeMap");
if (serverTypeMap == null) {
// application 스코프에서 가져오기 시도
serverTypeMap = (Map<String, List<DataSourceType>>)application.getAttribute("serverTypeMap");
}
Map<String, Integer> priorityMap = new HashMap<String, Integer>();
priorityMap.put("MCI", 0);
priorityMap.put("EAI", 1);
priorityMap.put("FEP", 2);
priorityMap.put("CGW", 3);
priorityMap.put("FGW", 4);
priorityMap.put("APIGW", 5);
priorityMap.put("BAP", 6);
Map<String,List<DataSourceType>> sortedMap = serverTypeMap.entrySet().stream()
.sorted(Comparator.comparingInt(e -> priorityMap.getOrDefault(e.getKey(), Integer.MAX_VALUE)))
.collect(Collectors.toMap(
Map.Entry::getKey
, Map.Entry::getValue
,(e1, e2) -> e1
, LinkedHashMap::new
));
if (sortedMap != null) {
// 서버 타입 필터 생성
for (Map.Entry<String, List<DataSourceType>> entry : sortedMap.entrySet()) {
String serverType = entry.getKey();
List<DataSourceType> servers = entry.getValue();
// BAT 서버는 제외
if (DataSourceTypeManager.BAT.equals(serverType) || DataSourceTypeManager.BAP.equals(serverType)) {
continue;
}
// 서버 타입에 해당하는 텍스트 가져오기 (첫 번째 서버의 텍스트 사용)
String serverTypeText = servers.size() > 0 ? servers.get(0).getText() : serverType;
%>
<button class="filter-btn" data-type="<%= serverType.toLowerCase() %>"><%= serverTypeText %></button>
<% }
} %>
</div>
<div class="search-container">
<i class="bi bi-search"></i>
<input type="text" id="server-search" placeholder="서버 검색..." />
</div>
</div>
</div>
<%
if (sortedMap != null) {
// 서버 타입별로 섹션 생성
for (Map.Entry<String, List<DataSourceType>> entry : sortedMap.entrySet()) {
String serverType = entry.getKey();
List<DataSourceType> servers = entry.getValue();
// BAT 서버는 제외
if (DataSourceTypeManager.BAT.equals(serverType) || DataSourceTypeManager.BAP.equals(serverType)) {
continue;
}
// 서버 타입에 해당하는 텍스트 가져오기 (첫 번째 서버의 텍스트 사용)
String serverTypeText = servers.size() > 0 ? servers.get(0).getText() : serverType;
// 서버 타입별 보더 색상 클래스
String borderColorClass = "";
if (serverType.equalsIgnoreCase("FEP")) {
borderColorClass = "border-primary";
} else if (serverType.equalsIgnoreCase("EAI")) {
borderColorClass = "border-success";
} else if (serverType.equalsIgnoreCase("EMS")) {
borderColorClass = "border-purple";
} else if (serverType.equalsIgnoreCase("EDI")) {
borderColorClass = "border-orange";
}
%>
<div class="server-section" id="server-section-<%= serverType.toLowerCase() %>">
<div class="card server-card-container <%= borderColorClass %>">
<div class="server-section-header">
<h3 class="server-section-title"><%= serverTypeText %> 서버</h3>
<span class="server-status-badge badge-success <%= serverType.toLowerCase() %>-status-badge">0 / 0 정상</span>
</div>
<div class="server-grid server-grid-<%= serverType.toLowerCase() %>" id="<%= serverType.toLowerCase() %>-servers-container">
<!-- 여기에 <%= serverTypeText %> 서버 카드가 동적으로 추가됩니다 -->
</div>
</div>
</div>
<% }
} %>
</div>
<!-- 서버 카드 템플릿 -->
<template id="server-card-template">
<div class="server-card">
<div class="server-header">
<h5 class="server-name">서버 이름</h5>
<span class="server-status-badge badge-success">정상</span>
</div>
<div class="server-metrics">
<!-- 메트릭 헤더 행 -->
<div class="metrics-row">
<!-- CPU 메트릭 -->
<div class="server-metric">
<div class="metric-header">
<span class="metric-name"><i class="bi bi-cpu" style="color: #0dcaf0; font-size: 1.1rem;"></i></span>
<span class="metric-value cpu-value">0%</span>
</div>
</div>
<!-- 메모리 메트릭 -->
<div class="server-metric">
<div class="metric-header">
<span class="metric-name"><i class="bi bi-memory" style="color: #6f42c1; font-size: 1.1rem;"></i></span>
<span class="metric-value memory-value">0%</span>
</div>
</div>
<!-- 디스크 메트릭 -->
<div class="server-metric">
<div class="metric-header">
<span class="metric-name"><i class="bi bi-hdd" style="color: #fd7e14; font-size: 1.1rem;"></i></span>
<span class="metric-value disk-value">0%</span>
</div>
</div>
</div>
<!-- 스파크라인 행 -->
<div class="sparklines-row">
<div class="sparkline cpu-sparkline">
<div class="sparkline-bar success" style="height: 10%"></div>
<div class="sparkline-bar success" style="height: 15%"></div>
<div class="sparkline-bar success" style="height: 20%"></div>
<div class="sparkline-bar success" style="height: 15%"></div>
<div class="sparkline-bar success" style="height: 25%"></div>
<div class="sparkline-bar success" style="height: 20%"></div>
<div class="sparkline-bar success" style="height: 15%"></div>
</div>
<div class="sparkline memory-sparkline">
<div class="sparkline-bar success" style="height: 20%"></div>
<div class="sparkline-bar success" style="height: 25%"></div>
<div class="sparkline-bar success" style="height: 30%"></div>
<div class="sparkline-bar success" style="height: 25%"></div>
<div class="sparkline-bar success" style="height: 35%"></div>
<div class="sparkline-bar success" style="height: 30%"></div>
<div class="sparkline-bar success" style="height: 25%"></div>
</div>
<div class="sparkline disk-sparkline">
<div class="sparkline-bar success" style="height: 30%"></div>
<div class="sparkline-bar success" style="height: 30%"></div>
<div class="sparkline-bar success" style="height: 30%"></div>
<div class="sparkline-bar success" style="height: 30%"></div>
<div class="sparkline-bar success" style="height: 30%"></div>
<div class="sparkline-bar success" style="height: 30%"></div>
<div class="sparkline-bar success" style="height: 30%"></div>
</div>
</div>
</div>
<!-- 인스턴스 테이블 -->
<div class="server-instances">
<table class="instance-table">
<thead>
<tr>
<th>인스턴스 ID</th>
<th>상태</th>
<th class="text-right">처리량</th>
</tr>
</thead>
<tbody class="instance-table-body">
<!-- 인스턴스 데이터가 동적으로 추가됩니다 -->
</tbody>
</table>
</div>
</div>
</template>
<!-- 인스턴스 행 템플릿 -->
<template id="instance-row-template">
<tr>
<td>
<span class="instance-status status-normal"></span>
<span class="instance-id">인스턴스 ID</span>
</td>
<td class="instance-status-text">정상</td>
<td class="text-right instance-throughput">0/s</td>
</tr>
</template>
<style>
/* 대시보드 헤더 스타일 */
.dashboard-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 0.5rem;
padding-bottom: 0.4rem;
border-bottom: 1px solid var(--color-gray-200);
}
.dashboard-header .section-title {
margin-bottom: 0;
padding-bottom: 0;
border-bottom: none;
flex-shrink: 0;
margin-right: 0.75rem;
}
.dashboard-header .server-filters {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0;
flex-grow: 1;
}
.dashboard-header .filter-group {
flex-shrink: 0;
}
.dashboard-header .search-container {
margin-left: auto;
}
/* 서버 상태 섹션 */
.server-section {
margin-bottom: 0.75rem;
}
.server-section-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 0.5rem;
}
.server-section-title {
font-size: 0.9rem;
font-weight: 600;
color: var(--color-gray-800);
margin: 0;
}
.server-filters {
display: flex;
align-items: center;
margin-bottom: 0.5rem;
gap: 0.5rem;
}
.filter-group {
display: flex;
gap: 0.4rem;
flex-wrap: wrap;
}
.server-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 0.5rem;
}
.server-card {
background-color: white;
border-radius: var(--rounded-md);
box-shadow: var(--shadow);
border: 1px solid var(--color-gray-200);
overflow: hidden;
transition: all 0.2s ease;
height: 100%;
padding: 0.75rem;
}
.server-card:hover {
box-shadow: var(--shadow-md);
}
.server-header {
padding: 1rem 1.25rem;
background-color: var(--color-gray-50);
border-bottom: 1px solid var(--color-gray-200);
display: flex;
align-items: center;
justify-content: space-between;
}
.server-name {
font-weight: 600;
font-size: 1rem;
color: var(--color-gray-800);
margin: 0;
}
.server-metrics {
padding: 1rem 1.25rem;
display: flex;
gap: 1.5rem;
}
.server-metric {
flex: 1;
}
.metric-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 0.5rem;
}
.metric-name {
font-size: 0.75rem;
color: var(--color-gray-500);
text-transform: uppercase;
letter-spacing: 0.05em;
}
.server-instances {
padding: 0 16px 16px 16px;
flex: 1;
overflow-y: auto;
max-height: 150px;
}
/* 스파크라인 스타일 */
.sparkline {
height: 28px;
display: flex;
align-items: flex-end;
gap: 2px;
margin-top: 0.5rem;
background-color: var(--color-gray-50);
border-radius: var(--rounded-sm);
padding: 0.25rem;
}
.sparkline-bar {
flex: 1;
background-color: var(--color-primary);
border-radius: 1px 1px 0 0;
}
.sparkline-bar.success {
background-color: var(--color-success);
}
.sparkline-bar.warning {
background-color: var(--color-warning);
}
.sparkline-bar.danger {
background-color: var(--color-danger);
}
/* 요약 섹션 */
.status-cards {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1rem;
margin-bottom: 1.5rem;
}
.status-card {
display: flex;
align-items: center;
padding: 1.5rem;
border-radius: var(--rounded-lg);
background-color: white;
box-shadow: var(--shadow);
transition: all 0.2s ease;
}
.status-card:hover {
box-shadow: var(--shadow-md);
}
.status-card.success {
border-left: 4px solid var(--color-success);
}
.status-card.warning {
border-left: 4px solid var(--color-warning);
}
.status-card.danger {
border-left: 4px solid var(--color-danger);
}
.status-icon {
font-size: 2rem;
margin-right: 1.25rem;
display: flex;
align-items: center;
}
.status-icon.success {
color: var(--color-success);
}
.status-icon.warning {
color: var(--color-warning);
}
.status-icon.danger {
color: var(--color-danger);
}
.status-content {
display: flex;
flex-direction: column;
}
.status-label {
font-size: 0.875rem;
color: var(--color-gray-500);
margin-bottom: 0.25rem;
}
.status-value {
font-size: 1.5rem;
font-weight: 600;
color: var(--color-gray-900);
}
/* 서버 섹션 스타일 - 기존 스타일 유지 */
.server-section {
margin-bottom: 1rem;
}
.server-card-container {
padding: 0.75rem;
margin-bottom: 1rem;
min-height: 296px;
}
.server-section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.5rem;
}
.server-section-title {
font-size: 1rem;
font-weight: 600;
color: var(--color-gray-800);
margin: 0;
}
/* 서버 타입별 보더 색상 */
.border-primary {
border-top: 2px solid #0d6efd;
}
.border-success {
border-top: 2px solid #198754;
}
.border-purple {
border-top: 2px solid #6f42c1;
}
.border-orange {
border-top: 2px solid #fd7e14;
}
/* 서버 그리드 - 한 줄에 2개씩 표시 */
.server-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 0.75rem;
}
/* 반응형 처리 - 화면 크기에 따라 그리드 조정 */
@media screen and (max-width: 1200px) {
.server-grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media screen and (max-width: 768px) {
.server-grid {
grid-template-columns: 1fr;
}
}
/* 서버 카드 높이 축소 */
.server-card {
padding: 0.5rem;
border: 1px solid var(--color-gray-200);
border-radius: var(--rounded-sm);
background-color: white;
}
.server-header {
padding: 0.4rem 0.5rem;
margin-bottom: 0.3rem;
border-bottom: 1px solid var(--color-gray-100);
}
.server-name {
font-size: 0.95rem;
}
/* 메트릭 스타일 조정 */
.server-metrics {
padding: 0.5rem 0;
display: flex;
flex-direction: column;
gap: 0.0rem;
border-top: 1px solid var(--color-gray-200);
border-bottom: 1px solid var(--color-gray-200);
}
.metrics-row,
.sparklines-row {
display: flex;
justify-content: space-around;
gap: 0;
}
.sparklines-row {
padding-top: 0.5rem;
}
.server-metric {
flex: 1;
min-width: 0; /* 오버플로우 방지 */
text-align: center;
padding: 0 0.5rem;
border-right: 1px solid var(--color-gray-200);
}
.server-metric:last-child {
border-right: none;
}
.metric-header {
margin-bottom: 0.2rem;
display: flex;
flex-direction: column; /* 아이콘과 값을 수직으로 정렬 */
justify-content: center; /* 수직 중앙 정렬 */
align-items: center; /* 수평 중앙 정렬 */
white-space: nowrap;
overflow: hidden;
}
.sparkline {
flex: 1;
min-width: 0;
padding: 0.25rem 0.5rem;
border-right: 1px solid var(--color-gray-200);
}
.sparkline:last-child {
border-right: none;
}
.metric-name {
display: flex;
align-items: center;
margin-bottom: 0.2rem; /* 아이콘과 값 사이 간격 조정 */
}
.metric-value {
margin-left: 0; /* 이전 margin-left 제거 */
font-size: 1.1rem; /* 값 폰트 크기 약간 키움 */
font-weight: 600; /* 값 폰트 굵기 */
}
/* 인스턴스 테이블 스타일 */
.server-instances {
padding: 0.5rem 0.5rem 0.5rem 0.5rem; /* 패딩 조정 */
max-height: 120px;
}
.instance-table {
width: 100%; /* 테이블 전체 너비 */
font-size: 0.85rem; /* 폰트 크기 약간 키움 */
border-collapse: collapse;
table-layout: fixed;
}
.instance-table th {
background-color: var(--color-gray-100); /* 헤더 배경색 */
font-weight: 600; /* 헤더 폰트 굵기 */
padding: 0.4rem 0.5rem; /* 헤더 패딩 조정 */
border-bottom: 1px solid var(--color-gray-200); /* 헤더 아래 보더 */
text-align: center; /* 모든 헤더 가운데 정렬 */
width: 33.3333%; /* 인스턴스 th 각 영역 균등하게, 위쪽 요소와 맞춤 */
box-sizing: border-box;
}
.instance-table td {
padding: 0.4rem 0.5rem; /* 셀 패딩 조정 */
white-space: nowrap;
border-bottom: 1px solid var(--color-gray-100); /* 셀 아래 보더 */
vertical-align: middle;
text-align: center; /* 모든 셀 내용 가운데 정렬 */
white-space: nowrap; /* 줄바꿈 방지 */
overflow: hidden; /* 칸을 넘어가는 글자 숨김 */
text-overflow: ellipsis; /* 넘어가는 글자를 ...으로 표시 */
}
.instance-table tbody tr:nth-child(odd) {
background-color: var(--color-gray-50); /* 홀수 행 배경색 */
}
.instance-table tbody tr:hover {
background-color: var(--color-gray-100); /* 호버 효과 */
}
/* 인스턴스 상태 점 스타일 */
.instance-status {
display: inline-block;
width: 10px; /* 크기 키움 */
height: 10px; /* 크기 키움 */
border-radius: 50%;
margin-right: 6px; /* 간격 조정 */
vertical-align: middle; /* 텍스트와 세로 정렬 */
}
/* 오류 상태일 때 인스턴스 ID 색상 변경 - :has()는 구형 브라우저에서 문제를 일으킬 수 있어 주석 처리
tr:has(.status-error) .instance-id,
tr:has(.status-inactive) .instance-id {
color: #dc3545;
font-weight: 600;
}
*/
</style>
<script>
// 서버 카드 생성 함수
function createServerCard(server, containerId) {
var template = document.getElementById('server-card-template');
var container = document.getElementById(containerId);
if (!container) return null;
// 템플릿 복제
var clone = document.importNode(template.content, true);
// 서버 이름 설정
clone.querySelector('.server-name').textContent = server.text || server.name;
// 컨테이너에 추가
container.appendChild(clone);
return container.lastElementChild;
}
// 인스턴스 행 생성 함수
function createInstanceRow(instanceData) {
var template = document.getElementById('instance-row-template');
var clone = document.importNode(template.content, true);
// 인스턴스 ID 설정
clone.querySelector('.instance-id').textContent = instanceData.id;
// 상태 설정
var statusClass = 'status-normal';
var statusText = '정상';
if (instanceData.status === 'warning') {
statusClass = 'status-warning';
statusText = '경고';
} else if (instanceData.status === 'error' || instanceData.status === 'inactive') {
statusClass = 'status-error';
statusText = instanceData.status === 'inactive' ? '비활성' : '오류';
}
clone.querySelector('.instance-status').className = 'instance-status ' + statusClass;
clone.querySelector('.instance-status-text').textContent = statusText;
// 처리량 설정
if (instanceData.throughput) {
clone.querySelector('.instance-throughput').textContent = instanceData.throughput;
}
return clone;
}
// 서버 상태 업데이트 함수
function updateServerStatus(data) {
if (!data || !data.servers) return;
var normalCount = 0;
var warningCount = 0;
var errorCount = 0;
// 서버 타입별 상태 카운트
var typeStatusCount = {};
// 각 서버 상태 업데이트
data.servers.forEach(function(server) {
// 서버 타입 추출 (서버 이름에서 괄호 안의 텍스트 추출)
var serverTypeMatch = server.text.match(/\(([^)]+)\)/);
var serverType = serverTypeMatch ? serverTypeMatch[1] : "unknown";
// 서버 이름에서 타입 정보 제거
var displayName = server.name;
// 서버 상태
var serverStatus = server.status;
// 서버 타입별 상태 카운트 초기화
if (!typeStatusCount[serverType]) {
typeStatusCount[serverType] = {
normal: 0,
warning: 0,
error: 0,
total: 0
};
}
typeStatusCount[serverType].total++;
// 전체 상태 카운트 업데이트
if (serverStatus === 'normal') {
normalCount++;
typeStatusCount[serverType].normal++;
} else if (serverStatus === 'warning') {
warningCount++;
typeStatusCount[serverType].warning++;
} else if (serverStatus === 'error') {
errorCount++;
typeStatusCount[serverType].error++;
}
// 서버 타입 소문자로 변환 (ID용)
var serverTypeId = serverType.toLowerCase().replace(/\s+/g, '-');
// 서버 카드 찾기 및 업데이트
var serverContainerId = serverTypeId + '-servers-container';
var serverContainer = document.getElementById(serverContainerId);
if (!serverContainer) return;
// 서버 카드가 없으면 생성
var serverCard = document.querySelector('#' + serverContainerId + ' .server-card[data-server-name="' + server.name + '"]');
if (!serverCard) {
serverCard = createServerCard(server, serverContainerId);
if (serverCard) {
serverCard.setAttribute('data-server-name', server.name);
}
}
if (!serverCard) return;
// 서버 이름 업데이트
var serverNameElement = serverCard.querySelector('.server-name');
if (serverNameElement) {
serverNameElement.textContent = displayName;
}
// 서버 상태 업데이트
var statusBadge = serverCard.querySelector('.server-status-badge');
statusBadge.className = 'server-status-badge';
if (serverStatus === 'normal') {
statusBadge.classList.add('badge-success');
statusBadge.textContent = '정상';
} else if (serverStatus === 'warning') {
statusBadge.classList.add('badge-warning');
statusBadge.textContent = '경고';
} else if (serverStatus === 'error') {
statusBadge.classList.add('badge-danger');
statusBadge.textContent = '오류';
}
// CPU, 메모리, 디스크 업데이트
updateResourceValue(serverCard, 'cpu', server.cpu);
updateResourceValue(serverCard, 'memory', server.memory);
updateResourceValue(serverCard, 'disk', server.disk);
// 인스턴스 테이블 업데이트
var instanceTableBody = serverCard.querySelector('.instance-table-body');
instanceTableBody.innerHTML = '';
if (server.instances && server.instances.length > 0) {
server.instances.forEach(function(instance) {
instanceTableBody.appendChild(createInstanceRow(instance));
});
}
});
// 요약 정보 업데이트
if (document.getElementById('normal-servers')) {
document.getElementById('normal-servers').textContent = normalCount;
}
if (document.getElementById('warning-servers')) {
document.getElementById('warning-servers').textContent = warningCount;
}
if (document.getElementById('error-servers')) {
document.getElementById('error-servers').textContent = errorCount;
}
// 서버 타입별 상태 배지 업데이트
for (var type in typeStatusCount) {
var typeId = type.toLowerCase().replace(/\s+/g, '-');
var badgeElement = document.querySelector('.' + typeId + '-status-badge');
if (badgeElement) {
var countData = typeStatusCount[type];
badgeElement.textContent = countData.normal + ' / ' + countData.total + ' 정상';
badgeElement.className = typeId + '-status-badge server-status-badge';
if (countData.error > 0) {
badgeElement.classList.add('badge-danger');
} else if (countData.warning > 0) {
badgeElement.classList.add('badge-warning');
} else {
badgeElement.classList.add('badge-success');
}
}
}
}
// 리소스 값 업데이트 함수 (CPU, 메모리, 디스크)
function updateResourceValue(serverCard, resourceType, value) {
var valueElement = serverCard.querySelector('.' + resourceType + '-value');
if (!valueElement) return;
valueElement.textContent = value + '%';
valueElement.className = 'metric-value ' + resourceType + '-value';
// 값에 따라 클래스 추가
if (value >= 90) {
valueElement.classList.add('danger');
} else if (value >= 70) {
valueElement.classList.add('warning');
} else {
valueElement.classList.add('success');
}
// 스파크라인 업데이트
var sparkline = serverCard.querySelector('.' + resourceType + '-sparkline');
if (!sparkline) return;
// 서버 이름 가져오기
var serverName = serverCard.getAttribute('data-server-name');
if (!serverName) return;
// 서버 리소스 시계열 데이터 가져오기
ModernDashboardApi.getServerResourceData(serverName, function(data) {
if (data && data.data) {
var resourceData = data.data;
var resourceValues = resourceData[resourceType];
// 스파크라인 업데이트
sparkline.innerHTML = '';
if (resourceValues && resourceValues.length > 0) {
resourceValues.forEach(function(val) {
var bar = document.createElement('div');
bar.className = 'sparkline-bar';
bar.style.height = val + '%';
// 값에 따라 클래스 추가
if (val >= 90) {
bar.classList.add('danger');
} else if (val >= 70) {
bar.classList.add('warning');
} else {
bar.classList.add('success');
}
sparkline.appendChild(bar);
});
} else {
// 데이터가 없는 경우 기본 스파크라인 생성
for (var i = 0; i < 7; i++) {
var bar = document.createElement('div');
bar.className = 'sparkline-bar success';
bar.style.height = value + '%';
sparkline.appendChild(bar);
}
}
} else {
// API 응답이 없는 경우 기본 스파크라인 생성
sparkline.innerHTML = '';
for (var i = 0; i < 7; i++) {
var bar = document.createElement('div');
bar.className = 'sparkline-bar success';
bar.style.height = value + '%';
sparkline.appendChild(bar);
}
}
});
}
// 서버 데이터 로드 함수
function loadServerData() {
console.log("서버 데이터 로드 시작: " + new Date().toLocaleTimeString());
ModernDashboardApi.getServerStatus(null, function(data) {
updateServerStatus(data);
console.log("서버 데이터 로드 완료: " + new Date().toLocaleTimeString());
});
}
// 서버 필터 버튼 클릭 이벤트
$('.filter-btn').click(function() {
var type = $(this).data('type');
if (type === 'all') {
// 전체 표시
$('.server-section').show();
$('.filter-btn').removeClass('active');
$(this).addClass('active');
$(".tran-filter-btn[data-type='all']").click();
} else {
// 필터링
$('.server-section').hide();
$('#server-section-' + type).show();
$('.filter-btn').removeClass('active');
$(this).addClass('active');
$(".tran-filter-btn[data-type='" + type + "']").click();
}
});
// 서버 검색 기능
$('#server-search').on('input', function() {
var searchText = $(this).val().toLowerCase();
if (searchText.length > 0) {
$('.server-card').each(function() {
var serverName = $(this).find('.server-name').text().toLowerCase();
if (serverName.indexOf(searchText) > -1) {
$(this).show();
} else {
$(this).hide();
}
});
} else {
$('.server-card').show();
}
});
// 초기 로드
$(document).ready(function() {
// 서버 데이터 로드
loadServerData();
// 이벤트 리스너 등록 - 중앙 이벤트 관리자 사용
if (window.DashboardEventManager) {
// 초기화 이벤트 리스너
window.DashboardEventManager.on('init', function() {
console.log("서버 상태 초기화 이벤트 수신");
// 이미 초기화되었으므로 추가 작업 필요 없음
});
// 새로고침 이벤트 리스너
window.DashboardEventManager.on('refresh', function() {
console.log("서버 상태 새로고침 이벤트 수신");
loadServerData();
});
} else {
console.error("DashboardEventManager가 정의되지 않았습니다. modern-dashboard.js가 먼저 로드되었는지 확인하세요.");
}
});
</script>