feat: v3.4.0 — OpenPanel plugin public release (42 tools)
OpenPanel product analytics plugin fully reviewed, tested, and published. Works with both self-hosted and cloud (openpanel.dev) instances. - 42 tools: event tracking, data export, analytics, project/client management - All tools use public REST APIs (Track, Export, Insights, Manage) - Client modes: write (tracking), read (analytics), root (full access) - Service page with description, setup notes, WordPress plugin download - Dynamic URL hints in Add Site form - 62 unit tests - ENABLED_PLUGINS default now includes openpanel Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -31,6 +31,31 @@
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Description & Notes -->
|
||||
{% if service.description %}
|
||||
<div class="bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-6">
|
||||
{% if lang == 'fa' and service.description.fa %}
|
||||
<p class="text-sm text-gray-600 dark:text-gray-300 leading-relaxed" dir="rtl">{{ service.description.fa }}</p>
|
||||
{% elif service.description.en %}
|
||||
<p class="text-sm text-gray-600 dark:text-gray-300 leading-relaxed">{{ service.description.en }}</p>
|
||||
{% endif %}
|
||||
|
||||
{% set notes_key = 'notes_fa' if lang == 'fa' else 'notes_en' %}
|
||||
{% if service.description[notes_key] %}
|
||||
<ul class="mt-4 space-y-2{% if lang == 'fa' %} text-right{% endif %}" {% if lang == 'fa' %}dir="rtl"{% endif %}>
|
||||
{% for note in service.description[notes_key] %}
|
||||
<li class="flex items-start gap-2 text-sm text-gray-500 dark:text-gray-400">
|
||||
<svg class="w-4 h-4 text-primary-400 mt-0.5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
<span>{{ note|safe }}</span>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Overview Cards -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<!-- Tools Count -->
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">{{ t.site_url }}</label>
|
||||
<input type="url" id="url" name="url" required placeholder="https://example.com"
|
||||
class="w-full bg-gray-50 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-lg px-4 py-2.5 text-gray-900 dark:text-white placeholder-gray-400 dark:placeholder-gray-500 focus:ring-2 focus:ring-blue-500 focus:border-transparent">
|
||||
<p id="url-hint" class="text-xs text-gray-500 dark:text-gray-400 mt-1 hidden"></p>
|
||||
</div>
|
||||
|
||||
<!-- Alias -->
|
||||
@@ -73,9 +74,23 @@
|
||||
<script>
|
||||
const pluginFields = {{ plugin_fields_json| safe }};
|
||||
|
||||
const urlHints = {
|
||||
'openpanel': 'OpenPanel API URL — Cloud: https://api.openpanel.dev | Self-hosted: your API service URL (e.g., https://analytics.example.com)',
|
||||
'supabase': 'Your Supabase project URL (e.g., https://xxxxx.supabase.co)',
|
||||
};
|
||||
|
||||
function updateFields() {
|
||||
const ptype = document.getElementById('plugin_type').value;
|
||||
const container = document.getElementById('credential-fields');
|
||||
const urlHintEl = document.getElementById('url-hint');
|
||||
|
||||
// Update URL hint
|
||||
if (urlHints[ptype]) {
|
||||
urlHintEl.textContent = urlHints[ptype];
|
||||
urlHintEl.classList.remove('hidden');
|
||||
} else {
|
||||
urlHintEl.classList.add('hidden');
|
||||
}
|
||||
|
||||
if (!ptype || !pluginFields[ptype]) {
|
||||
container.innerHTML = '<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ t.credentials }}</label><p class="text-sm text-gray-500 dark:text-gray-400">{{ t.select_plugin }}</p>';
|
||||
|
||||
BIN
core/templates/static/plugins/openpanel-self-hosted.zip
Normal file
BIN
core/templates/static/plugins/openpanel-self-hosted.zip
Normal file
Binary file not shown.
Reference in New Issue
Block a user