ui: simplify DDS default screens

This commit is contained in:
devmrko
2026-07-01 10:08:07 +09:00
parent 2a038662e0
commit 699909212f
4 changed files with 40 additions and 46 deletions

View File

@@ -70,10 +70,16 @@ body { margin: 0; background: var(--dds-bg); color: var(--dds-ink); font-family:
.page-title .context-summary { font-size: .95rem; max-width: 700px; }
.explanation-details > summary { color: #43516a; font-size: .86rem; }
.explanation-details > summary::marker { color: var(--dds-accent); }
.knowledge-entry-form { display: grid; gap: 1rem; margin-top: 1rem; max-width: 48rem; }
.knowledge-entry-form > label { color: var(--dds-muted); display: block; font-size: .875rem; font-weight: 600; }
.knowledge-entry-form .form-control, .knowledge-entry-form .form-select { margin-top: .4rem; width: 100%; }
.registration-advanced-options { background: #f8faff; border: 1px solid var(--dds-line); border-radius: 8px; padding: .85rem 1rem; }
.registration-advanced-options > summary { color: #43516a; cursor: pointer; font-size: .875rem; font-weight: 700; }
.registration-advanced-options > p { color: var(--dds-muted); font-size: .82rem; margin: .7rem 0; }
.registration-advanced-grid { align-items: end; }
.knowledge-options-grid { align-items: end; display: grid; gap: 1rem; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.knowledge-options-grid label { color: var(--dds-muted); font-size: .875rem; font-weight: 600; }
.knowledge-options-grid .form-control, .knowledge-options-grid .form-select { margin-top: .4rem; width: 100%; }
.knowledge-options-grid .full-row { grid-column: 1 / -1; }
.registration-checkbox { align-items: center; color: var(--dds-ink) !important; display: flex; gap: .5rem; }
.registration-checkbox input { height: 1rem; width: 1rem; }
.registration-actions { border-top: 1px solid var(--dds-line); padding-top: 1rem; }
@@ -87,6 +93,9 @@ body { margin: 0; background: var(--dds-bg); color: var(--dds-ink); font-family:
.registration-result dd { font-size: .9rem; font-weight: 700; margin: .2rem 0 0; }
.advanced-workflow > details > summary { color: var(--dds-ink); cursor: pointer; font-size: 1rem; font-weight: 700; }
.advanced-workflow .section-subtitle { margin: .4rem 0 0; }
.form-grid > .btn { justify-self: start; min-width: 7.5rem; width: auto; }
.wizard-progress, .wizard-step-number { display: none; }
.permission-wizard .wizard-panel-heading { align-items: flex-start; }
.protection-summary { border-top: 3px solid #3157d5; }
.protection-status-card { background: #fbfcff; border: 1px solid #dbe3f4; border-radius: 14px; margin-top: 1rem; padding: 1.25rem; }
.protection-status-card.status-danger { background: #fffafa; border-color: #f2c8c8; }
@@ -124,5 +133,7 @@ body { margin: 0; background: var(--dds-bg); color: var(--dds-ink); font-family:
.panel { padding: 19px; }
.hero { padding-top: 30px; }
.protection-status-topline, .protection-status-footer { align-items: flex-start; flex-direction: column; }
.knowledge-options-grid { grid-template-columns: 1fr; }
.knowledge-options-grid .full-row { grid-column: auto; }
.registration-result { flex-direction: column; }
}

View File

@@ -17,24 +17,6 @@
<div class="alert alert-warning" th:if="${runtimeError}">DDS 관리 데이터를 불러오지 못했습니다. <span th:text="${runtimeError}"></span></div>
<section class="journey-grid" aria-label="DDS 권한 적용 네 단계">
<a class="journey-card journey-card-compact" href="/permissions"><div><h2>권한 관리</h2><strong>열기 →</strong></div></a>
<a class="journey-card journey-card-compact" href="/dds-protection"><div><h2>보호 정책 관리</h2><strong>열기 →</strong></div></a>
<a class="journey-card journey-card-compact" href="/dds-provision"><div><h2>정책 적용</h2><strong>열기 →</strong></div></a>
<a class="journey-card journey-card-compact" href="/vector-knowledge"><div><h2>지식자료 관리</h2><strong>열기 →</strong></div></a>
<a class="journey-card journey-card-compact" href="/dds"><div><h2>보호 대상 관리</h2><strong>열기 →</strong></div></a>
</section>
<section class="content-band compact-context">
<details class="explanation-details m-0">
<summary>도움말</summary>
<div class="macro-micro-grid mt-3">
<div><span class="architecture-kicker">MACRO · 전체 관점</span><h2>관리 기준은 하나입니다.</h2><p>누가 어떤 지식자료를 볼 수 있는지는 사용자·그룹·역할·권한 규칙에서 설명합니다. VPD와 DDS는 같은 기준을 서로 다른 DB 보호 방식으로 집행합니다.</p></div>
<div><span class="architecture-kicker">MICRO · 실행 관점</span><h2>객체별 DATA GRANT가 최종 집행합니다.</h2><p>토큰 경로는 <code>Bearer → CB_AGENT_CTX → DATA GRANT predicate → 보호 VIEW</code>, 직접 비교는 <code>END USER → DATA ROLE → DATA GRANT → 보호 VIEW</code>입니다. 권한이 없으면 객체가 보이지 않아 <code>ORA-00942</code>가 될 수 있습니다.</p></div>
</div>
</details>
</section>
<section class="summary-grid" aria-label="현재 DDS 관리 현황">
<a class="summary-tile" href="/permissions"><span class="label">역할</span><strong th:text="${#lists.size(roles)}">0</strong></a>
<a class="summary-tile" href="/permissions"><span class="label">권한 규칙</span><strong th:text="${#lists.size(permissions)}">0</strong></a>
@@ -42,9 +24,9 @@
</section>
<section class="content-band">
<div class="section-heading"><div><h2>현재 보호 </h2></div></div>
<div class="table-responsive"><table class="table table-sm align-middle"><thead><tr><th>대상</th><th>보호 방식</th><th>검증</th></tr></thead><tbody>
<tr><td><code th:text="${vectorObject}">ADMIN.CB_DDS_VECTOR_SEARCH_DOCUMENTS</code></td><td>객체별 분류값 DATA GRANT + 토큰 Context + VECTOR_DISTANCE</td><td><a href="/vector-knowledge">지식 검색</a></td></tr>
<div class="section-heading"><div><h2>현재 보호 상</h2><p class="section-subtitle">지식자료 검색에 적용되는 보호 정책</p></div><a class="btn btn-sm rw-btn-primary" href="/dds-protection">정책 상태 확인</a></div>
<div class="table-responsive"><table class="table table-sm align-middle"><thead><tr><th>보호 대상</th><th>상태</th><th></th></tr></thead><tbody>
<tr><td>지식자료 검색</td><td>접근 태그 정책 적용</td><td><a href="/vector-knowledge">권한 검색</a></td></tr>
</tbody></table></div>
<details class="explanation-details mt-3">
<summary>기술 상세</summary>

View File

@@ -27,28 +27,27 @@
<div class="section-heading">
<div>
<h2>자료 등록</h2>
<p class="section-subtitle">제목, 원문, 접근 태그 입력합니다.</p>
<p class="section-subtitle">제목, 접근 태그, 문서 내용을 입력합니다.</p>
</div>
</div>
<details class="explanation-details">
<summary>도움말</summary>
<p class="mb-0">접근 태그는 이 자료를 볼 수 있는 권한 범위입니다. 권한 관리에 등록된 TAG 값과 일치하는 태그를 입력하세요. 등록 후 문서는 검색 단위로 나뉘고 임베딩이 생성됩니다.</p>
</details>
<form method="post" action="/vector-knowledge/ingest" class="form-grid mt-3">
<form method="post" action="/vector-knowledge/ingest" class="knowledge-entry-form">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
<label>자료 제목<input class="form-control" name="title" placeholder="예: DDS 기술 태그 권한 설계" required></label>
<label>원문 주소 <span class="text-muted fw-normal">(선택)</span><input class="form-control" name="sourceUri" placeholder="예: https://kb.example.com/dds-vector"></label>
<label class="span-2">접근 태그
<label>접근 태그
<input class="form-control" name="techTags" placeholder="예: SALES, INTERNAL" required>
<span class="form-hint">태그가 하나라도 허용되면 자료를 검색할 수 있습니다.</span>
</label>
<label class="span-2">문서 본문
<label>문서 본문
<textarea class="form-control" name="content" rows="8" placeholder="문서 내용을 붙여 넣으세요." required></textarea>
</label>
<details class="span-2 registration-advanced-options">
<details class="registration-advanced-options">
<summary>고급 설정</summary>
<p>기본 처리 방식을 변경하거나 기존 자료를 교체할 때만 사용합니다.</p>
<div class="form-grid registration-advanced-grid">
<div class="knowledge-options-grid">
<label>검색 단위 길이
<input class="form-control" name="chunkSize" type="number" min="80" max="2000" value="600">
</label>
@@ -58,16 +57,16 @@
<option value="AI" th:disabled="${!aiEmbeddingConfigured}">AI 임베딩</option>
</select>
</label>
<label class="span-2">교체할 자료 ID
<label class="full-row">교체할 자료 ID
<input class="form-control" name="documentId" placeholder="기존 등록 결과에 표시된 자료 ID">
<span class="form-hint">입력한 자료의 검색 단위를 새 내용으로 교체합니다.</span>
</label>
<label class="span-2 registration-checkbox">
<label class="full-row registration-checkbox">
<input type="checkbox" name="replaceExisting" value="true"> 기존 자료를 교체합니다.
</label>
</div>
</details>
<div class="span-2 registration-actions"><button class="btn rw-btn-primary" type="submit">등록</button></div>
<div class="registration-actions"><button class="btn rw-btn-primary" type="submit">등록</button></div>
</form>
<section class="registration-result mt-3" th:if="${ingestResult}" aria-live="polite">
<div>
@@ -110,18 +109,18 @@
<summary>도움말</summary>
<p class="mb-0">토큰은 검색하는 사용자를 확인하기 위한 임시 값이며 저장하지 않습니다. 회수되었거나 만료된 토큰은 사용할 수 없습니다.</p>
</details>
<form hx-post="/vector-knowledge/token-search" hx-target="#vector-token-search-result" hx-swap="innerHTML" class="form-grid mt-3">
<form hx-post="/vector-knowledge/token-search" hx-target="#vector-token-search-result" hx-swap="innerHTML" class="knowledge-entry-form">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
<label class="span-2">Bearer 토큰
<label>Bearer 토큰
<input class="form-control" name="bearerToken" type="password" autocomplete="off" placeholder="발급된 임시 토큰을 붙여 넣으세요." required>
<span class="form-hint">요청 처리 후 저장하지 않습니다. 회수·만료된 토큰은 거부됩니다.</span>
</label>
<label class="span-2">검색 질문
<label>검색 질문
<textarea class="form-control" name="query" rows="3" placeholder="예: 세일즈 파이프라인 후속 조치 기준" required></textarea>
</label>
<details class="span-2 registration-advanced-options">
<details class="registration-advanced-options">
<summary>검색 옵션</summary>
<div class="form-grid registration-advanced-grid mt-3">
<div class="knowledge-options-grid mt-3">
<label>결과 수<input class="form-control" name="limit" type="number" min="1" max="100" value="10"></label>
<label>임베딩 방식
<select class="form-select" name="embeddingMode">
@@ -131,7 +130,7 @@
</label>
</div>
</details>
<div class="span-2 registration-actions"><button class="btn rw-btn-primary" type="submit">검색</button></div>
<div class="registration-actions"><button class="btn rw-btn-primary" type="submit">검색</button></div>
</form>
<section id="vector-token-search-result" class="mt-3" aria-live="polite">
<div class="empty-result-guide">토큰과 검색 질문을 입력하면 허용된 자료만 표시합니다.</div>
@@ -146,7 +145,7 @@
<summary>도움말</summary>
<p class="mb-0">업무 사용자 토큰 경로와 별도로, DDS END USER와 DATA GRANT가 직접 적용되는 결과를 비교합니다. 운영 검색에는 권한 검색을 사용하세요.</p>
</details>
<form hx-post="/vector-knowledge/search" hx-target="#vector-search-result" hx-swap="innerHTML" class="form-grid mt-3">
<form hx-post="/vector-knowledge/search" hx-target="#vector-search-result" hx-swap="innerHTML" class="knowledge-entry-form">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
<label>검증 사용자
<select class="form-select" name="userKey" required>
@@ -162,10 +161,10 @@
<option value="AI" th:disabled="${!aiEmbeddingConfigured}">AI 임베딩</option>
</select>
</label>
<label class="span-2">검색 질문
<label>검색 질문
<textarea class="form-control" name="query" rows="3" placeholder="예: 기술 태그로 지식자료 검색 권한을 제한하는 방법" required></textarea>
</label>
<div class="span-2 registration-actions"><button class="btn rw-btn-secondary" type="submit">검증 실행</button></div>
<div class="registration-actions"><button class="btn rw-btn-secondary" type="submit">검증 실행</button></div>
</form>
<section id="vector-search-result" class="mt-3" aria-live="polite">
<div class="empty-result-guide">검증 사용자와 검색 질문을 입력하면 보호 결과를 표시합니다.</div>