feat(scaffold): Domain Category 콤보박스 및 카테고리 동적 로드 API 추가
All checks were successful
Deploy to OCIWP / deploy (push) Successful in 7m11s

This commit is contained in:
jade
2026-08-14 09:24:39 +09:00
parent 8a7697447f
commit 954d8879b7
2 changed files with 93 additions and 43 deletions

View File

@@ -155,6 +155,21 @@ public class ScaffoldingController {
.sorted().toList();
}
@GetMapping("/categories")
public List<String> listCategories(@RequestParam String moduleName) {
if (moduleName == null || !moduleName.matches("^dap-was-[a-z0-9-]+$")) {
throw new IllegalArgumentException("Invalid target module.");
}
String sourceDir = System.getenv("AXHUB_SOURCE_DIR");
if (sourceDir == null || sourceDir.isBlank()) sourceDir = System.getProperty("user.dir");
File bizDir = new File(sourceDir, moduleName + "/src/main/java/io/shinhanlife/dap/mcc/biz");
File[] dirs = bizDir.listFiles(File::isDirectory);
if (dirs == null) return List.of();
return Arrays.stream(dirs).map(File::getName)
.filter(name -> name.matches("^[a-z0-9]{3}$"))
.sorted().toList();
}
@PostMapping("/field-draft")
public ResponseEntity<?> generateFieldDraft(@RequestBody Map<String, String> req) {
String description = req.getOrDefault("description", "").trim();

View File

@@ -824,6 +824,50 @@
<!-- Tool Creation Form -->
<div class="tab-pane fade" id="tool" role="tabpanel">
<form id="toolForm">
<div class="row mb-4">
<div class="col-md-6">
<label class="form-label">Target Module</label>
<select class="form-select" name="moduleName" id="targetModuleSelect" required>
<option value="dap-was-cus">dap-was-cus</option>
<option value="dap-was-hr">dap-was-hr</option>
<option value="dap-was-sal">dap-was-sal</option>
<option value="dap-was-pro">dap-was-pro</option>
<option value="dap-was-sys">dap-was-sys</option>
</select>
<div class="input-hint">Destination Pod directory.</div>
</div>
<div class="col-md-6 mt-3 mt-md-0">
<label class="form-label">Gateway Registration</label>
<select class="form-select" name="register">
<option value="true" selected>True (Public)</option>
<option value="false">False (Private)</option>
</select>
<div class="input-hint">Controls dynamic routing exposure.</div>
</div>
</div>
<div class="row mb-3">
<div class="col-md-6">
<label class="form-label mb-1">Domain Category</label>
<div class="row g-2">
<div class="col-md-5">
<select id="domainCategorySelect" class="form-select">
<option value="">새 도메인 생성</option>
</select>
</div>
<div class="col-md-7">
<input type="text" id="domainCategoryName" class="form-control" name="categoryKey" pattern="^[a-z0-9]{3}$" maxlength="3" minlength="3" placeholder="e.g. cmm (3글자 영소문자)" oninput="this.value = this.value.toLowerCase()" required>
</div>
</div>
</div>
<div class="col-md-6 mt-3 mt-md-0">
<label class="form-label">Protocol</label>
<select class="form-select" name="routingType">
<option value="HTTP">HTTP (REST)</option>
<option value="MCI">MCI (Legacy)</option>
</select>
</div>
</div>
<div class="mb-4 p-3 rounded" style="background:#18181b; border:1px solid #3f3f46;">
<div class="d-flex justify-content-between align-items-center gap-3">
<div>
@@ -920,26 +964,6 @@
</div>
</div>
<div class="row mb-3">
<div class="col-md-6">
<label class="form-label">Domain Category</label>
<input type="text" class="form-control" name="categoryKey" pattern="^[a-z0-9]{3}$" maxlength="3" minlength="3" list="groupList" placeholder="e.g. cmm, smp, pay" oninput="this.value = this.value.toLowerCase()" required>
<datalist id="groupList">
<option value="smp">smp</option>
<option value="cmm">cmm</option>
<option value="cus">cus</option>
<option value="cnt">cnt</option>
<option value="clm">clm</option>
</datalist>
</div>
<div class="col-md-6 mt-3 mt-md-0">
<label class="form-label">Protocol</label>
<select class="form-select" name="routingType">
<option value="HTTP">HTTP (REST)</option>
<option value="MCI">MCI (Legacy)</option>
</select>
</div>
</div>
<div class="row mb-3">
<div class="col-md-6">
@@ -977,27 +1001,6 @@
</div>
</div>
<div class="row mb-4">
<div class="col-md-6">
<label class="form-label">Target Module</label>
<select class="form-select" name="moduleName" id="targetModuleSelect" required>
<option value="dap-was-cus">dap-was-cus</option>
<option value="dap-was-hr">dap-was-hr</option>
<option value="dap-was-sal">dap-was-sal</option>
<option value="dap-was-pro">dap-was-pro</option>
<option value="dap-was-sys">dap-was-sys</option>
</select>
<div class="input-hint">Destination Pod directory.</div>
</div>
<div class="col-md-6 mt-3 mt-md-0">
<label class="form-label">Gateway Registration</label>
<select class="form-select" name="register">
<option value="true" selected>True (Public)</option>
<option value="false">False (Private)</option>
</select>
<div class="input-hint">Controls dynamic routing exposure.</div>
</div>
</div>
<div class="row mb-4">
<div class="col-md-6">
@@ -1483,6 +1486,9 @@
if (modules && modules.length > 0) {
select.innerHTML = modules.map(m => `<option value="${m}" ${m === 'dap-was-cus' ? 'selected' : ''}>${m}</option>`).join('');
}
if (typeof loadCategoriesForSelection === 'function') {
loadCategoriesForSelection();
}
})
.catch(err => console.error('Failed to load modules:', err));
});
@@ -1569,8 +1575,37 @@
}
}
document.querySelector('#toolForm [name="categoryKey"]').addEventListener('change', loadUseCasesForSelection);
document.getElementById('targetModuleSelect').addEventListener('change', loadUseCasesForSelection);
async function loadCategoriesForSelection() {
const moduleName = document.getElementById('targetModuleSelect').value;
const select = document.getElementById('domainCategorySelect');
const nameInput = document.getElementById('domainCategoryName');
select.innerHTML = '<option value="">새 도메인 생성</option>';
try {
const response = await fetch(`/api/v1/scaffold/categories?moduleName=${encodeURIComponent(moduleName)}`);
if (!response.ok) throw new Error('Category 목록 조회 실패');
const categories = await response.json();
categories.forEach(cat => select.add(new Option(`기존 ${cat} 도메인`, cat)));
} catch (error) {
console.warn(error);
}
nameInput.value = '';
nameInput.readOnly = false;
loadUseCasesForSelection();
}
document.getElementById('domainCategoryName').addEventListener('input', loadUseCasesForSelection);
document.getElementById('targetModuleSelect').addEventListener('change', loadCategoriesForSelection);
document.getElementById('domainCategorySelect').addEventListener('change', function() {
const nameInput = document.getElementById('domainCategoryName');
if (this.value) {
nameInput.value = this.value;
nameInput.readOnly = true;
} else {
nameInput.value = '';
nameInput.readOnly = false;
}
loadUseCasesForSelection();
});
document.getElementById('toolGroupUseCaseSelect').addEventListener('change', function() {
const nameInput = document.getElementById('toolGroupUseCaseName');
if (this.value) {