Files
minecraft_launcher/views/op/datapack.ejs
claude-bot af884706d4 op: 데이터팩 출력을 실제 music_quiz zip 으로 교체
가이드 (mc_datapack/launcher_datapack_연동_가이드.txt) 에 따라:
- file/datapacks/music_quiz_template/ 에 mc_datapack 의 music_quiz/ 정적
  파일을 미리 동봉 (data/mq/function/init/songs.mcfunction 제외).
- src/server/datapack.ts: list.music → SNBT (`{title, author, alias}`)
  songs.mcfunction 빌더와 archiver 기반 zip 스트리머 추가.
- /op/datapack/:packName/generate 가 텍스트 placeholder 대신
  music_quiz_<key>.zip 을 Content-Disposition attachment 로 내려준다.
- datapack.ejs 의 코드블록·복사 UI 제거, 곡 수는 서버 렌더 시점에 표시.
- 더 이상 쓰이지 않는 locales 의 datapackOutput.* 키 제거, datapack
  버튼 라벨/상태 문구를 zip 다운로드용으로 정리.
2026-05-13 16:34:34 +09:00

103 lines
4.2 KiB
Plaintext

<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title><%= t('datapack.browserTitle') %></title>
<link rel="stylesheet" href="/static/styles.css" />
</head>
<body class="siteBody">
<%- include('../partials/navbar', { userId }) %>
<main class="pageWrap">
<section class="dashboardHeader">
<div>
<a class="ghostLink" href="/op/dashboard"><%= t('common.back') %></a>
<h1 style="margin-top:20px;"><%= t('datapack.title') %></h1>
</div>
</section>
<section class="dpControls">
<button type="button" class="primaryButton" id="pickPackBtn"><%= t('datapack.pickPack') %></button>
<span class="muted" id="pickedLabel"><%= t('datapack.pickedNone') %></span>
</section>
<p class="muted" id="countLabel"></p>
<section class="dpActions" hidden id="dpActions">
<button type="button" class="secondaryButton" id="exportBtn"><%= t('datapack.export') %></button>
<span class="statusText" id="dp-status"></span>
</section>
</main>
<!-- 음악퀴즈 선택 팝업 -->
<div class="modalOverlay" id="pickModal" hidden>
<div class="modalCard">
<header><h3><%= t('datapack.modalPickTitle') %></h3>
<button class="modalClose" type="button" data-modal-close><%= t('common.close') %></button>
</header>
<div class="modalBody">
<div class="cardRow horizontalScroll" id="pickList">
<% items.forEach(function (item) { %>
<article class="packCard pickable"
data-key="<%= item.key %>"
data-name="<%= item.definition ? item.definition.name : item.key %>"
data-music-count="<%= item.musicCount %>">
<h2><%= item.definition ? item.definition.name : item.key %></h2>
<p class="muted"><%= item.key %>.json</p>
<% if (item.definition) { %>
<ul class="metaList">
<li><%= t('dashboard.mcShort') %> <%= item.definition.mcVersion %></li>
<li><%= t('site.platform') %> <%= item.definition.platform.type %></li>
</ul>
<% } %>
</article>
<% }) %>
</div>
</div>
</div>
</div>
<script>
var I18N = <%- JSON.stringify(localeDict.datapack) %>;
</script>
<script>
(function () {
var pickModal = document.getElementById('pickModal')
var pickedKey = ''
document.getElementById('pickPackBtn').addEventListener('click', function () {
pickModal.hidden = false
})
document.querySelectorAll('[data-modal-close]').forEach(function (b) {
b.addEventListener('click', function () { pickModal.hidden = true })
})
pickModal.addEventListener('click', function (e) {
if (e.target === pickModal) pickModal.hidden = true
})
document.querySelectorAll('#pickList .pickable').forEach(function (card) {
card.addEventListener('click', function () {
pickedKey = card.getAttribute('data-key')
var name = card.getAttribute('data-name')
var count = card.getAttribute('data-music-count') || '0'
document.getElementById('pickedLabel').textContent = I18N.pickedLabel.replace('{{name}}', name)
document.getElementById('countLabel').textContent = I18N.totalCount.replace('{{count}}', count)
pickModal.hidden = true
document.getElementById('dpActions').hidden = false
document.getElementById('dp-status').textContent = ''
document.getElementById('dp-status').classList.remove('error')
})
})
document.getElementById('exportBtn').addEventListener('click', function () {
if (!pickedKey) return
var s = document.getElementById('dp-status')
s.textContent = I18N.exporting; s.classList.remove('error')
// zip 다운로드를 트리거하기 위해 location 으로 이동시킨다.
window.location.href = '/op/datapack/' + encodeURIComponent(pickedKey) + '/generate'
// 다운로드는 비동기 / 별도 응답이므로 약간의 지연 후 "완료" 표시.
setTimeout(function () { s.textContent = I18N.exported }, 500)
})
})()
</script>
</body>
</html>