개발자포탈 미게시 GW 인터페이스 표시 추가:
eapim-portal CI / build (push) Has been cancelled
eapim-portal Test / test (push) Has been cancelled

- hiddenApiCount 필드로 미게시 인터페이스 집계 노출
- API Pills 및 관련 CSS/JS 수정
- 영향 인터페이스 노출 로직 개선 및 VisibleApis 클래스 적용
This commit is contained in:
Rinjae
2026-08-05 10:44:50 +09:00
parent d71af34950
commit 2c63fa1557
14 changed files with 176 additions and 40 deletions
+12
View File
@@ -19008,6 +19008,12 @@ input[type=checkbox]:checked + .custom-checkbox {
font-weight: 700;
flex-shrink: 0;
}
.affected-api-badge.is-gw {
background-color: #ffffff;
border-style: dashed;
border-color: #cbd5e1;
color: #6b7280;
}
.btn-affected-toggle {
font-size: 13px;
@@ -26639,6 +26645,12 @@ input[type=checkbox]:checked + .custom-checkbox {
color: var(--as-muted);
cursor: default;
}
.api-status .as-api-pills .as-api-pill.is-gw {
background: #fff;
border: 1px dashed var(--as-border-strong);
color: var(--as-muted);
cursor: default;
}
.api-status .as-card-split {
margin-top: 16px;
display: grid;
File diff suppressed because one or more lines are too long
@@ -175,21 +175,31 @@
// ---------------- 이슈 카드 ----------------
/**
* 영향 API 태그. 오픈 API 목록에 있는 API 만 상세 화면으로 링크하고,
* 목록에 없는 API(비공개·미편성)는 링크 없이 흐리게 표시한다.
* 영향 API 태그.
*
* 서버가 이미 현재 사용자에게 게시된 API 만 내려주므로 여기 오는 항목은 전부 링크 대상이다.
* 게시되지 않은 GW 인터페이스는 개별 노출하지 않고 hiddenApiCount 로만 받아 건수로 묶는다.
*/
function apiPillsHtml(apis) {
if (!apis || !apis.length) return '';
const pills = apis.map(function (api) {
function apiPillsHtml(apis, hiddenCount) {
const hidden = hiddenCount || 0;
if ((!apis || !apis.length) && hidden === 0) return '';
const pills = (apis || []).map(function (api) {
const text = escapeHtml(api.apiName || api.apiId);
if (!linkableApiIds.has(api.apiId)) {
return '<span class="as-api-pill is-unlinked" title="공개된 API 목록에 없는 API 입니다">'
+ text + '</span>';
return '<span class="as-api-pill is-unlinked">' + text + '</span>';
}
return '<a class="as-api-pill" href="' + apiDetailBase + '?id=' + encodeURIComponent(api.apiId) + '">'
+ text + '</a>';
}).join('');
return '<div class="as-api-pills"><span>영향 API:</span>' + pills + '</div>';
// 개발자포탈에 게시되지 않은 GW 인터페이스는 개별 노출 없이 건수로만 알린다
const hiddenPill = hidden > 0
? '<span class="as-api-pill is-gw" title="개발자포탈에 게시되지 않은 게이트웨이 인터페이스입니다">'
+ 'GW 인터페이스 ' + hidden + '건</span>'
: '';
return '<div class="as-api-pills"><span>영향 API:</span>' + pills + hiddenPill + '</div>';
}
/**
@@ -254,7 +264,7 @@
+ '</div>'
+ '<h3 class="as-issue-title">' + escapeHtml(issue.title) + '</h3>'
+ splitHtml(inner, noticeHtml(issue))
+ apiPillsHtml(issue.impactedApis)
+ apiPillsHtml(issue.impactedApis, issue.hiddenApiCount)
+ '</article>';
}
+20 -11
View File
@@ -88,21 +88,30 @@
}
/**
* 영향 API 태그. 오픈 API 목록에 있는 API 만 상세 화면으로 링크하고,
* 목록에 없는 API(비공개·미편성)는 링크 없이 흐리게 표시한다.
* 영향 API 태그.
*
* 서버가 이미 현재 사용자에게 게시된 API 만 내려주므로 여기 오는 항목은 전부 링크 대상이다.
* 게시되지 않은 GW 인터페이스는 개별 노출하지 않고 hiddenApiCount 로만 받아 건수로 묶는다.
*/
function apiPillsHtml(apis, label) {
if (!apis || !apis.length) return '';
const pills = apis.map(function (api) {
function apiPillsHtml(apis, label, hiddenCount) {
const hidden = hiddenCount || 0;
if ((!apis || !apis.length) && hidden === 0) return '';
const pills = (apis || []).map(function (api) {
const text = escapeHtml(api.apiName || api.apiId);
if (!linkableApiIds.has(api.apiId)) {
return '<span class="as-api-pill is-unlinked" title="공개된 API 목록에 없는 API 입니다">'
+ text + '</span>';
return '<span class="as-api-pill is-unlinked">' + text + '</span>';
}
return '<a class="as-api-pill" href="' + apiDetailBase + '?id=' + encodeURIComponent(api.apiId) + '">'
+ text + '</a>';
}).join('');
return '<div class="as-api-pills"><span>' + escapeHtml(label) + '</span>' + pills + '</div>';
const hiddenPill = hidden > 0
? '<span class="as-api-pill is-gw" title="개발자포탈에 게시되지 않은 게이트웨이 인터페이스입니다">'
+ 'GW 인터페이스 ' + hidden + '건</span>'
: '';
return '<div class="as-api-pills"><span>' + escapeHtml(label) + '</span>' + pills + hiddenPill + '</div>';
}
/**
@@ -170,7 +179,7 @@
+ '</div>'
+ '<h2 class="as-alert-title">' + escapeHtml(incident.title) + '</h2>'
+ (incident.summary ? '<p class="as-meta">' + escapeHtml(incident.summary) + '</p>' : '')
+ apiPillsHtml(incident.apis, '영향 API:')
+ apiPillsHtml(incident.apis, '영향 API:', incident.hiddenApiCount)
+ splitHtml(timeline ? '<div class="as-alert-timeline">' + timeline + '</div>' : '',
noticeHtml(incident))
+ '</section>';
@@ -286,7 +295,7 @@
+ '</div>'
+ splitHtml(card.summary ? '<div class="as-maint-body">' + escapeHtml(card.summary) + '</div>' : '',
noticeHtml(card))
+ apiPillsHtml(card.impactedApis, '영향 API:')
+ apiPillsHtml(card.impactedApis, '영향 API:', card.hiddenApiCount)
+ '<div class="as-maint-meta">등록 ' + escapeHtml(formatDateTime(card.registeredAt))
+ (card.lastModifiedAt ? ' (최종 수정 ' + escapeHtml(formatDateTime(card.lastModifiedAt)) + ')' : '')
+ '</div>'
@@ -334,7 +343,7 @@
+ ' </div>'
+ ' <h3 class="as-issue-title">' + escapeHtml(issue.title) + '</h3>'
+ splitHtml(inner, noticeHtml(issue))
+ apiPillsHtml(issue.impactedApis, '영향 API:')
+ apiPillsHtml(issue.impactedApis, '영향 API:', issue.hiddenApiCount)
+ '</article>'
+ '</div>';
}
@@ -253,6 +253,14 @@
color: var(--as-muted);
cursor: default;
}
// 개발자포탈에 게시되지 않은 GW 인터페이스 묶음 ("GW 인터페이스 3건")
.as-api-pill.is-gw {
background: #fff;
border: 1px dashed var(--as-border-strong);
color: var(--as-muted);
cursor: default;
}
}
// 타임라인 | 공지 2열. 데스크탑(961px~)에서만 갈라지고 그 아래는 세로로 쌓인다.
@@ -358,6 +358,14 @@
font-weight: 700;
flex-shrink: 0;
}
// 개발자포탈에 게시되지 않은 GW 인터페이스 묶음 ("GW 인터페이스 3건")
&.is-gw {
background-color: #ffffff;
border-style: dashed;
border-color: #cbd5e1;
color: #6b7280;
}
}
.btn-affected-toggle {
@@ -78,29 +78,27 @@
<th>상태</th>
<td colspan="3" th:text="${portalNotice.state != null ? portalNotice.state : '-'}">-</td>
</tr>
<tr th:if="${portalNotice.affectedApis != null and !portalNotice.affectedApis.isEmpty()}">
<tr
th:if="${(portalNotice.affectedApis != null and !portalNotice.affectedApis.isEmpty()) or portalNotice.hiddenApiCount > 0}">
<th>영향 API</th>
<td colspan="3">
<div class="affected-apis-wrapper">
<!-- First 3 APIs (Always visible) -->
<!-- 개발자포탈에 게시된 API 만 개별 노출한다 (인터페이스 ID 는 표시하지 않음) -->
<div class="affected-apis-list">
<span class="affected-api-badge" th:each="api, iterStat : ${portalNotice.affectedApis}"
th:if="${iterStat.index < 3}">
<strong th:text="${api.apiId}">API_ID</strong><span
th:if="${api.apiName != null and !api.apiName.isEmpty()}"
th:text="| - ${api.apiName}|"></span>
</span>
th:if="${iterStat.index < 3}" th:text="${api.apiName}">API 명</span>
<!-- Rest of APIs (Hidden by default) -->
<th:block th:if="${portalNotice.affectedApis.size() > 3}">
<span class="affected-api-badge extra-api"
th:each="api, iterStat : ${portalNotice.affectedApis}" th:if="${iterStat.index >= 3}"
style="display: none;">
<strong th:text="${api.apiId}">API_ID</strong><span
th:if="${api.apiName != null and !api.apiName.isEmpty()}"
th:text="| - ${api.apiName}|"></span>
</span>
style="display: none;" th:text="${api.apiName}">API 명</span>
</th:block>
<!-- 게시되지 않은 GW 인터페이스는 건수로만 묶어서 표기 -->
<span class="affected-api-badge is-gw" th:if="${portalNotice.hiddenApiCount > 0}"
th:text="|GW 인터페이스 ${portalNotice.hiddenApiCount}건|"
title="개발자포탈에 게시되지 않은 게이트웨이 인터페이스입니다">GW 인터페이스 0건</span>
</div>
<!-- Toggle Button -->