Browse Source

update css

HANTE 1 month ago
parent
commit
1372bf1cf5

+ 6 - 0
.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
+  </component>
+</project>

+ 1 - 1
conf/icmp-ping-server.pid

@@ -1 +1 @@
-51520
+62900

+ 42 - 15
src/main/resources/static/css/logFiles.css

@@ -2,31 +2,60 @@
     padding: 20px;
 }
 
-#logFiles {
-    width: 100%;
-    table-layout: fixed;
+.log-table {
+    width: auto;
+    border-collapse: collapse;
+    table-layout: fixed;         /* 열 자동 분할 */
+    font-size: 14px;
 }
 
-#logFiles th,
-#logFiles td {
-    text-align: left;
-    padding: 6px 10px;
+.log-table th,
+.log-table td {
+    padding: 6px 12px;
+    border: 1px solid #ccc;
     white-space: nowrap;
     overflow: hidden;
     text-overflow: ellipsis;
+    text-align: center;
+    vertical-align: middle;
+}
+.log-table td:first-child {
+    text-align: left;
+    width: 200px;
+}
+
+.log-table td:nth-child(2) {
+    text-align: center;
+    width: 80px;
+}
+
+.log-table td:nth-child(3) {
+    text-align: center;
+    width: 150px;
 }
 
+
 .filename-cell {
     max-width: 480px;
     word-break: break-word;
     white-space: normal;
+    font-weight: bold;
+    text-align: left;
+    color: #333;
 }
 
-.size-text {
-    color: #888;
+.file-size {
+    color: #555;
+    text-align: right;
+}
+
+.file-size.empty {
+    color: #999;
+    font-style: italic;
     font-size: 0.9em;
 }
 
+/* 📄 로그 뷰 영역 */
 #logScroll {
     width: 98%;
     height: 660px;
@@ -36,24 +65,22 @@
     margin: 5px auto;
     font-family: monospace;
     font-size: 13px;
+    box-sizing: border-box;
 }
 
 .log-line {
     font-family: Consolas, monospace;
     font-size: 13px;
     white-space: pre-wrap;
-    text-align: left !important;
     line-height: 1.5em;
+    text-align: left !important;
 }
 
