Add Cora Reports to Run queue as first section on Link Building tab
Filters out automation-touched tasks (error, automation underway, complete, closed, done, internal review) and sorts by due date. Renders with 10-at-a-time pagination and responsive mobile layout. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>cora-start
parent
3f2798d338
commit
ee7b4cc256
|
|
@ -192,10 +192,17 @@ async def get_link_building_tasks():
|
||||||
]
|
]
|
||||||
|
|
||||||
# need_cora: open LB tasks where LB Method = "Cora Backlinks"
|
# need_cora: open LB tasks where LB Method = "Cora Backlinks"
|
||||||
|
# Exclude tasks that automation already touched
|
||||||
|
automation_touched = {
|
||||||
|
"error", "automation underway", "complete",
|
||||||
|
"closed", "done", "internal review",
|
||||||
|
}
|
||||||
need_cora = [
|
need_cora = [
|
||||||
t for t in active_lb
|
t for t in active_lb
|
||||||
if t["custom_fields"].get("LB Method") == "Cora Backlinks"
|
if t["custom_fields"].get("LB Method") == "Cora Backlinks"
|
||||||
|
and t["status"] not in automation_touched
|
||||||
]
|
]
|
||||||
|
need_cora.sort(key=lambda t: int(t.get("due_date") or "9999999999999"))
|
||||||
|
|
||||||
# recently_completed: closed/complete tasks with date_done in last 7 days
|
# recently_completed: closed/complete tasks with date_done in last 7 days
|
||||||
seven_days_ago_ms = (time.time() - 7 * 86400) * 1000
|
seven_days_ago_ms = (time.time() - 7 * 86400) * 1000
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,17 @@
|
||||||
|
|
||||||
<div class="stats-row" id="lb-stats"></div>
|
<div class="stats-row" id="lb-stats"></div>
|
||||||
|
|
||||||
|
<!-- Cora Reports to Run -->
|
||||||
|
<div class="section">
|
||||||
|
<div class="section__header">
|
||||||
|
<h2 class="section__title"><span class="icon">📋</span> Cora Reports to Run</h2>
|
||||||
|
<span class="section__badge" id="lb-cora-count">-</span>
|
||||||
|
</div>
|
||||||
|
<div class="task-table-wrap" id="lb-cora-table">
|
||||||
|
<p style="padding:1rem;color:var(--text-muted);">Loading...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Recently Completed (Past 7 Days) -->
|
<!-- Recently Completed (Past 7 Days) -->
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<div class="section__header">
|
<div class="section__header">
|
||||||
|
|
@ -523,6 +534,69 @@ function renderRecentTable(containerId, tasks) {
|
||||||
container.innerHTML = html;
|
container.innerHTML = html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderCoraQueue(containerId, tasks) {
|
||||||
|
const container = document.getElementById(containerId);
|
||||||
|
if (!tasks || tasks.length === 0) {
|
||||||
|
container.innerHTML = '<p style="padding:1rem;color:var(--text-muted);">No Cora reports queued.</p>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PAGE_SIZE = 10;
|
||||||
|
let showAll = false;
|
||||||
|
|
||||||
|
function render() {
|
||||||
|
const visible = showAll ? tasks : tasks.slice(0, PAGE_SIZE);
|
||||||
|
let html = `<table class="task-table task-table--dense">
|
||||||
|
<thead><tr>
|
||||||
|
<th class="cora-hide-mobile">#</th>
|
||||||
|
<th class="cora-hide-mobile">Task</th>
|
||||||
|
<th>Keyword</th>
|
||||||
|
<th>Company</th>
|
||||||
|
<th class="cora-hide-mobile">Due Date</th>
|
||||||
|
</tr></thead><tbody>`;
|
||||||
|
|
||||||
|
visible.forEach((t, i) => {
|
||||||
|
const company = t.custom_fields?.Customer || 'Unassigned';
|
||||||
|
const keyword = t.custom_fields?.Keyword || '';
|
||||||
|
const link = t.url ? `<a href="${esc(t.url)}" target="_blank" style="color:var(--cream-light);text-decoration:none;">${esc(t.name)}</a>` : esc(t.name);
|
||||||
|
let dueStr = '-';
|
||||||
|
if (t.due_date) {
|
||||||
|
const d = new Date(parseInt(t.due_date, 10));
|
||||||
|
dueStr = d.toLocaleDateString('en-US', {month:'short', day:'numeric'});
|
||||||
|
}
|
||||||
|
html += `<tr>
|
||||||
|
<td class="task-table__num cora-hide-mobile">${i + 1}</td>
|
||||||
|
<td class="task-table__title cora-hide-mobile">${link}</td>
|
||||||
|
<td class="task-table__keyword">${esc(keyword)}</td>
|
||||||
|
<td class="task-table__company">${esc(company)}</td>
|
||||||
|
<td class="cora-hide-mobile" style="white-space:nowrap;">${esc(dueStr)}</td>
|
||||||
|
</tr>`;
|
||||||
|
});
|
||||||
|
|
||||||
|
html += '</tbody></table>';
|
||||||
|
|
||||||
|
if (tasks.length > PAGE_SIZE) {
|
||||||
|
const remaining = tasks.length - PAGE_SIZE;
|
||||||
|
const label = showAll ? 'Show less' : `Show more (${remaining} remaining)`;
|
||||||
|
html += `<div style="text-align:center;padding:0.75rem;">
|
||||||
|
<button id="cora-toggle-btn" style="background:none;border:1px solid var(--border);color:var(--gold-light);padding:0.4rem 1.2rem;border-radius:var(--radius);cursor:pointer;font-size:0.8rem;">${label}</button>
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
container.innerHTML = html;
|
||||||
|
|
||||||
|
const btn = document.getElementById('cora-toggle-btn');
|
||||||
|
if (btn) {
|
||||||
|
btn.addEventListener('click', () => {
|
||||||
|
showAll = !showAll;
|
||||||
|
render();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render();
|
||||||
|
}
|
||||||
|
|
||||||
function renderOverviewTable(containerId, tasks, showDueDate) {
|
function renderOverviewTable(containerId, tasks, showDueDate) {
|
||||||
const container = document.getElementById(containerId);
|
const container = document.getElementById(containerId);
|
||||||
if (!tasks || tasks.length === 0) {
|
if (!tasks || tasks.length === 0) {
|
||||||
|
|
@ -644,6 +718,11 @@ async function loadLinkBuilding() {
|
||||||
`;
|
`;
|
||||||
document.getElementById('lb-stats').innerHTML = statsHtml;
|
document.getElementById('lb-stats').innerHTML = statsHtml;
|
||||||
|
|
||||||
|
// Cora Reports to Run
|
||||||
|
const coraQueue = data.need_cora || [];
|
||||||
|
document.getElementById('lb-cora-count').textContent = coraQueue.length;
|
||||||
|
renderCoraQueue('lb-cora-table', coraQueue);
|
||||||
|
|
||||||
// Recently Completed
|
// Recently Completed
|
||||||
const recent = data.recently_completed || [];
|
const recent = data.recently_completed || [];
|
||||||
document.getElementById('lb-recent-count').textContent = recent.length;
|
document.getElementById('lb-recent-count').textContent = recent.length;
|
||||||
|
|
|
||||||
|
|
@ -1014,6 +1014,10 @@ body {
|
||||||
min-width: 700px;
|
min-width: 700px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cora-hide-mobile {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.page-header__greeting {
|
.page-header__greeting {
|
||||||
font-size: 1.35rem;
|
font-size: 1.35rem;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue