agnes-the-ai-analyst/webapp/templates/login.html
Petr c6a711aa27 Extract pluggable auth provider system into auth/ package
Replace hardcoded Google OAuth + password auth registration with
auto-discovered auth providers. Each provider in auth/<name>/provider.py
implements AuthProvider ABC and is automatically registered at startup.

- auth/__init__.py: AuthProvider ABC + discover_providers() scanner
- auth/google/: Google OAuth provider (extracted from webapp/auth.py)
- auth/password/: Email/password provider (delegates to webapp/password_auth)
- auth/desktop/: Desktop JWT auth (API-only, not visible on login page)
- webapp/auth.py: stripped to core infra (login_required, /login, /logout)
- webapp/app.py: auto-discovery loop replaces manual blueprint registration
- login.html: dynamic provider buttons via Jinja loop
2026-03-09 13:02:08 +01:00

126 lines
5.9 KiB
HTML

{% extends "base_login.html" %}
{% block title %}Login - Data Analyst Portal{% endblock %}
{% block content %}
<div class="login-page">
<div class="login-split">
<!-- Left: Features & Value Proposition -->
<div class="login-features">
<div class="features-content">
<h1 class="features-title">{{ config.INSTANCE_NAME }}</h1>
<p class="features-subtitle">
Your local AI agent works with centralized data, shared context, and corporate memory that learns from everyone.
</p>
<div class="feature-cards">
<div class="feature-card">
<div class="feature-icon feature-icon-data">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<ellipse cx="12" cy="5" rx="9" ry="3"/>
<path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"/>
<path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/>
</svg>
</div>
<div class="feature-text">
<h3>Unified Data Access</h3>
<p>Synced data from central server with semantic layer, metrics definitions, and full documentation.</p>
</div>
</div>
<div class="feature-card">
<div class="feature-icon feature-icon-memory">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 2a4 4 0 0 1 4 4c0 1.1-.9 2-2 2h-4c-1.1 0-2-.9-2-2a4 4 0 0 1 4-4z"/>
<path d="M12 8v8"/>
<path d="M8 12h8"/>
<circle cx="12" cy="19" r="3"/>
</svg>
</div>
<div class="feature-text">
<h3>Corporate Memory</h3>
<p>Shared context across all users. When someone discovers something, everyone's AI knows it.</p>
</div>
</div>
<div class="feature-card">
<div class="feature-icon feature-icon-auto">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/>
</svg>
</div>
<div class="feature-text">
<h3>Instant Automation</h3>
<p>Turn any analysis into automated scripts. Runs without AI - fast, cheap, and repeatable.</p>
</div>
</div>
<div class="feature-card">
<div class="feature-icon feature-icon-notif">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/>
<path d="M13.73 21a2 2 0 0 1-3.46 0"/>
</svg>
</div>
<div class="feature-text">
<h3>Smart Notifications</h3>
<p>Your AI agent can set up alerts and deploy them to the cloud. Server monitors 24/7.</p>
</div>
</div>
<div class="feature-card">
<div class="feature-icon feature-icon-performance">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M3 3v18h18"/>
<path d="M18 17V9"/>
<path d="M13 17v-6"/>
<path d="M8 17v-3"/>
<polyline points="7 7 12 3 17 6 22 2"/>
</svg>
</div>
<div class="feature-text">
<h3>Performance Intelligence</h3>
<p>Track how data and AI drive measurable business outcomes. Real-time visibility into team maturity, process improvements, and ROI across departments.</p>
</div>
</div>
</div>
</div>
</div>
<!-- Right: Login Card -->
<div class="login-card-wrapper">
<div class="login-card">
<h2>Sign In</h2>
<p class="login-description">
Access your AI data analysis workspace
</p>
{% for btn in login_buttons %}
<a href="{{ btn.url }}" class="btn {{ btn.css_class|default('btn-secondary') }}" style="width: 100%; max-width: 280px;">
{% if btn.icon_html %}{{ btn.icon_html|safe }}{% endif %}
{{ btn.text }}
</a>
{% if btn.subtitle %}
<p class="login-note">
{{ btn.subtitle|safe }}
</p>
{% endif %}
{% if not loop.last %}
<div class="divider">
<span>or</span>
</div>
{% endif %}
{% endfor %}
{% if not login_buttons %}
<p class="login-note">
No authentication providers are configured. Please set up at least one provider.
</p>
{% endif %}
</div>
</div>
</div>
</div>
{% endblock %}