feat: rename Application Solutions to Agentic Apps in docs, UI, and codebase

This commit is contained in:
mik-tf
2025-09-08 11:43:53 -04:00
parent 2ddd538941
commit bfc24070d7
14 changed files with 46 additions and 46 deletions

View File

@@ -18,8 +18,8 @@ This document outlines the comprehensive redesign of the Project Mycelium market
- [ ] Update navigation and menus - [ ] Update navigation and menus
- [ ] Update backend user management - [ ] Update backend user management
- [ ] **Application Solutions → Agentic Apps** - [x] **Application Solutions → Agentic Apps**
- [ ] Update product categories - [x] Update product categories
- [ ] Update marketplace listings - [ ] Update marketplace listings
- [ ] Update search and filtering - [ ] Update search and filtering
- [ ] Update backend product models - [ ] Update backend product models

View File

@@ -14,7 +14,7 @@ The marketplace is organized into categories that align with the exchange mechan
| **[Bandwidth Providers](./bandwidth_providers.md)** | Bandwidth supply for TF-run Mycelium Gateways | Bandwidth providers | TF-run Mycelium Gateways | TFP paid based on TB of bandwidth delivered | | **[Bandwidth Providers](./bandwidth_providers.md)** | Bandwidth supply for TF-run Mycelium Gateways | Bandwidth providers | TF-run Mycelium Gateways | TFP paid based on TB of bandwidth delivered |
| **Mycelium Names** | Global fair name system | TF COOP (name provider) | Users registering names | TFP paid based on name length (shorter names cost more) | | **Mycelium Names** | Global fair name system | TF COOP (name provider) | Users registering names | TFP paid based on name length (shorter names cost more) |
| **Human Energy Services** | Professional technical services | Service providers (designers, admins, developers) | Users needing expertise | TFP transferred based on agreed rates | | **Human Energy Services** | Professional technical services | Service providers (designers, admins, developers) | Users needing expertise | TFP transferred based on agreed rates |
| **Application Solutions** | Pre-configured, self-healing applications | Solution providers | End users | Users provide slices to solution providers while maintaining sovereignty | | **Agentic Apps** | Pre-configured, self-healing applications | Solution providers | End users | Users provide slices to solution providers while maintaining sovereignty |
| **TFP Exchange** (phase 2)| Trading platform for TFP | TFP sellers | TFP buyers | Direct exchange of TFP for currencies (TFT, USD, etc.) | | **TFP Exchange** (phase 2)| Trading platform for TFP | TFP sellers | TFP buyers | Direct exchange of TFP for currencies (TFT, USD, etc.) |
## Marketplace Features ## Marketplace Features

View File

@@ -86,7 +86,7 @@ The TF Marketplace offers various products and services that facilitate the mutu
- Support for various domain types and structures - Support for various domain types and structures
## [Application Solutions](apps.md) ## [Agentic Apps](apps.md)
- **Definition**: Pre-configured, self-healing applications deployed on the platform - **Definition**: Pre-configured, self-healing applications deployed on the platform
- **Suppliers**: Solution providers who develop and maintain applications - **Suppliers**: Solution providers who develop and maintain applications

View File

