{% trans "Table of Contents" %}
- {% trans "Introduction" %} @@ -335,9 +435,17 @@
- {% trans "Troubleshooting" %}
- {% trans "Examples & References" %}
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 @@
/home/cyberpanel/plugins/
@@ -377,8 +491,11 @@
# 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." %}
+ __init__.py - {% trans "Required" %} - {% trans "Python package marker" %}templates/ - {% trans "Optional" %} - {% trans "HTML templates" %}static/ - {% trans "Optional" %} - {% trans "CSS, JS, images" %}{% trans "CyberPanel plugins use semantic versioning (SemVer) with a three-number format (X.Y.Z) to help users understand the impact of each update:" %}
<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 "The <type> field in meta.xml determines how your plugin is grouped in the Plugin Store. Use exactly one of these values (case-sensitive):" %}
Analytics | {% trans "Analytics, tracking, and reporting" %} |
{% 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:" %}
{% 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 "Always use the cyberpanel_login_required decorator:" %}
@cyberpanel_login_required
@@ -626,8 +761,11 @@ urlpatterns = [
{% load static %}
{% load i18n %}
{% endverbatim %}
+ from django.db import models
@@ -652,8 +790,11 @@ class MyForm(forms.Form):
def api_endpoint(request):
data = {'status': 'success'}
return JsonResponse(data)
+ cd /home/cyberpanel/plugins/myPlugin
zip -r myPlugin-v1.0.0.zip . \
-x "*.pyc" \
-x "__pycache__/*" \
-x "*.log"
+ @@ -769,16 +926,27 @@ zip -r myPlugin-v1.0.0.zip . \