feat(scaffold): Domain Category 콤보박스 및 카테고리 동적 로드 API 추가
All checks were successful
Deploy to OCIWP / deploy (push) Successful in 7m11s
All checks were successful
Deploy to OCIWP / deploy (push) Successful in 7m11s
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user