| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- {% extends "base.html" %}
- {% block title %}{{ 'Éditer' if job else 'Nouveau job' }}{% endblock %}
- {% block content %}
- <div class="max-w-2xl">
- <h1 class="text-xl font-bold text-gray-900 mb-6">
- {{ 'Éditer « ' + job.name + ' »' if job else 'Nouveau job de sauvegarde' }}
- </h1>
- <form method="post"
- action="{{ url_for('job_edit', job_id=job.id) if job else url_for('job_new') }}"
- class="space-y-6">
- {# ── Infos générales ── #}
- <div class="bg-white rounded-xl border border-gray-200 p-6 space-y-4">
- <h2 class="text-sm font-semibold text-gray-700 uppercase tracking-wide">Général</h2>
- <div>
- <label class="block text-sm font-medium text-gray-700 mb-1">Nom du job</label>
- <input type="text" name="name" required
- value="{{ job.name if job else '' }}"
- placeholder="ex: Nextcloud quotidien"
- class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500">
- </div>
- <div>
- <label class="block text-sm font-medium text-gray-700 mb-1">Type</label>
- <select name="type" id="job-type"
- class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500">
- {% for val, label in [('ynh_app','Application YunoHost'), ('ynh_system','Système YunoHost'),
- ('custom_dir','Répertoire custom (Phase 2)'), ('mysql','MySQL (Phase 2)'),
- ('postgresql','PostgreSQL (Phase 2)')] %}
- <option value="{{ val }}"
- {% if job and job.type == val %}selected{% endif %}
- {% if val in ('custom_dir','mysql','postgresql') %}disabled class="text-gray-400"{% endif %}>
- {{ label }}
- </option>
- {% endfor %}
- </select>
- </div>
- {# Type-specific config : ynh_app #}
- <div id="cfg-ynh_app" class="type-cfg space-y-3">
- <div>
- <label class="block text-sm font-medium text-gray-700 mb-1">Application YunoHost</label>
- <select name="app_id"
- class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500">
- {% set current_app_id = (job.config_json | fromjson).get('app_id', '') if job and job.config_json else '' %}
- {% for ynh_app in ynh_apps %}
- <option value="{{ ynh_app.id }}"
- {% if ynh_app.id == current_app_id %}selected{% endif %}>
- {{ ynh_app.id }}{% if ynh_app.label %} — {{ ynh_app.label }}{% endif %}
- </option>
- {% endfor %}
- {% if not ynh_apps %}
- <option value="">Aucune application trouvée</option>
- {% endif %}
- </select>
- </div>
- <div class="flex items-center gap-2">
- {% set core_only = (job.config_json | fromjson).get('core_only', False) if job and job.config_json else False %}
- <input type="checkbox" name="core_only" value="1" id="core_only"
- {% if core_only %}checked{% endif %}
- class="rounded border-gray-300 text-blue-600">
- <label for="core_only" class="text-sm text-gray-700">
- Core only (BACKUP_CORE_ONLY=1) — exclut les données utilisateur
- </label>
- </div>
- </div>
- {# Type-specific config : ynh_system (rien de spécifique) #}
- <div id="cfg-ynh_system" class="type-cfg hidden">
- <p class="text-sm text-gray-500 bg-gray-50 rounded-lg p-3">
- Sauvegarde la configuration système YunoHost complète.
- Aucun paramètre supplémentaire.
- </p>
- </div>
- </div>
- {# ── Planification ── #}
- <div class="bg-white rounded-xl border border-gray-200 p-6 space-y-4">
- <h2 class="text-sm font-semibold text-gray-700 uppercase tracking-wide">Planification</h2>
- <div>
- <label class="block text-sm font-medium text-gray-700 mb-1">Expression cron</label>
- <input type="text" name="cron_expr" required
- value="{{ job.cron_expr if job else '0 3 * * *' }}"
- placeholder="0 3 * * *"
- class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm font-mono focus:outline-none focus:ring-2 focus:ring-blue-500">
- <p class="text-xs text-gray-400 mt-1">
- Format : minute heure jour mois jour_semaine
- — ex: <code class="bg-gray-100 px-1 rounded">0 3 * * *</code> = tous les jours à 3h
- · <code class="bg-gray-100 px-1 rounded">0 3 * * 1</code> = chaque lundi à 3h
- </p>
- </div>
- </div>
- {# ── Rétention ── #}
- <div class="bg-white rounded-xl border border-gray-200 p-6 space-y-4">
- <h2 class="text-sm font-semibold text-gray-700 uppercase tracking-wide">Rétention</h2>
- <div class="grid grid-cols-2 gap-4">
- <div>
- <label class="block text-sm font-medium text-gray-700 mb-1">Mode</label>
- <select name="retention_mode"
- class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500">
- {% for val, label in [('count','Count — N dernières archives'),
- ('daily','Daily — 1 par jour sur N jours'),
- ('gfs','GFS — Grand/Père/Fils (Phase 4)')] %}
- <option value="{{ val }}"
- {% if job and job.retention_mode == val %}selected{% endif %}
- {% if val == 'gfs' %}disabled class="text-gray-400"{% endif %}>
- {{ label }}
- </option>
- {% endfor %}
- </select>
- </div>
- <div>
- <label class="block text-sm font-medium text-gray-700 mb-1">Valeur</label>
- <input type="number" name="retention_value" min="1" max="365" required
- value="{{ job.retention_value if job else 7 }}"
- class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500">
- </div>
- </div>
- </div>
- {# ── Options ── #}
- <div class="bg-white rounded-xl border border-gray-200 p-6">
- <div class="flex items-center gap-3">
- <input type="checkbox" name="enabled" value="1" id="enabled"
- {% if not job or job.enabled %}checked{% endif %}
- class="rounded border-gray-300 text-blue-600">
- <label for="enabled" class="text-sm font-medium text-gray-700">Job activé</label>
- </div>
- </div>
- {# ── Actions ── #}
- <div class="flex gap-3">
- <button type="submit"
- class="bg-blue-600 hover:bg-blue-700 text-white px-5 py-2 rounded-lg font-medium text-sm transition">
- {{ 'Enregistrer' if job else 'Créer le job' }}
- </button>
- <a href="{{ url_for('index') }}"
- class="bg-white hover:bg-gray-50 text-gray-700 border border-gray-300 px-5 py-2 rounded-lg font-medium text-sm transition">
- Annuler
- </a>
- </div>
- </form>
- </div>
- <script>
- function showTypeConfig() {
- document.querySelectorAll('.type-cfg').forEach(el => el.classList.add('hidden'));
- const type = document.getElementById('job-type').value;
- const el = document.getElementById('cfg-' + type);
- if (el) el.classList.remove('hidden');
- }
- document.getElementById('job-type').addEventListener('change', showTypeConfig);
- showTypeConfig();
- </script>
- {% endblock %}
|