177 lines
10 KiB
Handlebars
177 lines
10 KiB
Handlebars
<div class="page-header">
|
|
<div>
|
|
<h2>Edit playlist - {{playlist.name}}</h2>
|
|
<p>Adjust the playlist details, slide order, and scheduling.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row g-4 mb-4">
|
|
<div class="col-12 col-lg-8">
|
|
<div class="card card-outline card-primary mb-0">
|
|
<div class="card-header">
|
|
<h3 class="card-title">Playlist details</h3>
|
|
</div>
|
|
<div class="card-body">
|
|
<form id="playlist-edit-form" method="post" action="/playlists/{{playlist.id}}" data-async-save data-async-save-reload-on-success data-async-save-close-url="/playlists" data-async-save-new-url="/playlists/new">
|
|
<div class="row g-2 align-items-end">
|
|
<div class="col-12 col-lg-8">
|
|
<label for="playlist-name" class="form-label">Name</label>
|
|
<input id="playlist-name" name="name" class="form-control" value="{{playlist.name}}" required />
|
|
</div>
|
|
<div class="col-12 col-lg-4 d-flex align-items-lg-end justify-content-lg-start">
|
|
<div class="d-flex flex-column align-items-lg-start gap-1 w-100">
|
|
<label class="form-label d-none d-lg-block invisible">Add slide</label>
|
|
{{#if hasSlides}}
|
|
{{#if hasSelectableSlides}}
|
|
<button type="button" class="btn btn-primary w-100" id="playlist-open-slide-modal" data-bs-toggle="modal" data-bs-target="#playlist-add-slide-modal">Add slide</button>
|
|
{{else}}
|
|
<div class="text-body-secondary small text-lg-start">
|
|
{{#if playlistCanvasMismatch}}
|
|
Remove mismatched slides before adding more.
|
|
{{else if playlistCanvasSignature}}
|
|
No slides match this playlist canvas size.
|
|
{{else}}
|
|
No slides are currently available for this playlist.
|
|
{{/if}}
|
|
</div>
|
|
{{/if}}
|
|
{{else}}
|
|
<div class="text-body-secondary small text-lg-start">Create slides first.</div>
|
|
{{/if}}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="card-footer d-flex justify-content-end">
|
|
<div class="btn-group playlist-actions-group" role="group" aria-label="Playlist actions">
|
|
{{{saveActionButtons formId="playlist-edit-form" saveLabel="Save" saveAndCloseLabel="Save and Close" saveAndNewLabel="Save and New" saveAndCloseValue="close" saveAndNewValue="new"}}}
|
|
<a class="btn btn-warning" href="/playlists" data-confirm-unsaved="You have unsaved changes. Leave this page?">Cancel</a>
|
|
<button type="submit" class="btn btn-danger" form="delete-playlist-form">Delete</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-12 col-lg-4">
|
|
<div class="card card-outline card-light h-100 mb-0">
|
|
<div class="card-header">
|
|
<h4 class="card-title">Options</h4>
|
|
</div>
|
|
<div class="card-body py-3">
|
|
<div class="form-check form-switch mb-0">
|
|
<input class="form-check-input" type="checkbox" role="switch" id="playlist-fade-between-slides" name="fade_between_slides" value="1" form="playlist-edit-form" {{#if playlistFadeBetweenSlides}}checked{{/if}} />
|
|
<label class="form-check-label" for="playlist-fade-between-slides">Fade between slides</label>
|
|
</div>
|
|
<div class="form-check form-switch mt-3 mb-0">
|
|
<input class="form-check-input" type="checkbox" role="switch" id="playlist-skip-unavailable-rtmp" name="skip_unavailable_rtmp" value="1" form="playlist-edit-form" {{#if playlistSkipUnavailableRtmp}}checked{{/if}} />
|
|
<label class="form-check-label" for="playlist-skip-unavailable-rtmp">Skip RTMP slides when stream is unavailable</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row g-4 mb-4">
|
|
<div class="col-12">
|
|
<div class="card card-outline card-secondary mb-0">
|
|
<div class="card-header">
|
|
<h3 class="card-title">Playlist items</h3>
|
|
</div>
|
|
<div class="card-body table-responsive p-0">
|
|
<table class="table table-striped w-100 mb-0">
|
|
<thead><tr><th>Order</th><th>Slide</th><th>Schedule</th><th>Duration</th><th>Actions</th></tr></thead>
|
|
<tbody id="playlist-items-body" data-playlist-id="{{playlist.id}}">
|
|
{{#if playlistSlides.length}}
|
|
{{#each playlistSlides}}
|
|
<tr data-playlist-slide-row data-row-key="existing-{{id}}" data-slide-id="{{slide_id}}" data-canvas-signature="{{canvasSignature}}">
|
|
<td class="playlist-order-cell" data-label="Order">
|
|
<div class="playlist-order-cell-inner">
|
|
<button type="button" class="playlist-drag-handle btn btn-link p-0 text-body-secondary" data-playlist-drag-handle aria-label="Drag to reorder" title="Drag to reorder">
|
|
<span class="playlist-drag-handle-icon" aria-hidden="true">
|
|
<svg class="playlist-drag-handle-svg" viewBox="0 0 24 32" focusable="false" aria-hidden="true">
|
|
<polygon points="12,2 20,9 4,9"></polygon>
|
|
<rect x="4" y="14" width="16" height="4" rx="2"></rect>
|
|
<polygon points="4,23 20,23 12,30"></polygon>
|
|
</svg>
|
|
</span>
|
|
</button>
|
|
<span class="playlist-order-number">{{displayOrder}}</span>
|
|
</div>
|
|
</td>
|
|
<td data-label="Slide">
|
|
<div class="playlist-slide-cell">
|
|
<div class="playlist-slide-thumb" aria-hidden="true">
|
|
{{#if thumbnail_path}}
|
|
<img class="playlist-slide-thumb-image" src="{{thumbnail_path}}" alt="" loading="lazy" />
|
|
{{else}}
|
|
<span class="playlist-slide-thumb-placeholder"><i class="bi bi-image" aria-hidden="true"></i></span>
|
|
{{/if}}
|
|
</div>
|
|
<div class="playlist-slide-cell-content">
|
|
<span class="playlist-slide-title">{{title}}</span>
|
|
</div>
|
|
</div>
|
|
<input type="hidden" name="slide_id[]" value="{{slide_id}}" form="playlist-edit-form" />
|
|
</td>
|
|
<td data-label="Schedule">
|
|
<div class="playlist-schedule-summary">{{scheduleSummary}}</div>
|
|
<input type="hidden" name="schedule_mode[]" value="{{schedule_mode}}" form="playlist-edit-form" />
|
|
<input type="hidden" name="schedule_start_datetime[]" value="{{schedule_start_datetime}}" form="playlist-edit-form" />
|
|
<input type="hidden" name="schedule_end_datetime[]" value="{{schedule_end_datetime}}" form="playlist-edit-form" />
|
|
<input type="hidden" name="schedule_start_time[]" value="{{schedule_start_time}}" form="playlist-edit-form" />
|
|
<input type="hidden" name="schedule_end_time[]" value="{{schedule_end_time}}" form="playlist-edit-form" />
|
|
<input type="hidden" name="schedule_days_json[]" value="{{schedule_days_json}}" form="playlist-edit-form" />
|
|
</td>
|
|
<td data-label="Duration">
|
|
<input name="duration_seconds[]" type="number" min="1" value="{{duration_seconds}}" required form="playlist-edit-form" class="form-control form-control-sm playlist-duration-input text-end" />
|
|
</td>
|
|
<td data-label="Actions">
|
|
<div class="actions playlist-item-actions">
|
|
<button type="button" class="btn btn-sm btn-primary" data-schedule-config="/playlists/{{../playlist.id}}/slides/{{id}}/config" data-schedule-config-row="existing-{{id}}">Schedule</button>
|
|
<button type="button" class="btn btn-sm btn-danger" data-playlist-remove-row>Remove</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
{{/each}}
|
|
{{else}}
|
|
<tr class="playlist-empty-row"><td colspan="5" class="empty">No slides assigned yet.</td></tr>
|
|
{{/if}}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script type="application/json" id="playlist-add-slide-data">{{json selectableSlides}}</script>
|
|
|
|
{{#> modal-shell modalId="playlist-add-slide-modal" modalLabelId="playlist-add-slide-modal-label" modalDialogClass="modal-dialog-centered modal-dialog-scrollable modal-xl" modalBackdropStatic=true modalKeyboardDisabled=true}}
|
|
<div class="modal-header">
|
|
<div>
|
|
<h2 class="modal-title fs-5" id="playlist-add-slide-modal-label">Add slides to playlist</h2>
|
|
</div>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body playlist-slide-picker-modal-body">
|
|
<div class="playlist-slide-picker-toolbar">
|
|
<label class="form-label mb-1" for="playlist-slide-picker-search">Search</label>
|
|
<div class="input-group">
|
|
<span class="input-group-text" aria-hidden="true"><i class="bi bi-search"></i></span>
|
|
<input type="search" class="form-control" id="playlist-slide-picker-search" placeholder="Search slide titles" autocomplete="off" />
|
|
</div>
|
|
</div>
|
|
<div class="playlist-slide-picker-empty empty is-hidden" id="playlist-slide-picker-empty">No slides match your search.</div>
|
|
<div class="playlist-slide-picker-grid" id="playlist-slide-picker-grid" aria-live="polite"></div>
|
|
</div>
|
|
<div class="modal-footer justify-content-end">
|
|
<div class="d-flex flex-wrap align-items-center justify-content-end gap-2 w-100">
|
|
<div class="text-body-secondary small text-end" id="playlist-slide-picker-selected-count-wrap"><span id="playlist-slide-picker-selected-count">0</span> selected</div>
|
|
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancel</button>
|
|
<button type="button" class="btn btn-primary" id="playlist-confirm-add-slides" disabled>Add selected slides</button>
|
|
</div>
|
|
</div>
|
|
{{/modal-shell}}
|
|
|
|
<form id="delete-playlist-form" method="post" action="/playlists/{{playlist.id}}/delete" data-confirm-message="Delete this playlist?"></form>
|
|
|