From 86b5ed6e0eec85c26ca548ba8b3d6f60dbde158d Mon Sep 17 00:00:00 2001 From: master3395 Date: Sun, 1 Feb 2026 23:46:48 +0100 Subject: [PATCH] feat: no plugins required by default; Plugin Store category updates - Remove emailMarketing from default INSTALLED_APPS - Comment out emailMarketing URL (plugin installer adds when installed) - Bump emailMarketing, examplePlugin meta.xml to 1.0.1 - Plugin Holder: remove Plugin category, enforce Utility/Security/Backup/Performance - Add to-do/PLUGIN-DEFAULT-REMOVAL-2026-02-01.md --- CyberCP/settings.py | 3 +- CyberCP/urls.py | 3 +- emailMarketing/meta.xml | 4 +- examplePlugin/meta.xml | 4 +- pluginHolder/templates/pluginHolder/help.html | 4 + .../templates/pluginHolder/plugins.html | 454 +++++++++++++++--- pluginHolder/views.py | 88 ++-- to-do/PLUGIN-DEFAULT-REMOVAL-2026-02-01.md | 13 + 8 files changed, 473 insertions(+), 100 deletions(-) create mode 100644 to-do/PLUGIN-DEFAULT-REMOVAL-2026-02-01.md diff --git a/CyberCP/settings.py b/CyberCP/settings.py index 1edb42b25..2008956ad 100644 --- a/CyberCP/settings.py +++ b/CyberCP/settings.py @@ -65,7 +65,8 @@ INSTALLED_APPS = [ # Apps with multiple or complex dependencies 'emailPremium', - 'emailMarketing', # Depends on websiteFunctions and loginSystem + # Optional plugins (e.g. emailMarketing, discordWebhooks) - install via Plugin Store + # from https://github.com/master3395/cyberpanel-plugins - plugin installer adds them 'cloudAPI', # Depends on websiteFunctions 'containerization', # Depends on websiteFunctions 'IncBackups', # Depends on websiteFunctions and loginSystem diff --git a/CyberCP/urls.py b/CyberCP/urls.py index ea5ccf382..db097f5a0 100644 --- a/CyberCP/urls.py +++ b/CyberCP/urls.py @@ -51,7 +51,8 @@ urlpatterns = [ path('CloudLinux/', include('CLManager.urls')), path('IncrementalBackups/', include('IncBackups.urls')), path('aiscanner/', include('aiScanner.urls')), - path('emailMarketing/', include('emailMarketing.urls')), + # Optional plugin routes - added by plugin installer when plugins are installed from Plugin Store + # path('emailMarketing/', include('emailMarketing.urls')), # path('Terminal/', include('WebTerminal.urls')), path('', include('loginSystem.urls')), ] diff --git a/emailMarketing/meta.xml b/emailMarketing/meta.xml index 2c5d8e719..d125a471f 100644 --- a/emailMarketing/meta.xml +++ b/emailMarketing/meta.xml @@ -1,7 +1,7 @@ Email Marketing - plugin + Utility Email Marketing plugin for CyberPanel. - 1.0.0 + 1.0.1 \ No newline at end of file diff --git a/examplePlugin/meta.xml b/examplePlugin/meta.xml index 55990a577..9e7e58b4d 100644 --- a/examplePlugin/meta.xml +++ b/examplePlugin/meta.xml @@ -1,8 +1,8 @@ examplePlugin - plugin + Utility This is an example plugin - 1.0.0 + 1.0.1 usmannasir \ No newline at end of file diff --git a/pluginHolder/templates/pluginHolder/help.html b/pluginHolder/templates/pluginHolder/help.html index 4624368ac..66bdcbdea 100644 --- a/pluginHolder/templates/pluginHolder/help.html +++ b/pluginHolder/templates/pluginHolder/help.html @@ -401,6 +401,10 @@ mkdir -p migrations <settings_url>/plugins/myFirstPlugin/settings/</settings_url> </cyberpanelPluginConfig> +
+ {% trans "Required: Category (type)" %}: {% trans "The <type> field is required. Valid categories: Utility, Security, Backup, Performance. Plugins without a valid category will not appear in the Plugin Store." %} +
+

{% trans "Step 3: Create urls.py" %}

from django.urls import path
 from . import views
diff --git a/pluginHolder/templates/pluginHolder/plugins.html b/pluginHolder/templates/pluginHolder/plugins.html
index f53e351a0..49d9c7dc4 100644
--- a/pluginHolder/templates/pluginHolder/plugins.html
+++ b/pluginHolder/templates/pluginHolder/plugins.html
@@ -592,11 +592,150 @@
         100% { transform: rotate(360deg); }
     }
     
