From 8861b32ae5c80a305ee3fd5bbf1f40018a17408d Mon Sep 17 00:00:00 2001 From: Austin Godber Date: Mon, 15 Sep 2025 08:03:39 -0700 Subject: [PATCH] add about modal --- src/embeddingbuddy/app.py | 31 +++++++++ .../ui/callbacks/interactions.py | 10 +++ src/embeddingbuddy/ui/components/about.py | 69 +++++++++++++++++++ src/embeddingbuddy/ui/layout.py | 16 ++++- 4 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 src/embeddingbuddy/ui/components/about.py diff --git a/src/embeddingbuddy/app.py b/src/embeddingbuddy/app.py index dae0a47..5bbf165 100644 --- a/src/embeddingbuddy/app.py +++ b/src/embeddingbuddy/app.py @@ -16,11 +16,42 @@ def create_app(): app = dash.Dash( __name__, + title="EmbeddingBuddy", external_stylesheets=[ dbc.themes.BOOTSTRAP, "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css", ], assets_folder=assets_path, + meta_tags=[ + { + "name": "description", + "content": "Interactive embedding visualization tool for exploring high-dimensional vectors through dimensionality reduction techniques like PCA, t-SNE, and UMAP." + }, + { + "name": "author", + "content": "EmbeddingBuddy" + }, + { + "name": "keywords", + "content": "embeddings, visualization, dimensionality reduction, PCA, t-SNE, UMAP, machine learning, data science" + }, + { + "name": "viewport", + "content": "width=device-width, initial-scale=1.0" + }, + { + "property": "og:title", + "content": "EmbeddingBuddy - Interactive Embedding Visualization" + }, + { + "property": "og:description", + "content": "Explore and visualize embedding vectors through interactive 2D/3D plots with multiple dimensionality reduction techniques." + }, + { + "property": "og:type", + "content": "website" + } + ], ) # Allow callbacks to components that are dynamically created in tabs diff --git a/src/embeddingbuddy/ui/callbacks/interactions.py b/src/embeddingbuddy/ui/callbacks/interactions.py index b9130f7..b8191c8 100644 --- a/src/embeddingbuddy/ui/callbacks/interactions.py +++ b/src/embeddingbuddy/ui/callbacks/interactions.py @@ -7,6 +7,16 @@ class InteractionCallbacks: self._register_callbacks() def _register_callbacks(self): + @callback( + Output("about-modal", "is_open"), + [Input("about-button", "n_clicks"), Input("about-modal-close", "n_clicks")], + prevent_initial_call=True, + ) + def toggle_about_modal(about_clicks, close_clicks): + if about_clicks or close_clicks: + return True if about_clicks else False + return False + @callback( [ Output("processed-data", "data", allow_duplicate=True), diff --git a/src/embeddingbuddy/ui/components/about.py b/src/embeddingbuddy/ui/components/about.py new file mode 100644 index 0000000..78e166c --- /dev/null +++ b/src/embeddingbuddy/ui/components/about.py @@ -0,0 +1,69 @@ +from dash import html, dcc +import dash_bootstrap_components as dbc + + +class AboutComponent: + def _get_about_content(self): + return """ +# 🔍 Interactive Embedding Visualization + +EmbeddingBuddy is a modular Python Dash web application for interactive exploration and visualization of embedding vectors through dimensionality reduction techniques (PCA, t-SNE, UMAP). + +## ✨ Features + +- Drag-and-drop NDJSON file upload +- Multiple dimensionality reduction algorithms +- 2D/3D interactive plots with Plotly +- Color coding by categories, subcategories, or tags +- In-browser embedding generation +- OpenSearch integration for data loading + +## 🔧 Supported Algorithms + +- **PCA** (Principal Component Analysis) +- **t-SNE** (t-Distributed Stochastic Neighbor Embedding) +- **UMAP** (Uniform Manifold Approximation and Projection) + +--- + +📂 [View on GitHub](https://github.com/godber/EmbeddingBuddy) + +*Built with: Python, Dash, Plotly, scikit-learn, OpenTSNE, UMAP* + """.strip() + + def create_about_modal(self): + return dbc.Modal( + [ + dbc.ModalHeader( + dbc.ModalTitle("About EmbeddingBuddy"), + close_button=True, + ), + dbc.ModalBody([ + dcc.Markdown( + self._get_about_content(), + className="mb-0" + ) + ]), + dbc.ModalFooter([ + dbc.Button( + "Close", + id="about-modal-close", + color="secondary", + n_clicks=0 + ) + ]), + ], + id="about-modal", + is_open=False, + size="lg", + ) + + def create_about_button(self): + return dbc.Button( + [html.I(className="fas fa-info-circle me-2"), "About"], + id="about-button", + color="outline-info", + size="sm", + n_clicks=0, + className="ms-2" + ) \ No newline at end of file diff --git a/src/embeddingbuddy/ui/layout.py b/src/embeddingbuddy/ui/layout.py index f3d1fea..3958537 100644 --- a/src/embeddingbuddy/ui/layout.py +++ b/src/embeddingbuddy/ui/layout.py @@ -1,16 +1,19 @@ from dash import dcc, html import dash_bootstrap_components as dbc from .components.sidebar import SidebarComponent +from .components.about import AboutComponent class AppLayout: def __init__(self): self.sidebar = SidebarComponent() + self.about = AboutComponent() def create_layout(self): return dbc.Container( [self._create_header(), self._create_main_content()] - + self._create_stores(), + + self._create_stores() + + [self.about.create_about_modal()], fluid=True, ) @@ -19,7 +22,16 @@ class AppLayout: [ dbc.Col( [ - html.H1("EmbeddingBuddy", className="text-center mb-4"), + html.Div( + [ + html.H1("EmbeddingBuddy", className="text-center mb-4 d-inline"), + html.Div( + [self.about.create_about_button()], + className="float-end" + ), + ], + className="d-flex justify-content-between align-items-center" + ), # Load Transformers.js from CDN html.Script( """