From 5fe21528fccf341d35126efa33f7ed7776fbee02 Mon Sep 17 00:00:00 2001 From: backuppc Date: Tue, 30 Dec 2025 17:35:02 +0900 Subject: [PATCH] Refactor/Fix: Standardize Dialog Themes & Fix WebSocket Fragmentation. Detail: UserInfoDialog design refresh, standardized all dialogs, fixed backend WebSocketServer fragmentation bug. --- Project/EETGW.csproj | 1 + Project/Setting.cs | 3 + .../MachineBridge/MachineBridge.Settings.cs | 58 ++ Project/Web/MachineBridge/WebSocketServer.cs | 40 +- .../components/customs/CustomEditDialog.tsx | 8 +- .../components/favorite/FavoriteDialog.tsx | 8 +- .../holiday/HolidayRequestDialog.tsx | 8 +- .../src/components/items/ItemEditDialog.tsx | 112 ++-- .../jobreport/JobReportDayDialog.tsx | 8 +- .../jobreport/JobTypeSelectModal.tsx | 23 +- .../jobreport/JobreportEditModal.tsx | 13 +- .../jobreport/JobreportTypeModal.tsx | 8 +- .../jobreport/ProjectSearchDialog.tsx | 22 +- .../src/components/kuntae/KuntaeEditModal.tsx | 8 +- .../kuntae/KuntaeErrorCheckDialog.tsx | 13 +- .../components/license/LicenseEditDialog.tsx | 8 +- .../src/components/mail/MailTestDialog.tsx | 8 +- .../src/components/project/PartListDialog.tsx | 13 +- .../project/ProjectDetailDialog.tsx | 6 +- .../components/settings/SettingsDialog.tsx | 8 +- .../src/components/user/UserGroupDialog.tsx | 20 +- .../src/components/user/UserInfoDialog.tsx | 540 ++++++++++-------- .../src/components/user/UserSearchDialog.tsx | 15 +- Project/frontend/src/pages/Dashboard.tsx | 16 +- Project/frontend/src/pages/Items.tsx | 16 +- Project/frontend/src/pages/Jobreport.tsx | 8 +- Project/frontend/src/pages/Todo.tsx | 10 +- 27 files changed, 590 insertions(+), 411 deletions(-) create mode 100644 Project/Web/MachineBridge/MachineBridge.Settings.cs diff --git a/Project/EETGW.csproj b/Project/EETGW.csproj index 6a5b84c..aade157 100644 --- a/Project/EETGW.csproj +++ b/Project/EETGW.csproj @@ -374,6 +374,7 @@ + diff --git a/Project/Setting.cs b/Project/Setting.cs index 7287985..962f6da 100644 --- a/Project/Setting.cs +++ b/Project/Setting.cs @@ -83,6 +83,9 @@ namespace Project [DisplayName("Tool Bar")] public eToolPosition HideToolbar { get; set; } + [DisplayName("테마")] + public string Theme { get; set; } + public Setting() : this(Util.CurrentPath + "setting.xml") { } diff --git a/Project/Web/MachineBridge/MachineBridge.Settings.cs b/Project/Web/MachineBridge/MachineBridge.Settings.cs new file mode 100644 index 0000000..a4c7e2f --- /dev/null +++ b/Project/Web/MachineBridge/MachineBridge.Settings.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Newtonsoft.Json; +using Project; + +namespace Project.Web +{ + public partial class MachineBridge + { + public string GetSettings() + { + try + { + return JsonConvert.SerializeObject(Pub.setting); + } + catch (Exception ex) + { + return JsonConvert.SerializeObject(new { Error = ex.Message }); + } + } + + public string SaveSettings(string jsonSettings) + { + try + { + if (string.IsNullOrEmpty(jsonSettings)) + { + return JsonConvert.SerializeObject(new { Success = false, Message = "Empty settings data" }); + } + + var dict = JsonConvert.DeserializeObject>(jsonSettings); + + // Update properties using reflection or manual mapping + // Since Setting class inherits arUtil.Setting and might have complex types, manual mapping for known properties or generic reflection is better. + // For now, let's target 'Theme' specifically as requested, and generic handling for others if possible? + // Actually, Pub.setting is an instance. We can try to deserialize INTO it, or update properties. + + if (dict.ContainsKey("Theme")) + { + Pub.setting.Theme = dict["Theme"]?.ToString(); + } + + // Add other setting properties here as needed in the future + // or implement a generic property updater + + Pub.setting.Save(); // Save to XML + + return JsonConvert.SerializeObject(new { Success = true }); + } + catch (Exception ex) + { + return JsonConvert.SerializeObject(new { Success = false, Message = ex.Message }); + } + } + } +} diff --git a/Project/Web/MachineBridge/WebSocketServer.cs b/Project/Web/MachineBridge/WebSocketServer.cs index c0b3b5f..77748d1 100644 --- a/Project/Web/MachineBridge/WebSocketServer.cs +++ b/Project/Web/MachineBridge/WebSocketServer.cs @@ -124,14 +124,23 @@ namespace Project.Web { try { - var result = await socket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None); - if (result.MessageType == WebSocketMessageType.Close) + List messageBytes = new List(); + WebSocketReceiveResult result; + do { - await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None); + result = await socket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None); + if (result.MessageType == WebSocketMessageType.Close) + { + await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None); + return; + } + messageBytes.AddRange(new ArraySegment(buffer, 0, result.Count)); } - else if (result.MessageType == WebSocketMessageType.Text) + while (!result.EndOfMessage); + + if (result.MessageType == WebSocketMessageType.Text) { - string msg = Encoding.UTF8.GetString(buffer, 0, result.Count); + string msg = Encoding.UTF8.GetString(messageBytes.ToArray()); await HandleMessage(msg, socket); } } @@ -551,7 +560,7 @@ namespace Project.Web case "USERLIST_GET_LIST": { - string process = json.process ?? "%"; + string process = json.process ?? string.Empty; string result = _bridge.UserList_GetList(process); var response = new { type = "USERLIST_LIST_DATA", data = JsonConvert.DeserializeObject(result) }; await Send(socket, JsonConvert.SerializeObject(response)); @@ -725,6 +734,25 @@ namespace Project.Web } break; + + // ===== Settings API ===== + case "GET_SETTINGS": + { + string result = _bridge.GetSettings(); + var response = new { type = "SETTINGS_DATA", data = JsonConvert.DeserializeObject(result) }; + await Send(socket, JsonConvert.SerializeObject(response)); + } + break; + + case "SAVE_SETTINGS": + { + string settingsData = JsonConvert.SerializeObject(json.settings); + string result = _bridge.SaveSettings(settingsData); + var response = new { type = "SETTINGS_SAVED", data = JsonConvert.DeserializeObject(result) }; + await Send(socket, JsonConvert.SerializeObject(response)); + } + break; + // ===== Kuntae API ===== case "GET_KUNTAE_LIST": { diff --git a/Project/frontend/src/components/customs/CustomEditDialog.tsx b/Project/frontend/src/components/customs/CustomEditDialog.tsx index 294acfd..b2791d4 100644 --- a/Project/frontend/src/components/customs/CustomEditDialog.tsx +++ b/Project/frontend/src/components/customs/CustomEditDialog.tsx @@ -126,14 +126,14 @@ export function CustomEditDialog({ isOpen, onClose, onSaved, item }: CustomEditD /> {/* 다이얼로그 콘텐트 */} -
-
+
+
-

+

{item ? '업체 정보 수정' : '새 업체 등록'}

@@ -329,7 +329,7 @@ export function CustomEditDialog({ isOpen, onClose, onSaved, item }: CustomEditD

{/* 푸터 버튼 */} -
+
{item && (
@@ -310,7 +355,7 @@ export function ItemEditDialog({ item, isOpen, onClose, onSave, onDelete }: Item
-
+
{/* 공급처 */}
@@ -332,17 +377,17 @@ export function ItemEditDialog({ item, isOpen, onClose, onSave, onDelete }: Item className="w-full px-3 py-2 bg-white/10 border border-white/20 rounded-lg text-white" />
-
- {/* 보관장소 */} -
- - setEditData({ ...editData, storage: e.target.value })} - className="w-full px-3 py-2 bg-white/10 border border-white/20 rounded-lg text-white" - /> + {/* 보관장소 */} +
+ + setEditData({ ...editData, storage: e.target.value })} + className="w-full px-3 py-2 bg-white/10 border border-white/20 rounded-lg text-white" + /> +
{/* 메모 */} @@ -356,17 +401,7 @@ export function ItemEditDialog({ item, isOpen, onClose, onSave, onDelete }: Item />
- {/* 비활성화 */} -
- setEditData({ ...editData, disable: e.target.checked })} - className="w-4 h-4 rounded border-white/20 bg-white/10" - /> - -
+
{/* 오른쪽: 이미지 영역 */} @@ -380,11 +415,10 @@ export function ItemEditDialog({ item, isOpen, onClose, onSave, onDelete }: Item onDragLeave={handleDragLeave} onDragOver={handleDragOver} onDrop={handleDrop} - className={`flex-1 min-h-[200px] rounded-lg border-2 border-dashed transition-colors flex items-center justify-center overflow-hidden ${ - isDragging - ? 'border-blue-400 bg-blue-500/20' - : 'border-white/20 bg-white/5 hover:border-white/40' - }`} + className={`flex-1 min-h-[200px] rounded-lg border-2 border-dashed transition-colors flex items-center justify-center overflow-hidden ${isDragging + ? 'border-blue-400 bg-blue-500/20' + : 'border-white/20 bg-white/5 hover:border-white/40' + }`} > {imageLoading ? (
@@ -468,7 +502,7 @@ export function ItemEditDialog({ item, isOpen, onClose, onSave, onDelete }: Item
{/* 푸터 */} -
+
{!isNew && ( - - -
-
- - {/* 비고: 남은 높이 채우기 */} -
- -