+    .category-filter {
+        display: flex;
+        flex-wrap: wrap;
+        gap: 10px;
+        margin-bottom: 15px;
+        padding: 15px;
+        background: var(--bg-secondary, #f8f9ff);
+        border-radius: 8px;
+    }
+    
+    .category-btn {
+        padding: 8px 16px;
+        border: 1px solid var(--border-primary, #e8e9ff);
+        background: var(--bg-primary, white);
+        border-radius: 8px;
+        font-size: 13px;
+        font-weight: 600;
+        cursor: pointer;
+        transition: all 0.2s;
+        color: var(--text-secondary, #64748b);
+        display: inline-flex;
+        align-items: center;
+        gap: 8px;
+    }
+    
+    .category-btn:hover {
+        background: var(--bg-hover, #f0f1ff);
+        border-color: #5856d6;
+        color: #5856d6;
+    }
+    
+    .category-btn.active {
+        background: #5856d6;
+        color: white;
+        border-color: #5856d6;
+    }
+    
+    .category-btn i {
+        font-size: 14px;
+    }
+    
+    .store-search-bar {
+        position: relative;
+        margin-bottom: 15px;
+        max-width: 480px;
+    }
+    
+    .store-search-icon {
+        position: absolute;
+        left: 16px;
+        top: 50%;
+        transform: translateY(-50%);
+        color: #64748b;
+        font-size: 16px;
+        pointer-events: none;
+        z-index: 1;
+        width: 20px;
+        text-align: center;
+    }
+    
+    .store-search-input {
+        width: 100%;
+        padding-left: 46px;
+        padding-right: 40px;
+        padding-top: 12px;
+        padding-bottom: 12px;
+        border: 1px solid #cbd5e1;
+        border-radius: 8px;
+        font-size: 14px;
+        background: #f8fafc;
+        color: #1e293b;
+        transition: border-color 0.2s, box-shadow 0.2s, background 0.2s;
+    }
+    
+    .store-search-input:focus {
+        outline: none;
+        border-color: #5856d6;
+        background: #ffffff;
+        box-shadow: 0 0 0 3px rgba(88, 86, 214, 0.15);
+    }
+    
+    .store-search-input::placeholder {
+        color: #64748b;
+    }
+    
+    .store-search-clear {
+        position: absolute;
+        right: 10px;
+        top: 50%;
+        transform: translateY(-50%);
+        background: none;
+        border: none;
+        color: var(--text-muted, #94a3b8);
+        cursor: pointer;
+        padding: 6px;
+        border-radius: 4px;
+        font-size: 14px;
+        transition: color 0.2s, background 0.2s;
+    }
+    
+    .store-search-clear:hover {
+        color: #5856d6;
+        background: var(--bg-secondary, #f8f9ff);
+    }
+    
+    .alphabet-filter-wrapper {
+        margin-bottom: 20px;
+    }
+    
+    .alphabet-toggle-btn {
+        display: inline-flex;
+        align-items: center;
+        gap: 8px;
+        padding: 8px 16px;
+        border: 1px solid var(--border-primary, #e8e9ff);
+        background: var(--bg-primary, white);
+        border-radius: 8px;
+        font-size: 13px;
+        font-weight: 600;
+        color: var(--text-secondary, #64748b);
+        cursor: pointer;
+        transition: all 0.2s;
+    }
+    
+    .alphabet-toggle-btn:hover {
+        background: var(--bg-hover, #f8f9ff);
+        border-color: #5856d6;
+        color: #5856d6;
+    }
+    
+    .alphabet-toggle-btn[aria-expanded="true"] .alphabet-chevron {
+        transform: rotate(180deg);
+    }
+    
+    .alphabet-chevron {
+        font-size: 10px;
+        transition: transform 0.2s;
+    }
+    
     .alphabet-filter {
         display: flex;
         flex-wrap: wrap;
         gap: 8px;
-        margin-bottom: 20px;
+        margin-top: 12px;
         padding: 15px;
         background: var(--bg-secondary, #f8f9ff);
         border-radius: 8px;
@@ -971,15 +1110,15 @@
             {% if plugins %}
             
             
- - - @@ -995,13 +1134,13 @@
- {% if plugin.type == "Security" %} + {% if plugin.type|lower == "security" %} - {% elif plugin.type == "Performance" %} + {% elif plugin.type|lower == "performance" %} - {% elif plugin.type == "Utility" %} + {% elif plugin.type|lower == "utility" %} - {% elif plugin.type == "Backup" %} + {% elif plugin.type|lower == "backup" %} {% else %} @@ -1216,15 +1355,15 @@
- - - @@ -1274,35 +1413,63 @@
- -