mirror of
https://github.com/DRYTRIX/TimeTracker.git
synced 2026-05-20 05:10:26 -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.
222 lines
13 KiB
HTML
222 lines
13 KiB
HTML
{% extends "base.html" %}
|
|
{% from "components/ui.html" import page_header %}
|
|
|
|
{% block title %}{{ _('CalDAV Calendar Setup') }} - {{ app_name }}{% endblock %}
|
|
|
|
{% block content %}
|
|
{% set breadcrumbs = [
|
|
{'text': 'Integrations', 'url': url_for('integrations.list_integrations')},
|
|
{'text': 'CalDAV Calendar Setup'}
|
|
] %}
|
|
|
|
{{ page_header(
|
|
icon_class='fas fa-calendar',
|
|
title_text=_('CalDAV Calendar Setup'),
|
|
subtitle_text=_('Connect to a CalDAV server (e.g., Zimbra) to import calendar events as time entries'),
|
|
breadcrumbs=breadcrumbs
|
|
) }}
|
|
|
|
<div class="bg-card-light dark:bg-card-dark p-6 rounded-xl border border-border-light dark:border-border-dark shadow-sm mb-6">
|
|
<form method="POST">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
|
|
|
<div class="space-y-6">
|
|
<div>
|
|
<h3 class="text-lg font-semibold mb-4">{{ _('Server Connection') }}</h3>
|
|
<div class="space-y-4">
|
|
<div>
|
|
<label for="server_url" class="block text-sm font-medium mb-2">
|
|
{{ _('CalDAV Server URL') }} <span class="text-text-muted-light dark:text-text-muted-dark">({{ _('optional if calendar URL is provided') }})</span>
|
|
</label>
|
|
<input type="url"
|
|
name="server_url"
|
|
id="server_url"
|
|
value="{{ integration.config.get('server_url', '') if integration.config else '' }}"
|
|
class="w-full px-3 py-2 border border-border-light dark:border-border-dark rounded-lg bg-card-light dark:bg-card-dark"
|
|
placeholder="https://mail.example.com/dav">
|
|
<p class="mt-1 text-xs text-text-muted-light dark:text-text-muted-dark">
|
|
{{ _('Base URL of your CalDAV server. Used for calendar discovery.') }}
|
|
{{ _('Example: https://mail.example.com/dav for Zimbra') }}
|
|
</p>
|
|
</div>
|
|
|
|
<div>
|
|
<label for="calendar_url" class="block text-sm font-medium mb-2">
|
|
{{ _('Calendar URL') }} <span class="text-text-muted-light dark:text-text-muted-dark">({{ _('optional if server URL is provided') }})</span>
|
|
</label>
|
|
<input type="url"
|
|
name="calendar_url"
|
|
id="calendar_url"
|
|
value="{{ integration.config.get('calendar_url', '') if integration.config else '' }}"
|
|
class="w-full px-3 py-2 border border-border-light dark:border-border-dark rounded-lg bg-card-light dark:bg-card-dark"
|
|
placeholder="https://mail.example.com/dav/user@example.com/Calendar/">
|
|
<p class="mt-1 text-xs text-text-muted-light dark:text-text-muted-dark">
|
|
{{ _('Direct URL to your calendar collection. If provided, server URL is only used for discovery.') }}
|
|
</p>
|
|
</div>
|
|
|
|
<div>
|
|
<label for="calendar_name" class="block text-sm font-medium mb-2">
|
|
{{ _('Calendar Name') }} <span class="text-text-muted-light dark:text-text-muted-dark">({{ _('optional') }})</span>
|
|
</label>
|
|
<input type="text"
|
|
name="calendar_name"
|
|
id="calendar_name"
|
|
value="{{ integration.config.get('calendar_name', '') if integration.config else '' }}"
|
|
class="w-full px-3 py-2 border border-border-light dark:border-border-dark rounded-lg bg-card-light dark:bg-card-dark"
|
|
placeholder="{{ _('My Calendar') }}">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<h3 class="text-lg font-semibold mb-4">{{ _('Authentication') }}</h3>
|
|
<div class="space-y-4">
|
|
<div>
|
|
<label for="username" class="block text-sm font-medium mb-2">
|
|
{{ _('Username') }} <span class="text-red-500">*</span>
|
|
</label>
|
|
<input type="text"
|
|
name="username"
|
|
id="username"
|
|
value="{{ integration.credentials.extra_data.get('username', '') if integration.credentials and integration.credentials.extra_data else '' }}"
|
|
class="w-full px-3 py-2 border border-border-light dark:border-border-dark rounded-lg bg-card-light dark:bg-card-dark"
|
|
placeholder="user@example.com"
|
|
required>
|
|
<p class="mt-1 text-xs text-text-muted-light dark:text-text-muted-dark">
|
|
{{ _('Your CalDAV username (usually your email address).') }}
|
|
</p>
|
|
</div>
|
|
|
|
<div>
|
|
<label for="password" class="block text-sm font-medium mb-2">
|
|
{{ _('Password') }} {% if not integration.credentials %}<span class="text-red-500">*</span>{% endif %}
|
|
</label>
|
|
<input type="password"
|
|
name="password"
|
|
id="password"
|
|
class="w-full px-3 py-2 border border-border-light dark:border-border-dark rounded-lg bg-card-light dark:bg-card-dark"
|
|
placeholder="{{ _('Leave empty to keep current password') }}"
|
|
{% if not integration.credentials %}required{% endif %}>
|
|
<p class="mt-1 text-xs text-text-muted-light dark:text-text-muted-dark">
|
|
{{ _('Your CalDAV password or app-specific password.') }}
|
|
{% if integration.credentials %}
|
|
{{ _('Leave empty to keep your current password.') }}
|
|
{% endif %}
|
|
</p>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="flex items-center">
|
|
<input type="checkbox"
|
|
name="verify_ssl"
|
|
id="verify_ssl"
|
|
{% if integration.config and integration.config.get('verify_ssl', True) %}checked{% endif %}
|
|
class="mr-2">
|
|
<span class="text-sm">{{ _('Verify SSL certificate') }}</span>
|
|
</label>
|
|
<p class="mt-1 text-xs text-text-muted-light dark:text-text-muted-dark ml-6">
|
|
{{ _('Uncheck only if using a self-signed certificate.') }}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<h3 class="text-lg font-semibold mb-4">{{ _('Import Settings') }}</h3>
|
|
<div class="space-y-4">
|
|
<div>
|
|
<label for="default_project_id" class="block text-sm font-medium mb-2">
|
|
{{ _('Default Project') }} <span class="text-text-muted-light dark:text-text-muted-dark">({{ _('optional') }})</span>
|
|
</label>
|
|
{% if projects %}
|
|
<select name="default_project_id"
|
|
id="default_project_id"
|
|
class="w-full px-3 py-2 border border-border-light dark:border-border-dark rounded-lg bg-card-light dark:bg-card-dark">
|
|
<option value="">{{ _('No project (import without project)') }}</option>
|
|
{% for project in projects %}
|
|
<option value="{{ project.id }}"
|
|
{% if integration.config and integration.config.get('default_project_id') == project.id %}selected{% endif %}>
|
|
{{ project.name }}
|
|
</option>
|
|
{% endfor %}
|
|
</select>
|
|
<p class="mt-1 text-xs text-text-muted-light dark:text-text-muted-dark">
|
|
{{ _('Calendar events will be imported as time entries. If a project is selected, events will be assigned to that project.') }}
|
|
{{ _('If an event title contains a project name, that project will be used instead.') }}
|
|
{{ _('If no project is selected, events will be imported without a project.') }}
|
|
</p>
|
|
{% else %}
|
|
<div class="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-4">
|
|
<p class="text-sm text-blue-800 dark:text-blue-200">
|
|
<i class="fas fa-info-circle mr-2"></i>
|
|
{{ _('No active projects found. Events will be imported without a project.') }}
|
|
{{ _('You can create a project later and assign events to it.') }}
|
|
</p>
|
|
<a href="{{ url_for('projects.create_project') }}" class="mt-2 inline-block text-sm text-blue-800 dark:text-blue-200 hover:underline">
|
|
{{ _('Create a project') }} →
|
|
</a>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div>
|
|
<label for="lookback_days" class="block text-sm font-medium mb-2">
|
|
{{ _('Lookback Days') }}
|
|
</label>
|
|
<input type="number"
|
|
name="lookback_days"
|
|
id="lookback_days"
|
|
value="{{ integration.config.get('lookback_days', 90) if integration.config else 90 }}"
|
|
min="1"
|
|
max="365"
|
|
class="w-full px-3 py-2 border border-border-light dark:border-border-dark rounded-lg bg-card-light dark:bg-card-dark">
|
|
<p class="mt-1 text-xs text-text-muted-light dark:text-text-muted-dark">
|
|
{{ _('How many days back to import events from (default: 90).') }}
|
|
</p>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="flex items-center">
|
|
<input type="checkbox"
|
|
name="auto_sync"
|
|
id="auto_sync"
|
|
{% if integration.config and integration.config.get('auto_sync', True) %}checked{% endif %}
|
|
class="mr-2">
|
|
<span class="text-sm">{{ _('Enable automatic sync') }}</span>
|
|
</label>
|
|
<p class="mt-1 text-xs text-text-muted-light dark:text-text-muted-dark ml-6">
|
|
{{ _('Automatically sync calendar events every hour. You can still trigger manual syncs.') }}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-6 flex flex-col sm:flex-row gap-3">
|
|
<button type="submit"
|
|
class="bg-primary text-white px-6 py-2 min-h-[44px] rounded-lg hover:bg-primary/90 transition-colors">
|
|
<i class="fas fa-save mr-2"></i>{{ _('Save Configuration') }}
|
|
</button>
|
|
<a href="{{ url_for('integrations.list_integrations') }}" class="bg-gray-200 dark:bg-gray-700 px-6 py-2 min-h-[44px] rounded-lg hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors inline-flex items-center justify-center">
|
|
{{ _('Cancel') }}
|
|
</a>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
{% if integration.credentials %}
|
|
<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">{{ _('Test Connection') }}</h3>
|
|
<p class="text-sm text-text-muted-light dark:text-text-muted-dark mb-4">
|
|
{{ _('After saving, you can test the connection and discover available calendars.') }}
|
|
</p>
|
|
<a href="{{ url_for('integrations.view_integration', integration_id=integration.id) }}" class="bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors inline-block">
|
|
<i class="fas fa-vial mr-2"></i>{{ _('Test Connection') }}
|
|
</a>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% endblock %}
|
|
|