Promote Support & Purchase Key page across app and docs

Make https://timetracker.drytrix.com/support.html visible so users can purchase a key to hide donate/support UI (one key per instance, €25 one-time).

- Add SUPPORT_PURCHASE_URL config and support_purchase_url in template context
- Donate page: 'Remove Donation Messages' section and CTA, link in Other Ways to Help
- Admin Settings: Support visibility copy and 'Get key at Support & Purchase' button
- User Settings: line and link for admins to purchase a key
- Support banner: 'Purchase key to hide' link
- Dashboard widget: 'Want to hide this widget? Purchase a key'
- README: Support section bullet and intro line for support/purchase key
- SUPPORT_VISIBILITY.md: 'How to get a code' subsection, issuing codes note
- docs/README.md: Support visibility in Configuration with purchase link
- messages.po: add new translatable strings
This commit is contained in:
Dries Peeters
2026-02-14 22:14:57 +01:00
parent e68f231b91
commit 93d1111791
11 changed files with 126 additions and 5 deletions
+3
View File
@@ -22,6 +22,8 @@ TimeTracker is a **self-hosted, web-based time tracking application** designed f
- 🏢 **Agencies** needing detailed reporting and client billing
- 🔒 **Privacy-focused organizations** wanting self-hosted solutions
You can [support the project and purchase a key](https://timetracker.drytrix.com/support.html) to hide donate prompts in your instance.
---
## 🛠️ Technology Stack
@@ -984,6 +986,7 @@ This means you can:
## 🆘 Support
- 💙 **Support the project & purchase key:** [Support & Purchase Key](https://timetracker.drytrix.com/support.html) — donate or purchase a one-time key to remove donate/support prompts in your instance
- 📖 **Documentation**: Check the [`docs/`](docs/) directory
- 🐛 **Bug Reports**: [Open an issue](https://github.com/drytrix/TimeTracker/issues)
- 💬 **Discussions**: [GitHub Discussions](https://github.com/drytrix/TimeTracker/discussions)
+5
View File
@@ -120,6 +120,11 @@ class Config:
_donate_secret = ""
DONATE_HIDE_UNLOCK_SECRET = _donate_secret
# Support & Purchase Key page URL (for links to purchase a key to hide donate UI)
SUPPORT_PURCHASE_URL = os.getenv(
"SUPPORT_PURCHASE_URL", "https://timetracker.drytrix.com/support.html"
).strip()
# Backup settings
BACKUP_RETENTION_DAYS = int(os.getenv("BACKUP_RETENTION_DAYS", 30))
BACKUP_TIME = os.getenv("BACKUP_TIME", "02:00")
+8 -2
View File
@@ -141,7 +141,13 @@
<div class="border-b border-border-light dark:border-border-dark pb-6" id="donateVisibilitySection">
<h2 class="text-lg font-semibold mb-4"><i class="fas fa-eye-slash mr-2"></i>{{ _('Support visibility') }}</h2>
<p class="text-sm text-text-muted-light dark:text-text-muted-dark mb-4">
{{ _('Hide donate and support UI for all users by verifying a code. The code is generated from the system ID (see internal documentation).') }}
{{ _('Hide donate and support UI for all users by entering a code. Get your code by purchasing a key at the link below (one key per instance).') }}
</p>
<p class="mb-4">
<a href="{{ support_purchase_url }}" target="_blank" rel="noopener noreferrer" class="inline-flex items-center gap-2 px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white text-sm font-medium rounded-md transition">
<i class="fas fa-key mr-1"></i>{{ _('Get key at Support & Purchase') }}
<i class="fas fa-external-link-alt text-xs"></i>
</a>
</p>
{% if system_instance_id %}
<div class="mb-4">
@@ -152,7 +158,7 @@
<i class="fas fa-copy mr-1"></i>{{ _('Copy') }}
</button>
</div>
<p class="mt-1 text-xs text-text-muted-light dark:text-text-muted-dark">{{ _('Use this ID to generate the code (see internal documentation).') }}</p>
<p class="mt-1 text-xs text-text-muted-light dark:text-text-muted-dark">{{ _('Use this ID when requesting your key at the support page above.') }}</p>
</div>
{% endif %}
{% if settings.donate_ui_hidden %}
+3
View File
@@ -1137,6 +1137,9 @@
class="px-3 py-1.5 text-white text-sm font-medium rounded-lg transition-colors border border-blue-600 hover:opacity-90" style="background: linear-gradient(to right, #0070ba, #003087);">
<i class="fab fa-paypal mr-1"></i>{{ _('PayPal') }}
</a>
<a href="{{ support_purchase_url }}" target="_blank" rel="noopener noreferrer" class="text-xs text-amber-700 dark:text-amber-300 hover:underline self-center">
{{ _('Purchase key to hide') }}
</a>
<button onclick="dismissSupportBanner()"
class="p-1.5 text-amber-600 dark:text-amber-400 hover:bg-amber-100 dark:hover:bg-amber-900/30 rounded transition-colors"
aria-label="{{ _('Dismiss') }}">
+4
View File
@@ -473,6 +473,10 @@
<i class="fas fa-external-link-alt ml-2 text-xs"></i>
</a>
</div>
<p class="mt-3 text-xs opacity-90">
{{ _('Want to hide this widget?') }}
<a href="{{ support_purchase_url }}" target="_blank" rel="noopener noreferrer" class="underline hover:no-underline font-medium">{{ _('Purchase a key') }}</a>.
</p>
</div>
{% endif %}
</div>
+34
View File
@@ -86,6 +86,27 @@
</div>
</div>
<!-- Remove Donation Messages -->
<div class="bg-card-light dark:bg-card-dark p-6 rounded-lg shadow border border-border-light dark:border-border-dark mb-6 border-l-4 border-l-blue-500">
<h2 class="text-2xl font-semibold mb-4">
<i class="fas fa-eye-slash text-blue-500 mr-2"></i>
{{ _('Remove Donation Messages') }}
</h2>
<p class="mb-4 text-text-light dark:text-text-dark">
{{ _('Purchase a key to hide donate and support prompts in this TimeTracker instance. One key per instance; the key is sent by email after payment (€25 one-time).') }}
</p>
<p class="mb-4 text-sm text-text-muted-light dark:text-text-muted-dark">
{{ _('Admins: find your System ID in Admin → Settings → Support visibility.') }}
</p>
<a href="{{ support_purchase_url }}"
target="_blank"
rel="noopener noreferrer"
class="inline-flex items-center justify-center gap-2 px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white rounded-lg font-semibold transition-all shadow-md hover:shadow-lg">
<i class="fas fa-key mr-2"></i>{{ _('Get Key') }}
<i class="fas fa-external-link-alt text-sm"></i>
</a>
</div>
<!-- Your Usage Stats -->
{% if time_entries_count > 0 or total_hours > 0 %}
<div class="bg-card-light dark:bg-card-dark p-6 rounded-lg shadow border border-border-light dark:border-border-dark mb-6">
@@ -210,6 +231,19 @@
</div>
</div>
</a>
<a href="{{ support_purchase_url }}"
target="_blank"
rel="noopener noreferrer"
class="flex items-center gap-3 p-4 bg-background-light dark:bg-background-dark rounded-lg hover:bg-background-hover-light dark:hover:bg-background-hover-dark transition-colors">
<i class="fas fa-key text-2xl text-text-light dark:text-text-dark"></i>
<div>
<div class="font-semibold">{{ _('Purchase a key to hide donate UI') }}</div>
<div class="text-sm text-text-muted-light dark:text-text-muted-dark">
{{ _('One-time key per instance to remove donate and support prompts') }}
</div>
</div>
</a>
</div>
</div>
</div>
+2
View File
@@ -325,6 +325,8 @@
<p class="text-sm text-text-muted-light dark:text-text-muted-dark">
{{ _('Support visibility (hiding donate/support UI) is configured system-wide by administrators in Admin → Settings.') }}
{{ _('Administrators can purchase a key to hide these prompts:') }}
<a href="{{ support_purchase_url }}" target="_blank" rel="noopener noreferrer" class="text-blue-600 dark:text-blue-400 hover:underline">{{ _('Support & Purchase Key') }}</a>.
</p>
<!-- Save Button -->
+5
View File
@@ -149,6 +149,10 @@ def register_context_processors(app):
rtl_languages = current_app.config.get("RTL_LANGUAGES", set())
is_rtl = short_locale in rtl_languages
support_purchase_url = current_app.config.get(
"SUPPORT_PURCHASE_URL", "https://timetracker.drytrix.com/support.html"
)
return {
"app_name": "Time Tracker",
"app_version": version_value,
@@ -161,6 +165,7 @@ def register_context_processors(app):
"is_rtl": is_rtl,
"available_languages": available_languages,
"config": current_app.config,
"support_purchase_url": support_purchase_url,
}
@app.before_request
+1
View File
@@ -82,6 +82,7 @@ See [features/](features/) for additional feature documentation.
- **[Docker Startup Troubleshooting](admin/configuration/DOCKER_STARTUP_TROUBLESHOOTING.md)** — Fix startup issues
- **[Email Configuration](admin/configuration/EMAIL_CONFIGURATION.md)** — Email setup
- **[OIDC Setup](admin/configuration/OIDC_SETUP.md)** — OIDC/SSO authentication setup
- **[Support visibility](admin/configuration/SUPPORT_VISIBILITY.md)** — Hide donate/support UI with a purchased key; [purchase key](https://timetracker.drytrix.com/support.html)
### Deployment
- **[Version Management](admin/deployment/VERSION_MANAGEMENT.md)** — Managing versions
@@ -8,6 +8,10 @@ This guide describes how to configure the optional **Support visibility** featur
- After a valid code is entered and **Verify and hide for everyone** is clicked, donate and support UI is hidden **system-wide** for all users.
- The System ID does not change between restarts; it identifies your instance so you can request the correct code.
### How to get a code
To purchase a key and receive your code, go to **[Support & Purchase Key](https://timetracker.drytrix.com/support.html)**. You will need your **System ID**, shown in Admin → Settings → Support visibility. One key per instance; the code is sent by email after payment.
## Server configuration
You can enable verification in two ways. Only one is required.
@@ -70,9 +74,7 @@ If neither is set, the feature is disabled: no code will be accepted and the Sup
Codes are **per installation**: each instance has its own System ID, and a valid code for one instance is not valid for another.
- An admin copies the **System ID** from Admin → Settings → Support visibility (or you provide it from your deployment).
- You generate the code for that System ID using the procedure and tools described in **internal documentation**. The code-generation script, key-generation steps, and private key handling are not in the public repository; maintainers use a separate, non-committed guide and script.
- You send the code to the admin; they enter it in Admin → Settings and click **Verify and hide for everyone**.
The public-facing way for admins to obtain a code is via the [Support & Purchase Key](https://timetracker.drytrix.com/support.html) page (see **How to get a code** above). For maintainers: an admin copies the **System ID** from Admin → Settings → Support visibility (or you provide it from your deployment); you generate the code for that System ID using the procedure and tools described in **internal documentation**. The code-generation script, key-generation steps, and private key handling are not in the public repository; maintainers use a separate, non-committed guide and script. You send the code to the admin; they enter it in Admin → Settings and click **Verify and hide for everyone**.
## User experience
+56
View File
@@ -22162,6 +22162,62 @@ msgstr ""
msgid "Please log in to access this page"
msgstr ""
#: app/templates/main/donate.html
msgid "Remove Donation Messages"
msgstr ""
#: app/templates/main/donate.html
msgid "Purchase a key to hide donate and support prompts in this TimeTracker instance. One key per instance; the key is sent by email after payment (€25 one-time)."
msgstr ""
#: app/templates/main/donate.html
msgid "Admins: find your System ID in Admin → Settings → Support visibility."
msgstr ""
#: app/templates/main/donate.html
msgid "Get Key"
msgstr ""
#: app/templates/main/donate.html
msgid "Purchase a key to hide donate UI"
msgstr ""
#: app/templates/main/donate.html
msgid "One-time key per instance to remove donate and support prompts"
msgstr ""
#: app/templates/admin/settings.html
msgid "Hide donate and support UI for all users by entering a code. Get your code by purchasing a key at the link below (one key per instance)."
msgstr ""
#: app/templates/admin/settings.html
msgid "Get key at Support & Purchase"
msgstr ""
#: app/templates/admin/settings.html
msgid "Use this ID when requesting your key at the support page above."
msgstr ""
#: app/templates/user/settings.html
msgid "Administrators can purchase a key to hide these prompts:"
msgstr ""
#: app/templates/user/settings.html
msgid "Support & Purchase Key"
msgstr ""
#: app/templates/base.html
msgid "Purchase key to hide"
msgstr ""
#: app/templates/main/dashboard.html
msgid "Want to hide this widget?"
msgstr ""
#: app/templates/main/dashboard.html
msgid "Purchase a key"
msgstr ""
#~ msgid "Log"
#~ msgstr "Log"