feat(dashboard): rework paperless review actions
This commit is contained in:
@@ -333,13 +333,15 @@ def paperless_review_section()->str:
|
||||
state=load_paperless_state()
|
||||
if not items: return collapsible_section('📄 Paperless Review','No documents waiting.','<p class="empty">No documents waiting.</p>','paperless-review',open_by_default=False,extra_class='panel')
|
||||
urgency_class={'high':'warn','medium':'info','low':'ok','none':'ok'}
|
||||
active=[]; acknowledged=[]
|
||||
active=[]; needs_attention=[]
|
||||
for item in items:
|
||||
status=((state.get(str(item.get('id'))) or {}).get('status') or '').lower()
|
||||
if status=='dismissed':
|
||||
if status in {'dismissed','good_to_go'}:
|
||||
continue
|
||||
(acknowledged if status=='acknowledged' else active).append(item)
|
||||
def render_card(item:dict[str,Any], acknowledged_card:bool=False)->str:
|
||||
if status=='acknowledged':
|
||||
status='needs_attention'
|
||||
(needs_attention if status=='needs_attention' else active).append(item)
|
||||
def render_card(item:dict[str,Any], needs_attention_card:bool=False)->str:
|
||||
triage=item.get('triage',{}) or {}
|
||||
current=item.get('current',{}) or {}
|
||||
urgency=triage.get('urgency','none')
|
||||
@@ -347,9 +349,11 @@ def paperless_review_section()->str:
|
||||
reason=strip_markup(triage.get('reason',''))
|
||||
meta_parts=[x for x in [triage.get('document_type',''), current.get('correspondent','')] if x]
|
||||
meta=' • '.join(str(x) for x in meta_parts)
|
||||
status_class=' acknowledged' if acknowledged_card else ''
|
||||
status_class=' needs-attention' if needs_attention_card else ''
|
||||
primary_label='Clear flag' if needs_attention_card else 'Needs attention'
|
||||
primary_action='needs_attention'
|
||||
return f"""<article class='paperless-card {urgency_class.get(urgency,'ok')}{status_class}' data-paperless-id='{esc(item.get('id'))}'>
|
||||
<div class='paperless-head'><div class='meta'><span class='urgency {urgency_class.get(urgency,'ok')}' data-urgency='{esc(urgency)}'>{esc(str(urgency).upper())}</span><span>{esc(item.get('original_filename') or 'Document #'+str(item.get('id','')))}</span></div><div class='paperless-actions'><button type='button' class='paperless-btn' data-paperless-action='acknowledge'>{'Unack' if acknowledged_card else 'Acknowledge'}</button><button type='button' class='paperless-btn danger' data-paperless-action='dismiss'>Dismiss</button>{f"<a href='{esc(item.get('archive_url',''))}' class='link' target='_blank' rel='noreferrer'>View in Paperless</a>" if item.get('archive_url') else ''}</div></div>
|
||||
<div class='paperless-head'><div class='meta'><span class='urgency {urgency_class.get(urgency,'ok')}' data-urgency='{esc(urgency)}'>{esc(str(urgency).upper())}</span><span>{esc(item.get('original_filename') or 'Document #'+str(item.get('id','')))}</span></div><div class='paperless-actions'><button type='button' class='paperless-btn' data-paperless-action='{primary_action}'>{primary_label}</button><button type='button' class='paperless-btn good' data-paperless-action='good_to_go'>Good to go</button>{f"<a href='{esc(item.get('archive_url',''))}' class='link' target='_blank' rel='noreferrer'>View in Paperless</a>" if item.get('archive_url') else ''}</div></div>
|
||||
<h4>{esc(item.get('title') or triage.get('suggested_title','Untitled'))}</h4>
|
||||
{f"<p class='summary'>{esc(summary)}</p>" if summary else ''}
|
||||
{f"<p class='paperless-meta'>{esc(meta)}</p>" if meta else ''}
|
||||
@@ -358,17 +362,17 @@ def paperless_review_section()->str:
|
||||
visible_active=active[:3]
|
||||
overflow_active=active[3:]
|
||||
active_cards=''.join(render_card(item,False) for item in visible_active)
|
||||
acked_cards=''.join(render_card(item,True) for item in acknowledged[:8])
|
||||
flagged_cards=''.join(render_card(item,True) for item in needs_attention[:8])
|
||||
count=len(active)
|
||||
ack_count=len(acknowledged)
|
||||
flag_count=len(needs_attention)
|
||||
body=f"<div class='paperless-grid'>{active_cards or '<p class=\'empty\'>No active documents waiting.</p>'}</div>"
|
||||
if overflow_active:
|
||||
body += f"<details class='paperless-more'><summary>Show {esc(str(len(overflow_active)))} more active items</summary><div class='paperless-grid overflow-grid'>{''.join(render_card(item,False) for item in overflow_active[:8])}</div></details>"
|
||||
if ack_count:
|
||||
body += f"<details class='paperless-acked'><summary>Acknowledged <span class='badge'>{esc(str(ack_count))}</span></summary><div class='paperless-grid acked-grid'>{acked_cards}</div></details>"
|
||||
if count+ack_count>3:
|
||||
if flag_count:
|
||||
body += f"<details class='paperless-acked' open><summary>Needs attention <span class='badge'>{esc(str(flag_count))}</span></summary><div class='paperless-grid acked-grid'>{flagged_cards}</div><p class='empty'>Flagged items stay here so I can revisit them later and, if needed, ask you about the issue.</p></details>"
|
||||
if count+flag_count>3:
|
||||
body += f"<p class='empty'>Showing {esc(str(min(count,3)))} active up front and keeping the rest tucked away to cut page bloat.</p>"
|
||||
return collapsible_section(f'📄 Paperless Review ({count} active)',f'{ack_count} acknowledged · review queue written by n8n paperless-intake-triage workflow.',body,'paperless-review',open_by_default=count>0,extra_class='panel')
|
||||
return collapsible_section(f'📄 Paperless Review ({count} active)',f'{flag_count} flagged for follow-up · review queue written by n8n paperless-intake-triage workflow.',body,'paperless-review',open_by_default=(count+flag_count)>0,extra_class='panel')
|
||||
|
||||
def list_panel(title:str,items:list[dict[str,Any]],empty:str)->str:
|
||||
if not items:
|
||||
@@ -499,11 +503,7 @@ def feedback_bootstrap()->str:
|
||||
const action=btn.dataset.paperlessAction;
|
||||
btn.disabled=true;
|
||||
postJson('/api/paperless-action',{id,action}).then(()=>{
|
||||
if(action==='dismiss'){
|
||||
card.remove();
|
||||
} else {
|
||||
card.classList.toggle('acknowledged');
|
||||
}
|
||||
window.location.reload();
|
||||
}).catch(err=>{console.warn('paperless action failed',err); btn.disabled=false;});
|
||||
});
|
||||
const reset=document.querySelector('[data-reset-topic-prefs]');
|
||||
|
||||
Reference in New Issue
Block a user