Files
minecraft_launcher/admin/public/index.html
claude-bot c4cdd0ceba
Some checks failed
Build / release (macos-latest) (push) Has been cancelled
Build / release (ubuntu-latest) (push) Has been cancelled
Build / release (windows-latest) (push) Has been cancelled
Windows Smoke Test / windows-smoke (push) Has been cancelled
Add launcher admin catalog site
2026-05-05 18:48:13 +09:00

190 lines
9.8 KiB
HTML

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Launcher Admin</title>
<link rel="stylesheet" href="./styles.css">
</head>
<body>
<div class="adminShell">
<aside class="sidebar">
<div class="brandBlock">
<span class="eyebrow">Launcher Admin</span>
<h1>프로필 관리</h1>
<p>설치 페이지에 표시할 실제 프로필을 UI로 관리합니다.</p>
</div>
<div class="metaPanel">
<div class="metaRow">
<span class="metaLabel">런처 카탈로그</span>
<code id="launcherCatalogPath">불러오는 중</code>
</div>
<div class="metaRow">
<span class="metaLabel">로컬 catalog URL</span>
<a id="localCatalogUrl" href="#" target="_blank" rel="noreferrer">불러오는 중</a>
</div>
</div>
<div class="addButtons">
<button type="button" class="primaryAction" data-add-kind="modpack">모드팩 추가</button>
<button type="button" class="secondaryAction" data-add-kind="map">맵 추가</button>
<button type="button" class="secondaryAction" data-add-kind="server-pack">서버팩 추가</button>
</div>
<div class="profileListHeader">
<span>프로필 목록</span>
<span id="profileCount">0개</span>
</div>
<div id="profileList" class="profileList"></div>
</aside>
<main class="editorPane">
<div class="topBar">
<div>
<span class="eyebrow">Catalog Editor</span>
<h2>선택한 프로필 편집</h2>
<p id="editorHint">왼쪽에서 프로필을 선택하거나 새 프로필을 추가하세요.</p>
</div>
<div class="topBarActions">
<button type="button" id="duplicateProfileButton" class="secondaryAction" disabled>복제</button>
<button type="button" id="deleteProfileButton" class="dangerAction" disabled>삭제</button>
<button type="button" id="saveCatalogButton" class="primaryAction">카탈로그 저장</button>
</div>
</div>
<div id="statusBanner" class="statusBanner" hidden></div>
<div id="emptyState" class="emptyState">
<h3>프로필이 없습니다</h3>
<p>왼쪽 버튼으로 새 모드팩, 맵, 서버팩 프로필을 추가하세요.</p>
</div>
<form id="profileEditorForm" class="editorForm" hidden>
<section class="fieldSection">
<div class="sectionHeader">
<h3>기본 정보</h3>
</div>
<div class="fieldGrid">
<label class="fieldBlock">
<span>프로필 ID</span>
<input id="field-id" type="text" autocomplete="off">
</label>
<label class="fieldBlock">
<span>종류</span>
<select id="field-kind">
<option value="modpack">modpack</option>
<option value="map">map</option>
<option value="server-pack">server-pack</option>
</select>
</label>
<label class="fieldBlock fieldBlockFull">
<span>표시 이름</span>
<input id="field-name" type="text" autocomplete="off">
</label>
<label class="fieldBlock fieldBlockFull">
<span>짧은 설명</span>
<input id="field-description" type="text" autocomplete="off">
</label>
<label class="fieldBlock fieldBlockFull">
<span>자세한 설명</span>
<textarea id="field-details" rows="6"></textarea>
</label>
</div>
</section>
<section class="fieldSection">
<div class="sectionHeader">
<h3>클라이언트 배포</h3>
</div>
<div class="fieldGrid">
<label class="fieldBlock fieldBlockFull">
<span>distribution.json 경로 또는 URL</span>
<div class="uploadField">
<input id="field-distributionUrl" type="text" autocomplete="off">
<button type="button" class="secondaryAction uploadButton" data-upload-target="distributionUrl" data-upload-accept=".json,application/json">파일 업로드</button>
</div>
</label>
<label class="fieldBlock">
<span>기본 접속 주소</span>
<input id="field-defaultServerAddress" type="text" autocomplete="off" placeholder="example.com:25565">
</label>
<label class="toggleBlock">
<input id="field-allowCustomServerAddress" type="checkbox">
<span>사용자가 라이브러리에서 주소를 바꿀 수 있음</span>
</label>
</div>
</section>
<section id="mapSection" class="fieldSection" hidden>
<div class="sectionHeader">
<h3>맵 자료</h3>
</div>
<div class="fieldGrid">
<label class="fieldBlock fieldBlockFull">
<span>월드 ZIP 경로 또는 URL</span>
<div class="uploadField">
<input id="field-worldArchiveUrl" type="text" autocomplete="off">
<button type="button" class="secondaryAction uploadButton" data-upload-target="worldArchiveUrl" data-upload-accept=".zip,application/zip">파일 업로드</button>
</div>
</label>
<label class="fieldBlock">
<span>월드 폴더 이름</span>
<input id="field-worldDirectoryName" type="text" autocomplete="off">
</label>
</div>
</section>
<section id="serverPackSection" class="fieldSection" hidden>
<div class="sectionHeader">
<h3>서버팩 자료</h3>
</div>
<div class="fieldGrid">
<label class="fieldBlock fieldBlockFull">
<span>서버 번들 ZIP 경로 또는 URL</span>
<div class="uploadField">
<input id="field-serverBundleUrl" type="text" autocomplete="off">
<button type="button" class="secondaryAction uploadButton" data-upload-target="serverBundleUrl" data-upload-accept=".zip,application/zip">파일 업로드</button>
</div>
</label>
<label class="fieldBlock">
<span>서버 폴더 이름</span>
<input id="field-serverDirectoryName" type="text" autocomplete="off">
</label>
<label class="fieldBlock fieldBlockFull">
<span>서버 실행 명령</span>
<input id="field-serverLaunchCommand" type="text" autocomplete="off" placeholder="java -jar server.jar nogui">
</label>
<label class="fieldBlock">
<span>작업 디렉터리</span>
<input id="field-serverWorkingDirectory" type="text" autocomplete="off" placeholder="빈 값이면 서버 루트">
</label>
<label class="fieldBlock">
<span>서버 포트</span>
<input id="field-serverPort" type="number" min="1" max="65535" step="1">
</label>
<label class="fieldBlock fieldBlockFull">
<span>터널 명령</span>
<input id="field-tunnelCommand" type="text" autocomplete="off" placeholder="예: playit-cli --port ${port}">
</label>
<label class="fieldBlock fieldBlockFull">
<span>터널 주소 추출 정규식</span>
<input id="field-tunnelAddressRegex" type="text" autocomplete="off" placeholder="예: ([a-zA-Z0-9.-]+:\\d+)">
</label>
</div>
</section>
<section class="fieldSection helperSection">
<div class="sectionHeader">
<h3>운영 메모</h3>
</div>
<p>업로드 버튼은 현재 프로젝트 기준 상대 경로를 자동으로 채웁니다. 로컬 테스트에는 바로 쓸 수 있고, 외부 배포용으로는 URL로 바꿔도 됩니다.</p>
</section>
</form>
</main>
</div>
<script src="./app.js"></script>
</body>
</html>