File size: 6,053 Bytes
443db46
 
 
3a76be2
2f9afec
 
 
 
 
 
 
 
 
 
3a76be2
2f9afec
 
 
 
 
 
 
 
 
 
3a76be2
2f9afec
 
 
 
 
 
 
 
 
 
3a76be2
2f9afec
 
 
 
 
 
 
 
 
 
3a76be2
2f9afec
 
 
de05b98
d26ce00
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2f9afec
d26ce00
d1ce44b
d26ce00
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2f9afec
d26ce00
d1ce44b
d26ce00
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2f9afec
d26ce00
46a1acf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import gradio as gr
import sys
from typing import List, Dict, Any

# --- Consent/Event Audit Panel ---
def consent_audit_panel(consent_events: List[Dict[str, Any]]):
    """
    UI Panel to show all consent events, opt-outs, and compliance flags per contact and batch.
    Accepts a list of consent event dicts with structure as returned from backend JSON.
    """
    audit_md = "# Consent/Event Audit\nPer-contact and batch consent history."
    for event in consent_events:
        audit_md += f"\n- Contact: {event.get('contact_id','?')} | Event: {event.get('event_type','?')} | Opt-out: {event.get('opt_out',False)} | Compliance: {event.get('compliance_flag','?')})"
    return gr.Markdown(audit_md)

# --- Dynamic Branching Composer for Cadence Editing ---
def branching_composer(branches: List[Dict[str, Any]]):
    """
    Visual sequence builder for editing cadences.
    Structure assumed to be a list of dict branches with JSON mirroring backend.
    """
    builder_md = "# Dynamic Cadence Branching\n" + "\n## Sequence Tree:"
    for b in branches:
        builder_md += f"\n- Step {b.get('step','?')}: {b.get('description','?')} (Next: {b.get('next','?')})"
    return gr.Markdown(builder_md)

# --- Live Diagnostics Panel for Cadence Errors/Health ---
def diagnostics_panel(events: List[Dict[str, Any]]):
    """
    Incident/event log UI widget to show errors and health of cadence system.
    Format is a simple list of event dicts from backend state.
    """
    diag_md = "# Live Diagnostics: Cadence Health\n"
    for e in events:
        diag_md += f"\n- [{e.get('timestamp','?')}] {e.get('type','?')}: {e.get('message','?')}{' [ERROR]' if e.get('level','').lower()=='error' else ''}"
    return gr.Markdown(diag_md)

# --- Exportable Audit Trail Widget ---
def audit_trail_widget(audit_history: List[Dict[str, Any]]):
    """
    Compliance and debug history view for export.
    Accepts audit events from backend JSON/state.
    """
    audit_log = 'Contact,Event,Opt-out,Compliance\n'
    for item in audit_history:
        audit_log += f"{item.get('contact_id','?')},{item.get('event_type','?')},{item.get('opt_out',False)},{item.get('compliance_flag','?')}\n"
    return gr.Textbox(label="Audit Trail CSV", value=audit_log, lines=10)

# Example usage in Gradio Blocks
with gr.Blocks(title="StrategyStack UI") as demo:
    gr.Markdown("# Outreach Cadence & Compliance Dashboard")
consent_events_sample = [
        {
            "contact_id": "LEAD_001",
            "event_type": "consent_given",
            "timestamp": "2025-11-06T06:20:00Z",
            "opt_out": False,
            "compliance_flag": "ok",
            "region": "EU",
            "method": "checkbox_onboarding_form",
            "actor": "user",
            "batch_id": "BATCH_Q4_2025_HEALTHCARE"
        },
        {
            "contact_id": "LEAD_002",
            "event_type": "opt_out",
            "timestamp": "2025-11-06T06:21:00Z",
            "opt_out": True,
            "compliance_flag": "flagged",
            "region": "US",
            "method": "footer_unsubscribe",
            "actor": "user",
            "batch_id": "BATCH_Q4_2025_HEALTHCARE"
        },
        {
            "contact_id": "LEAD_003",
            "event_type": "consent_given",
            "timestamp": "2025-11-06T07:15:00Z",
            "opt_out": False,
            "compliance_flag": "ok",
            "region": "US",
            "method": "api_integration",
            "actor": "system",
            "batch_id": "BATCH_Q4_2025_SAAS"
        }
    ]
    
branches_sample = [
        {
            "step": 1,
            "description": "Initial Welcome Email - Personalized Industry Context",
            "channel": "email",
            "timing": "immediate",
            "next": 2,
            "condition": "not_opted_out"
        },
        {
            "step": 2,
            "description": "LinkedIn Connection Request with Custom Note",
            "channel": "linkedin",
            "timing": "2_days_after_step_1",
            "next": 3,
            "condition": "no_reply_from_step_1"
        },
        {
            "step": 3,
            "description": "Follow-up Call - Pain Point Discovery",
            "channel": "phone",
            "timing": "3_days_after_step_2",
            "next": 4,
            "condition": "engagement_score_below_0.7"
        },
        {
            "step": 4,
            "description": "Case Study Email - Relevant to Industry",
            "channel": "email",
            "timing": "1_day_after_step_3",
            "next": "END",
            "condition": "not_connected"
        }
    ]
    
diagnostics_sample = [
        {
            "timestamp": "2025-11-06T06:23:00Z",
            "type": "info",
            "message": "Cadence started for BATCH_Q4_2025_HEALTHCARE with 150 leads",
            "level": "info",
            "agent": "cadence_orchestrator"
        },
        {
            "timestamp": "2025-11-06T06:29:00Z",
            "type": "error",
            "message": "Compliance block: Message suppressed for LEAD_002 - opted out via footer_unsubscribe",
            "level": "error",
            "agent": "compliance_agent"
        },
        {
            "timestamp": "2025-11-06T06:33:00Z",
            "type": "warning",
            "message": "Rate limit reached for LinkedIn API; implementing exponential backoff for 15 minutes",
            "level": "warning",
            "agent": "outreach_agent"
        },
        {
            "timestamp": "2025-11-06T06:45:00Z",
            "type": "success",
            "message": "Enrichment completed for 45 leads with intent_score > 0.8",
            "level": "info",
            "agent": "enrichment_agent"
        },
        {
            "timestamp": "2025-11-06T07:00:00Z",
            "type": "warning",
            "message": "5 leads flagged for human validation due to incomplete firmographic data",
            "level": "warning",
            "agent": "validation_agent"
        }
    ]
    
audit_history_sample = consent_events_sample