Newer
Older
medialib-manager / templates / audio-tracks.html
{% include "partials/head.html" %}

<div class="container mt-4">
    <h1 class="mb-4">// audio tracks</h1>

    <div class="card">
        <div class="card-header">
            <h2 class="h5 mb-0">// extracted tracks</h2>
        </div>
        <div class="card-body p-0">
            <div class="audio-tracks-empty text-muted text-center py-4" style="display:none">no extracted tracks yet</div>
            <table class="table mb-0 audio-tracks-table" style="display:none">
                <thead>
                    <tr>
                        <th>file</th>
                        <th>lang</th>
                        <th>codec</th>
                        <th>bitrate</th>
                        <th>channels</th>
                        <th>title</th>
                        <th>created</th>
                        <th></th>
                    </tr>
                </thead>
                <tbody></tbody>
            </table>
        </div>
    </div>
</div>

<!-- Delete confirmation modal -->
<div class="modal fade" id="confirm-delete-track" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog modal-dialog-centered">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title h6 mb-0">// delete audio track</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
            </div>
            <div class="modal-body">
                <p class="mb-1">Delete <strong id="confirm-delete-filename"></strong>?</p>
                <small class="text-muted">The file will be permanently removed from disk.</small>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-outline-secondary btn-sm" data-bs-dismiss="modal">cancel</button>
                <button type="button" class="btn btn-danger btn-sm" id="confirm-delete-btn">
                    <span class="spinner-border spinner-border-sm" style="display:none"></span>
                    delete
                </button>
            </div>
        </div>
    </div>
</div>

<script>
function loadAudioTracks() {
    $.getJSON("/audio/tracks", function(tracks) {
        const empty = $(".audio-tracks-empty");
        const table = $(".audio-tracks-table");
        const tbody = table.find("tbody");

        tbody.empty();
        if (!tracks.length) {
            empty.show(); table.hide();
            return;
        }

        empty.hide(); table.show();
        tracks.forEach(t => {
            const date = t.created_at
                ? new Date(t.created_at + "Z").toLocaleString()
                : "—";
            const filename = t.path.split("/").at(-1);
            tbody.append(`
                <tr data-id="${t.id}">
                    <td><a href="/single?path=${encodeURIComponent(t.source_path)}">${t.source_name}</a></td>
                    <td>${t.language || "—"}</td>
                    <td>${t.codec || "—"}</td>
                    <td>${t.bitrate || "—"}</td>
                    <td>${t.channels || "—"}</td>
                    <td>${t.title || "—"}</td>
                    <td><small class="text-muted">${date}</small></td>
                    <td>
                        <button class="btn btn-outline-secondary btn-sm btn-delete-track" data-id="${t.id}">
                            <span class="spinner-border spinner-border-sm" style="display:none"></span>
                            <i class="bi bi-trash"></i>
                        </button>
                    </td>
                </tr>
            `);
        });
    });
}

$(document).ready(function() {
    loadAudioTracks();

    let pendingDeleteId = null;
    const deleteModal = new bootstrap.Modal(document.getElementById("confirm-delete-track"));

    $(document).on("click", ".btn-delete-track", function() {
        const row = $(this).closest("tr");
        const filename = row.find("td:first a").text() || "this track";
        pendingDeleteId = $(this).data("id");
        $("#confirm-delete-filename").text(filename);
        deleteModal.show();
    });

    $("#confirm-delete-btn").on("click", function() {
        if (!pendingDeleteId) return;
        const id = pendingDeleteId;
        const confirmBtn = $(this);
        confirmBtn.prop("disabled", true).find(".spinner-border").show();

        $.ajax({
            url: `/audio/tracks/${id}`,
            method: "DELETE",
            success: function() {
                deleteModal.hide();
                confirmBtn.prop("disabled", false).find(".spinner-border").hide();
                pendingDeleteId = null;
                loadAudioTracks();
            },
            error: function(xhr) {
                confirmBtn.prop("disabled", false).find(".spinner-border").hide();
                deleteModal.hide();
                pendingDeleteId = null;
                pushErrMsg("Delete failed: " + (xhr.responseJSON?.error || "unknown error"));
            }
        });
    });

    document.getElementById("confirm-delete-track").addEventListener("hidden.bs.modal", function() {
        pendingDeleteId = null;
        $("#confirm-delete-btn").prop("disabled", false).find(".spinner-border").hide();
    });
});
</script>

{% include "partials/footer.html" %}