@@ -79,8 +79,8 @@ impl DashboardController {
Some(user) Some(user)
} }
/// Helper function to count deployments across all users for a specific app provider /// Helper function to count deployments across all users for a specific application provider
fn count_cross_user_deployments(app_provider_email: &str) -> std::collections::HashMap<String, i32> { fn count_cross_user_deployments(application_provider_email: &str) -> std::collections::HashMap<String, i32> {
use std::collections::HashMap; use std::collections::HashMap;
let mut deployment_counts: HashMap<String, i32> = HashMap::new(); let mut deployment_counts: HashMap<String, i32> = HashMap::new();
@@ -108,8 +108,8 @@ impl DashboardController {
// Count deployments for this app provider's apps // Count deployments for this app provider's apps
for deployment in &user_data.application_deployments { for deployment in &user_data.application_deployments {
// Check if this deployment belongs to an app from our app provider // Check if this deployment belongs to an app from our app provider
// We need to get the app provider's apps to match // We need to get the application provider's apps to match
let provider_apps = UserPersistence::get_user_apps(app_provider_email); let provider_apps = UserPersistence::get_user_apps(application_provider_email);
for provider_app in &provider_apps { for provider_app in &provider_apps {
if deployment.app_id == provider_app.id && deployment.status == "Active" { if deployment.app_id == provider_app.id && deployment.status == "Active" {
@@ -517,7 +517,7 @@ impl DashboardController {
let mut ctx = crate::models::builders::ContextBuilder::new() let mut ctx = crate::models::builders::ContextBuilder::new()
.active_page("dashboard") .active_page("dashboard")
.build(); .build();
ctx.insert("active_section", "app_provider"); ctx.insert("active_section", "application_provider");
let config = get_app_config(); let config = get_app_config();
ctx.insert("gitea_enabled", &config.is_gitea_enabled()); ctx.insert("gitea_enabled", &config.is_gitea_enabled());
@@ -607,7 +607,7 @@ impl DashboardController {
}) })
.collect(); .collect();
let app_provider_data = crate::models::user::AppProviderData { let application_provider_data = crate::models::user::AppProviderData {
published_apps: fresh_apps.len() as i32, published_apps: fresh_apps.len() as i32,
total_deployments: fresh_apps.iter().map(|a| a.deployments).sum::<i32>(), total_deployments: fresh_apps.iter().map(|a| a.deployments).sum::<i32>(),
active_deployments, active_deployments,
@@ -618,7 +618,7 @@ impl DashboardController {
revenue_history: Vec::new(), revenue_history: Vec::new(),
}; };
ctx.insert("app_provider_data", &app_provider_data); ctx.insert("application_provider_data", &application_provider_data);
} else { } else {
// Ensure template always has a defined structure even without a logged-in user // Ensure template always has a defined structure even without a logged-in user
let empty: crate::models::user::AppProviderData = crate::models::user::AppProviderData { let empty: crate::models::user::AppProviderData = crate::models::user::AppProviderData {
@@ -631,10 +631,10 @@ impl DashboardController {
deployment_stats: Vec::new(), deployment_stats: Vec::new(),
revenue_history: Vec::new(), revenue_history: Vec::new(),
}; };
ctx.insert("app_provider_data", &empty); ctx.insert("application_provider_data", &empty);
} }
render_template(&tmpl, "dashboard/app_provider.html", &ctx) render_template(&tmpl, "dashboard/application_provider.html", &ctx)
} }
/// Renders the service provider section of the dashboard /// Renders the service provider section of the dashboard
@@ -2936,7 +2936,7 @@ impl DashboardController {
} }
}).collect(); }).collect();
let app_provider_data = crate::models::user::AppProviderData { let application_provider_data = crate::models::user::AppProviderData {
apps: fresh_apps.clone(), apps: fresh_apps.clone(),
published_apps: fresh_apps.len() as i32, published_apps: fresh_apps.len() as i32,
total_deployments, total_deployments,
@@ -2947,7 +2947,7 @@ impl DashboardController {
revenue_history: Vec::new(), revenue_history: Vec::new(),
}; };
return Ok(ResponseBuilder::ok().json(app_provider_data).build()); return Ok(ResponseBuilder::ok().json(application_provider_data).build());
} else { } else {
} }

View File

