Add Team tab with per-member submenu (data starts Dec 2026)

New tab for analyzing each team member's own personal LinkedIn export
data (separate from the Page-level Content/Followers/Visitors exports),
starting December 2026 per Mckinley. Submenu dropdown lists Peter Gaal,
Daniel Schmidt, Niklas Meidow, Aleksandra Kotenko, Mckinley Black.

Same "starts empty" pattern as the Engagement Response tab: a hand-
maintained team_exports.py module (empty for now) backs the tab, and
each person shows a clean placeholder until their real export data
gets added - no other code changes needed at that point.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
beantownbabeandClaude Sonnet 5 committed 2026-10-30 10:10:04 +01:00
1 parent ad2f8698f7
commit 436e52254a
2 files changed
+66

No files matched your search

+39
View File
@@ -17,6 +17,7 @@ import follower_directory_data
import engagement_audit
import theme_tracker
import conversation_tracker
import team_exports
# Overridable via env var so the same code runs unmodified in Docker/internal deployments —
# defaults to this machine's path for local dev.
@@ -2330,6 +2331,23 @@ def _build_engagement_response_tab():
return dbc.Container([theme_card, convo_card], fluid=True, className="pb-3")
_TEAM_MEMBER_OPTIONS = [{"label": name, "value": name} for name in team_exports.TEAM_MEMBERS]
_TEAM_DEFAULT_MEMBER = team_exports.TEAM_MEMBERS[0]
team_tab = dbc.Container([
html.Div([
html.Label("Team member", style={"fontSize": "0.75rem", "fontWeight": "600",
"marginBottom": "4px", "display": "block"}),
dcc.Dropdown(
id="team-member-select",
options=_TEAM_MEMBER_OPTIONS, value=_TEAM_DEFAULT_MEMBER,
clearable=False, searchable=False, style={"width": "280px"},
),
], style={"marginBottom": "1.25rem"}),
html.Div(id="team-content-area"),
], fluid=True, className="pb-3")
refresh_data()
engagement_response_tab = _build_engagement_response_tab()
@@ -2351,6 +2369,7 @@ NAV_ITEMS = [
("growth", "Growth", growth_tab),
("reports", "Reports", reports_tab),
("engagement-response", "Engagement Response", engagement_response_tab),
("team", "Team", team_tab),
]
TAB_CONTENT_MAP = {key: content for key, _, content in NAV_ITEMS}
@@ -2363,6 +2382,7 @@ TAB_HERO = {
"growth": ("Growth", "Historical follower growth, tracked weekly against your own rolling best."),
"reports": ("Reports", "Monthly progress reports for LinkedIn, combining the dashboard data with the Follower Directory."),
"engagement-response": ("Engagement Response", "Theme performance across the whole campaign and a tracker for every real conversation, so none get left open."),
"team": ("Team", "Each team member's own personal LinkedIn export data, starting December 2026."),
"roadmap-insights": ("Campaign Roadmap — Insights", ""),
"all-posts-insights": ("All Posts — Insights", "The Content tab's own post list and format/activity charts, mirrored here for the selected month."),
"follower-growth-insights": ("Follower Growth — Insights", "The Overview and Growth tabs' own follower charts, mirrored here for the selected month."),
@@ -2662,6 +2682,25 @@ def _switch_to_insights_page(pathname, selected_month):
return classes + [content, hero_title, _hero_subtitle_children(active), _hero_actions(active, month_value)]
@app.callback(
Output("team-content-area", "children"),
Input("team-member-select", "value"),
)
def _render_team_tab(name):
"""Starts empty for everyone - personal-profile exports begin December 2026 (see
team_exports.py). Shows the same clean "nothing yet" treatment as the Engagement
Response tab's theme/conversation cards until a person's real data lands."""
data = team_exports.exports_for(name)
if not data:
return dbc.Alert(
f"No personal LinkedIn export data for {name} yet - this starts December 2026. "
"Add an entry to team_exports.TEAM_EXPORTS as each person's export data comes in, "
"no other code changes needed for it to show up here.",
color="info",
)
return html.Div(f"Export data for {name}: {data}")
@app.callback(
Output("fb-expanded", "data", allow_duplicate=True),
Input("fb-expand-btn", "n_clicks"),
+27
View File
@@ -0,0 +1,27 @@
"""Per-team-member personal LinkedIn export data, starting December 2026. The Page-level
exports (Content/Followers/Visitors/Competitors) only cover the TXproducts Company Page -
this is for each team member's own personal profile activity (their own post performance,
follower growth, etc.), tracked separately starting when that analysis begins.
Empty until December 2026 - add each person's export data here as it starts coming in,
no other code changes needed for it to show up in the Team tab. The exact per-person
schema isn't fixed yet (personal-profile exports aren't the same shape as the Page's own
exports), so this starts as a simple hand-maintained dict keyed by name; replace a
person's entry with whatever structure their real export data turns out to need.
"""
TEAM_MEMBERS = [
"Peter Gaal",
"Daniel Schmidt",
"Niklas Meidow",
"Aleksandra Kotenko",
"Mckinley Black",
]
# "Peter Gaal": {"exports": [...], "notes": "..."},
TEAM_EXPORTS = {
}
def exports_for(name):
return TEAM_EXPORTS.get(name)