diff --git a/api_server.py b/api_server.py
index 1a5e1a8..9272436 100644
--- a/api_server.py
+++ b/api_server.py
@@ -361,13 +361,63 @@ async def get_integrations():
@app.get("/api/categories")
async def get_categories():
- """Get available service categories for filtering."""
+ """Get available workflow categories for filtering."""
try:
- categories = db.get_service_categories()
- return {"categories": categories}
+ # Try to load from the generated unique categories file
+ categories_file = Path("context/unique_categories.json")
+ if categories_file.exists():
+ with open(categories_file, 'r', encoding='utf-8') as f:
+ categories = json.load(f)
+ return {"categories": categories}
+ else:
+ # Fallback: extract categories from search_categories.json
+ search_categories_file = Path("context/search_categories.json")
+ if search_categories_file.exists():
+ with open(search_categories_file, 'r', encoding='utf-8') as f:
+ search_data = json.load(f)
+
+ unique_categories = set()
+ for item in search_data:
+ if item.get('category'):
+ unique_categories.add(item['category'])
+ else:
+ unique_categories.add('Uncategorized')
+
+ categories = sorted(list(unique_categories))
+ return {"categories": categories}
+ else:
+ # Last resort: return basic categories
+ return {"categories": ["Uncategorized"]}
+
except Exception as e:
+ print(f"Error loading categories: {e}")
raise HTTPException(status_code=500, detail=f"Error fetching categories: {str(e)}")
+@app.get("/api/category-mappings")
+async def get_category_mappings():
+ """Get filename to category mappings for client-side filtering."""
+ try:
+ search_categories_file = Path("context/search_categories.json")
+ if not search_categories_file.exists():
+ return {"mappings": {}}
+
+ with open(search_categories_file, 'r', encoding='utf-8') as f:
+ search_data = json.load(f)
+
+ # Convert to a simple filename -> category mapping
+ mappings = {}
+ for item in search_data:
+ filename = item.get('filename')
+ category = item.get('category') or 'Uncategorized'
+ if filename:
+ mappings[filename] = category
+
+ return {"mappings": mappings}
+
+ except Exception as e:
+ print(f"Error loading category mappings: {e}")
+ raise HTTPException(status_code=500, detail=f"Error fetching category mappings: {str(e)}")
+
@app.get("/api/workflows/category/{category}", response_model=SearchResponse)
async def search_workflows_by_category(
category: str,
diff --git a/create_categories.py b/create_categories.py
index c534fa7..374b6a4 100644
--- a/create_categories.py
+++ b/create_categories.py
@@ -75,6 +75,25 @@ def main():
print(f"Generated search_categories.json with {len(search_categories)} entries")
+ # Generate unique categories list for API
+ unique_categories = set()
+ for item in search_categories:
+ if item['category']:
+ unique_categories.add(item['category'])
+
+ # Always include 'Uncategorized' for workflows without categories
+ unique_categories.add('Uncategorized')
+
+ # Sort categories alphabetically
+ categories_list = sorted(list(unique_categories))
+
+ # Write unique categories to a separate file for API consumption
+ categories_output_path = Path("context/unique_categories.json")
+ with open(categories_output_path, 'w', encoding='utf-8') as f:
+ json.dump(categories_list, f, indent=2, ensure_ascii=False)
+
+ print(f"Generated unique_categories.json with {len(categories_list)} categories")
+
# Print some statistics
categorized = sum(1 for item in search_categories if item['category'])
uncategorized = len(search_categories) - categorized
diff --git a/static/index.html b/static/index.html
index 967b8f3..132991e 100644
--- a/static/index.html
+++ b/static/index.html
@@ -302,6 +302,16 @@
font-weight: 500;
}
+ .category-badge {
+ background: var(--bg-tertiary);
+ color: var(--text-secondary);
+ padding: 0.125rem 0.375rem;
+ border-radius: 0.25rem;
+ font-size: 0.75rem;
+ border: 1px solid var(--border);
+ font-weight: 500;
+ }
+
.workflow-title {
font-size: 1.25rem;
font-weight: 600;
@@ -623,6 +633,14 @@
+
+
+
+
+
${this.escapeHtml(workflow.trigger_type)}
@@ -1090,12 +1286,14 @@
this.elements.modalDescription.textContent = workflow.description;
// Update stats
+ const category = this.getWorkflowCategory(workflow.filename);
this.elements.modalStats.innerHTML = `
Status: ${workflow.active ? 'Active' : 'Inactive'}
Trigger: ${workflow.trigger_type}
Complexity: ${workflow.complexity}
Nodes: ${workflow.node_count}
+
Category: ${this.escapeHtml(category)}
`;