Make Follower Study's cumulative tables tell the monthly story, not just repeat it

Per feedback: a monthly report showing the same near-identical cumulative
tables every month, marginally bigger each time, isn't earning its keep.
Fixed by making the cumulative views themselves show where this month's
people landed, instead of adding that only as a separate summary:

- Account Clusters now annotates each company's growth inline (e.g. "DESY:
  5 (+3 this month)") instead of a flat all-time count with no monthly
  story.
- Notable Contacts highlights rows added this month in place, in context
  with everyone else at that seniority level, instead of only being named
  in a separate bullet list above.
- Dropped the cumulative Sector/Function/Seniority/Country table entirely —
  Audience Composition already owns that exact breakdown for the month,
  so repeating the all-time version here was pure duplication with no
  monthly-specific value.
- Kept the Sector x Seniority crosstab as pure cumulative reference (still
  needs the full ~100+ scale to mean anything, no individual-level "new"
  story to tell).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
beantownbabeandClaude Sonnet 5 committed 2026-08-31 13:51:24 +02:00
1 parent 5e20823947
commit 9155e708b4
1 file changed
+36 -19
+36 -19
View File
@@ -4066,38 +4066,51 @@ def _follower_study_insights_page(month_value="2026-07"):
from collections import Counter
companies = Counter(d.get("company", "").strip() for d in non_team if d.get("company", "").strip())
clusters = [(c, n) for c, n in companies.most_common() if n >= 2]
month_companies = Counter(d.get("company", "").strip() for d in month_rows
if d.get("company", "").strip())
# Followers column shows this month's contribution inline (e.g. "5 (+3 this
# month)") rather than a flat all-time count with no monthly story — the whole
# point of surfacing this in an End of Month report is seeing where this
# month's people actually landed, not repeating a near-identical cumulative
# table every month with a marginally bigger number.
cluster_table = dbc.Table([
html.Thead(html.Tr([html.Th("Company", style={"backgroundColor": "#fdf6d8"}),
html.Th("Followers", style={"backgroundColor": "#fdf6d8"})])),
html.Tbody([html.Tr([html.Td(c), html.Td(str(n))]) for c, n in clusters]),
html.Tbody([
html.Tr([
html.Td(c),
html.Td([str(n), html.Span(f" (+{month_companies[c]} this month)",
style={"color": "#2e7d32", "fontWeight": "600"})
if month_companies.get(c) else None]),
]) for c, n in clusters
]),
], bordered=True, size="sm", style={"fontSize": "0.8rem"})
notable = [d for d in non_team if d.get("seniority") in _NOTABLE_SENIORITIES]
notable.sort(key=lambda d: (d.get("seniority") != "C-Level/Founder", d.get("name", "")))
def _notable_row(d):
# Rows added this month are highlighted in place, in context with everyone
# else at that seniority level, rather than only being called out in a
# separate list. Bootstrap's table CSS sets its own background on <td>
# itself, which paints over a <tr>-level style — the highlight has to go
# on each cell.
td_style = {"backgroundColor": "#e8f5e9"} if d.get("followedSort") == month_value else {}
return html.Tr([html.Td(d.get("name", ""), style=td_style),
html.Td(d.get("seniority", ""), style=td_style),
html.Td(d.get("company", ""), style=td_style),
html.Td(d.get("country", ""), style=td_style)])
notable_table = dbc.Table([
html.Thead(html.Tr([html.Th(c) for c in ["Name", "Seniority", "Company", "Country"]])),
html.Tbody([
html.Tr([html.Td(d.get("name", "")), html.Td(d.get("seniority", "")),
html.Td(d.get("company", "")), html.Td(d.get("country", ""))])
for d in notable
]),
html.Tbody([_notable_row(d) for d in notable]),
], bordered=True, size="sm")
return dbc.Container([
_follower_study_findings(whole, non_team, period_label, month_rows, clusters),
dbc.Card([
dbc.CardHeader(f"All {whole['total']} Followers to Date (through {period_label}), by "
f"Sector, Function, Seniority and Country"),
dbc.CardBody(dbc.Row([
dbc.Col(_composition_count_table(whole["sector"], "Sector"), md=3),
dbc.Col(_composition_count_table(whole["function"], "Function"), md=3),
dbc.Col(_composition_count_table(whole["seniority"], "Seniority"), md=3),
dbc.Col(_composition_count_table(whole["country"], "Country"), md=3),
])),
], className="mb-3 shadow-sm"),
dbc.Row([
dbc.Col(dbc.Card([
dbc.CardHeader("Sector x Seniority"),
dbc.CardHeader("Sector x Seniority (cumulative, to date)"),
dbc.CardBody(_sector_seniority_crosstab(non_team)),
], className="mb-3 shadow-sm h-100"), md=7),
dbc.Col(dbc.Card([
@@ -4108,8 +4121,12 @@ def _follower_study_insights_page(month_value="2026-07"):
dbc.Card([
dbc.CardHeader("Notable Contacts (C-Level/Founder and Director/Head/Principal)"),
dbc.CardBody([
html.P(f"{len(notable)} followers sit at C-Level/Founder or Director/Head/Principal "
f"seniority (internal team members excluded).", style={"fontSize": "0.85rem"}),
html.P([
f"{len(notable)} followers sit at C-Level/Founder or Director/Head/Principal "
"seniority (internal team members excluded). ",
html.Span("Highlighted rows", style={"backgroundColor": "#e8f5e9", "fontWeight": "600"}),
" joined this month.",
], style={"fontSize": "0.85rem"}),
notable_table,
]),
], className="mb-3 shadow-sm"),