mirror of
https://github.com/DRYTRIX/TimeTracker.git
synced 2026-05-24 07:10:21 -05:00
463704f054
Unify buttons, cards, headers, toasts, and form treatments across the app so screens feel consistent and are easier to scan on desktop and mobile. Update the broader template set to use the shared UI primitives and responsive spacing patterns introduced in this refresh.
168 lines
11 KiB
HTML
168 lines
11 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}{{ integration.name }} - {{ _('Integration') }} - {{ app_name }}{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="flex flex-col md:flex-row justify-between items-start md:items-center mb-6">
|
|
<div>
|
|
<h1 class="text-2xl font-bold">{{ integration.name }}</h1>
|
|
<p class="text-text-muted-light dark:text-text-muted-dark">{{ integration.provider|title }}</p>
|
|
</div>
|
|
<a href="{{ url_for('integrations.list_integrations') }}" class="bg-gray-200 dark:bg-gray-700 px-4 py-2 rounded-lg mt-4 md:mt-0">{{ _('Back to Integrations') }}</a>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
<div class="lg:col-span-2 space-y-6">
|
|
<div class="bg-card-light dark:bg-card-dark p-6 rounded-xl border border-border-light dark:border-border-dark shadow-sm">
|
|
<h2 class="text-lg font-semibold mb-4">{{ _('Integration Status') }}</h2>
|
|
<dl class="space-y-3">
|
|
<div>
|
|
<dt class="text-sm font-medium text-text-muted-light dark:text-text-muted-dark">{{ _('Status') }}</dt>
|
|
<dd>
|
|
{% if integration.is_active %}
|
|
<span class="px-2 py-1 text-xs rounded bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200">{{ _('Active') }}</span>
|
|
{% else %}
|
|
<span class="px-2 py-1 text-xs rounded bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-200">{{ _('Inactive') }}</span>
|
|
{% endif %}
|
|
</dd>
|
|
</div>
|
|
{% if credentials %}
|
|
<div>
|
|
<dt class="text-sm font-medium text-text-muted-light dark:text-text-muted-dark">{{ _('Connected') }}</dt>
|
|
<dd class="text-text-light dark:text-text-dark">{{ _('Yes') }}</dd>
|
|
</div>
|
|
{% if credentials.expires_at %}
|
|
<div>
|
|
<dt class="text-sm font-medium text-text-muted-light dark:text-text-muted-dark">{{ _('Token Expires') }}</dt>
|
|
<dd class="text-text-light dark:text-text-dark">{{ credentials.expires_at|user_datetime }}</dd>
|
|
</div>
|
|
{% endif %}
|
|
{% else %}
|
|
<div>
|
|
<dt class="text-sm font-medium text-text-muted-light dark:text-text-muted-dark">{{ _('Connected') }}</dt>
|
|
<dd class="text-text-light dark:text-text-dark">{{ _('No') }}</dd>
|
|
</div>
|
|
{% endif %}
|
|
{% if integration.last_sync_at %}
|
|
<div>
|
|
<dt class="text-sm font-medium text-text-muted-light dark:text-text-muted-dark">{{ _('Last Sync') }}</dt>
|
|
<dd class="text-text-light dark:text-text-dark">
|
|
{{ integration.last_sync_at|user_datetime }}
|
|
{% if integration.last_sync_status %}
|
|
{% if integration.last_sync_status == 'success' %}
|
|
<span class="ml-2 px-2 py-1 text-xs rounded bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200">{{ _('Success') }}</span>
|
|
{% elif integration.last_sync_status == 'error' %}
|
|
<span class="ml-2 px-2 py-1 text-xs rounded bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200">{{ _('Error') }}</span>
|
|
{% else %}
|
|
<span class="ml-2 px-2 py-1 text-xs rounded bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200">{{ _('Pending') }}</span>
|
|
{% endif %}
|
|
{% endif %}
|
|
</dd>
|
|
</div>
|
|
{% endif %}
|
|
{% if integration.last_error %}
|
|
<div>
|
|
<dt class="text-sm font-medium text-text-muted-light dark:text-text-muted-dark">{{ _('Last Error') }}</dt>
|
|
<dd class="text-text-light dark:text-text-dark text-sm text-red-600 dark:text-red-400">{{ integration.last_error[:100] }}{% if integration.last_error|length > 100 %}...{% endif %}</dd>
|
|
</div>
|
|
{% endif %}
|
|
</dl>
|
|
</div>
|
|
|
|
<!-- Sync Events Log -->
|
|
<div class="bg-card-light dark:bg-card-dark p-6 rounded-xl border border-border-light dark:border-border-dark shadow-sm mt-6">
|
|
<h2 class="text-lg font-semibold mb-4">{{ _('Sync History') }}</h2>
|
|
{% if recent_events %}
|
|
<div class="space-y-2 max-h-96 overflow-y-auto">
|
|
{% for event in recent_events %}
|
|
<div class="border-b border-border-light dark:border-border-dark pb-2 last:border-0">
|
|
<div class="flex items-start justify-between">
|
|
<div class="flex-1">
|
|
<div class="flex items-center gap-2">
|
|
<span class="text-sm font-medium text-text-light dark:text-text-dark">{{ event.event_type|replace('_', ' ')|title }}</span>
|
|
{% if event.status == 'success' %}
|
|
<span class="px-2 py-0.5 text-xs rounded bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200">{{ _('Success') }}</span>
|
|
{% elif event.status == 'error' %}
|
|
<span class="px-2 py-0.5 text-xs rounded bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200">{{ _('Error') }}</span>
|
|
{% else %}
|
|
<span class="px-2 py-0.5 text-xs rounded bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200">{{ _('Pending') }}</span>
|
|
{% endif %}
|
|
</div>
|
|
{% if event.message %}
|
|
<p class="text-sm text-text-muted-light dark:text-text-muted-dark mt-1">{{ event.message }}</p>
|
|
{% endif %}
|
|
<p class="text-xs text-text-muted-light dark:text-text-muted-dark mt-1">{{ event.created_at|user_datetime }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% else %}
|
|
<p class="text-text-muted-light dark:text-text-muted-dark">{{ _('No sync events yet') }}</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<div class="bg-card-light dark:bg-card-dark p-6 rounded-xl border border-border-light dark:border-border-dark shadow-sm">
|
|
<h3 class="text-lg font-semibold mb-4">{{ _('Actions') }}</h3>
|
|
{% if connector_error %}
|
|
<div class="mb-4 p-3 bg-red-100 dark:bg-red-900/20 border border-red-300 dark:border-red-800 rounded-lg">
|
|
<p class="text-sm text-red-800 dark:text-red-200">
|
|
<i class="fas fa-exclamation-triangle mr-2"></i>
|
|
{{ _('Connector Error') }}: {{ connector_error }}
|
|
</p>
|
|
{% if integration.provider == 'caldav_calendar' %}
|
|
<a href="{{ url_for('integrations.caldav_setup') }}" class="mt-2 inline-block text-sm text-red-800 dark:text-red-200 hover:underline">
|
|
{{ _('Configure CalDAV Integration') }} →
|
|
</a>
|
|
{% elif integration.provider == 'activitywatch' %}
|
|
<a href="{{ url_for('integrations.activitywatch_setup') }}" class="mt-2 inline-block text-sm text-red-800 dark:text-red-200 hover:underline">
|
|
{{ _('Configure ActivityWatch') }} →
|
|
</a>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
<div class="space-y-2">
|
|
{% if connector %}
|
|
<form method="POST" action="{{ url_for('integrations.test_integration', integration_id=integration.id) }}" class="mb-2">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
|
<button type="submit" class="w-full bg-blue-600 text-white px-4 py-2 min-h-[44px] rounded-lg hover:bg-blue-700 transition-colors {% if not connector %}opacity-50 cursor-not-allowed{% endif %}" {% if not connector %}disabled{% endif %}>
|
|
<i class="fas fa-vial mr-2"></i>{{ _('Test Connection') }}
|
|
</button>
|
|
</form>
|
|
<form method="POST" action="{{ url_for('integrations.sync_integration', integration_id=integration.id) }}" class="mb-2">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
|
<button type="submit" class="w-full bg-green-600 text-white px-4 py-2 min-h-[44px] rounded-lg hover:bg-green-700 transition-colors {% if not connector %}opacity-50 cursor-not-allowed{% endif %}" {% if not connector %}disabled{% endif %}>
|
|
<i class="fas fa-sync mr-2"></i>{{ _('Sync Now') }}
|
|
</button>
|
|
</form>
|
|
{% endif %}
|
|
<form method="POST" action="{{ url_for('integrations.reset_integration', integration_id=integration.id) }}" onsubmit="return confirm('{{ _('Are you sure you want to reset this integration? This will remove all credentials and configuration.') }}')" class="mb-2">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
|
<button type="submit" class="w-full bg-orange-600 text-white px-4 py-2 min-h-[44px] rounded-lg hover:bg-orange-700 transition-colors">
|
|
<i class="fas fa-redo mr-2"></i>{{ _('Reset') }}
|
|
</button>
|
|
</form>
|
|
<form method="POST" action="{{ url_for('integrations.delete_integration', integration_id=integration.id) }}" onsubmit="return confirm('{{ _('Are you sure you want to delete this integration? This action cannot be undone.') }}')">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
|
<button type="submit" class="w-full bg-red-600 text-white px-4 py-2 min-h-[44px] rounded-lg hover:bg-red-700 transition-colors">
|
|
<i class="fas fa-trash mr-2"></i>{{ _('Delete') }}
|
|
</button>
|
|
</form>
|
|
{% if integration.provider == 'caldav_calendar' %}
|
|
<a href="{{ url_for('integrations.caldav_setup') }}" class="block w-full bg-gray-600 text-white px-4 py-2 rounded-lg hover:bg-gray-700 transition-colors text-center">
|
|
<i class="fas fa-cog mr-2"></i>{{ _('Edit Configuration') }}
|
|
</a>
|
|
{% elif integration.provider == 'activitywatch' %}
|
|
<a href="{{ url_for('integrations.activitywatch_setup') }}" class="block w-full bg-gray-600 text-white px-4 py-2 rounded-lg hover:bg-gray-700 transition-colors text-center">
|
|
<i class="fas fa-cog mr-2"></i>{{ _('Edit Configuration') }}
|
|
</a>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|