-.loading-text {
-    color: gray;
-    text-align: center;
-}
-
+.loading-text,
 .placeholder-text {
     color: gray;
     text-align: center;
+    font-style: italic;
 }
 
 .error-text {

+ 49 - 3
src/main/resources/static/css/main.css

@@ -35,7 +35,9 @@ body {
 .navigation {
     background-color: #fff;
     text-align: center;
-    padding: 12px 0;
+    /*padding: 12px 0;*/
+    padding: 8px 0;
+    margin-bottom: 0;
 }
 
 .menu-list {
@@ -61,12 +63,56 @@ body {
 }
 
 .main-content {
-    padding: 24px;
+    margin-top: 0;
+    padding: 16px;
 }
 
 .content-view {
     background-color: #fff;
-    padding: 24px;
+    /*padding: 24px;*/
+    margin: 0;
     border-radius: 8px;
     box-shadow: 0 2px 6px rgba(0,0,0,0.05);
+}
+
+fieldset {
+    padding: 20px;
+    border-radius: 8px;
+    border: 1px solid #ccc;
+    background-color: #fafafa;
+}
+
+legend {
+    font-weight: bold;
+    font-size: 16px;
+    color: #333;
+    padding: 0 10px;
+}
+
+.sub-main-info table {
+    margin: 0 auto;
+}
+
+.sub-main-info table td {
+    padding: 3px 6px;
+    font-size: 13px;
+}
+
+.sub-detail-info table {
+    margin: 0 auto;
+}
+
+.button-link {
+    color: #007acc;
+    text-decoration: underline;
+    background: none;
+    border: none;
+    font: inherit;
+    padding: 0;
+    cursor: pointer;
+}
+
+.button-link:hover {
+    color: #005fa3;
+    text-decoration: underline;
 }

+ 35 - 16
src/main/resources/static/css/pingPage.css

@@ -4,23 +4,46 @@
     box-sizing: border-box;
 }
 
-.right-align {
+.right-align,
+.ping-controls {
     text-align: right;
     margin: 10px 30px;
 }
 
+.ping-controls {
+    margin: 10px 0;
+}
+
+.ping-table-wrapper {
+    overflow-x: auto;
+}
+
 .ping-table {
-    width: 100%;
+    width: 70%;
     border-collapse: collapse;
+    font-size: 14px;
+    table-layout: auto;
 }
 
 .ping-table th,
 .ping-table td {
-    padding: 6px 12px;
+    padding: 6px 10px;
     border: 1px solid #ccc;
-    word-break: keep-all;
+    text-align: center;
     white-space: nowrap;
-    text-align: left;
+    word-break: keep-all;
+}
+
+.loading-text,
+.placeholder-text {
+    color: gray;
+    text-align: center;
+    font-style: italic;
+}
+
+.error-text {
+    color: crimson;
+    font-weight: bold;
 }
 
 #FileForm {
@@ -44,21 +67,17 @@
     font-family: Consolas, monospace;
     font-size: 13px;
     white-space: pre-wrap;
-    text-align: left !important;
     line-height: 1.5em;
+    text-align: left;
 }
 
-.placeholder-text {
-    color: gray;
-    text-align: center;
-}
-
-.loading-text {
-    color: gray;
-    text-align: center;
+.alive {
+    color: green;
+    font-weight: bold;
 }
 
-.error-text {
+.dead {
     color: crimson;
     font-weight: bold;
-}
+}
+

+ 4 - 22
src/main/resources/static/css/system.css

@@ -5,30 +5,12 @@
     font-size: 14px;
 }
 
-fieldset {
-    padding: 20px;
-    border-radius: 8px;
-    border: 1px solid #ccc;
-    background-color: #fafafa;
-}
-
-legend {
-    font-weight: bold;
-    font-size: 16px;
-    color: #333;
-    padding: 0 10px;
-}
-
-table {
-    width: 100%;
+.system-table {
+    width: 500px;
     border-collapse: collapse;
 }
 
-td {
-    padding: 10px 5px;
-}
-
-td:first-child {
+.system-table td:first-child {
     text-align: right;
     font-weight: bold;
     color: #555;
@@ -37,7 +19,7 @@ td:first-child {
 
 input[disabled] {
     width: 100%;
-    padding: 8px;
+    padding: 2px;
     background-color: #f0f0f0;
     color: #333;
     border: 1px solid #ccc;

+ 5 - 0
src/main/resources/static/html/login.html

@@ -3,11 +3,16 @@
 <head>
     <meta charset="UTF-8" />
     <title>Login</title>
+    <link rel="stylesheet" href="/css/reset.css" />
     <link rel="stylesheet" href="/css/main.css" />
     <link rel="stylesheet" href="/css/login.css" />
     <script type="module" src="/js/login.js"></script>
 </head>
 <body>
+<header class="app-header">
+    <h1 class="app-title">ICMP Ping Server</h1>
+</header>
+
 <div class="login-container">
     <form id="loginForm">
         <div class="form-group">

+ 1 - 0
src/main/resources/static/html/main.html

@@ -3,6 +3,7 @@
 <head>
     <meta charset="UTF-8" />
     <title>ICMP Ping Server</title>
+    <link rel="stylesheet" href="/css/reset.css" />
     <link rel="stylesheet" href="/css/main.css" />
     <link rel="stylesheet" href="/css/system.css" />
     <link rel="stylesheet" href="/css/logFiles.css" />

+ 37 - 28
src/main/resources/static/js/logFiles.js

@@ -4,38 +4,47 @@ let _fileViewTimer = null;
 
 export function main(container) {
 	container.innerHTML = `
-    <div class="logfiles-container">
-      <div class="content">
-        <fieldset>
-          <legend>📂 Log Files</legend>
-          <table class="tree-basic table-bordered" id="logFiles">
-            <thead>
+  <section class="sub-main-info">
+    <fieldset>
+      <legend>📜 Log Files</legend>
+      <div>
+        <table class="log-table" id="logFiles">
+          <thead>
+            <tr>
+              <th width="70%">파일명</th>
+              <th width="10%">내용</th>
+              <th width="20%">동작</th>
+            </tr>
+          </thead>
+          <tbody id="logTbody">
+            <tr>
+              <td colspan="3" class="loading-text">로딩 중입니다...</td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </fieldset>
+  </section>
+
+  <section class="sub-detail-info">
+    <div class="content">
+      <fieldset id="FileForm">
+        <legend id="logFileName">Log File View</legend>
+        <div id="logScroll">
+          <table>
+            <tbody id="fileTbody">
               <tr>
-                <th>파일명</th>
-                <th>보기</th>
-                <th>다운로드</th>
+                <td class="placeholder-text">목록에서 파일을 선택해주세요.</td>
               </tr>
-            </thead>
-            <tbody id="logTbody">
-              <tr><td colspan="3" class="loading-text">로딩 중입니다...</td></tr>
             </tbody>
           </table>
-        </fieldset>
-      </div>
-
-      <div class="content">
-        <fieldset id="FileForm">
-          <legend id="logFileName">Log File View</legend>
-          <div id="logScroll">
-            <table><tbody id="fileTbody">
-              <tr><td class="placeholder-text">목록에서 파일을 선택해주세요.</td></tr>
-            </tbody></table>
-          </div>
-        </fieldset>
-      </div>
+        </div>
+      </fieldset>
     </div>
+  </section>
   `;
 
+
 	apiRequest("GET", "/api/log-files")
 		.then(data => {
 			const tbody = document.getElementById("logTbody");
@@ -68,9 +77,9 @@ function renderTree(node, parentId, tbody) {
 
 	if (isFile) {
 		tr.innerHTML = `
-      <td class="filename-cell">${name} <span class="size-text">(${size} Byte)</span></td>
-      <td><a href="#" data-action="view" data-path="${node.filePath}" data-name="${node.fileName}">보기</a></td>
-      <td><a href="#" data-action="download" data-path="${node.filePath}" data-name="${node.fileName}">다운로드</a></td>
+      <td class="filename-cell">${name} <span class="file-size">(${size} Byte)</span></td>
+      <td><a href="#" class="button-link" data-action="view" data-path="${node.filePath}" data-name="${node.fileName}">보기</a></td>
+      <td><a href="#" class="button-link" data-action="download" data-path="${node.filePath}" data-name="${node.fileName}">다운로드</a></td>
     `;
 	} else {
 		tr.innerHTML = `<td colspan="3"><strong>📁 ${name}</strong></td>`;

+ 2 - 2
src/main/resources/static/js/main.js

@@ -9,7 +9,7 @@ function main() {
     const token = getApiToken();
     if (!token) {
         alert("로그인이 필요합니다.");
-        location.href = "/html/login.html";
+        location.href = "/login";
         return;
     }
 
@@ -23,7 +23,7 @@ function main() {
         .catch(() => {
             alert("세션이 만료되었거나 인증 실패했습니다.");
             clearApiToken();
-            location.href = "/html/login.html";
+            location.href = "/login";
         });
 }
 

+ 5 - 14
src/main/resources/static/js/menu.js

@@ -10,8 +10,8 @@ export function renderMenus(facilities) {
     // 동적 메뉴
     facilities.forEach(facility => {
         // const url = `/html/facility.html?name=${encodeURIComponent(facility.name)}`;
-        const url = `pingPage?facility=${encodeURIComponent(facility.name)}`;
-        addMenuItem(`🏭 ${facility.description}`, () => loadView(url));
+        // const url = `pingPage?facility=${encodeURIComponent(facility.name)}`;
+        addMenuItem(`🏭 ${facility.description}`, () => loadView("pingPage",{ facility }));
     });
 
     addMenuItem("📜 Log Files", () => loadView("logFiles"));
@@ -28,23 +28,14 @@ function addMenuItem(label, handler) {
     document.getElementById("menu").appendChild(li);
 }
 
-export function loadView(viewRoute) {
-    const view = document.getElementById("view");
-    const [base, query] = viewRoute.split("?");
-    const viewName = base.replace(".html", "").replace(/^\/?html\//, "");
+export function loadView(viewName, props = {}) {
+    const container = document.getElementById("view");
     const jsPath = `/js/${viewName}.js`;
 
-    // 선택적으로 쿼리파라미터 반영 (브라우저 주소에 표시)
-    if (query) {
-        const url = new URL(location.href);
-        url.search = `?${query}`;
-        history.replaceState(null, "", url);
-    }
-
     import(jsPath)
         .then(mod => {
             if (typeof mod.main === "function") {
-                mod.main(view);
+                mod.main(container, props);
             } else {
                 console.warn(`[loadView] ${jsPath}에 main() 함수 없음`);
                 view.innerHTML = `<p>해당 화면의 main()을 찾을 수 없습니다.</p>`;

+ 40 - 30
src/main/resources/static/js/pingPage.js

@@ -2,36 +2,44 @@ import { apiRequest } from "./common.js";
 
 let _controllerList = [];
 
-export function main(container) {
-	const params = new URLSearchParams(location.search);
-	const facility = params.get("facility") || "(시설물 없음)";
+export function main(container, { facility } = {}) {
+	const facilityCode = facility?.name ?? "-";
+	const facilityDesc = facility?.description ?? "-";
 
 	container.innerHTML = `
-    <div class="pingpage-container">
-      <div class="content right-align">
-        <button id="pingAllBtn">전체 Ping</button>
-      </div>
+<!--    <div class="pingpage-container">-->
+    <section class="sub-main-info">
+  <fieldset>
+    <legend>🏭 ${facilityDesc} Network Ping Information</legend>
 
-      <div class="content">
-        <h2 id="facility-title">📡 ${facility} PING 결과</h2>
-        <table id="facilityTable" class="ping-table">
-          <thead>
-            <tr>
-              <th>관리번호</th>
-              <th>ID</th>
-              <th>명칭</th>
-              <th>IP</th>
-              <th>상태</th>
-              <th>마지막 ping</th>
-              <th>명령</th>
-            </tr>
-          </thead>
-          <tbody id="tableBody">
-            <tr><td colspan="7" class="loading-text">로딩 중입니다...</td></tr>
-          </tbody>
-        </table>
-      </div>
+    <div class="ping-controls">
+      <button id="pingAllBtn" class="button-link">전체 Ping</button>
+    </div>
 
+    <div class="ping-table-wrapper">
+      <table id="facilityTable" class="ping-table">
+        <thead>
+          <tr>
+            <th>관리번호</th>
+            <th>ID</th>
+            <th>명칭</th>
+            <th>IP</th>
+            <th>상태</th>
+            <th>마지막 ping</th>
+            <th>명령</th>
+          </tr>
+        </thead>
+        <tbody id="tableBody">
+          <tr>
+            <td colspan="7" class="loading-text">로딩 중입니다...</td>
+          </tr>
+        </tbody>
+      </table>
+    </div>
+  </fieldset>
+</section>
+
+	<section class="sub-detail-info">
       <div class="content">
         <fieldset id="FileForm">
           <legend id="logFileName">Ping Test</legend>
@@ -42,10 +50,12 @@ export function main(container) {
           </div>
         </fieldset>
       </div>
-    </div>
+    </section>
+      
+<!--    </div>-->
   `;
 
-	apiRequest("GET", `/api/facility/${facility}`)
+	apiRequest("GET", `/api/facility/${facilityCode}`)
 		.then(list => {
 			_controllerList = list || [];
 			const tbody = document.getElementById("tableBody");
@@ -58,9 +68,9 @@ export function main(container) {
           <td>${entry.ctlrId || "-"}</td>
           <td>${entry.istlLctnNm || "-"}</td>
           <td>${entry.ctlrIp || "-"}</td>
-          <td>${entry.netState === 0 ? "-" : "Alive"}</td>
+          <td class="${entry.netState === 1 ? 'alive' : 'dead'}">${entry.netState === 0 ? "-" : "Alive"}</td>
           <td>${entry.pingTime || "-"}</td>
-          <td><a href="#" data-id="${entry.ctlrId}" data-name="${entry.istlLctnNm}" data-ip="${entry.ctlrIp}">ping</a></td>
+          <td><a href="#" class="button-link"data-id="${entry.ctlrId}" data-name="${entry.istlLctnNm}" data-ip="${entry.ctlrIp}">ping</a></td>
         `;
 				tbody.appendChild(tr);
 

+ 3 - 3
src/main/resources/static/js/system.js

@@ -2,10 +2,10 @@ import { apiRequest } from "./common.js";
 
 export function main(container) {
 	container.innerHTML = `
-    <section class="system-info">
+    <section class="sub-main-info">
       <fieldset>
-        <legend>System Information</legend>
-        <table>
+        <legend>💻 System Information</legend>
+        <table class="system-table">
           <tr><td>system id :</td><td><input type="text" id="processId" disabled /></td></tr>
           <tr><td>ping timeout :</td><td><input type="text" id="timeout" disabled /></td></tr>
           <tr><td>ping core threads :</td><td><input type="text" id="coreSize" disabled /></td></tr>