{% extends "base.html" %}{% block content %}
<script>
  let autoRefreshInterval;
  const protocol = "{{ protocol }}";
  const host = window.location.host;
  const prefix = "{{ prefix }}";
  const baseurl = protocol + "://" + host + prefix;

  function escapeHtml(s) {
    if (s == null) return '';
    return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
  }

  function showNotification(message) {
    var notification = document.createElement("div");
    notification.className = "notification";
    notification.textContent = message;
    document.body.appendChild(notification);
    setTimeout(function () { document.body.removeChild(notification); }, 3000);
  }

  function showErrorNotification(message) {
    var notification = document.createElement("div");
    notification.className = "error-notification";
    notification.textContent = message;
    document.body.appendChild(notification);
    setTimeout(function () { document.body.removeChild(notification); }, 3000);
  }

  function startAutorefresh() {
    clearInterval(autoRefreshInterval);
    autoRefreshInterval = setInterval(function () { if (window.autoRefreshEnabled) updateJobsData(); }, 5000);
  }

  function stopAutorefresh() {
    clearInterval(autoRefreshInterval);
  }

  let page = 1;

  function nextPage() {
    page += 1;
    updatePageNumber();
    updateJobsData();
  }

  function previousPage() {
    if (page > 1) {
      page -= 1;
      updatePageNumber();
      updateJobsData();
    }
  }

  function updatePageNumber() {
    document.getElementById("page-number").textContent = page;
  }

  function updateJobsData() {
    var selectedState = document.getElementById("state-filter").value;
    var selectedQueue = document.getElementById("queue-name-filter").value;
    fetch(baseurl + "/jobs/json?state=" + selectedState + "&queue_name=" + selectedQueue + "&page=" + page)
      .then(function (r) { return r.json(); })
      .then(function (data) { updateJobsTable(data); })
      .catch(function (error) {
        console.error("Error fetching jobs data: ", error);
        showErrorNotification("Error fetching jobs data");
      });
  }

  function updateJobsTable(data) {
    var tableBody = document.querySelector("#jobs tbody");
    tableBody.innerHTML = "";

    var states = ["scheduled", "queued", "started", "failed", "deferred", "finished"];
    data.forEach(function (queue) {
      states.forEach(function (state) {
        if (!queue[state]) return;
        queue[state].forEach(function (job) {
          var formattedDate = new Date(job.created_at).toLocaleString();
          var requeueBtn = state === "failed"
            ? '<button class="btn-requeue" data-requeue-id="' + job.id + '" title="Requeue"><svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M1 4v6h6M23 20v-6h-6"/><path stroke-linecap="round" stroke-linejoin="round" d="M20.49 9A9 9 0 005.64 5.64L1 10m22 4l-4.64 4.36A9 9 0 013.51 15"/></svg></button>'
            : '';
          var safeId = escapeHtml(job.id);
          var safeName = escapeHtml(job.name);
          tableBody.innerHTML +=
            '<tr class="tr-stripe">' +
            '<td class="td-cell"><a class="text-blue-700 dark:text-blue-400" href="' + baseurl + '/job/' + encodeURIComponent(job.id) + '">' + safeId + '</a></td>' +
            '<td class="td-cell"><span class="badge-' + state + '">' + state + '</span></td>' +
            '<td class="td-cell max-w-[200px] overflow-hidden text-ellipsis whitespace-nowrap">' + safeName + '</td>' +
            '<td class="td-cell">' + formattedDate + '</td>' +
            '<td class="td-cell"><div class="flex items-center gap-1"><button class="btn-delete" data-delete-id="' + safeId + '" title="Delete"><svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M3 6h18M8 6V4a2 2 0 012-2h4a2 2 0 012 2v2m3 0v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6h14"/></svg></button>' + requeueBtn + '</div></td>' +
            '</tr>';
        });
      });
    });

    tableBody.querySelectorAll('[data-delete-id]').forEach(function (btn) {
      btn.addEventListener('click', function () { deleteJob(this.getAttribute('data-delete-id')); });
    });
    tableBody.querySelectorAll('[data-requeue-id]').forEach(function (btn) {
      btn.addEventListener('click', function () { requeueJob(this.getAttribute('data-requeue-id')); });
    });
  }

  function deleteJob(job_id) {
    fetch(baseurl + "/job/" + job_id, { method: "DELETE" })
      .then(function (r) {
        if (!r.ok) { showErrorNotification("Error deleting job"); }
      })
      .catch(function (error) {
        console.error("Error deleting job: ", error);
        showErrorNotification("Error deleting job");
      });
  }

  function requeueJob(job_id) {
    fetch(baseurl + "/job/" + job_id + "/requeue", { method: "POST" })
      .then(function (r) {
        if (!r.ok) { showErrorNotification("Error requeueing job"); }
      })
      .catch(function (error) {
        console.error("Error requeueing job: ", error);
        showErrorNotification("Error requeueing job");
      });
  }

  document.addEventListener("DOMContentLoaded", function () {
    if (window.autoRefreshEnabled) { startAutorefresh(); }

    var urlParams = new URLSearchParams(window.location.search);
    var defaultState = urlParams.get("state") || "all";
    document.getElementById("state-filter").value = defaultState;
    var defaultQueue = urlParams.get("queue_name") || "all";
    document.getElementById("queue-name-filter").value = defaultQueue;

    document.getElementById("state-filter").addEventListener("change", function () { updateJobsData(); });
    document.getElementById("queue-name-filter").addEventListener("change", function () { updateJobsData(); });
    document.getElementById("btn-prev").addEventListener("click", previousPage);
    document.getElementById("btn-next").addEventListener("click", nextPage);

    var jobLinks = document.querySelectorAll("a[data-job-id]");
    jobLinks.forEach(function (link) {
      var jobId = link.getAttribute("data-job-id");
      link.href = baseurl + "/job/" + jobId;
    });

    updatePageNumber();
    updateJobsData();
  });

  document.addEventListener("autorefresh-changed", function (e) {
    if (e.detail.enabled) {
      startAutorefresh();
      showNotification("Autorefresh enabled");
    } else {
      stopAutorefresh();
      showNotification("Autorefresh disabled");
    }
  });
