213 lines
11 KiB
HTML
213 lines
11 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" id="addProfileButton">프로필 추가</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 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="toggleBlock">
|
|
<input id="field-modsEnabled" type="checkbox">
|
|
<span>모드 사용</span>
|
|
</label>
|
|
<label class="toggleBlock">
|
|
<input id="field-pluginsEnabled" type="checkbox">
|
|
<span>플러그인 사용</span>
|
|
</label>
|
|
<label class="toggleBlock">
|
|
<input id="field-serverEnabled" type="checkbox">
|
|
<span>서버 사용</span>
|
|
</label>
|
|
<div class="fieldHelpText fieldBlockFull">
|
|
맵은 모든 프로필의 기본입니다. 플러그인을 켜면 서버 사용도 자동으로 같이 켜집니다.
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="fieldSection">
|
|
<div class="sectionHeader">
|
|
<h3>클라이언트 배포</h3>
|
|
</div>
|
|
<div class="fieldGrid">
|
|
<label class="fieldBlock fieldBlockFull">
|
|
<span>distribution 파일</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">JSON 업로드</button>
|
|
<button type="button" id="editDistributionButton" class="secondaryAction">JSON 편집</button>
|
|
<button type="button" id="createDistributionButton" class="secondaryAction">새로 만들기</button>
|
|
</div>
|
|
</label>
|
|
<div class="fieldHelpText fieldBlockFull">
|
|
distribution.json은 여기서 직접 업로드하거나 JSON 편집기로 새로 만들 수 있습니다.
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="fieldSection">
|
|
<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="serverSection" class="fieldSection" hidden>
|
|
<div class="sectionHeader">
|
|
<h3>서버 자료 / 설정</h3>
|
|
</div>
|
|
<div class="fieldGrid">
|
|
<label class="fieldBlock fieldBlockFull">
|
|
<span>버킷 JAR 경로 또는 URL</span>
|
|
<div class="uploadField">
|
|
<input id="field-serverJarUrl" type="text" autocomplete="off">
|
|
<button type="button" class="secondaryAction uploadButton" data-upload-target="serverJarUrl" data-upload-accept=".jar,application/java-archive">JAR 업로드</button>
|
|
</div>
|
|
</label>
|
|
<label class="fieldBlock">
|
|
<span>서버 포트</span>
|
|
<input id="field-serverPort" type="number" min="1" max="65535" step="1">
|
|
</label>
|
|
<label class="fieldBlock">
|
|
<span>서버 메모리 (MB)</span>
|
|
<input id="field-serverMemoryMb" type="number" min="512" step="256">
|
|
</label>
|
|
<label class="fieldBlock">
|
|
<span>최대 인원수</span>
|
|
<input id="field-serverMaxPlayers" type="number" min="1" max="200" step="1">
|
|
</label>
|
|
<label class="toggleBlock">
|
|
<input id="field-serverWhitelistEnabled" type="checkbox">
|
|
<span>화이트리스트 사용</span>
|
|
</label>
|
|
<div class="fieldHelpText fieldBlockFull">
|
|
직접 실행 시 런처가 `eula.txt`, `server.properties`를 자동으로 만들고 업로드한 버킷 JAR을 실행합니다.
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="fieldSection helperSection">
|
|
<div class="sectionHeader">
|
|
<h3>운영 메모</h3>
|
|
</div>
|
|
<p>업로드 버튼은 현재 프로젝트 기준 상대 경로를 자동으로 채웁니다. 접속주소는 관리자 사이트가 아니라, 사용자가 라이브러리에서 직접 넣는 구조입니다.</p>
|
|
</section>
|
|
</form>
|
|
</main>
|
|
</div>
|
|
|
|
<div id="distributionEditorModal" class="modalBackdrop" hidden>
|
|
<div class="modalPanel">
|
|
<div class="modalHeader">
|
|
<div>
|
|
<span class="eyebrow">Distribution Editor</span>
|
|
<h3>distribution.json 편집</h3>
|
|
<p id="distributionEditorHint">프로필에 연결할 distribution.json 내용을 사이트 안에서 직접 관리합니다.</p>
|
|
</div>
|
|
<button type="button" id="closeDistributionEditorButton" class="secondaryAction">닫기</button>
|
|
</div>
|
|
<textarea id="distributionEditorTextarea" class="distributionTextarea" spellcheck="false"></textarea>
|
|
<div class="modalActions">
|
|
<button type="button" id="loadDistributionTemplateButton" class="secondaryAction">샘플 불러오기</button>
|
|
<button type="button" id="saveDistributionFileButton" class="primaryAction">distribution 저장</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="./app.js"></script>
|
|
</body>
|
|
</html>
|