From d6d1f2d993c0445d8300a21b3298800eb50ee9c5 Mon Sep 17 00:00:00 2001 From: master3395 Date: Mon, 2 Feb 2026 02:35:23 +0100 Subject: [PATCH] Plugin Development Guide: add collapsible accordion sections --- pluginHolder/templates/pluginHolder/help.html | 216 ++++++++++++++++-- 1 file changed, 192 insertions(+), 24 deletions(-) diff --git a/pluginHolder/templates/pluginHolder/help.html b/pluginHolder/templates/pluginHolder/help.html index da5e53b13..bfed986de 100644 --- a/pluginHolder/templates/pluginHolder/help.html +++ b/pluginHolder/templates/pluginHolder/help.html @@ -274,6 +274,100 @@ text-decoration: underline; } + /* Collapsible sections */ + .help-section { + border: 1px solid var(--border-primary, #e8e9ff); + border-radius: 8px; + margin-bottom: 12px; + overflow: hidden; + } + + .help-section-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 16px 20px; + background: var(--bg-secondary, #f8f9ff); + cursor: pointer; + user-select: none; + transition: background 0.2s ease; + } + + .help-section-header:hover { + background: #eef0ff; + } + + .help-section-header h2 { + margin: 0; + padding: 0; + border: none; + font-size: 18px; + font-weight: 600; + color: var(--text-primary, #2f3640); + } + + .help-section-header .section-toggle { + width: 28px; + height: 28px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 6px; + background: rgba(88,86,214,0.15); + color: #5856d6; + transition: transform 0.25s ease; + } + + .help-section.expanded .section-toggle { + transform: rotate(180deg); + } + + .help-section-body { + max-height: 0; + overflow: hidden; + transition: max-height 0.35s ease-out; + } + + .help-section.expanded .help-section-body { + max-height: 8000px; + transition: max-height 0.5s ease-in; + } + + .help-section-content { + padding: 20px 24px 24px; + border-top: 1px solid var(--border-primary, #e8e9ff); + } + + .help-section-content h2 { + display: none; + } + + .help-section-content > h3:first-child { + margin-top: 0; + } + + .help-expand-all { + display: flex; + gap: 12px; + margin-top: 12px; + flex-wrap: wrap; + } + + .help-expand-all button { + padding: 6px 14px; + font-size: 13px; + border-radius: 6px; + border: 1px solid var(--border-primary, #e8e9ff); + background: var(--bg-primary, white); + color: #5856d6; + cursor: pointer; + transition: background 0.2s; + } + + .help-expand-all button:hover { + background: #eef0ff; + } + @media (max-width: 768px) { .help-wrapper { padding: 15px; @@ -314,7 +408,13 @@
-
+
+
+

{% trans "Table of Contents" %}

+ +
+
+

{% trans "Table of Contents" %}

+
+ + +
+
+
-

{% trans "Introduction" %}

+
+

{% trans "Introduction" %}

+

{% trans "CyberPanel's plugin system allows developers to extend the control panel's functionality with custom features. Plugins integrate seamlessly with CyberPanel's Django-based architecture, providing access to the full power of the platform while maintaining security and consistency." %}

{% trans "What Can Plugins Do?" %}

@@ -350,8 +458,11 @@
  • {% trans "Create custom reporting tools" %}
  • {% trans "Integrate security features" %}
  • +
    -

    {% trans "Prerequisites" %}

    +
    +

    {% trans "Prerequisites" %}

    +

    {% trans "Required Knowledge" %}

    • Python 3.6+: {% trans "Basic to intermediate Python knowledge" %}
    • @@ -360,8 +471,11 @@
    • Linux/Unix: {% trans "Basic command-line familiarity" %}
    • XML: {% trans "Understanding of XML structure for meta.xml" %}
    +
    -

    {% trans "Plugin Architecture Overview" %}

    +
    +

    {% trans "Plugin Architecture Overview" %}

    +

    {% trans "How Plugins Work" %}

    1. {% trans "Plugin Source Location" %}: /home/cyberpanel/plugins/ @@ -377,8 +491,11 @@
    +
    -

    {% trans "Creating Your First Plugin" %}

    +
    +

    {% trans "Creating Your First Plugin" %}

    +

    {% trans "Step 1: Create Plugin Directory Structure" %}

    # Navigate to plugins directory
     cd /home/cyberpanel/plugins
    @@ -465,8 +582,11 @@ def main_view(request):
             
    {% trans "Important" %}: {% trans "Always use the @cyberpanel_login_required decorator for all views to ensure users are authenticated." %}
    +
    -

    {% trans "Plugin Structure & Files" %}

    +
    +

    {% trans "Plugin Structure & Files" %}

    +

    {% trans "Required Files" %}

    • __init__.py - {% trans "Required" %} - {% trans "Python package marker" %}
    • @@ -483,8 +603,11 @@ def main_view(request):
    • templates/ - {% trans "Optional" %} - {% trans "HTML templates" %}
    • static/ - {% trans "Optional" %} - {% trans "CSS, JS, images" %}
    +
    -

    {% trans "Version Numbering (Semantic Versioning)" %}

    +
    +

    {% trans "Version Numbering (Semantic Versioning)" %}

    +

    {% trans "CyberPanel plugins use semantic versioning (SemVer) with a three-number format (X.Y.Z) to help users understand the impact of each update:" %}

    @@ -512,8 +635,11 @@ def main_view(request):

    {% trans "Version Format in meta.xml" %}

    <version>1.0.0</version>

    {% trans "Never use formats like '1.0' or 'v1.0'. Always use the full semantic version: '1.0.0'" %}

    +
    -

    {% trans "Plugin Categories" %}

    +
    +

    {% trans "Plugin Categories" %}

    +

    {% trans "The <type> field in meta.xml determines how your plugin is grouped in the Plugin Store. Use exactly one of these values (case-sensitive):" %}

    @@ -534,8 +660,11 @@ def main_view(request):
    Analytics{% trans "Analytics, tracking, and reporting" %}
    +
    -

    {% trans "Freshness Badges" %}

    +
    +

    {% trans "Freshness Badges" %}

    +

    {% trans "The Plugin Store and Installed Plugins views display freshness badges based on the last update date (modify_date from GitHub commit or meta.xml file mtime). These help users quickly see how actively maintained a plugin is:" %}

    @@ -553,8 +682,11 @@ def main_view(request):

    {% trans "Badges are calculated automatically from the plugin's modify_date. For plugins in the Plugin Store, this comes from the GitHub repository's last commit. For installed plugins, it uses the meta.xml file modification time." %}

    +
    -

    {% trans "Premium/Paid Plugin Creation" %}

    +
    +

    {% trans "Premium/Paid Plugin Creation" %}

    +

    {% trans "You can create premium (paid) plugins and implement your own verification system. This includes optional encryption between the plugin and your verification site to prevent unauthorized bypass." %}

    {% trans "1. Mark Your Plugin as Paid in meta.xml" %}

    @@ -599,8 +731,11 @@ def main_view(request):
    {% trans "Tip" %}: {% trans "Provide multiple verification paths: Patreon for subscribers, PayPal for one-time purchasers, Plugin Grants for beta testers or sponsors, and activation keys for manual grants. Encryption is optional but recommended for paid plugins to deter bypass attempts." %}
    +
    -

    {% trans "Core Components" %}

    +
    +

    {% trans "Core Components" %}

    +

    {% trans "1. Authentication & Security" %}

    {% trans "Always use the cyberpanel_login_required decorator:" %}

    @cyberpanel_login_required
    @@ -626,8 +761,11 @@ urlpatterns = [
     {% load static %}
     {% load i18n %}
    {% endverbatim %} +
    -

    {% trans "Advanced Features" %}

    +
    +

    {% trans "Advanced Features" %}

    +

    {% trans "Database Models" %}

    from django.db import models
     
    @@ -652,8 +790,11 @@ class MyForm(forms.Form):
     def api_endpoint(request):
         data = {'status': 'success'}
         return JsonResponse(data)
    +
    -

    {% trans "Best Practices" %}

    +
    +

    {% trans "Best Practices" %}

    +
    • {% trans "Keep files under 500 lines - split into modules if needed" %}
    • {% trans "Use descriptive names for functions and variables" %}
    • @@ -663,8 +804,11 @@ def api_endpoint(request):
    • {% trans "Use Django ORM instead of raw SQL" %}
    • {% trans "Test your plugin thoroughly before distribution" %}
    +
    -

    {% trans "Security Guidelines" %}

    +
    +

    {% trans "Security Guidelines" %}

    +
    {% trans "Security is Critical" %}: {% trans "Always validate input, use parameterized queries, sanitize output, and check user permissions." %}
    @@ -676,8 +820,11 @@ def api_endpoint(request):
  • {% trans "Use HTTPS for sensitive operations" %}
  • {% trans "Implement rate limiting for API endpoints" %}
  • +
    -

    {% trans "Testing & Debugging" %}

    +
    +

    {% trans "Testing & Debugging" %}

    +

    {% trans "Common Issues" %}

    • {% trans "Template Not Found" %}: {% trans "Check template path and name" %}
    • @@ -695,16 +842,22 @@ xmllint --noout meta.xml # View logs tail -f /usr/local/lscp/logs/error.log
      +
    -

    {% trans "Packaging & Distribution" %}

    +
    +

    {% trans "Packaging & Distribution" %}

    +

    {% trans "Create Plugin Package" %}

    cd /home/cyberpanel/plugins/myPlugin
     zip -r myPlugin-v1.0.0.zip . \
         -x "*.pyc" \
         -x "__pycache__/*" \
         -x "*.log"
    +
    -

    {% trans "Troubleshooting" %}

    +
    +

    {% trans "Troubleshooting" %}

    +

    {% trans "Installation Issues" %}

    • {% trans "Check meta.xml format and validity" %}
    • @@ -720,8 +873,11 @@ zip -r myPlugin-v1.0.0.zip . \
    • {% trans "Review template paths" %}
    • {% trans "Check for JavaScript errors" %}
    +
    -

    {% trans "Examples & References" %}

    +
    +

    {% trans "Examples & References" %}

    +

    {% trans "Reference Plugins" %}

    • examplePlugin: {% trans "Basic plugin structure" %} @@ -757,6 +913,7 @@ zip -r myPlugin-v1.0.0.zip . \
      {% trans "Ready to Start?" %} {% trans "Begin with a simple plugin and gradually add more features as you become familiar with the system. Check the examplePlugin and testPlugin directories for complete working examples." %}
      +

    @@ -769,16 +926,27 @@ zip -r myPlugin-v1.0.0.zip . \