</script>

<div class="max-w-[90%] mx-auto mt-6 px-4">
  <p class="text-sm text-gray-600 dark:text-gray-400">
    This list contains all the jobs that are currently queued. Filter the search
    by job state and queue name. Each job can be deleted or requeued by clicking
    the corresponding button.
  </p>
  <table id="jobs" class="data-table">
    <thead>
      <tr>
        <th class="th-cell">ID</th>
        <th class="th-cell">
          <div class="flex flex-col gap-1">
            <span>Status</span>
            <select id="state-filter" class="text-xs font-normal normal-case tracking-normal px-1.5 py-1 rounded border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-200 cursor-pointer">
              <option value="all">All</option>
              <option value="scheduled">Scheduled</option>
              <option value="queued">Queued</option>
              <option value="started">Started</option>
              <option value="failed">Failed</option>
              <option value="deferred">Deferred</option>
              <option value="finished">Finished</option>
            </select>
          </div>
        </th>
        <th class="th-cell">
          <div class="flex flex-col gap-1">
            <span>Name</span>
            <select id="queue-name-filter" class="text-xs font-normal normal-case tracking-normal px-1.5 py-1 rounded border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-200 cursor-pointer">
              <option value="all">All queues</option>
              {% for queue in job_data %}
              <option value="{{ queue.queue_name }}">{{ queue.queue_name }}</option>
              {% endfor %}
            </select>
          </div>
        </th>
        <th class="th-cell">Created At</th>
        <th class="th-cell">Options</th>
      </tr>
    </thead>
    <tbody>
      {% for queue in job_data %} {% for state in ["queued", "started",
      "failed", "deferred", "scheduled", "finished"] %} {% for job in queue[state] %}
      <tr class="tr-stripe">
        <td class="td-cell">
          <a class="text-blue-700 dark:text-blue-400" href="#" data-job-id="{{ job.id }}">{{ job.id }}</a>
        </td>
        <td class="td-cell"><span class="badge-{{ state }}">{{ state }}</span></td>
        <td class="td-cell max-w-[200px] overflow-hidden text-ellipsis whitespace-nowrap">{{ job.name }}</td>
        <td class="td-cell">{{ job.created_at }}</td>
        <td class="td-cell">
          <div class="flex items-center gap-1">
            <button class="btn-delete" data-delete-ssr="{{ job.id }}" title="Delete">
              <svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M3 6h18M8 6V4a2 2 0 012-2h4a2 2 0 012 2v2m3 0v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6h14"/></svg>
            </button>
            {% if state == "failed" %}
            <button class="btn-requeue" data-requeue-ssr="{{ job.id }}" title="Requeue">
              <svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M1 4v6h6M23 20v-6h-6"/><path stroke-linecap="round" stroke-linejoin="round" d="M20.49 9A9 9 0 005.64 5.64L1 10m22 4l-4.64 4.36A9 9 0 013.51 15"/></svg>
            </button>
            {% endif %}
          </div>
        </td>
      </tr>
      {% endfor %} {% endfor %} {% endfor %}
    </tbody>
  </table>
  <div class="flex justify-center mt-2.5 gap-2 items-center">
    <button id="btn-prev" class="btn-pagination" title="Previous page">
      <svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M15 19l-7-7 7-7"/></svg>
    </button>
    <span class="text-sm text-gray-500 dark:text-gray-400"><span id="page-number">{{ page }}</span></span>
    <button id="btn-next" class="btn-pagination" title="Next page">
      <svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7"/></svg>
    </button>
  </div>
</div>

<script>
  document.addEventListener("DOMContentLoaded", function () {
    document.querySelectorAll("[data-delete-ssr]").forEach(function (btn) {
      btn.addEventListener("click", function () { deleteJob(this.getAttribute("data-delete-ssr")); });
    });
    document.querySelectorAll("[data-requeue-ssr]").forEach(function (btn) {
      btn.addEventListener("click", function () { requeueJob(this.getAttribute("data-requeue-ssr")); });
    });
  });
</script>
{% endblock %}