@@ -405,11 +405,11 @@ impl Default for ServiceLevelAgreement {
/// Application deployment configuration /// Application deployment configuration
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AppDeployment { pub struct ApplicationDeployment {
pub id: String, pub id: String,
pub app_id: String, pub app_id: String,
pub customer_email: String, pub customer_email: String,
pub deployment_status: AppDeploymentStatus, pub deployment_status: ApplicationDeploymentStatus,
pub resource_allocation: ResourceUtilization, pub resource_allocation: ResourceUtilization,
pub monthly_cost: rust_decimal::Decimal, pub monthly_cost: rust_decimal::Decimal,
pub deployed_at: Option<DateTime<Utc>>, pub deployed_at: Option<DateTime<Utc>>,
@@ -418,9 +418,9 @@ pub struct AppDeployment {
pub monitoring_enabled: bool, pub monitoring_enabled: bool,
} }
/// App deployment status /// Application deployment status
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub enum AppDeploymentStatus { pub enum ApplicationDeploymentStatus {
Pending, Pending,
Deploying, Deploying,
Running, Running,
@@ -429,7 +429,7 @@ pub enum AppDeploymentStatus {
Maintenance, Maintenance,
} }
impl Default for AppDeploymentStatus { impl Default for ApplicationDeploymentStatus {
fn default() -> Self { fn default() -> Self {
Self::Pending Self::Pending
} }

View File

@@ -804,8 +804,8 @@ impl OrderService {
// Only create deployments for application products // Only create deployments for application products
if item.product_category == "application" { if item.product_category == "application" {
// Find the app provider by looking up who published this app // Find the application provider by looking up who published this app
if let Some(app_provider_email) = self.find_app_provider(&item.product_id) { if let Some(application_provider_email) = self.find_application_provider(&item.product_id) {
// Create deployment for each quantity ordered // Create deployment for each quantity ordered
for _i in 0..item.quantity { for _i in 0..item.quantity {
@@ -838,7 +838,7 @@ impl OrderService {
.unwrap(); .unwrap();
// Add deployment to application provider's data // Add deployment to application provider's data
if let Err(e) = UserPersistence::add_user_application_deployment(&app_provider_email, deployment.clone()) { if let Err(e) = UserPersistence::add_user_application_deployment(&application_provider_email, deployment.clone()) {
} else { } else {
} }
@@ -857,8 +857,8 @@ impl OrderService {
Ok(()) Ok(())
} }
/// Find the app provider (user who published the app) by product ID /// Find the application provider (user who published the app) by product ID
fn find_app_provider(&self, product_id: &str) -> Option<String> { fn find_application_provider(&self, product_id: &str) -> Option<String> {
// Get all user data files and search for the app // Get all user data files and search for the app
let user_data_dir = std::path::Path::new("user_data"); let user_data_dir = std::path::Path::new("user_data");
if !user_data_dir.exists() { if !user_data_dir.exists() {

View File

@@ -33,7 +33,7 @@ class UserDatabase {
display_name: 'Alex Thompson', display_name: 'Alex Thompson',
email: 'user2@example.com', email: 'user2@example.com',
password: 'password', password: 'password',
role: 'app_provider', role: 'application_provider',
location: 'Berlin, Germany', location: 'Berlin, Germany',
joined_date: '2024-02-20', joined_date: '2024-02-20',
reputation: 4.9, reputation: 4.9,
@@ -84,7 +84,7 @@ class UserDatabase {
display_name: 'Jordan Mitchell', display_name: 'Jordan Mitchell',
email: 'user5@example.com', email: 'user5@example.com',
password: 'password', password: 'password',
role: 'multi', // Can be resource_provider, app_provider, service_provider, user role: 'multi', // Can be resource_provider, application_provider, service_provider, user
location: 'Toronto, Canada', location: 'Toronto, Canada',
joined_date: new Date().toISOString().split('T')[0], joined_date: new Date().toISOString().split('T')[0],
reputation: 5.0, reputation: 5.0,

View File

@@ -13,7 +13,7 @@
<div class="stats-card info"> <div class="stats-card info">
<h5 class="card-title">Published Apps</h5> <h5 class="card-title">Published Apps</h5>
<div class="d-flex justify-content-between align-items-end"> <div class="d-flex justify-content-between align-items-end">
<h2 class="mb-0">{% if app_provider_data is defined and app_provider_data.published_apps is defined %}{{ app_provider_data.published_apps }}{% else %}0{% endif %}</h2> <h2 class="mb-0">{% if application_provider_data is defined and application_provider_data.published_apps is defined %}{{ application_provider_data.published_apps }}{% else %}0{% endif %}</h2>
<small class="text-muted">Active</small> <small class="text-muted">Active</small>
</div> </div>
</div> </div>
@@ -22,7 +22,7 @@
<div class="stats-card primary"> <div class="stats-card primary">
<h5 class="card-title">Active Deployments</h5> <h5 class="card-title">Active Deployments</h5>
<div class="d-flex justify-content-between align-items-end"> <div class="d-flex justify-content-between align-items-end">
<h2 class="mb-0">{% if app_provider_data is defined and app_provider_data.active_deployments is defined %}{{ app_provider_data.active_deployments }}{% else %}0{% endif %}</h2> <h2 class="mb-0">{% if application_provider_data is defined and application_provider_data.active_deployments is defined %}{{ application_provider_data.active_deployments }}{% else %}0{% endif %}</h2>
<small class="text-muted">Instances</small> <small class="text-muted">Instances</small>
</div> </div>
</div> </div>
@@ -31,7 +31,7 @@
<div class="stats-card warning"> <div class="stats-card warning">
<h5 class="card-title">Customer Base</h5> <h5 class="card-title">Customer Base</h5>
<div class="d-flex justify-content-between align-items-end"> <div class="d-flex justify-content-between align-items-end">
<h2 class="mb-0">{% if app_provider_data is defined and app_provider_data.total_deployments is defined %}{{ app_provider_data.total_deployments }}{% else %}0{% endif %}</h2> <h2 class="mb-0">{% if application_provider_data is defined and application_provider_data.total_deployments is defined %}{{ application_provider_data.total_deployments }}{% else %}0{% endif %}</h2>
<small class="text-muted">Total Deployments</small> <small class="text-muted">Total Deployments</small>
</div> </div>
</div> </div>
@@ -40,7 +40,7 @@
<div class="stats-card success"> <div class="stats-card success">
<h5 class="card-title">Monthly Earnings</h5> <h5 class="card-title">Monthly Earnings</h5>
<div class="d-flex justify-content-between align-items-end"> <div class="d-flex justify-content-between align-items-end">
<h2 class="mb-0">{% if app_provider_data is defined and app_provider_data.monthly_revenue_usd is defined %}{{ app_provider_data.monthly_revenue_usd }}{% else %}0{% endif %}</h2> <h2 class="mb-0">{% if application_provider_data is defined and application_provider_data.monthly_revenue_usd is defined %}{{ application_provider_data.monthly_revenue_usd }}{% else %}0{% endif %}</h2>
<small class="text-muted">$/month</small> <small class="text-muted">$/month</small>
</div> </div>
</div> </div>
@@ -232,8 +232,8 @@
{{ super() }} {{ super() }}
<!-- Hydration JSON for initial app provider dashboard data (safe, non-executable) --> <!-- Hydration JSON for initial app provider dashboard data (safe, non-executable) -->
<script id="ap-dashboard-hydration" type="application/json"> <script id="ap-dashboard-hydration" type="application/json">
{% if app_provider_data is defined %} {% if application_provider_data is defined %}
{{ app_provider_data | json_encode() }} {{ application_provider_data | json_encode() }}
{% else %} {% else %}
null null
{% endif %} {% endif %}

View File

@@ -92,7 +92,7 @@
<div class="row align-items-center mb-4"> <div class="row align-items-center mb-4">
<div class="col-md-6"> <div class="col-md-6">
<img src="/static/images/docs/application-flow.svg" alt="Application Solution Flow Diagram" class="img-fluid rounded shadow"> <img src="/static/images/docs/application-flow.svg" alt="Agentic Apps Flow Diagram" class="img-fluid rounded shadow">
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<ol class="list-group list-group-numbered mb-0"> <ol class="list-group list-group-numbered mb-0">

View File

@@ -58,7 +58,7 @@
<td><a href="/docs/gateways" class="btn btn-sm btn-outline-primary">Learn More</a></td> <td><a href="/docs/gateways" class="btn btn-sm btn-outline-primary">Learn More</a></td>
</tr> </tr>
<tr> <tr>
<td><strong>Application Solutions</strong></td> <td><strong>Agentic Apps</strong></td>
<td>Pre-configured, self-healing applications</td> <td>Pre-configured, self-healing applications</td>
<td>Credits paid to application providers for application management while users maintain sovereignty</td> <td>Credits paid to application providers for application management while users maintain sovereignty</td>
<td><a href="/docs/applications" class="btn btn-sm btn-outline-primary">Learn More</a></td> <td><a href="/docs/applications" class="btn btn-sm btn-outline-primary">Learn More</a></td>

View File

@@ -44,7 +44,7 @@
<td>Credits paid based on bandwidth consumption</td> <td>Credits paid based on bandwidth consumption</td>
</tr> </tr>
<tr> <tr>
<td><strong>Application Solutions</strong></td> <td><strong>Agentic Apps</strong></td>
<td>Pre-configured, self-healing applications</td> <td>Pre-configured, self-healing applications</td>
<td>Users provide slices to application providers while maintaining sovereignty</td> <td>Users provide slices to application providers while maintaining sovereignty</td>
</tr> </tr>

View File

@@ -70,7 +70,7 @@
<li>Mycelium Nodes</li> <li>Mycelium Nodes</li>
<li>Mycelium Gateways</li> <li>Mycelium Gateways</li>
<li>Bandwidth Providers</li> <li>Bandwidth Providers</li>
<li>Application Solutions</li> <li>Agentic Apps</li>
<li>Human Energy Services</li> <li>Human Energy Services</li>
</ul> </ul>

View File

@@ -42,12 +42,12 @@ async fn test_complete_provider_dashboards_ux_workflow() {
// Test users for different provider types // Test users for different provider types
let farmer_email = "farmer_dashboard_test@example.com"; let farmer_email = "farmer_dashboard_test@example.com";
let app_provider_email = "app_provider_test@example.com"; let application_provider_email = "application_provider_test@example.com";
let service_provider_email = "service_provider_test@example.com"; let service_provider_email = "service_provider_test@example.com";
// Clean up any existing test data // Clean up any existing test data
cleanup_test_user_data(farmer_email); cleanup_test_user_data(farmer_email);
cleanup_test_user_data(app_provider_email); cleanup_test_user_data(application_provider_email);
cleanup_test_user_data(service_provider_email); cleanup_test_user_data(service_provider_email);
// Initialize services // Initialize services
@@ -133,8 +133,8 @@ async fn test_complete_provider_dashboards_ux_workflow() {
println!("✅ Farmer Dashboard: WORKING - Node management, capacity planning, earnings tracking"); println!("✅ Farmer Dashboard: WORKING - Node management, capacity planning, earnings tracking");
// Step 3: Test Application Provider Dashboard (/dashboard/app-provider) // Step 3: Test Application Provider Dashboard (/dashboard/application-provider)
println!("\n🔧 Step 3: Test Application Provider Dashboard (/dashboard/app-provider)"); println!("\n🔧 Step 3: Test Application Provider Dashboard (/dashboard/application-provider)");
// Create test app provider profile // Create test app provider profile
let published_apps = vec![ let published_apps = vec![
@@ -144,7 +144,7 @@ async fn test_complete_provider_dashboards_ux_workflow() {
("backup-solution", "Automated Backup Tool", 34, 4.1, "pending"), ("backup-solution", "Automated Backup Tool", 34, 4.1, "pending"),
]; ];
println!(" 📱 Application Provider: {}", app_provider_email); println!(" 📱 Application Provider: {}", application_provider_email);
println!(" 📊 Published Applications:"); println!(" 📊 Published Applications:");
let mut total_installs = 0; let mut total_installs = 0;
@@ -282,7 +282,7 @@ async fn test_complete_provider_dashboards_ux_workflow() {
// Final cleanup // Final cleanup
cleanup_test_user_data(farmer_email); cleanup_test_user_data(farmer_email);
cleanup_test_user_data(app_provider_email); cleanup_test_user_data(application_provider_email);
cleanup_test_user_data(service_provider_email); cleanup_test_user_data(service_provider_email);
// Final verification // Final verification
@@ -321,7 +321,7 @@ async fn test_provider_dashboards_performance() {
let start_time = std::time::Instant::now(); let start_time = std::time::Instant::now();
// Simulate dashboard data loading // Simulate dashboard data loading
let provider_types = vec!["farmer", "app_provider", "service_provider"]; let provider_types = vec!["farmer", "application_provider", "service_provider"];
for provider_type in provider_types { for provider_type in provider_types {
// Simulate dashboard page load // Simulate dashboard page load

View File

@@ -165,7 +165,7 @@ impl TestDataManager {
/// Create test marketplace data /// Create test marketplace data
fn create_test_marketplace_data(personas: &HashMap<UserRole, TestPersona>) -> TestMarketplaceData { fn create_test_marketplace_data(personas: &HashMap<UserRole, TestPersona>) -> TestMarketplaceData {
let farmer_email = personas.get(&UserRole::Farmer).unwrap().email.clone(); let farmer_email = personas.get(&UserRole::Farmer).unwrap().email.clone();
let app_provider_email = personas.get(&UserRole::AppProvider).unwrap().email.clone(); let application_provider_email = personas.get(&UserRole::AppProvider).unwrap().email.clone();
let service_provider_email = personas.get(&UserRole::ServiceProvider).unwrap().email.clone(); let service_provider_email = personas.get(&UserRole::ServiceProvider).unwrap().email.clone();
TestMarketplaceData { TestMarketplaceData {
@@ -186,7 +186,7 @@ impl TestDataManager {
price: 25.0, price: 25.0,
currency: "TFC".to_string(), currency: "TFC".to_string(),
description: "Test application for UX testing".to_string(), description: "Test application for UX testing".to_string(),
provider_email: app_provider_email.clone(), provider_email: application_provider_email.clone(),
}, },
], ],
services: vec![ services: vec![