feat(playlist): import UI with drag reorder + random/sequential ID toggle (STEP 5)

Adds /op/folder/:top/:sub/playlist/new page that lets the operator paste a
YouTube playlist URL, probe entries via yt-dlp, reorder them by drag, edit
title/ID per row, and choose between random IDs or zero-padded sequential
IDs before registering all jobs in one batch.
This commit is contained in:
Claude (owner)
2026-06-01 00:15:39 +09:00
parent 36c9899040
commit 31c754a3ad
4 changed files with 610 additions and 0 deletions

64
views/op/playlist.ejs Normal file
View File

@@ -0,0 +1,64 @@
<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>플레이리스트 추가 · <%= breadcrumb.join(' / ') %></title>
<link rel="stylesheet" href="/static/styles.css" />
</head>
<body class="siteBody">
<%
var folderPathEnc = breadcrumb.map(function (s) { return encodeURIComponent(s) }).join('/')
var folderHref = '/op/folder/' + folderPathEnc
var folderLabel = breadcrumb.join(' / ')
%>
<header class="editorNav">
<div class="editorNavLeft">
<a class="muted" href="<%= folderHref %>">← <%= folderLabel %></a>
<span class="titleInput" style="cursor:default;">플레이리스트 추가</span>
</div>
</header>
<main class="editorMain">
<section class="playlistProbeSection">
<p class="muted">유튜브 플레이리스트 주소를 입력하면 항목 목록을 불러옵니다.</p>
<div class="playlistProbeRow">
<input type="text" id="playlistUrl" placeholder="https://www.youtube.com/playlist?list=..." />
<button type="button" class="primaryButton" id="probeBtn">목록 불러오기</button>
</div>
<p id="probeStatus" class="muted"></p>
</section>
<section class="playlistEntriesSection" id="entriesSection" hidden>
<div class="playlistControlsRow">
<div class="idModeBox">
<span class="idModeLabel">영상 ID 생성 방식</span>
<label><input type="radio" name="idMode" value="random" checked /> 랜덤</label>
<label><input type="radio" name="idMode" value="sequential" /> 정렬된 번호</label>
<label class="zeroPadWrap" id="zeroPadWrap" hidden>
<input type="checkbox" id="zeroPadToggle" /> 자릿수 채우기 (예: 001)
</label>
</div>
<div class="playlistSummary">
<span id="entriesCount" class="muted">0 항목</span>
</div>
</div>
<ol class="playlistEntryList" id="entryList"></ol>
<div class="playlistFooter">
<p id="registerStatus" class="muted"></p>
<button type="button" class="primaryButton" id="registerBtn">등록 &amp; 다운로드 시작</button>
</div>
</section>
</main>
<script>
window.__PLAYLIST__ = {
folderPath: <%- jsonForScript(breadcrumb) %>,
folderId: <%- jsonForScript(folder.id) %>
}
</script>
<script src="/static/playlist.js"></script>
</body>
</html>