diff --git a/src/main/java/org/mobidgim/mobidigimproject/model/device/enums/CanBusType.java b/src/main/java/org/mobidgim/mobidigimproject/model/device/enums/CanBusType.java index 075c34f..e5fedf0 100644 --- a/src/main/java/org/mobidgim/mobidigimproject/model/device/enums/CanBusType.java +++ b/src/main/java/org/mobidgim/mobidigimproject/model/device/enums/CanBusType.java @@ -5,6 +5,7 @@ import lombok.AllArgsConstructor; @AllArgsConstructor public enum CanBusType { + NONE(""), EXTENDED("extended"), STANDARD("standard"); private final String Type; diff --git a/src/main/java/org/mobidgim/mobidigimproject/model/device/enums/CanSpeed.java b/src/main/java/org/mobidgim/mobidigimproject/model/device/enums/CanSpeed.java index 2aa5621..29e79e0 100644 --- a/src/main/java/org/mobidgim/mobidigimproject/model/device/enums/CanSpeed.java +++ b/src/main/java/org/mobidgim/mobidigimproject/model/device/enums/CanSpeed.java @@ -5,15 +5,16 @@ import lombok.AllArgsConstructor; @AllArgsConstructor public enum CanSpeed { + NONE(null), CAN_SPEED_1000(1000), CAN_SPEED_2500(2500), CAN_SPEED_5000(5000), CAN_SPEED_10000(10000); - private final int value; + private final Integer value; @JsonValue - public int getValue() { + public Integer getValue() { return value; } } diff --git a/src/main/java/org/mobidgim/mobidigimproject/model/device/enums/ImuRemap.java b/src/main/java/org/mobidgim/mobidigimproject/model/device/enums/ImuRemap.java index b85bb51..5049e32 100644 --- a/src/main/java/org/mobidgim/mobidigimproject/model/device/enums/ImuRemap.java +++ b/src/main/java/org/mobidgim/mobidigimproject/model/device/enums/ImuRemap.java @@ -6,6 +6,7 @@ import lombok.AllArgsConstructor; @AllArgsConstructor public enum ImuRemap { + NONE(""), X("x"), Y("y"), Z("z"); diff --git a/src/main/java/org/mobidgim/mobidigimproject/model/device/enums/ImuRemapSign.java b/src/main/java/org/mobidgim/mobidigimproject/model/device/enums/ImuRemapSign.java index 05b913b..bafbbcd 100644 --- a/src/main/java/org/mobidgim/mobidigimproject/model/device/enums/ImuRemapSign.java +++ b/src/main/java/org/mobidgim/mobidigimproject/model/device/enums/ImuRemapSign.java @@ -5,6 +5,7 @@ import lombok.AllArgsConstructor; @AllArgsConstructor public enum ImuRemapSign { + NONE(""), MINUS("minus"), PLUS("plus"); private final String sign; diff --git a/src/main/java/org/mobidgim/mobidigimproject/model/device/enums/Rs485Baudrate.java b/src/main/java/org/mobidgim/mobidigimproject/model/device/enums/Rs485Baudrate.java index b0ac889..cbc90a7 100644 --- a/src/main/java/org/mobidgim/mobidigimproject/model/device/enums/Rs485Baudrate.java +++ b/src/main/java/org/mobidgim/mobidigimproject/model/device/enums/Rs485Baudrate.java @@ -5,13 +5,14 @@ import lombok.AllArgsConstructor; @AllArgsConstructor public enum Rs485Baudrate { + NONE(null), MODBUS_SPEED_9600(9600), MODBUS_SPEED_115200(115200); - private final int value; + private final Integer value; @JsonValue - public int getValue() { + public Integer getValue() { return value; } } diff --git a/src/main/java/org/mobidgim/mobidigimproject/model/device/enums/Rs485Mode.java b/src/main/java/org/mobidgim/mobidigimproject/model/device/enums/Rs485Mode.java index ce622cc..89ba102 100644 --- a/src/main/java/org/mobidgim/mobidigimproject/model/device/enums/Rs485Mode.java +++ b/src/main/java/org/mobidgim/mobidigimproject/model/device/enums/Rs485Mode.java @@ -5,6 +5,7 @@ import lombok.AllArgsConstructor; @AllArgsConstructor public enum Rs485Mode { + NONE(""), HALF_DUPLEX("half"), FULL_DUPLEX("full"); private final String value; diff --git a/src/main/resources/static/index.html b/src/main/resources/static/index.html index 0bd4170..83ba6d3 100644 --- a/src/main/resources/static/index.html +++ b/src/main/resources/static/index.html @@ -4,228 +4,7 @@ Device Configuration UI - - + @@ -870,7 +649,6 @@ \ No newline at end of file diff --git a/src/main/resources/static/style.css b/src/main/resources/static/style.css new file mode 100644 index 0000000..2589757 --- /dev/null +++ b/src/main/resources/static/style.css @@ -0,0 +1,218 @@ +* {margin: 0;padding: 0;box-sizing: border-box} +body {font-family: "Pretendard", sans-serif;min-height: 100vh;display: flex;background: #fff;color: #111} + +/* ───── Sidebar ───── */ +.sidebar {width: 260px;border-right: 1px solid #ddd;padding: 32px 24px;display: flex;flex-direction: column} +.sidebar h2 {font-size: 24px;margin-bottom: 32px} +details.nav { + margin-bottom: 24px +} + +.nav > summary { + list-style: none; + cursor: pointer; + display: flex; + align-items: center; + font-size: 20px +} + +.nav > summary::before { + content: ""; + width: 8px; + height: 8px; + margin-right: 8px; + border-left: 2px solid #111; + border-bottom: 2px solid #111; + transform: rotate(-135deg); + transition: .2s +} + +.nav[open] > summary::before { + transform: rotate(-45deg) +} + +.nav-items { + display: flex; + flex-direction: column; + margin-top: 10px; + padding-left: 16px; + gap: 6px +} + +.nav-items button { + background: none; + border: none; + cursor: pointer; + font-size: 16px; + text-align: left; + padding: 4px 0 +} + +/* ───── Top-bar ───── */ +.topbar { + height: 68px; + background: #d9d9d9; + display: flex; + align-items: center; + padding: 0 32px; + font-size: 28px; + font-weight: 500; + box-shadow: 0 2px 4px rgba(0, 0, 0, .15) inset +} + +/* ───── Main Board ───── */ +.content { + flex: 1; + display: flex; + flex-direction: column +} + +.board { + flex: 1; + overflow: auto; + padding: 40px; + display: flex; + flex-direction: column; + gap: 32px +} + +.card { + background: #fff; + border: 1px solid #e5e5e5; + box-shadow: 0 2px 4px rgba(0, 0, 0, .15) inset; + padding: 32px; + border-radius: 8px +} + +.card h3 { + font-size: 24px; + margin-bottom: 24px +} + +/* SSID rows */ +.ssid-row { + display: grid; + grid-template-columns:220px 220px 60px 120px; + gap: 16px; + margin-bottom: 12px +} + +.ssid-row input, .ssid-row select { + padding: 6px 8px; + font-size: 16px; + border: 1px solid #aaa; + border-radius: 4px; + width: 100% +} + +.ssid-row button {padding: 6px 10px;font-size: 14px;background: #f1f1f1;border: 1px solid #777;border-radius: 4px;cursor: pointer} + +/* 3-column grids (Network / Server) */ +.grid-3-col {display: grid;grid-template-columns:180px 240px 120px;align-items: center;gap: 16px} +.grid-3-col input {padding: 6px 8px;font-size: 16px;border: 1px solid #aaa;border-radius: 1px;width: 100%} +/* radio */ +.radio-group {display: flex;align-items: center;gap: 24px} + +.radio-label {display: inline-flex;align-items: center;gap: 4px;cursor: pointer} +.radio-label input {margin: 0} +/* I/O */ +.io-top {display: grid;grid-template-columns:repeat(auto-fit, minmax(360px, 1fr));gap: 40px;margin-bottom: 32px} +.io-bot {display: grid; /* Ethernet·LTE와 같은 2열(가변) 그리드 */grid-template-columns:repeat(auto-fit, minmax(360px, 1fr));gap: 40px;} +.io-group {display: flex;flex-direction: column;gap: 8px} +.io-group h4 {font-size: 20px;font-weight: 600;margin-bottom: 16px;display: flex;align-items: center;gap: 8px} +.io-group h4::before {content: "";width: 8px;height: 8px;background: #aaa;display: inline-block} +.io-fieldset {border: 1px solid #bbb;padding: 24px 32px;border-radius: 4px;display: flex;flex-direction: column;gap: 16px;width: 100%} +.io-row {display: grid;grid-template-columns:120px 12px 1fr;align-items: center;gap: 8px} +.io-row input, .io-row select {padding: 4px 6px;border: 1px solid #aaa;border-radius: 4px;font-size: 14px;width: 50%} +.io-row span.label {font-size: 14px;color: #333;display: block;width: 100%;} +.io-row span.label-inline {font-size: 14px;color: #333;display: inline;width: auto} +.io-row span.colon {font-size: 14px;color: #333;text-align: center;} +.reg-io-grid {display: grid;grid-template-columns: 1fr 1fr;gap: 4px} +.reg-io-grid .io-fieldset .io-row {display: grid;grid-template-columns: 140px 220px;align-items: center;gap: 4px;margin-bottom: 8px;} + +/* config 내부 라벨 */ +.reg-io-grid .io-fieldset .io-row span.label {font-size: 14px;color: #333;} +.reg-io-grid .io-fieldset .io-row input, +.reg-io-grid .io-fieldset .io-row select {padding: 4px 6px;border: 1px solid #aaa;border-radius: 4px;font-size: 14px;width: 100%;box-sizing: border-box;} +.reg-io-grid .io-fieldset .io-row.checkbox-group {display: flex;align-items: center;gap: 16px;grid-column: 2 / 3;} +.reg-io-grid .io-fieldset .io-row .checkbox-with-text {display: flex;align-items: center;gap: 10px;width: 100%;} +.reg-io-grid .io-fieldset .io-row .checkbox-with-text input[type="checkbox"] {width: auto;margin: 0;} + +/* 비활성 input 시각화 */ +.disabled {background: #f5f5f5;cursor: not-allowed} +/* Footer Buttons */ +.actions {display: flex;gap: 24px;justify-content: center;padding: 20px} +.actions button {min-width: 140px;padding: 10px 18px;font-size: 16px;border: 1px solid #bbb;background: #d9d9d9;border-radius: 4px;cursor: pointer} +.config-actions{display: flex;gap: 24px;justify-content: center;background: #f7f7f7;border: 1px solid #bbb;border-radius: 4px;margin: 24px 0 0 0;padding: 20px 0;} +.config-actions button{min-width:140px;padding:10px 18px;font-size:16px;border:1px solid #bbb;background:#d9d9d9;border-radius:4px;cursor:pointer} +.topbar { + display: flex; + justify-content: space-between; + align-items: center; + padding: 0 32px; + height: 68px; + background: #d9d9d9; + font-size: 28px; + font-weight: 500; + box-shadow: 0 2px 4px rgba(0, 0, 0, .15) inset; +} + +.save-file { + font-size: 16px; + padding: 8px 16px; + background-color: #4caf50; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; +} +/* MODBUS 화면 심플 스타일 */ +#page-modbus .card {background: #f7f7f7;border: 1px solid #bbb;box-shadow: none;padding: 24px;border-radius: 4px;display: flex;flex-direction: column;} +#page-modbus table {width: 100%;border-collapse: collapse;background: #fff;border: 1px solid #bbb;} +#page-modbus th, #page-modbus td {border: 1px solid #bbb;padding: 6px 8px;text-align: left;background: #fff;} +#page-modbus th {background: #e5e5e5;font-weight: 500;} +#page-modbus .modbus-input-area {display: grid;grid-template-columns: 200px 200px 200px 200px;gap: 20px 20px;margin: 24px auto 16px auto;background: #eaeaea;padding: 16px;border-radius: 4px;margin-left: auto;margin-right: auto;} +#page-modbus .input-row {display: contents;} +#page-modbus .modbus-input-area label.nowrap {white-space: nowrap;} +#page-modbus .modbus-input-area label {min-width: auto;color: #444;white-space: normal;} +#page-modbus .modbus-input-area input {background: #e0e0e0;border: none;border-radius: 2px;padding: 4px 8px;min-width: auto;} +#page-modbus .modbus-actions {display: flex;gap: 24px;justify-content: center;margin: 16px 0 0 0;} +#page-modbus .modbus-actions button {background: #d3d3d3;border: 1px solid #aaa;border-radius: 2px;padding: 8px 24px;font-size: 16px;cursor: pointer;} +/* 하단 버튼 영역 */ +#modbus-bottom-actions {display: flex;gap: 24px;justify-content: center;background: #f7f7f7;border: 1px solid #bbb;border-radius: 4px;margin: 24px 0 0 0;padding: 20px 0;} +#modbus-bottom-actions button {background: #e0e0e0;border: 1px solid #aaa;border-radius: 2px;padding: 10px 18px;font-size: 16px;min-width: 140px;cursor: pointer;} + +/* OPC_UA 화면 */ +#page-opcua .card {background: #f7f7f7;border: 1px solid #bbb;box-shadow: none;padding: 24px;border-radius: 4px;display: flex;flex-direction: column;} +#page-opcua table {width: 100%;border-collapse: collapse;background: #fff;border: 1px solid #bbb;} +#page-opcua th, #page-opcua td {border: 1px solid #bbb;padding: 6px 8px;text-align: left;background: #fff;} +#page-opcua th {background: #e5e5e5;font-weight: 500;} +#page-opcua .opcua-input-area {display: grid;grid-template-columns: 200px 200px 200px 200px;gap: 20px 20px;margin: 24px auto 16px auto;background: #eaeaea;padding: 16px;border-radius: 4px;margin-left: auto;margin-right: auto;} +#page-opcua .input-row {display: contents;} +#page-opcua .opcua-input-area label.nowrap {white-space: nowrap;} +#page-opcua .opcua-input-area label {min-width: auto;color: #444;white-space: normal;} +#page-opcua .opcua-input-area input {background: #e0e0e0;border: none;border-radius: 2px;padding: 4px 8px;min-width: auto;} +#page-opcua .opcua-actions {display: flex;gap: 24px;justify-content: center;margin: 16px 0 0 0;} +#page-opcua .opcua-actions button {background: #d3d3d3;border: 1px solid #aaa;border-radius: 2px;padding: 8px 24px;font-size: 16px;cursor: pointer;} +#opcUa-bottom-actions {display: flex;gap: 24px;justify-content: center;background: #f7f7f7;border: 1px solid #bbb;border-radius: 4px;margin: 24px 0 0 0;padding: 20px 0;} +#opcUa-bottom-actions button {background: #e0e0e0;border: 1px solid #aaa;border-radius: 2px;padding: 10px 18px;font-size: 16px;min-width: 140px;cursor: pointer;} + +/* CAN 화면 스타일 */ +#page-can .card {background: #f7f7f7;border: 1px solid #bbb;box-shadow: none;padding: 24px;border-radius: 4px;display: flex;flex-direction: column;} +#page-can table {width: 100%;border-collapse: collapse;background: #fff;border: 1px solid #bbb;} +#page-can th, #page-can td {border: 1px solid #bbb;padding: 6px 8px;text-align: left;background: #fff;} +#page-can th {background: #e5e5e5;font-weight: 500;} +#page-can .can-input-area {display: grid;grid-template-columns: 200px 200px 200px 200px;gap: 20px 20px;margin: 24px auto 16px auto;background: #eaeaea;padding: 16px;border-radius: 4px;margin-left: auto;margin-right: auto;} +#page-can .input-row {display: contents;} +#page-can .can-input-area label.nowrap {white-space: nowrap;} +#page-can .can-input-area label {min-width: auto;color: #444;white-space: normal;} +#page-can .can-input-area input {background: #e0e0e0;border: none;border-radius: 2px;padding: 4px 8px;min-width: auto;} +#page-can .can-actions {display: flex;gap: 24px;justify-content: center;margin: 16px 0 0 0;} +#page-can .can-actions button {background: #d3d3d3;border: 1px solid #aaa;border-radius: 2px;padding: 8px 24px;font-size: 16px;cursor: pointer;} +#can-bottom-actions {display: flex;gap: 24px;justify-content: center;background: #f7f7f7;border: 1px solid #bbb;border-radius: 4px;margin: 24px 0 0 0;padding: 20px 0;} +#can-bottom-actions button {background: #e0e0e0;border: 1px solid #aaa;border-radius: 2px;padding: 10px 18px;font-size: 16px;min-width: 140px;cursor: pointer;} + +.selected-row {background: #d0e6ff !important;} +.selected-row > td {background: #d0e6ff !important;} + +.file-upload-section{padding: 10px;margin: 10px;text-align: center;} \ No newline at end of file