Refine Doris dashboard story dedupe
This commit is contained in:
@@ -1534,10 +1534,11 @@ def focus_card(title:str,kicker:str,headline:str,body:str,tone:str='',href:str='
|
||||
return f"<a class='focus-card-link' href='{esc(href)}'{target_attr}>{card_html}</a>"
|
||||
|
||||
|
||||
def build_focus_cards(local_items:list[dict[str,Any]], todos:list[dict[str,Any]], pulse:list[dict[str,str]], paperless:dict[str,Any], hermes:dict[str,Any])->tuple[str,str]:
|
||||
def build_focus_cards(local_items:list[dict[str,Any]], todos:list[dict[str,Any]], pulse:list[dict[str,str]], paperless:dict[str,Any], hermes:dict[str,Any], excluded_story_keys:set[str] | None=None)->tuple[str,str]:
|
||||
urgent_todos=[item for item in todos if (item.get('state') or '') in {'overdue','today'} and (item.get('source') or '') != 'Dashboard']
|
||||
warn_items=[item for item in pulse if item.get('state')=='warn']
|
||||
local_story=local_items[0] if local_items else None
|
||||
excluded_story_keys=excluded_story_keys or set()
|
||||
local_story=next((item for item in local_items if story_key(item) not in excluded_story_keys), None)
|
||||
cron_summary=hermes_cron_summary()
|
||||
session_window=find_usage_window(hermes.get('account_windows',[]), 'session') if hermes.get('ok') else None
|
||||
session_remaining=session_window.get('remaining_percent') if session_window else None
|
||||
@@ -1564,6 +1565,12 @@ def build_focus_cards(local_items:list[dict[str,Any]], todos:list[dict[str,Any]]
|
||||
hermes_headline='Hermes telemetry unavailable'
|
||||
hermes_body='Could not read local Hermes usage stats right now.'
|
||||
local_state='attention' if local_story else 'ok'
|
||||
local_headline=str(local_story.get('title') or '') if local_story else ('Local lane already covered' if local_items else 'Local lane quiet')
|
||||
local_body=(
|
||||
f"{local_story.get('source','Local feed')} • {label(local_story.get('category','local'))}"
|
||||
if local_story else
|
||||
('The strongest local item is already promoted above, so this slot stays out of the way.' if local_items else 'Nothing local survived filtering hard enough to earn the homepage.')
|
||||
)
|
||||
chores_state='warn' if urgent_todos else 'ok'
|
||||
paperless_state='warn' if paperless.get('flagged_count',0) else ('ok' if not paperless.get('active_count',0) else 'attention')
|
||||
homelab_state='warn' if warn_items else 'ok'
|
||||
@@ -1573,8 +1580,8 @@ def build_focus_cards(local_items:list[dict[str,Any]], todos:list[dict[str,Any]]
|
||||
focus_card(
|
||||
'Local watch',
|
||||
'Useful nearby',
|
||||
(local_story.get('title') if local_story else 'Local lane quiet'),
|
||||
(f"{local_story.get('source','Local feed')} • {label(local_story.get('category','local'))}" if local_story else 'Nothing local survived filtering hard enough to earn the homepage.'),
|
||||
local_headline,
|
||||
local_body,
|
||||
f'local {local_state}'.strip(),
|
||||
href=str(local_story.get('url') or '') if local_story else '' ,
|
||||
target='_blank' if local_story and local_story.get('url') else ''
|
||||
@@ -1671,6 +1678,39 @@ def choose_feature_story(preferred_items:list[dict[str,Any]], fallback_items:lis
|
||||
return None
|
||||
|
||||
|
||||
def choose_secondary_feature_story(preferred_items:list[dict[str,Any]], fallback_items:list[dict[str,Any]], primary_story:dict[str,Any] | None, prefs:dict[str,Any])->dict[str,Any] | None:
|
||||
primary_key=story_key(primary_story) if primary_story else ''
|
||||
state=load_lead_warrant_state()
|
||||
feedback=load_dashboard_feedback()
|
||||
acknowledged=set(state.get('acknowledged',[]))
|
||||
ignored_sources=set(state.get('ignored_sources',[]))
|
||||
ignored_topics=set(state.get('ignored_topics',[]))
|
||||
candidates=[]
|
||||
fallback=[]
|
||||
seen=set()
|
||||
for pool_name,pool in (('preferred',preferred_items),('fallback',fallback_items)):
|
||||
for item in pool:
|
||||
key=story_key(item)
|
||||
dedupe=key or f"{str(item.get('source') or '').strip().lower()}::{str(item.get('title') or '').strip().lower()}"
|
||||
if dedupe in seen or (primary_key and key == primary_key):
|
||||
continue
|
||||
seen.add(dedupe)
|
||||
fallback.append(item)
|
||||
if good_lead_candidate(item,prefs,feedback,ignored_sources,ignored_topics):
|
||||
candidates.append(item)
|
||||
for item in candidates:
|
||||
if story_key(item) not in acknowledged:
|
||||
return item
|
||||
if candidates:
|
||||
return candidates[0]
|
||||
for item in fallback:
|
||||
if story_key(item) not in acknowledged:
|
||||
return item
|
||||
if fallback:
|
||||
return fallback[0]
|
||||
return None
|
||||
|
||||
|
||||
def build_feature_story(feature_item:dict[str,Any] | None)->str:
|
||||
if not feature_item:
|
||||
return ''
|
||||
@@ -1680,7 +1720,7 @@ def build_feature_story(feature_item:dict[str,Any] | None)->str:
|
||||
when=(feature_item.get('published_at','')[:16].replace('T',' '))
|
||||
category=str(feature_item.get('category') or 'other')
|
||||
url=str(feature_item.get('url') or '')
|
||||
feature_label='Lead local item' if category=='local' else ('Lead homelab item' if category in {'homelab','smart_home','radio'} else 'Lead signal')
|
||||
feature_label='Next local signal' if category=='local' else ('Next homelab signal' if category in {'homelab','smart_home','radio'} else 'Next signal')
|
||||
why_text=why(feature_item)
|
||||
return f"""
|
||||
<section class='feature-story'>
|
||||
@@ -1695,7 +1735,7 @@ def build_feature_story(feature_item:dict[str,Any] | None)->str:
|
||||
</div>
|
||||
<div class='feature-actions'>
|
||||
<a href='{esc(url)}' target='_blank' rel='noreferrer' class='feature-open'>Open story</a>
|
||||
<span class='feature-note'>Promoted so you get one strong item instead of four equal tiles.</span>
|
||||
<span class='feature-note'>Secondary signal so the warrant and the next-click card are not the same story.</span>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
@@ -2105,15 +2145,17 @@ def render()->str:
|
||||
pulse_metrics=''.join(metric_card(x['label'],x['value'],x['state'],x['state']) for x in pulse)
|
||||
forecast_html=forecast_panel(weather)
|
||||
hero_summary=build_hero_summary(groups['local'],todos,pulse,paperless,hermes)
|
||||
focus_html,focus_state=build_focus_cards(groups['local'],todos,pulse,paperless,hermes)
|
||||
feature_item=choose_feature_story(top_briefing, selected, prefs)
|
||||
secondary_feature_item=choose_secondary_feature_story(top_briefing, selected, feature_item, prefs)
|
||||
excluded_focus_story_keys={key for key in [story_key(feature_item), story_key(secondary_feature_item)] if key}
|
||||
focus_html,focus_state=build_focus_cards(groups['local'],todos,pulse,paperless,hermes,excluded_story_keys=excluded_focus_story_keys)
|
||||
focus_signature=donetick_focus_signature(todos)
|
||||
hermes_html=build_hermes_section(hermes)
|
||||
system_html=build_system_section(system)
|
||||
hero_tokens=compact_number(hermes.get('total_tokens',0)) if hermes.get('ok') else '—'
|
||||
snapshot_html=build_operator_snapshot(todos,pulse,paperless,hermes)
|
||||
feature_item=choose_feature_story(top_briefing, selected, prefs)
|
||||
hero_caseboard_html=build_hero_caseboard(feature_item,todos,paperless)
|
||||
feature_html=build_feature_story(feature_item)
|
||||
feature_html=build_feature_story(secondary_feature_item)
|
||||
session_window=find_usage_window(hermes.get('account_windows',[]),'session') if hermes.get('ok') else None
|
||||
primary_html=''.join([
|
||||
feature_html,
|
||||
|
||||
Reference in New Issue
Block a user