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:
@@ -312,3 +312,90 @@ body.siteBody.centerLayout { display: flex; align-items: center; justify-content
|
||||
}
|
||||
.adminFolder { position: relative; }
|
||||
.adminVideo { position: relative; }
|
||||
|
||||
/* ─── 플레이리스트 import ────────────────────────────────────────────── */
|
||||
|
||||
.playlistProbeSection {
|
||||
background: var(--bg-card); border: 1px solid var(--border);
|
||||
border-radius: 12px; padding: 18px 20px;
|
||||
}
|
||||
.playlistProbeRow {
|
||||
display: flex; gap: 10px; margin-top: 10px; flex-wrap: wrap;
|
||||
}
|
||||
.playlistProbeRow input[type="text"] {
|
||||
flex: 1; min-width: 320px;
|
||||
background: var(--bg); border: 1px solid var(--border); border-radius: 8px;
|
||||
color: var(--text); padding: 8px 12px; font-size: 14px;
|
||||
}
|
||||
|
||||
.playlistEntriesSection {
|
||||
margin-top: 18px;
|
||||
display: flex; flex-direction: column; gap: 14px;
|
||||
}
|
||||
|
||||
.playlistControlsRow {
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
flex-wrap: wrap; gap: 12px;
|
||||
}
|
||||
.idModeBox {
|
||||
display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
|
||||
background: var(--bg-card); border: 1px solid var(--border);
|
||||
border-radius: 10px; padding: 10px 14px;
|
||||
}
|
||||
.idModeLabel { color: var(--text-muted); font-size: 13px; }
|
||||
.idModeBox label { color: var(--text); font-size: 14px; cursor: pointer; }
|
||||
.zeroPadWrap { margin-left: 8px; color: var(--text-muted) !important; font-size: 13px; }
|
||||
.playlistSummary { color: var(--text-muted); font-size: 13px; }
|
||||
|
||||
.playlistEntryList {
|
||||
list-style: none; margin: 0; padding: 0;
|
||||
display: flex; flex-direction: column; gap: 6px;
|
||||
}
|
||||
.playlistEntryRow {
|
||||
display: grid;
|
||||
grid-template-columns: 26px 36px 1fr 70px 28px;
|
||||
align-items: center; gap: 10px;
|
||||
background: var(--bg-card); border: 1px solid var(--border);
|
||||
border-radius: 10px; padding: 8px 10px;
|
||||
}
|
||||
.playlistEntryRow.dragGhost { opacity: 0.5; }
|
||||
.dragHandle {
|
||||
cursor: grab; color: var(--text-muted); font-size: 18px;
|
||||
user-select: none; text-align: center;
|
||||
}
|
||||
.entryNum {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||||
color: var(--text-muted); font-size: 13px; text-align: right;
|
||||
}
|
||||
.entryFields {
|
||||
display: flex; flex-direction: column; gap: 4px; min-width: 0;
|
||||
}
|
||||
.entryTitleInput {
|
||||
background: var(--bg); border: 1px solid var(--border); border-radius: 6px;
|
||||
color: var(--text); padding: 5px 8px; font-size: 14px; width: 100%;
|
||||
}
|
||||
.entryIdRow {
|
||||
display: flex; align-items: center; gap: 8px;
|
||||
}
|
||||
.entryIdInput {
|
||||
background: var(--bg); border: 1px solid var(--border); border-radius: 6px;
|
||||
color: var(--text); padding: 4px 8px; font-size: 13px;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||||
width: 240px; max-width: 100%;
|
||||
}
|
||||
.entryIdStatus { font-size: 12px; }
|
||||
.entryDuration {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||||
font-size: 12px; text-align: right;
|
||||
}
|
||||
.entryRemove {
|
||||
background: transparent; border: 1px solid var(--border);
|
||||
color: var(--text-muted); border-radius: 6px; cursor: pointer;
|
||||
width: 28px; height: 28px; padding: 0; font-size: 14px;
|
||||
}
|
||||
.entryRemove:hover { color: #e57373; border-color: #e57373; }
|
||||
|
||||
.playlistFooter {
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
gap: 12px; flex-wrap: wrap; margin-top: 8px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user