ui: simplify DDS default screens
This commit is contained in:
@@ -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; }
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
<h1>역할</h1>
|
||||
<details class="explanation-details">
|
||||
<summary>도움말</summary>
|
||||
<p>사용자에게 부여할 역할을 관리합니다. 표시 보호 등급 상한은 허용된 행에서 원문으로 볼 수 있는 컬럼 등급의 참고값이며, 행 접근 권한은 권한 규칙과 VPD에서 결정합니다.</p>
|
||||
<p th:if="${backofficeTrack == 'DDS'}">역할은 사용자와 접근 태그 규칙을 연결하는 기준입니다. 실제 접근 범위는 접근 규칙에서 관리합니다.</p>
|
||||
<p th:unless="${backofficeTrack == 'DDS'}">사용자에게 부여할 역할을 관리합니다. 표시 보호 등급 상한은 허용된 행에서 원문으로 볼 수 있는 컬럼 등급의 참고값이며, 행 접근 권한은 권한 규칙과 VPD에서 결정합니다.</p>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
@@ -19,7 +20,8 @@
|
||||
<h2>역할 추가</h2>
|
||||
<form method="post" action="/roles" class="form-grid">
|
||||
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
|
||||
<label>
|
||||
<input th:if="${backofficeTrack == 'DDS'}" type="hidden" name="maxSensitivityLevel" value="PUBLIC">
|
||||
<label th:unless="${backofficeTrack == 'DDS'}">
|
||||
역할명
|
||||
<input class="form-control" name="roleName" placeholder="HR_DEPT_ROLE" required>
|
||||
</label>
|
||||
@@ -49,7 +51,7 @@
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>역할명</th>
|
||||
<th>표시 보호 등급 상한</th>
|
||||
<th th:unless="${backofficeTrack == 'DDS'}">표시 보호 등급 상한</th>
|
||||
<th>삭제 영향</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
@@ -60,7 +62,7 @@
|
||||
hasDependencies=${impact != null && (!#lists.isEmpty(impact.directUsers()) || !#lists.isEmpty(impact.groups()) || impact.permissionCount() > 0)}">
|
||||
<td th:text="${role.roleId()}">10</td>
|
||||
<td th:text="${role.roleName()}">HR_DEPT_ROLE</td>
|
||||
<td>
|
||||
<td th:unless="${backofficeTrack == 'DDS'}">
|
||||
<span class="badge text-bg-light" th:title="${'허용된 행의 컬럼 표시 상한: ' + role.maxSensitivityLevel()}"
|
||||
th:text="${role.maxSensitivityLevel()}">PUBLIC</span>
|
||||
<form method="post" action="/roles/max-sensitivity" class="inline-form">
|
||||
@@ -111,7 +113,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr th:if="${#lists.isEmpty(roles)}">
|
||||
<td colspan="5" class="text-muted">등록된 역할이 없습니다.</td>
|
||||
<td th:colspan="${backofficeTrack == 'DDS'} ? 4 : 5" class="text-muted">등록된 역할이 없습니다.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
Reference in New Issue
Block a user