e518bce922
Resolve all merge conflicts between our automation feature branch and current main (v0.163.0, 920 commits ahead). Conflicts resolved: - app/api/__init__.py: add automation_router alongside main's new routers (classification_rules, qr_auth, sessions, system_reset) - app/config.py: add main's new settings (dropbox_use_global_credentials, factory_reset_on_startup, enable_factory_reset) - app/models.py: add main's new models (ClassificationRuleModel, UserSession, QRLoginChallenge, SharePoint integration type) - app/utils/settings_service.py: merge automation_hooks_enabled with main's new metadata entries - docs/API.md: merge automation API docs with main's classification rules docs - docs/ConfigurationGuide.md: add factory reset settings - tests/conftest.py: import both AutomationHook and new main models Migration renumbered: - 037_add_automation_hooks → 040_add_automation_hooks - down_revision: 039_add_classification_rules (was 036_add_document_translation_fields) - Chain: 036 → 037 → 038 → 039 → 040 (automation hooks) For all non-automation files with conflicts, main's version was taken since our branch did not modify those files (conflicts were from a stale prior merge). Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com> Agent-Logs-Url: https://github.com/christianlouis/DocuElevate/sessions/cb62f012-3b69-4415-835e-3857ce3e9f45
549 lines
25 KiB
HTML
549 lines
25 KiB
HTML
{% extends "base.html" %}
|
||
{% block title %}{{ _("help.page_title") }} – DocuElevate{% endblock %}
|
||
|
||
{% block head_extra %}
|
||
<!-- SEO meta tags -->
|
||
<meta name="description" content="{{ _('help.meta_description') }}">
|
||
<meta name="keywords" content="DocuElevate, help, support, document processing, OCR, cloud storage, workflow automation, SaaS">
|
||
<meta name="robots" content="index, follow">
|
||
<link rel="canonical" href="https://{{ external_hostname }}/help">
|
||
|
||
<!-- Open Graph -->
|
||
<meta property="og:title" content="{{ _('help.page_title') }} – DocuElevate">
|
||
<meta property="og:description" content="{{ _('help.og_description') }}">
|
||
<meta property="og:type" content="website">
|
||
<meta property="og:url" content="https://{{ external_hostname }}/help">
|
||
|
||
<!-- Structured data (JSON-LD) for FAQ rich results -->
|
||
<script type="application/ld+json">
|
||
{
|
||
"@context": "https://schema.org",
|
||
"@type": "FAQPage",
|
||
"mainEntity": [
|
||
{
|
||
"@type": "Question",
|
||
"name": "How do I upload documents to DocuElevate?",
|
||
"acceptedAnswer": {
|
||
"@type": "Answer",
|
||
"text": "Navigate to the Upload page, drag-and-drop your files or click Choose File, and DocuElevate will automatically process them with OCR and AI metadata extraction."
|
||
}
|
||
},
|
||
{
|
||
"@type": "Question",
|
||
"name": "Which cloud storage providers does DocuElevate support?",
|
||
"acceptedAnswer": {
|
||
"@type": "Answer",
|
||
"text": "DocuElevate integrates with Dropbox, Google Drive, OneDrive, SharePoint, Amazon S3, Nextcloud, WebDAV, SFTP, FTP, and Paperless-ngx."
|
||
}
|
||
},
|
||
{
|
||
"@type": "Question",
|
||
"name": "Can I automatically ingest documents from email?",
|
||
"acceptedAnswer": {
|
||
"@type": "Answer",
|
||
"text": "Yes. Configure one or more IMAP mailboxes under Email Ingestion and DocuElevate will poll for new attachments and process them automatically."
|
||
}
|
||
},
|
||
{
|
||
"@type": "Question",
|
||
"name": "How do processing pipelines work?",
|
||
"acceptedAnswer": {
|
||
"@type": "Answer",
|
||
"text": "Pipelines let you chain processing steps (OCR, AI extraction, format conversion) and route the result to one or more destinations. Create and manage them from the Pipelines page."
|
||
}
|
||
}
|
||
]
|
||
}
|
||
</script>
|
||
{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="container mx-auto px-4 py-10 max-w-6xl">
|
||
|
||
<!-- ═══════════════════════ Hero Section ═══════════════════════ -->
|
||
<header class="text-center mb-14">
|
||
<h1 class="text-4xl md:text-5xl font-extrabold text-gray-900 mb-4">
|
||
<i class="fas fa-life-ring text-blue-500 mr-2" aria-hidden="true"></i>{{ _("help.heading") }}
|
||
</h1>
|
||
<p class="text-lg md:text-xl text-gray-600 max-w-2xl mx-auto leading-relaxed">
|
||
{{ _("help.subheading") }}
|
||
</p>
|
||
</header>
|
||
|
||
<!-- ═══════════════════════ Quick-start Cards ═══════════════════════ -->
|
||
<section aria-labelledby="quickstart-heading" class="mb-16">
|
||
<h2 id="quickstart-heading" class="text-2xl font-bold text-gray-800 mb-6">
|
||
<i class="fas fa-rocket text-blue-500 mr-2" aria-hidden="true"></i>{{ _("help.quickstart_heading") }}
|
||
</h2>
|
||
<div class="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
|
||
|
||
<!-- Card: Upload -->
|
||
<article class="bg-white shadow rounded-lg p-6 hover:shadow-lg transition-shadow">
|
||
<div class="flex items-center mb-3">
|
||
<span class="flex items-center justify-center w-10 h-10 rounded-full bg-blue-100 text-blue-600 mr-3" aria-hidden="true">
|
||
<i class="fas fa-cloud-arrow-up"></i>
|
||
</span>
|
||
<h3 class="text-lg font-semibold text-gray-800">{{ _("help.quickstart_upload") }}</h3>
|
||
</div>
|
||
<p class="text-gray-600 text-sm leading-relaxed">
|
||
{{ _("help.quickstart_upload_desc") }}
|
||
</p>
|
||
</article>
|
||
|
||
<!-- Card: Connect Storage -->
|
||
<article class="bg-white shadow rounded-lg p-6 hover:shadow-lg transition-shadow">
|
||
<div class="flex items-center mb-3">
|
||
<span class="flex items-center justify-center w-10 h-10 rounded-full bg-green-100 text-green-600 mr-3" aria-hidden="true">
|
||
<i class="fas fa-plug"></i>
|
||
</span>
|
||
<h3 class="text-lg font-semibold text-gray-800">{{ _("help.quickstart_storage") }}</h3>
|
||
</div>
|
||
<p class="text-gray-600 text-sm leading-relaxed">
|
||
{{ _("help.quickstart_storage_desc_full") }}
|
||
</p>
|
||
</article>
|
||
|
||
<!-- Card: Automate -->
|
||
<article class="bg-white shadow rounded-lg p-6 hover:shadow-lg transition-shadow">
|
||
<div class="flex items-center mb-3">
|
||
<span class="flex items-center justify-center w-10 h-10 rounded-full bg-purple-100 text-purple-600 mr-3" aria-hidden="true">
|
||
<i class="fas fa-wand-magic-sparkles"></i>
|
||
</span>
|
||
<h3 class="text-lg font-semibold text-gray-800">{{ _("help.quickstart_workflows") }}</h3>
|
||
</div>
|
||
<p class="text-gray-600 text-sm leading-relaxed">
|
||
{{ _("help.quickstart_workflows_desc") }}
|
||
</p>
|
||
</article>
|
||
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ═══════════════════════ Sources ═══════════════════════ -->
|
||
<section aria-labelledby="sources-heading" class="mb-16">
|
||
<h2 id="sources-heading" class="text-2xl font-bold text-gray-800 mb-6">
|
||
<i class="fas fa-arrow-right-to-bracket text-blue-500 mr-2" aria-hidden="true"></i>{{ _("help.sources_heading") }}
|
||
</h2>
|
||
<div class="grid gap-6 sm:grid-cols-2">
|
||
|
||
<article class="bg-white shadow rounded-lg p-6">
|
||
<h3 class="font-semibold text-gray-800 mb-2"><i class="fas fa-upload mr-2 text-gray-400" aria-hidden="true"></i>{{ _("help.sources_web_upload") }}</h3>
|
||
<p class="text-gray-600 text-sm">
|
||
{{ _("help.sources_web_upload_desc") }}
|
||
</p>
|
||
</article>
|
||
|
||
<article class="bg-white shadow rounded-lg p-6">
|
||
<h3 class="font-semibold text-gray-800 mb-2"><i class="fas fa-envelope-open-text mr-2 text-gray-400" aria-hidden="true"></i>{{ _("help.sources_email_ingestion") }}</h3>
|
||
<p class="text-gray-600 text-sm">
|
||
{{ _("help.sources_email_ingestion_desc") }}
|
||
</p>
|
||
</article>
|
||
|
||
<article class="bg-white shadow rounded-lg p-6">
|
||
<h3 class="font-semibold text-gray-800 mb-2"><i class="fas fa-code mr-2 text-gray-400" aria-hidden="true"></i>{{ _("help.sources_rest_api") }}</h3>
|
||
<p class="text-gray-600 text-sm">
|
||
{{ _("help.sources_rest_api_desc") }}
|
||
</p>
|
||
</article>
|
||
|
||
<article class="bg-white shadow rounded-lg p-6">
|
||
<h3 class="font-semibold text-gray-800 mb-2"><i class="fas fa-print mr-2 text-gray-400" aria-hidden="true"></i>{{ _("help.sources_scanner") }}</h3>
|
||
<p class="text-gray-600 text-sm">
|
||
{{ _("help.sources_scanner_desc_full") }}
|
||
</p>
|
||
</article>
|
||
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ═══════════════════════ Destinations ═══════════════════════ -->
|
||
<section aria-labelledby="destinations-heading" class="mb-16">
|
||
<h2 id="destinations-heading" class="text-2xl font-bold text-gray-800 mb-6">
|
||
<i class="fas fa-arrow-right-from-bracket text-blue-500 mr-2" aria-hidden="true"></i>{{ _("help.destinations_heading") }}
|
||
</h2>
|
||
<div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
||
|
||
<div class="flex items-start bg-white shadow rounded-lg p-5">
|
||
<i class="fab fa-dropbox text-blue-500 text-xl mr-3 mt-0.5" aria-hidden="true"></i>
|
||
<div>
|
||
<h3 class="font-semibold text-gray-800 text-sm">{{ _("help.destinations_dropbox") }}</h3>
|
||
<p class="text-gray-500 text-xs">{{ _("help.destinations_dropbox_desc") }}</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="flex items-start bg-white shadow rounded-lg p-5">
|
||
<i class="fab fa-google-drive text-green-500 text-xl mr-3 mt-0.5" aria-hidden="true"></i>
|
||
<div>
|
||
<h3 class="font-semibold text-gray-800 text-sm">{{ _("help.destinations_google_drive") }}</h3>
|
||
<p class="text-gray-500 text-xs">{{ _("help.destinations_google_drive_desc") }}</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="flex items-start bg-white shadow rounded-lg p-5">
|
||
<i class="fab fa-microsoft text-blue-600 text-xl mr-3 mt-0.5" aria-hidden="true"></i>
|
||
<div>
|
||
<h3 class="font-semibold text-gray-800 text-sm">{{ _("help.destinations_onedrive") }}</h3>
|
||
<p class="text-gray-500 text-xs">{{ _("help.destinations_onedrive_desc") }}</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="flex items-start bg-white shadow rounded-lg p-5">
|
||
<i class="fab fa-microsoft text-purple-600 text-xl mr-3 mt-0.5" aria-hidden="true"></i>
|
||
<div>
|
||
<h3 class="font-semibold text-gray-800 text-sm">SharePoint</h3>
|
||
<p class="text-gray-500 text-xs">Upload to SharePoint Online document libraries via Graph API.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="flex items-start bg-white shadow rounded-lg p-5">
|
||
<i class="fab fa-aws text-yellow-600 text-xl mr-3 mt-0.5" aria-hidden="true"></i>
|
||
<div>
|
||
<h3 class="font-semibold text-gray-800 text-sm">{{ _("help.destinations_s3") }}</h3>
|
||
<p class="text-gray-500 text-xs">{{ _("help.destinations_s3_desc") }}</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="flex items-start bg-white shadow rounded-lg p-5">
|
||
<i class="fas fa-cloud text-blue-400 text-xl mr-3 mt-0.5" aria-hidden="true"></i>
|
||
<div>
|
||
<h3 class="font-semibold text-gray-800 text-sm">{{ _("help.destinations_nextcloud") }}</h3>
|
||
<p class="text-gray-500 text-xs">{{ _("help.destinations_nextcloud_desc") }}</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="flex items-start bg-white shadow rounded-lg p-5">
|
||
<i class="fas fa-leaf text-green-600 text-xl mr-3 mt-0.5" aria-hidden="true"></i>
|
||
<div>
|
||
<h3 class="font-semibold text-gray-800 text-sm">{{ _("help.destinations_paperless") }}</h3>
|
||
<p class="text-gray-500 text-xs">{{ _("help.destinations_paperless_desc") }}</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="flex items-start bg-white shadow rounded-lg p-5">
|
||
<i class="fas fa-server text-gray-500 text-xl mr-3 mt-0.5" aria-hidden="true"></i>
|
||
<div>
|
||
<h3 class="font-semibold text-gray-800 text-sm">{{ _("help.destinations_sftp") }}</h3>
|
||
<p class="text-gray-500 text-xs">{{ _("help.destinations_sftp_desc") }}</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="flex items-start bg-white shadow rounded-lg p-5">
|
||
<i class="fas fa-envelope text-red-400 text-xl mr-3 mt-0.5" aria-hidden="true"></i>
|
||
<div>
|
||
<h3 class="font-semibold text-gray-800 text-sm">{{ _("help.destinations_email") }}</h3>
|
||
<p class="text-gray-500 text-xs">{{ _("help.destinations_email_desc") }}</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="flex items-start bg-white shadow rounded-lg p-5">
|
||
<i class="fas fa-link text-indigo-500 text-xl mr-3 mt-0.5" aria-hidden="true"></i>
|
||
<div>
|
||
<h3 class="font-semibold text-gray-800 text-sm">{{ _("help.destinations_webhook") }}</h3>
|
||
<p class="text-gray-500 text-xs">{{ _("help.destinations_webhook_desc") }}</p>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ═══════════════════════ Workflows / Pipelines ═══════════════════════ -->
|
||
<section aria-labelledby="workflows-heading" class="mb-16">
|
||
<h2 id="workflows-heading" class="text-2xl font-bold text-gray-800 mb-6">
|
||
<i class="fas fa-diagram-project text-blue-500 mr-2" aria-hidden="true"></i>{{ _("help.workflows_heading") }}
|
||
</h2>
|
||
<div class="bg-white shadow rounded-lg p-6">
|
||
<div class="grid gap-6 md:grid-cols-2">
|
||
<div>
|
||
<h3 class="font-semibold text-gray-800 mb-2">{{ _("help.workflows_what_is") }}</h3>
|
||
<p class="text-gray-600 text-sm leading-relaxed mb-4">
|
||
{{ _("help.workflows_definition") }}
|
||
</p>
|
||
<h3 class="font-semibold text-gray-800 mb-2">{{ _("help.workflows_typical_steps") }}</h3>
|
||
<ol class="list-decimal list-inside text-gray-600 text-sm space-y-1">
|
||
<li>{{ _("help.workflows_step_1_full") }}</li>
|
||
<li>{{ _("help.workflows_step_2_full") }}</li>
|
||
<li>{{ _("help.workflows_step_3_full") }}</li>
|
||
<li>{{ _("help.workflows_step_4") }}</li>
|
||
</ol>
|
||
</div>
|
||
<div>
|
||
<h3 class="font-semibold text-gray-800 mb-2">{{ _("help.workflows_creating") }}</h3>
|
||
<ol class="list-decimal list-inside text-gray-600 text-sm space-y-2 leading-relaxed">
|
||
<li>{{ _("help.workflows_step_1_create") }}</li>
|
||
<li>{{ _("help.workflows_step_2_create") }}</li>
|
||
<li>{{ _("help.workflows_step_3_create") }}</li>
|
||
<li>{{ _("help.workflows_step_4_create") }}</li>
|
||
<li>{{ _("help.workflows_step_5_create") }}</li>
|
||
</ol>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ═══════════════════════ Data Ingestion Tools ═══════════════════════ -->
|
||
<section aria-labelledby="ingestion-heading" class="mb-16">
|
||
<h2 id="ingestion-heading" class="text-2xl font-bold text-gray-800 mb-6">
|
||
<i class="fas fa-toolbox text-blue-500 mr-2" aria-hidden="true"></i>{{ _("help.ingestion_heading") }}
|
||
</h2>
|
||
<div class="bg-white shadow rounded-lg p-6 space-y-6">
|
||
|
||
<article>
|
||
<h3 class="font-semibold text-gray-800 mb-1"><i class="fas fa-terminal mr-2 text-gray-400" aria-hidden="true"></i>{{ _("help.ingestion_curl") }}</h3>
|
||
<p class="text-gray-600 text-sm mb-2">{{ _("help.ingestion_curl_desc") }}</p>
|
||
<pre class="bg-gray-50 text-sm rounded p-3 overflow-x-auto"><code>curl -X POST https://your-instance/api/upload \
|
||
-H "Authorization: Bearer YOUR_TOKEN" \
|
||
-F "file=@/path/to/document.pdf"</code></pre>
|
||
</article>
|
||
|
||
<article>
|
||
<h3 class="font-semibold text-gray-800 mb-1"><i class="fas fa-folder-open mr-2 text-gray-400" aria-hidden="true"></i>{{ _("help.ingestion_watched_folders") }}</h3>
|
||
<p class="text-gray-600 text-sm">
|
||
{{ _("help.ingestion_watched_folders_desc") }}
|
||
</p>
|
||
</article>
|
||
|
||
<article>
|
||
<h3 class="font-semibold text-gray-800 mb-1"><i class="fas fa-print mr-2 text-gray-400" aria-hidden="true"></i>{{ _("help.ingestion_scanners") }}</h3>
|
||
<p class="text-gray-600 text-sm">
|
||
{{ _("help.ingestion_scanners_desc") }}
|
||
</p>
|
||
</article>
|
||
|
||
<article>
|
||
<h3 class="font-semibold text-gray-800 mb-1"><i class="fas fa-mobile-screen-button mr-2 text-gray-400" aria-hidden="true"></i>{{ _("help.ingestion_mobile") }}</h3>
|
||
<p class="text-gray-600 text-sm">
|
||
{{ _("help.ingestion_mobile_desc") }}
|
||
</p>
|
||
</article>
|
||
|
||
<article>
|
||
<h3 class="font-semibold text-gray-800 mb-1"><i class="fas fa-shuffle mr-2 text-gray-400" aria-hidden="true"></i>{{ _("help.ingestion_zapier") }}</h3>
|
||
<p class="text-gray-600 text-sm">
|
||
{{ _("help.ingestion_zapier_desc") }}
|
||
</p>
|
||
</article>
|
||
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ═══════════════════════ FAQ ═══════════════════════ -->
|
||
<section aria-labelledby="faq-heading" class="mb-16">
|
||
<h2 id="faq-heading" class="text-2xl font-bold text-gray-800 mb-6">
|
||
<i class="fas fa-circle-question text-blue-500 mr-2" aria-hidden="true"></i>{{ _("help.faq_heading") }}
|
||
</h2>
|
||
<div class="space-y-4" x-data="{ open: null }">
|
||
|
||
<div class="bg-white shadow rounded-lg">
|
||
<button type="button"
|
||
class="w-full flex justify-between items-center px-6 py-4 text-left font-medium text-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-400 rounded-lg"
|
||
@click="open = open === 1 ? null : 1"
|
||
:aria-expanded="open === 1 ? 'true' : 'false'"
|
||
aria-controls="faq-1">
|
||
<span>{{ _("help.faq_1_q") }}</span>
|
||
<i class="fas fa-chevron-down text-gray-400 transition-transform" :class="{ 'rotate-180': open === 1 }" aria-hidden="true"></i>
|
||
</button>
|
||
<div id="faq-1" x-show="open === 1" x-collapse class="px-6 pb-4 text-gray-600 text-sm leading-relaxed">
|
||
{{ _("help.faq_1_a") }}
|
||
</div>
|
||
</div>
|
||
|
||
<div class="bg-white shadow rounded-lg">
|
||
<button type="button"
|
||
class="w-full flex justify-between items-center px-6 py-4 text-left font-medium text-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-400 rounded-lg"
|
||
@click="open = open === 2 ? null : 2"
|
||
:aria-expanded="open === 2 ? 'true' : 'false'"
|
||
aria-controls="faq-2">
|
||
<span>{{ _("help.faq_2_q") }}</span>
|
||
<i class="fas fa-chevron-down text-gray-400 transition-transform" :class="{ 'rotate-180': open === 2 }" aria-hidden="true"></i>
|
||
</button>
|
||
<div id="faq-2" x-show="open === 2" x-collapse class="px-6 pb-4 text-gray-600 text-sm leading-relaxed">
|
||
{{ _("help.faq_2_a") }}
|
||
</div>
|
||
</div>
|
||
|
||
<div class="bg-white shadow rounded-lg">
|
||
<button type="button"
|
||
class="w-full flex justify-between items-center px-6 py-4 text-left font-medium text-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-400 rounded-lg"
|
||
@click="open = open === 3 ? null : 3"
|
||
:aria-expanded="open === 3 ? 'true' : 'false'"
|
||
aria-controls="faq-3">
|
||
<span>{{ _("help.faq_3_q") }}</span>
|
||
<i class="fas fa-chevron-down text-gray-400 transition-transform" :class="{ 'rotate-180': open === 3 }" aria-hidden="true"></i>
|
||
</button>
|
||
<div id="faq-3" x-show="open === 3" x-collapse class="px-6 pb-4 text-gray-600 text-sm leading-relaxed">
|
||
{{ _("help.faq_3_a") }}
|
||
</div>
|
||
</div>
|
||
|
||
<div class="bg-white shadow rounded-lg">
|
||
<button type="button"
|
||
class="w-full flex justify-between items-center px-6 py-4 text-left font-medium text-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-400 rounded-lg"
|
||
@click="open = open === 4 ? null : 4"
|
||
:aria-expanded="open === 4 ? 'true' : 'false'"
|
||
aria-controls="faq-4">
|
||
<span>{{ _("help.faq_4_q") }}</span>
|
||
<i class="fas fa-chevron-down text-gray-400 transition-transform" :class="{ 'rotate-180': open === 4 }" aria-hidden="true"></i>
|
||
</button>
|
||
<div id="faq-4" x-show="open === 4" x-collapse class="px-6 pb-4 text-gray-600 text-sm leading-relaxed">
|
||
{{ _("help.faq_4_a") }}
|
||
</div>
|
||
</div>
|
||
|
||
<div class="bg-white shadow rounded-lg">
|
||
<button type="button"
|
||
class="w-full flex justify-between items-center px-6 py-4 text-left font-medium text-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-400 rounded-lg"
|
||
@click="open = open === 5 ? null : 5"
|
||
:aria-expanded="open === 5 ? 'true' : 'false'"
|
||
aria-controls="faq-5">
|
||
<span>{{ _("help.faq_5_q") }}</span>
|
||
<i class="fas fa-chevron-down text-gray-400 transition-transform" :class="{ 'rotate-180': open === 5 }" aria-hidden="true"></i>
|
||
</button>
|
||
<div id="faq-5" x-show="open === 5" x-collapse class="px-6 pb-4 text-gray-600 text-sm leading-relaxed">
|
||
{{ _("help.faq_5_a_pre") }}<a href="/privacy" class="text-blue-600 hover:underline">{{ _("help.privacy_notice") }}</a>{{ _("help.faq_5_a_post") }}
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ═══════════════════════ Contact / Support ═══════════════════════ -->
|
||
<section aria-labelledby="support-heading" class="mb-10">
|
||
<h2 id="support-heading" class="text-2xl font-bold text-gray-800 mb-6">
|
||
<i class="fas fa-headset text-blue-500 mr-2" aria-hidden="true"></i>{{ _("help.support_heading") }}
|
||
</h2>
|
||
|
||
<div class="grid gap-6 md:grid-cols-2">
|
||
|
||
<!-- Left column: info -->
|
||
<div class="bg-white shadow rounded-lg p-6 space-y-4">
|
||
<p class="text-gray-600 text-sm leading-relaxed">
|
||
{{ _("help.support_description") }}
|
||
</p>
|
||
|
||
{% if support_email %}
|
||
<div class="flex items-center text-sm text-gray-700">
|
||
<i class="fas fa-envelope text-blue-500 mr-2" aria-hidden="true"></i>
|
||
<a href="mailto:{{ support_email }}" class="text-blue-600 hover:underline">{{ support_email }}</a>
|
||
</div>
|
||
{% endif %}
|
||
|
||
{% if zammad_chat_enabled and zammad_url %}
|
||
<div class="flex items-center text-sm text-gray-700">
|
||
<i class="fas fa-comments text-blue-500 mr-2" aria-hidden="true"></i>
|
||
<span>{{ _("help.support_live_chat") }}</span>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
|
||
<!-- Right column: Zammad ticket form -->
|
||
{% if zammad_form_enabled and zammad_url %}
|
||
<div class="bg-white shadow rounded-lg p-6">
|
||
<h3 class="font-semibold text-gray-800 mb-3">
|
||
<i class="fas fa-ticket mr-2 text-gray-400" aria-hidden="true"></i>{{ _("help.support_ticket_heading") }}
|
||
</h3>
|
||
<p class="text-gray-600 text-sm mb-4">
|
||
{{ _("help.support_ticket_desc") }}
|
||
</p>
|
||
<button id="zammad-feedback-form"
|
||
type="button"
|
||
class="inline-flex items-center bg-blue-600 hover:bg-blue-700 text-white font-semibold py-2 px-5 rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-blue-400 min-h-[44px]">
|
||
<i class="fas fa-paper-plane mr-2" aria-hidden="true"></i>{{ _("help.support_ticket_button") }}
|
||
</button>
|
||
</div>
|
||
{% elif not zammad_form_enabled and not support_email and not zammad_chat_enabled %}
|
||
<div class="bg-white shadow rounded-lg p-6 flex flex-col items-center justify-center text-center">
|
||
<i class="fas fa-info-circle text-blue-400 text-2xl mb-2" aria-hidden="true"></i>
|
||
<p class="text-gray-500 text-sm">
|
||
{{ _("help.support_admin_message") }}
|
||
</p>
|
||
</div>
|
||
{% endif %}
|
||
|
||
</div>
|
||
</section>
|
||
|
||
</div>
|
||
{% endblock %}
|
||
|
||
{% block scripts %}
|
||
{% if zammad_url and zammad_form_enabled %}
|
||
<!-- Zammad Feedback Form -->
|
||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"
|
||
integrity="sha384-vtXRMe3mGCbOeY7l30aIg8H9p3GdeSe4IFlP6G8JMa7o7lXvnz3GFKzPxzJdPfGK"
|
||
crossorigin="anonymous"></script>
|
||
<script id="zammad_form_script" src="{{ zammad_url }}/assets/form/form.js"></script>
|
||
<script>
|
||
$(function() {
|
||
$('#zammad-feedback-form').ZammadForm({
|
||
messageTitle: 'DocuElevate Support',
|
||
messageSubmit: 'Submit',
|
||
messageThankYou: 'Thank you for your request (#%s)! We will get back to you shortly.',
|
||
modal: true
|
||
});
|
||
|
||
{% if user_name or user_email %}
|
||
{# ── Auto-fill Zammad form fields from the authenticated user context ── #}
|
||
$('#zammad-feedback-form').on('click', function() {
|
||
var maxAttempts = 30; /* ~3 s total wait for modal to appear */
|
||
var retryDelayMs = 100;
|
||
var attempts = 0;
|
||
var prefillForm = function() {
|
||
var $modal = $('.zammad-form-modal, .js-zammad-form-modal');
|
||
if ($modal.length === 0 && attempts < maxAttempts) {
|
||
attempts++;
|
||
setTimeout(prefillForm, retryDelayMs);
|
||
return;
|
||
}
|
||
var $name = $modal.find('input[name="name"]');
|
||
var $email = $modal.find('input[name="email"]');
|
||
{% if user_name %}
|
||
if ($name.length && !$name.val()) $name.val({{ user_name | tojson }});
|
||
{% endif %}
|
||
{% if user_email %}
|
||
if ($email.length && !$email.val()) $email.val({{ user_email | tojson }});
|
||
{% endif %}
|
||
};
|
||
var initialDelayMs = 200; /* wait for modal DOM to start rendering */
|
||
setTimeout(prefillForm, initialDelayMs);
|
||
});
|
||
|
||
{# ── Append user metadata to the ticket body before Zammad posts it ── #}
|
||
$.ajaxPrefilter(function(options) {
|
||
if (options.url && options.url.indexOf('/api/v1/form_submit') !== -1 && options.data) {
|
||
try {
|
||
var data = JSON.parse(options.data);
|
||
if (data.body && data.body.indexOf('\n--- DocuElevate User Context ---') === -1) {
|
||
var ctx = '\n\n--- DocuElevate User Context ---';
|
||
{% if user_name %}ctx += '\nName: ' + {{ user_name | tojson }};{% endif %}
|
||
{% if user_email %}ctx += '\nEmail: ' + {{ user_email | tojson }};{% endif %}
|
||
{% if user_id %}ctx += '\nUsername: ' + {{ user_id | tojson }};{% endif %}
|
||
data.body += ctx;
|
||
options.data = JSON.stringify(data);
|
||
}
|
||
} catch(e) { /* ignore parse errors from non-JSON payloads */ }
|
||
}
|
||
});
|
||
{% endif %}
|
||
});
|
||
</script>
|
||
{% endif %}
|
||
|
||
{% if zammad_url and zammad_chat_enabled %}
|
||
<!-- Zammad Live Chat Widget -->
|
||
<script src="{{ zammad_url }}/assets/chat/chat-no-jquery.min.js"></script>
|
||
<script>
|
||
(function() {
|
||
new ZammadChat({
|
||
fontSize: '12px',
|
||
flat: true,
|
||
chatId: {{ zammad_chat_id | int }},
|
||
title: '<strong>Chat</strong> with us!'{% if user_name or user_email %},
|
||
name: {{ user_name | tojson }},
|
||
email: {{ user_email | tojson }}{% endif %}
|
||
});
|
||
})();
|
||
</script>
|
||
{% endif %}
|
||
{% endblock %}
|