AYI-NEDJIMI's picture
Initial Zero Trust Architecture Explorer Space
089b2af verified
import gradio as gr
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from datasets import load_dataset
# ---------------------------------------------------------------------------
# Data loading
# ---------------------------------------------------------------------------
def load_data(lang="en"):
repo = "AYI-NEDJIMI/zero-trust-en" if lang == "en" else "AYI-NEDJIMI/zero-trust-fr"
try:
ds = load_dataset(repo, split="train")
df = ds.to_pandas()
except Exception as e:
print(f"Error loading {repo}: {e}")
df = pd.DataFrame()
return df
data_cache = {}
def get_data(lang):
if lang not in data_cache:
data_cache[lang] = load_data(lang)
return data_cache[lang]
def safe_col(df, col):
return df[col] if col in df.columns else pd.Series([""] * len(df), name=col)
def filter_type(df, entry_type):
if "type" in df.columns:
return df[df["type"] == entry_type].reset_index(drop=True)
return pd.DataFrame()
ALL_FIELDS = [
"type", "principle_name", "description", "implementation_guide",
"maturity_levels", "nist_reference", "benefits", "challenges",
"framework_name", "organization", "pillars", "key_documents",
"pillar_name", "technologies", "tools", "implementation_steps",
"quick_wins", "common_mistakes", "category", "name", "vendor",
"features", "pricing_model", "deployment_model", "strengths",
"weaknesses", "scenario", "industry", "challenge",
"zero_trust_solution", "architecture_components",
"implementation_timeline", "roi_metrics", "question", "answer",
"difficulty",
]
def ensure_columns(df):
for col in ALL_FIELDS:
if col not in df.columns:
df[col] = ""
return df
def fmt(value):
"""Format a cell value for display."""
if value is None:
return ""
if isinstance(value, list):
return "\n".join(f"• {v}" for v in value)
if isinstance(value, dict):
return "\n".join(f"**{k}:** {v}" for k, v in value.items())
return str(value)
# ---------------------------------------------------------------------------
# Labels per language
# ---------------------------------------------------------------------------
LABELS = {
"en": {
"title": "🔐 Zero Trust Architecture Explorer",
"subtitle": "Explore principles, frameworks, pillars, tools, use cases & Q&A",
"principles": "Principles",
"frameworks": "Frameworks",
"pillars": "Implementation Pillars",
"tools": "Solutions & Tools",
"usecases": "Use Cases",
"qa": "Q&A",
"stats": "Statistics",
"language": "Language",
"filter_org": "Filter by Organization",
"filter_cat": "Filter by Category",
"filter_ind": "Filter by Industry",
"all": "All",
"select_entry": "Select an entry",
"no_data": "No data available for this section.",
"total_entries": "Total entries",
"by_type": "Entries by Type",
"by_category": "Tools by Category",
"by_industry": "Use Cases by Industry",
"difficulty_dist": "Q&A Difficulty Distribution",
},
"fr": {
"title": "🔐 Explorateur d'Architecture Zero Trust",
"subtitle": "Explorez les principes, cadres, piliers, outils, cas d'usage et Q&R",
"principles": "Principes",
"frameworks": "Cadres",
"pillars": "Piliers d'Implémentation",
"tools": "Solutions & Outils",
"usecases": "Cas d'Usage",
"qa": "Q&R",
"stats": "Statistiques",
"language": "Langue",
"filter_org": "Filtrer par Organisation",
"filter_cat": "Filtrer par Catégorie",
"filter_ind": "Filtrer par Industrie",
"all": "Tous",
"select_entry": "Sélectionnez une entrée",
"no_data": "Aucune donnée disponible pour cette section.",
"total_entries": "Total des entrées",
"by_type": "Entrées par Type",
"by_category": "Outils par Catégorie",
"by_industry": "Cas d'Usage par Industrie",
"difficulty_dist": "Distribution de Difficulté Q&R",
},
}
# ---------------------------------------------------------------------------
# Tab builders
# ---------------------------------------------------------------------------
def build_principles(df, lang):
L = LABELS[lang]
sub = filter_type(df, "principle")
if sub.empty:
return f"### {L['no_data']}"
blocks = []
for _, row in sub.iterrows():
blocks.append(
f"## {fmt(row.get('principle_name',''))}\n\n"
f"**Description:** {fmt(row.get('description',''))}\n\n"
f"**Implementation Guide:** {fmt(row.get('implementation_guide',''))}\n\n"
f"**Benefits:** {fmt(row.get('benefits',''))}\n\n"
f"**Challenges:** {fmt(row.get('challenges',''))}\n\n---\n"
)
return "\n".join(blocks)
def build_frameworks(df, lang, org_filter="All"):
L = LABELS[lang]
sub = filter_type(df, "framework")
if sub.empty:
return f"### {L['no_data']}", []
orgs = sorted(set(str(v) for v in sub["organization"].dropna().unique()))
org_choices = [L["all"]] + orgs
if org_filter and org_filter != L["all"] and org_filter != "All":
sub = sub[sub["organization"] == org_filter]
blocks = []
for _, row in sub.iterrows():
blocks.append(
f"## {fmt(row.get('framework_name',''))}\n\n"
f"**Organization:** {fmt(row.get('organization',''))}\n\n"
f"**Description:** {fmt(row.get('description',''))}\n\n"
f"**Pillars:** {fmt(row.get('pillars',''))}\n\n"
f"**Maturity Levels:** {fmt(row.get('maturity_levels',''))}\n\n---\n"
)
return "\n".join(blocks) if blocks else f"### {L['no_data']}", org_choices
def build_pillars(df, lang):
L = LABELS[lang]
sub = filter_type(df, "pillar")
if sub.empty:
return f"### {L['no_data']}"
blocks = []
for _, row in sub.iterrows():
blocks.append(
f"## {fmt(row.get('pillar_name',''))}\n\n"
f"**Description:** {fmt(row.get('description',''))}\n\n"
f"**Technologies:** {fmt(row.get('technologies',''))}\n\n"
f"**Tools:** {fmt(row.get('tools',''))}\n\n"
f"**Implementation Steps:** {fmt(row.get('implementation_steps',''))}\n\n"
f"**Quick Wins:** {fmt(row.get('quick_wins',''))}\n\n---\n"
)
return "\n".join(blocks)
def build_tools(df, lang, cat_filter="All"):
L = LABELS[lang]
sub = filter_type(df, "tool")
if sub.empty:
return f"### {L['no_data']}", []
cats = sorted(set(str(v) for v in sub["category"].dropna().unique()))
cat_choices = [L["all"]] + cats
if cat_filter and cat_filter != L["all"] and cat_filter != "All":
sub = sub[sub["category"] == cat_filter]
blocks = []
for _, row in sub.iterrows():
blocks.append(
f"## {fmt(row.get('name',''))}\n\n"
f"**Vendor:** {fmt(row.get('vendor',''))}\n\n"
f"**Category:** {fmt(row.get('category',''))}\n\n"
f"**Features:** {fmt(row.get('features',''))}\n\n"
f"**Pricing Model:** {fmt(row.get('pricing_model',''))}\n\n"
f"**Strengths:** {fmt(row.get('strengths',''))}\n\n"
f"**Weaknesses:** {fmt(row.get('weaknesses',''))}\n\n---\n"
)
return "\n".join(blocks) if blocks else f"### {L['no_data']}", cat_choices
def build_usecases(df, lang, ind_filter="All"):
L = LABELS[lang]
sub = filter_type(df, "usecase")
if sub.empty:
return f"### {L['no_data']}", []
inds = sorted(set(str(v) for v in sub["industry"].dropna().unique()))
ind_choices = [L["all"]] + inds
if ind_filter and ind_filter != L["all"] and ind_filter != "All":
sub = sub[sub["industry"] == ind_filter]
blocks = []
for _, row in sub.iterrows():
blocks.append(
f"## {fmt(row.get('scenario',''))}\n\n"
f"**Industry:** {fmt(row.get('industry',''))}\n\n"
f"**Challenge:** {fmt(row.get('challenge',''))}\n\n"
f"**Zero Trust Solution:** {fmt(row.get('zero_trust_solution',''))}\n\n"
f"**Architecture Components:** {fmt(row.get('architecture_components',''))}\n\n"
f"**Implementation Timeline:** {fmt(row.get('implementation_timeline',''))}\n\n"
f"**ROI Metrics:** {fmt(row.get('roi_metrics',''))}\n\n---\n"
)
return "\n".join(blocks) if blocks else f"### {L['no_data']}", ind_choices
def build_qa(df, lang):
L = LABELS[lang]
sub = filter_type(df, "qa")
if sub.empty:
return f"### {L['no_data']}"
blocks = []
for _, row in sub.iterrows():
diff = fmt(row.get("difficulty", ""))
badge = f" `[{diff}]`" if diff else ""
blocks.append(
f"### ❓ {fmt(row.get('question',''))}{badge}\n\n"
f"**Answer:** {fmt(row.get('answer',''))}\n\n---\n"
)
return "\n".join(blocks)
def build_stats(df, lang):
L = LABELS[lang]
figs = []
if "type" in df.columns:
type_counts = df["type"].value_counts().reset_index()
type_counts.columns = ["Type", "Count"]
fig1 = px.bar(type_counts, x="Type", y="Count", title=L["by_type"],
color="Type", text_auto=True)
fig1.update_layout(showlegend=False)
figs.append(fig1)
tools_df = filter_type(df, "tool")
if not tools_df.empty and "category" in tools_df.columns:
cat_counts = tools_df["category"].value_counts().reset_index()
cat_counts.columns = ["Category", "Count"]
fig2 = px.pie(cat_counts, names="Category", values="Count", title=L["by_category"])
figs.append(fig2)
uc_df = filter_type(df, "usecase")
if not uc_df.empty and "industry" in uc_df.columns:
ind_counts = uc_df["industry"].value_counts().reset_index()
ind_counts.columns = ["Industry", "Count"]
fig3 = px.bar(ind_counts, x="Industry", y="Count", title=L["by_industry"],
color="Industry", text_auto=True)
fig3.update_layout(showlegend=False)
figs.append(fig3)
qa_df = filter_type(df, "qa")
if not qa_df.empty and "difficulty" in qa_df.columns:
diff_counts = qa_df["difficulty"].value_counts().reset_index()
diff_counts.columns = ["Difficulty", "Count"]
fig4 = px.pie(diff_counts, names="Difficulty", values="Count", title=L["difficulty_dist"])
figs.append(fig4)
return figs
# ---------------------------------------------------------------------------
# Footer HTML
# ---------------------------------------------------------------------------
FOOTER_HTML = """
<div style="text-align:center; padding:20px; margin-top:30px; border-top:1px solid #444; font-size:0.9em; color:#aaa;">
<p><strong>Zero Trust Architecture Explorer</strong> — Built by AYI-NEDJIMI Consultants</p>
<p>
<a href="https://ayinedjimi-consultants.fr" target="_blank" style="margin:0 10px;">🌐 ayinedjimi-consultants.fr</a>
<a href="https://www.linkedin.com/company/ayi-nedjimi" target="_blank" style="margin:0 10px;">💼 LinkedIn</a>
<a href="https://github.com/AYI-NEDJIMI" target="_blank" style="margin:0 10px;">🐙 GitHub</a>
<a href="https://x.com/AYI_NEDJIMI" target="_blank" style="margin:0 10px;">🐦 X / Twitter</a>
</p>
</div>
"""
# ---------------------------------------------------------------------------
# Main app
# ---------------------------------------------------------------------------
def create_app():
# Pre-load both languages
for lang in ("en", "fr"):
df = get_data(lang)
ensure_columns(df)
with gr.Blocks(
title="Zero Trust Architecture Explorer",
theme=gr.themes.Soft(primary_hue="blue", secondary_hue="indigo"),
css="""
.main-title {text-align:center; margin-bottom:0;}
.sub-title {text-align:center; color:#666; margin-top:0;}
"""
) as demo:
# State
lang_state = gr.State("en")
# Header
title_md = gr.Markdown("# 🔐 Zero Trust Architecture Explorer", elem_classes=["main-title"])
subtitle_md = gr.Markdown("*Explore principles, frameworks, pillars, tools, use cases & Q&A*",
elem_classes=["sub-title"])
with gr.Row():
lang_toggle = gr.Radio(
choices=["English", "Français"],
value="English",
label="Language / Langue",
scale=1,
)
entry_count = gr.Markdown("")
# ----- Tabs -----
with gr.Tabs() as tabs:
# 1 - Principles
with gr.Tab("Principles", id="tab_principles") as tab_principles:
principles_md = gr.Markdown()
# 2 - Frameworks
with gr.Tab("Frameworks", id="tab_frameworks") as tab_frameworks:
fw_org_filter = gr.Dropdown(label="Filter by Organization", choices=["All"], value="All", interactive=True)
frameworks_md = gr.Markdown()
# 3 - Pillars
with gr.Tab("Implementation Pillars", id="tab_pillars") as tab_pillars:
pillars_md = gr.Markdown()
# 4 - Tools
with gr.Tab("Solutions & Tools", id="tab_tools") as tab_tools:
tools_cat_filter = gr.Dropdown(label="Filter by Category", choices=["All"], value="All", interactive=True)
tools_md = gr.Markdown()
# 5 - Use Cases
with gr.Tab("Use Cases", id="tab_usecases") as tab_usecases:
uc_ind_filter = gr.Dropdown(label="Filter by Industry", choices=["All"], value="All", interactive=True)
usecases_md = gr.Markdown()
# 6 - Q&A
with gr.Tab("Q&A", id="tab_qa") as tab_qa:
qa_md = gr.Markdown()
# 7 - Statistics
with gr.Tab("Statistics", id="tab_stats") as tab_stats:
stats_plots = [gr.Plot() for _ in range(4)]
# Footer
gr.HTML(FOOTER_HTML)
# ----- Callbacks -----
def refresh_all(lang_label, org_f, cat_f, ind_f):
lang = "fr" if lang_label == "Français" else "en"
L = LABELS[lang]
df = get_data(lang)
ensure_columns(df)
count_text = f"**{L['total_entries']}:** {len(df)}"
# Principles
p_md = build_principles(df, lang)
# Frameworks
fw_md, fw_orgs = build_frameworks(df, lang, org_f)
fw_org_val = org_f if org_f in fw_orgs else (L["all"] if fw_orgs else "All")
# Pillars
pl_md = build_pillars(df, lang)
# Tools
t_md, t_cats = build_tools(df, lang, cat_f)
t_cat_val = cat_f if cat_f in t_cats else (L["all"] if t_cats else "All")
# Use Cases
uc_md, uc_inds = build_usecases(df, lang, ind_f)
uc_ind_val = ind_f if ind_f in uc_inds else (L["all"] if uc_inds else "All")
# Q&A
q_md = build_qa(df, lang)
# Stats
stat_figs = build_stats(df, lang)
while len(stat_figs) < 4:
stat_figs.append(go.Figure())
return [
f"# {L['title']}",
f"*{L['subtitle']}*",
count_text,
p_md,
gr.update(choices=fw_orgs if fw_orgs else ["All"], value=fw_org_val, label=L["filter_org"]),
fw_md,
pl_md,
gr.update(choices=t_cats if t_cats else ["All"], value=t_cat_val, label=L["filter_cat"]),
t_md,
gr.update(choices=uc_inds if uc_inds else ["All"], value=uc_ind_val, label=L["filter_ind"]),
uc_md,
q_md,
] + stat_figs
outputs = [
title_md, subtitle_md, entry_count,
principles_md,
fw_org_filter, frameworks_md,
pillars_md,
tools_cat_filter, tools_md,
uc_ind_filter, usecases_md,
qa_md,
] + stats_plots
# Language toggle triggers full refresh
lang_toggle.change(
fn=refresh_all,
inputs=[lang_toggle, fw_org_filter, tools_cat_filter, uc_ind_filter],
outputs=outputs,
)
# Filter dropdowns
fw_org_filter.change(
fn=refresh_all,
inputs=[lang_toggle, fw_org_filter, tools_cat_filter, uc_ind_filter],
outputs=outputs,
)
tools_cat_filter.change(
fn=refresh_all,
inputs=[lang_toggle, fw_org_filter, tools_cat_filter, uc_ind_filter],
outputs=outputs,
)
uc_ind_filter.change(
fn=refresh_all,
inputs=[lang_toggle, fw_org_filter, tools_cat_filter, uc_ind_filter],
outputs=outputs,
)
# Initial load
demo.load(
fn=refresh_all,
inputs=[lang_toggle, fw_org_filter, tools_cat_filter, uc_ind_filter],
outputs=outputs,
)
return demo
if __name__ == "__main__":
app = create_app()
app.launch()