Fix Cora filter, speed up Overview, add inbox path link
Remove status gate from Cora filter — LB Method is the discriminator, not status. Derive Overview stats and Cora section from /tasks data directly (no slow /tasks/link-building fetch). Add click-to-copy Z:\cora-inbox path next to Cora header. Show due dates in This Month. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>cora-start
parent
f67f1b9124
commit
01ba657b35
|
|
@ -184,11 +184,17 @@ async def get_link_building_tasks():
|
||||||
|
|
||||||
# -- Build focused groups --
|
# -- Build focused groups --
|
||||||
|
|
||||||
# need_cora: status "to do" AND LB Method = "Cora Backlinks"
|
# Split active vs closed
|
||||||
need_cora = [
|
closed_statuses = {"complete", "closed", "done"}
|
||||||
|
active_lb = [
|
||||||
t for t in lb_tasks
|
t for t in lb_tasks
|
||||||
if t["status"] == "to do"
|
if not any(kw in t["status"] for kw in closed_statuses)
|
||||||
and t["custom_fields"].get("LB Method") == "Cora Backlinks"
|
]
|
||||||
|
|
||||||
|
# need_cora: open LB tasks where LB Method = "Cora Backlinks"
|
||||||
|
need_cora = [
|
||||||
|
t for t in active_lb
|
||||||
|
if t["custom_fields"].get("LB Method") == "Cora Backlinks"
|
||||||
]
|
]
|
||||||
|
|
||||||
# recently_completed: closed/complete tasks with date_done in last 7 days
|
# recently_completed: closed/complete tasks with date_done in last 7 days
|
||||||
|
|
@ -215,13 +221,6 @@ async def get_link_building_tasks():
|
||||||
kv = t.get("kv_state")
|
kv = t.get("kv_state")
|
||||||
if kv is None or kv.get("state", "") in early_states:
|
if kv is None or kv.get("state", "") in early_states:
|
||||||
in_progress_not_started.append(t)
|
in_progress_not_started.append(t)
|
||||||
|
|
||||||
# Group by company (exclude closed from the active list for the grid)
|
|
||||||
closed_statuses = {"complete", "closed", "done"}
|
|
||||||
active_lb = [
|
|
||||||
t for t in lb_tasks
|
|
||||||
if not any(kw in t["status"] for kw in closed_statuses)
|
|
||||||
]
|
|
||||||
by_company: dict[str, list] = {}
|
by_company: dict[str, list] = {}
|
||||||
for task in active_lb:
|
for task in active_lb:
|
||||||
company = task["custom_fields"].get("Customer") or "Unassigned"
|
company = task["custom_fields"].get("Customer") or "Unassigned"
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,7 @@
|
||||||
<div class="section section--tight">
|
<div class="section section--tight">
|
||||||
<div class="section__header">
|
<div class="section__header">
|
||||||
<h2 class="section__title"><span class="icon">📋</span> Cora Reports Needed</h2>
|
<h2 class="section__title"><span class="icon">📋</span> Cora Reports Needed</h2>
|
||||||
|
<span onclick="navigator.clipboard.writeText('Z:\\cora-inbox');this.textContent='Copied!';setTimeout(()=>this.textContent='Z:\\cora-inbox',1500)" style="font-size:0.75rem;color:var(--gold-light);cursor:pointer;margin-left:0.5rem;" title="Click to copy path">Z:\cora-inbox</span>
|
||||||
<span class="section__badge"><a href="#" class="section__link" data-tab="linkbuilding">View LB</a></span>
|
<span class="section__badge"><a href="#" class="section__link" data-tab="linkbuilding">View LB</a></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="task-table-wrap task-table-wrap--compact" id="overview-cora">
|
<div class="task-table-wrap task-table-wrap--compact" id="overview-cora">
|
||||||
|
|
@ -350,39 +351,35 @@ function updateGreeting() {
|
||||||
// --- Overview Tab ---
|
// --- Overview Tab ---
|
||||||
|
|
||||||
async function loadOverview() {
|
async function loadOverview() {
|
||||||
const [tasks, lb, pr, agents, health] = await Promise.all([
|
const [tasks, agents, health] = await Promise.all([
|
||||||
fetchJSON('/tasks'),
|
fetchJSON('/tasks'),
|
||||||
fetchJSON('/tasks/link-building'),
|
|
||||||
fetchJSON('/tasks/press-releases'),
|
|
||||||
fetchJSON('/agents'),
|
fetchJSON('/agents'),
|
||||||
fetchJSON('/system/health'),
|
fetchJSON('/system/health'),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Cache for other tabs
|
// Cache for other tabs
|
||||||
_cache.tasks = tasks;
|
_cache.tasks = tasks;
|
||||||
_cache.lb = lb;
|
|
||||||
_cache.pr = pr;
|
|
||||||
_cache.agents = agents;
|
_cache.agents = agents;
|
||||||
_cache.health = health;
|
_cache.health = health;
|
||||||
|
|
||||||
// Stats
|
// Stats — derive LB/PR counts from tasks data
|
||||||
if (tasks) {
|
if (tasks && tasks.tasks) {
|
||||||
document.getElementById('stat-total').textContent = tasks.count || 0;
|
document.getElementById('stat-total').textContent = tasks.count || 0;
|
||||||
document.getElementById('stat-total-detail').textContent = `ClickUp tasks`;
|
document.getElementById('stat-total-detail').textContent = `ClickUp tasks`;
|
||||||
}
|
|
||||||
if (lb) {
|
const lbTasks = tasks.tasks.filter(t => t.task_type === 'Link Building');
|
||||||
document.getElementById('stat-lb').textContent = lb.total || 0;
|
const prTasks = tasks.tasks.filter(t => t.task_type === 'Press Release');
|
||||||
document.getElementById('stat-lb-detail').textContent =
|
|
||||||
`${lb.companies ? lb.companies.length : 0} companies`;
|
document.getElementById('stat-lb').textContent = lbTasks.length;
|
||||||
document.getElementById('badge-lb').textContent = lb.total || 0;
|
const lbCompanies = new Set(lbTasks.map(t => t.custom_fields?.Customer || 'Unassigned'));
|
||||||
}
|
document.getElementById('stat-lb-detail').textContent = `${lbCompanies.size} companies`;
|
||||||
if (pr) {
|
document.getElementById('badge-lb').textContent = lbTasks.length;
|
||||||
document.getElementById('stat-pr').textContent = pr.total || 0;
|
|
||||||
document.getElementById('stat-pr-detail').textContent =
|
document.getElementById('stat-pr').textContent = prTasks.length;
|
||||||
`${pr.companies ? pr.companies.length : 0} companies`;
|
const prCompanies = new Set(prTasks.map(t => t.custom_fields?.Customer || 'Unassigned'));
|
||||||
document.getElementById('badge-pr').textContent = pr.total || 0;
|
document.getElementById('stat-pr-detail').textContent = `${prCompanies.size} companies`;
|
||||||
}
|
document.getElementById('badge-pr').textContent = prTasks.length;
|
||||||
if (tasks && tasks.tasks) {
|
|
||||||
const companies = new Set(tasks.tasks.map(t => t.custom_fields?.Customer || 'Unassigned'));
|
const companies = new Set(tasks.tasks.map(t => t.custom_fields?.Customer || 'Unassigned'));
|
||||||
document.getElementById('stat-companies').textContent = companies.size;
|
document.getElementById('stat-companies').textContent = companies.size;
|
||||||
const names = [...companies].filter(c => c !== 'Unassigned').slice(0, 4).join(', ');
|
const names = [...companies].filter(c => c !== 'Unassigned').slice(0, 4).join(', ');
|
||||||
|
|
@ -443,12 +440,14 @@ async function loadOverview() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
document.getElementById('this-month-count').textContent = thisMonth.length;
|
document.getElementById('this-month-count').textContent = thisMonth.length;
|
||||||
renderOverviewTable('overview-this-month', thisMonth, false);
|
renderOverviewTable('overview-this-month', thisMonth, true);
|
||||||
}
|
|
||||||
|
|
||||||
// -- Cora Reports Needed --
|
// -- Cora Reports Needed: LB tasks with LB Method = Cora Backlinks --
|
||||||
if (lb && lb.need_cora) {
|
const needCora = openTasks.filter(t =>
|
||||||
renderOverviewTable('overview-cora', lb.need_cora, false);
|
t.task_type === 'Link Building'
|
||||||
|
&& t.custom_fields?.['LB Method'] === 'Cora Backlinks'
|
||||||
|
);
|
||||||
|
renderOverviewTable('overview-cora', needCora, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Health inline
|
// Health inline
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue