초기 커밋: SheetMe 서식생성기 (P0~P5 완료 상태)
레거시 서식생성기(VB.NET WinForms) 대체용 C#/.NET 10 WPF 디자이너. 기준선: 실DB 활성 디자인 1,271건 왕복 의미론 diff 0 / 예외 0, 단위 테스트 49/49. 이 커밋에 함께 포함된 자격증명 분리: - appsettings.json 을 __HOST__/__PASSWORD__ 플레이스홀더로 전환 - 실접속 정보는 appsettings.Development.json 으로 분리(.gitignore 제외, csproj Debug 조건부 복사라 Release 산출물에 실리지 않음) - ConfigLoader 를 환경변수 > Development > appsettings 순 레이어링으로 변경, 미치환 플레이스홀더는 '미설정'으로 간주 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Windows;
|
||||
using SheetMe.Data.Stores;
|
||||
|
||||
namespace SheetMe.Designer.Views;
|
||||
|
||||
/// <summary>
|
||||
/// 서식별 상용구 관리 대화상자 — E_SHTWRDMST 1단계 문구 추가/수정/삭제/순서.
|
||||
/// 레거시 런타임 상용구 팝업(MRecordWord)이 그대로 읽어가는 데이터를 관리한다.
|
||||
/// </summary>
|
||||
public partial class RecordWordDialogView : Window
|
||||
{
|
||||
#region Member Fields
|
||||
private readonly RecordWordStore store;
|
||||
private readonly string shtCod;
|
||||
private readonly ObservableCollection<RecordWordInfo> words = new();
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public RecordWordDialogView(RecordWordStore store, string shtCod, string sheetTitle)
|
||||
{
|
||||
this.store = store;
|
||||
this.shtCod = shtCod;
|
||||
InitializeComponent();
|
||||
HeaderText.Text = $"[{shtCod}] {sheetTitle} — 작성 화면의 상용구 팝업에 표시되는 문구입니다. " +
|
||||
"(텍스트박스의 '상용구 사용'이 켜져 있어야 합니다)";
|
||||
WordList.ItemsSource = words;
|
||||
Loaded += (_, _) => Reload();
|
||||
NewWordBox.Loaded += (_, _) => NewWordBox.Focus();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
private void Reload()
|
||||
{
|
||||
try
|
||||
{
|
||||
words.Clear();
|
||||
foreach (var word in store.List(shtCod))
|
||||
{
|
||||
words.Add(word);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"상용구 조회 중 오류가 발생했습니다.\n\n{ex.Message}", "오류",
|
||||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAdd(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var value = NewWordBox.Text.Trim();
|
||||
if (value.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
store.Add(shtCod, value, Environment.UserName);
|
||||
NewWordBox.Clear();
|
||||
NewWordBox.Focus();
|
||||
Reload();
|
||||
WordList.SelectedIndex = words.Count - 1;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"추가 중 오류가 발생했습니다.\n\n{ex.Message}", "오류",
|
||||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEdit(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (WordList.SelectedItem is not RecordWordInfo selected)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var editor = new QueryEditorWindow($"상용구 수정", selected.Value) { Owner = this };
|
||||
// QueryEditorWindow 재사용(큰 편집 영역) — 변수 삽입은 무시해도 무해
|
||||
if (editor.ShowDialog() != true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var newValue = editor.QueryText.Trim();
|
||||
if (newValue.Length == 0 || newValue == selected.Value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
store.Update(selected.Key, newValue, Environment.UserName);
|
||||
Reload();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"수정 중 오류가 발생했습니다.\n\n{ex.Message}", "오류",
|
||||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnRemove(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (WordList.SelectedItem is not RecordWordInfo selected)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (MessageBox.Show($"삭제할까요?\n\n{Truncate(selected.Value)}", "상용구 삭제",
|
||||
MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes)
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
store.Remove(selected.Key);
|
||||
Reload();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"삭제 중 오류가 발생했습니다.\n\n{ex.Message}", "오류",
|
||||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMoveUp(object sender, RoutedEventArgs e) => Move(-1);
|
||||
|
||||
private void OnMoveDown(object sender, RoutedEventArgs e) => Move(+1);
|
||||
|
||||
private void Move(int delta)
|
||||
{
|
||||
var index = WordList.SelectedIndex;
|
||||
var target = index + delta;
|
||||
if (index < 0 || target < 0 || target >= words.Count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
words.Move(index, target);
|
||||
store.Reorder(words.Select(w => w.Key).ToList(), Environment.UserName);
|
||||
WordList.SelectedIndex = target;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"순서 변경 중 오류가 발생했습니다.\n\n{ex.Message}", "오류",
|
||||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
Reload();
|
||||
}
|
||||
}
|
||||
|
||||
private static string Truncate(string value)
|
||||
=> value.Length > 80 ? value[..80] + "…" : value;
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user