mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-04-10 21:03:01 +00:00
Feature/soccer scroll support (#186)
* fix: Use plugin.modes instead of manifest.json for available modes - Display controller now checks plugin_instance.modes first before falling back to manifest - This allows plugins to dynamically provide modes based on enabled leagues - Fixes issue where disabled leagues (WNBA, NCAAW) appeared in available modes - Plugins can now control their available modes at runtime based on config * fix: Handle permission errors when removing plugin directories - Added _safe_remove_directory() method to handle permission errors gracefully - Fixes permissions on __pycache__ directories before removal - Updates uninstall_plugin() and install methods to use safe removal - Resolves [Errno 13] Permission denied errors during plugin install/uninstall * debug(display): Change FPS check logging from debug to info level - Change FPS check log from DEBUG to INFO to help diagnose scrolling FPS issues - Add active_mode to log message for clarity - Helps identify if plugins are being detected for high-FPS mode * debug(display): Add logging for display_interval in both FPS loops - Log display_interval when entering high-FPS and normal loops - Shows expected FPS for high-FPS mode - Helps diagnose why news ticker shows 50 FPS despite high-FPS detection * feat: Update soccer-scoreboard submodule with scroll display support - Submodule now includes full feature parity with football-scoreboard - Granular display modes for 8 leagues (24 total modes) - Scroll display mode with game_renderer.py and scroll_display.py - League registry system with enabled state filtering - Modernized config_schema.json with per-league scroll settings - League-aware logo caching to prevent collisions - Pillow 8.x compatibility for image resampling Submodule branch: feature/football-feature-parity Commit: e22a16d * style(web): Update plugin button colors and reorganize documentation - Change update button color to yellow-600 in installed plugins section to match plugin config page - Change refresh plugins button color to blue-600 to match restart display button - Move DEVELOPMENT.md and MIGRATION_GUIDE.md from root to docs/ directory - Remove IMPACT_EXPLANATION.md and MERGE_CONFLICT_RESOLUTION_PLAN.md --------- Co-authored-by: Chuck <chuck@example.com>
This commit is contained in:
@@ -1,245 +0,0 @@
|
|||||||
# Impact Explanation: Config Schema Validation Fixes
|
|
||||||
|
|
||||||
## Current Problem (Before Fixes)
|
|
||||||
|
|
||||||
### What Users Experience Now
|
|
||||||
|
|
||||||
**Scenario**: User wants to configure a plugin (e.g., hockey-scoreboard)
|
|
||||||
|
|
||||||
1. User opens web interface → Plugins tab → hockey-scoreboard configuration
|
|
||||||
2. User changes some settings (e.g., favorite teams, display duration)
|
|
||||||
3. User clicks "Save Configuration" button
|
|
||||||
4. **ERROR**: "Configuration validation failed: Missing required field: 'enabled'"
|
|
||||||
5. **RESULT**: Configuration changes are NOT saved
|
|
||||||
6. User is frustrated - can't save their configuration
|
|
||||||
|
|
||||||
**Why This Happens**:
|
|
||||||
- Plugin schema has `"required": ["enabled"]`
|
|
||||||
- `enabled` field is system-managed (controlled by PluginManager/enable toggle)
|
|
||||||
- Config doesn't have `enabled` field (it's managed separately)
|
|
||||||
- Validation fails because `enabled` is required but missing
|
|
||||||
|
|
||||||
### Real-World Impact
|
|
||||||
|
|
||||||
- **186 validation errors** across all 20 plugins
|
|
||||||
- **ALL plugins** currently fail to save configs via web interface
|
|
||||||
- Users cannot configure plugins through the UI
|
|
||||||
- This is a **blocking issue** for plugin configuration
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Priority 1 Fix: Remove Core Properties from Required Array
|
|
||||||
|
|
||||||
### What Changes Technically
|
|
||||||
|
|
||||||
**File**: `src/plugin_system/schema_manager.py`
|
|
||||||
|
|
||||||
**Change**: After injecting core properties (`enabled`, `display_duration`, `live_priority`) into schema properties, also remove them from the `required` array.
|
|
||||||
|
|
||||||
**Before**:
|
|
||||||
```python
|
|
||||||
# Core properties added to properties (allowed)
|
|
||||||
enhanced_schema["properties"]["enabled"] = {...}
|
|
||||||
|
|
||||||
# But still in required array (validation fails if missing)
|
|
||||||
enhanced_schema["required"] = ["enabled", ...] # ❌ Still requires enabled
|
|
||||||
```
|
|
||||||
|
|
||||||
**After**:
|
|
||||||
```python
|
|
||||||
# Core properties added to properties (allowed)
|
|
||||||
enhanced_schema["properties"]["enabled"] = {...}
|
|
||||||
|
|
||||||
# Removed from required array (not required for validation)
|
|
||||||
enhanced_schema["required"] = [...] # ✅ enabled removed, validation passes
|
|
||||||
```
|
|
||||||
|
|
||||||
### Why This Is Correct
|
|
||||||
|
|
||||||
- `enabled` is managed by PluginManager (system-level concern)
|
|
||||||
- User doesn't set `enabled` in plugin config form (it's a separate toggle)
|
|
||||||
- Config validation should check user-provided config, not system-managed fields
|
|
||||||
- Core properties should be **allowed** but not **required**
|
|
||||||
|
|
||||||
### User Experience After Fix
|
|
||||||
|
|
||||||
**Scenario**: User configures hockey-scoreboard plugin
|
|
||||||
|
|
||||||
1. User opens web interface → Plugins tab → hockey-scoreboard configuration
|
|
||||||
2. User changes settings (favorite teams, display duration)
|
|
||||||
3. User clicks "Save Configuration" button
|
|
||||||
4. **SUCCESS**: Configuration saves without errors
|
|
||||||
5. Changes are persisted and plugin uses new configuration
|
|
||||||
|
|
||||||
**Impact**:
|
|
||||||
- ✅ All 20 plugins can now save configs successfully
|
|
||||||
- ✅ ~150 validation errors eliminated (all "enabled" related)
|
|
||||||
- ✅ Users can configure plugins normally
|
|
||||||
- ✅ This is the **primary fix** that unblocks plugin configuration
|
|
||||||
|
|
||||||
### Technical Details
|
|
||||||
|
|
||||||
- Issue count: 186 → ~30-40 (most issues resolved)
|
|
||||||
- No breaking changes - only affects validation logic
|
|
||||||
- Backward compatible - configs that work will continue to work
|
|
||||||
- Makes validation logic match the actual architecture
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Priority 2 Fix: Verify Default Merging Logic
|
|
||||||
|
|
||||||
### What This Addresses
|
|
||||||
|
|
||||||
Some plugins have required fields that have default values in their schemas. For example:
|
|
||||||
- `calendar` plugin requires `credentials_file` but schema provides default: `"credentials.json"`
|
|
||||||
- When user saves config without this field, the default should be applied automatically
|
|
||||||
- Then validation passes because the field is present (with default value)
|
|
||||||
|
|
||||||
### Current Behavior
|
|
||||||
|
|
||||||
The code already has default merging logic:
|
|
||||||
```python
|
|
||||||
defaults = schema_mgr.generate_default_config(plugin_id, use_cache=True)
|
|
||||||
plugin_config = schema_mgr.merge_with_defaults(plugin_config, defaults)
|
|
||||||
```
|
|
||||||
|
|
||||||
**But audit shows some plugins still fail**, which suggests either:
|
|
||||||
1. Default merging isn't working correctly for all cases, OR
|
|
||||||
2. Some required fields don't have defaults in schemas (schema design issue)
|
|
||||||
|
|
||||||
### What We'll Verify
|
|
||||||
|
|
||||||
1. Check if `merge_with_defaults()` handles nested objects correctly
|
|
||||||
2. Verify defaults are applied before validation runs
|
|
||||||
3. Test with problematic plugins to see why they still fail
|
|
||||||
4. Fix any issues found OR identify that schemas need defaults added
|
|
||||||
|
|
||||||
### User Experience Impact
|
|
||||||
|
|
||||||
**If defaults are working correctly**:
|
|
||||||
- Users don't need to manually add every field
|
|
||||||
- Fields with defaults "just work" automatically
|
|
||||||
- Easier plugin configuration
|
|
||||||
|
|
||||||
**If defaults aren't working**:
|
|
||||||
- After fix, plugins with schema defaults will validate correctly
|
|
||||||
- Fewer manual field entries required
|
|
||||||
- Better user experience
|
|
||||||
|
|
||||||
### Technical Details
|
|
||||||
|
|
||||||
- Issue count: ~30-40 → ~5-10 (after Priority 1)
|
|
||||||
- Addresses remaining validation failures
|
|
||||||
- May involve schema updates if defaults are missing
|
|
||||||
- Improves robustness of config system
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Priority 3 Fix: Calendar Plugin Cleanup
|
|
||||||
|
|
||||||
### What This Addresses
|
|
||||||
|
|
||||||
Calendar plugin has configuration fields that don't match its schema:
|
|
||||||
- `show_all_day` in config, but schema defines `show_all_day_events` (field name mismatch)
|
|
||||||
- `date_format` and `time_format` in config but not in schema (deprecated fields)
|
|
||||||
|
|
||||||
### Current Problems
|
|
||||||
|
|
||||||
1. **Field name mismatch**: `show_all_day` vs `show_all_day_events`
|
|
||||||
- Schema filtering removes `show_all_day` during save
|
|
||||||
- User's setting for all-day events doesn't actually work
|
|
||||||
- This is a **bug** where the setting is ignored
|
|
||||||
|
|
||||||
2. **Deprecated fields**: `date_format` and `time_format`
|
|
||||||
- Not used in plugin code
|
|
||||||
- Confusing to see in config
|
|
||||||
- Schema filtering removes them anyway (just creates warnings)
|
|
||||||
|
|
||||||
### What We'll Fix
|
|
||||||
|
|
||||||
1. **Fix field name**: Rename `show_all_day` → `show_all_day_events` in config
|
|
||||||
- Makes config match schema
|
|
||||||
- Fixes bug where all-day events setting doesn't work
|
|
||||||
|
|
||||||
2. **Remove deprecated fields**: Remove `date_format` and `time_format` from config
|
|
||||||
- Cleans up config file
|
|
||||||
- Removes confusion
|
|
||||||
- No functional impact (fields weren't used)
|
|
||||||
|
|
||||||
### User Experience Impact
|
|
||||||
|
|
||||||
**Before**:
|
|
||||||
- User sets "show all day events" = true
|
|
||||||
- Setting doesn't work (field name mismatch)
|
|
||||||
- User confused why setting isn't applied
|
|
||||||
|
|
||||||
**After**:
|
|
||||||
- User sets "show all day events" = true
|
|
||||||
- Setting works correctly (field name matches schema)
|
|
||||||
- Config is cleaner and matches schema
|
|
||||||
|
|
||||||
### Technical Details
|
|
||||||
|
|
||||||
- Issue count: ~5-10 → ~3-5 (after Priority 1 & 2)
|
|
||||||
- Fixes a bug (show_all_day_events not working)
|
|
||||||
- Cleanup/improvement, not critical
|
|
||||||
- Only affects calendar plugin
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Summary: Real-World Impact
|
|
||||||
|
|
||||||
### Before All Fixes
|
|
||||||
|
|
||||||
**User tries to configure any plugin**:
|
|
||||||
- ❌ Config save fails with validation errors
|
|
||||||
- ❌ Cannot configure plugins via web interface
|
|
||||||
- ❌ 186 validation errors across all plugins
|
|
||||||
- ❌ System is essentially broken for plugin configuration
|
|
||||||
|
|
||||||
### After Priority 1 Fix
|
|
||||||
|
|
||||||
**When configuring a plugin**:
|
|
||||||
- ✅ Config saves successfully for most plugins
|
|
||||||
- ✅ Can configure plugins via web interface
|
|
||||||
- ✅ ~150 errors resolved (enabled field issues)
|
|
||||||
- ✅ System is functional for plugin configuration
|
|
||||||
|
|
||||||
**Remaining issues**: ~30-40 validation errors
|
|
||||||
- Mostly fields without defaults that need user input
|
|
||||||
- Still some plugins that can't save (but most work)
|
|
||||||
|
|
||||||
### After Priority 2 Fix
|
|
||||||
|
|
||||||
**During plugin configuration**:
|
|
||||||
- ✅ Config saves successfully for almost all plugins
|
|
||||||
- ✅ Defaults applied automatically (easier configuration)
|
|
||||||
- ✅ ~30-40 errors → ~5-10 errors
|
|
||||||
- ✅ System is robust and user-friendly
|
|
||||||
|
|
||||||
**Remaining issues**: ~5-10 edge cases
|
|
||||||
- Complex validation scenarios
|
|
||||||
- Possibly some schema design issues
|
|
||||||
|
|
||||||
### After Priority 3 Fix
|
|
||||||
|
|
||||||
**All plugins**:
|
|
||||||
- ✅ Configs match schemas exactly
|
|
||||||
- ✅ No confusing warnings
|
|
||||||
- ✅ Calendar plugin bug fixed (show_all_day_events works)
|
|
||||||
- ✅ ~3-5 remaining edge cases only
|
|
||||||
- ✅ System is clean and fully functional
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Bottom Line
|
|
||||||
|
|
||||||
**Current State**: Plugin configuration saving is broken (186 errors, all plugins fail)
|
|
||||||
|
|
||||||
**After Fixes**: Plugin configuration saving works correctly (3-5 edge cases remain, all plugins functional)
|
|
||||||
|
|
||||||
**User Impact**: Users can configure plugins successfully instead of getting validation errors
|
|
||||||
|
|
||||||
**Technical Impact**: Validation logic correctly handles system-managed fields and schema defaults
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,188 +0,0 @@
|
|||||||
# Merge Conflict Resolution Plan: plugins → main
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
This document outlines the plan to resolve merge conflicts when merging the `plugins` branch into `main`. The conflicts occur because the plugins branch refactored the architecture from built-in managers to a plugin-based system.
|
|
||||||
|
|
||||||
## Conflicted Files
|
|
||||||
|
|
||||||
### 1. `src/clock.py`
|
|
||||||
**Status**: EXISTS in `main`, DELETED in `plugins`
|
|
||||||
|
|
||||||
**Reason for Conflict**:
|
|
||||||
- In `main`: Clock functionality is implemented as a built-in manager (`src/clock.py`)
|
|
||||||
- In `plugins`: Clock functionality has been migrated to a plugin (`plugins/clock-simple/manager.py`)
|
|
||||||
|
|
||||||
**Resolution Strategy**:
|
|
||||||
- ✅ **DELETE** `src/clock.py` from `main` when merging
|
|
||||||
- The plugin version at `plugins/clock-simple/manager.py` replaces this file
|
|
||||||
- Functionality is preserved in the plugin architecture
|
|
||||||
|
|
||||||
**Action Required**:
|
|
||||||
```bash
|
|
||||||
git rm src/clock.py
|
|
||||||
```
|
|
||||||
|
|
||||||
**Verification**:
|
|
||||||
- Ensure `plugins/clock-simple/` plugin exists and works
|
|
||||||
- Verify clock functionality works via the plugin system
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 2. `src/news_manager.py`
|
|
||||||
**Status**: EXISTS in `main`, DELETED in `plugins`
|
|
||||||
|
|
||||||
**Reason for Conflict**:
|
|
||||||
- In `main`: News functionality is implemented as a built-in manager (`src/news_manager.py`)
|
|
||||||
- In `plugins`: News functionality has been migrated to a plugin (`plugins/ledmatrix-news/manager.py`)
|
|
||||||
|
|
||||||
**Resolution Strategy**:
|
|
||||||
- ✅ **DELETE** `src/news_manager.py` from `main` when merging
|
|
||||||
- The plugin version at `plugins/ledmatrix-news/manager.py` replaces this file
|
|
||||||
- Functionality is preserved in the plugin architecture
|
|
||||||
|
|
||||||
**Action Required**:
|
|
||||||
```bash
|
|
||||||
git rm src/news_manager.py
|
|
||||||
```
|
|
||||||
|
|
||||||
**Verification**:
|
|
||||||
- Ensure `plugins/ledmatrix-news/` plugin exists and works
|
|
||||||
- Verify news functionality works via the plugin system
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 3. `README.md`
|
|
||||||
**Status**: SIGNIFICANTLY DIFFERENT in both branches
|
|
||||||
|
|
||||||
**Main Differences**:
|
|
||||||
|
|
||||||
| Aspect | `main` branch | `plugins` branch |
|
|
||||||
|--------|--------------|------------------|
|
|
||||||
| Introduction | Has detailed "Core Features" section with screenshots | Has "Plugins Version is HERE!" introduction |
|
|
||||||
| Architecture | Describes built-in managers | Describes plugin-based architecture |
|
|
||||||
| Website Link | Includes link to website write-up | Removed website link, added ko-fi link |
|
|
||||||
| Content Focus | Feature showcase with images | Plugin system explanation |
|
|
||||||
|
|
||||||
**Resolution Strategy**:
|
|
||||||
- ✅ **KEEP** `plugins` branch version as the base (it's current and accurate for plugin architecture)
|
|
||||||
- ⚠️ **CONSIDER** preserving valuable content from `main`:
|
|
||||||
- The detailed "Core Features" section with screenshots might be valuable for documentation
|
|
||||||
- The website write-up link might be worth preserving
|
|
||||||
- However, since plugins branch is more current and accurate, prefer plugins version
|
|
||||||
|
|
||||||
**Recommended Approach**:
|
|
||||||
1. Keep plugins branch README.md as-is (it's current and accurate)
|
|
||||||
2. The old "Core Features" section in main is outdated for the plugin architecture
|
|
||||||
3. If website link is important, it can be added back to plugins version separately
|
|
||||||
|
|
||||||
**Action Required**:
|
|
||||||
```bash
|
|
||||||
# Accept plugins branch version
|
|
||||||
git checkout --theirs README.md
|
|
||||||
# OR manually review and merge, keeping plugins version as base
|
|
||||||
```
|
|
||||||
|
|
||||||
**Verification**:
|
|
||||||
- README.md accurately describes the plugin architecture
|
|
||||||
- All installation and configuration instructions are current
|
|
||||||
- Links are working
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Step-by-Step Resolution Process
|
|
||||||
|
|
||||||
### Step 1: Checkout main branch and prepare for merge
|
|
||||||
```bash
|
|
||||||
git checkout main
|
|
||||||
git fetch origin
|
|
||||||
git merge origin/plugins --no-commit --no-ff
|
|
||||||
```
|
|
||||||
|
|
||||||
### Step 2: Resolve file deletion conflicts
|
|
||||||
```bash
|
|
||||||
# Remove files that were migrated to plugins
|
|
||||||
git rm src/clock.py
|
|
||||||
git rm src/news_manager.py
|
|
||||||
```
|
|
||||||
|
|
||||||
### Step 3: Resolve README.md conflict
|
|
||||||
```bash
|
|
||||||
# Option A: Accept plugins version (recommended)
|
|
||||||
git checkout --theirs README.md
|
|
||||||
|
|
||||||
# Option B: Manually review and merge
|
|
||||||
# Edit README.md to combine best of both if needed
|
|
||||||
```
|
|
||||||
|
|
||||||
### Step 4: Verify no references to deleted files
|
|
||||||
```bash
|
|
||||||
# Check if any code references the deleted files
|
|
||||||
grep -r "from src.clock import" .
|
|
||||||
grep -r "from src.news_manager import" .
|
|
||||||
grep -r "import src.clock" .
|
|
||||||
grep -r "import src.news_manager" .
|
|
||||||
|
|
||||||
# If found, these need to be updated to use plugins instead
|
|
||||||
```
|
|
||||||
|
|
||||||
### Step 5: Test the resolved merge
|
|
||||||
```bash
|
|
||||||
# Verify plugins are loaded correctly
|
|
||||||
python3 -c "from src.plugin_system.plugin_manager import PluginManager; print('OK')"
|
|
||||||
|
|
||||||
# Check that clock-simple plugin exists
|
|
||||||
ls -la plugins/clock-simple/
|
|
||||||
|
|
||||||
# Check that ledmatrix-news plugin exists
|
|
||||||
ls -la plugins/ledmatrix-news/
|
|
||||||
```
|
|
||||||
|
|
||||||
### Step 6: Complete the merge
|
|
||||||
```bash
|
|
||||||
git add .
|
|
||||||
git commit -m "Merge plugins into main: Remove deprecated managers, keep plugin-based README"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Verification Checklist
|
|
||||||
|
|
||||||
- [ ] `src/clock.py` is deleted (functionality in `plugins/clock-simple/`)
|
|
||||||
- [ ] `src/news_manager.py` is deleted (functionality in `plugins/ledmatrix-news/`)
|
|
||||||
- [ ] `README.md` reflects plugin architecture (plugins branch version)
|
|
||||||
- [ ] No import statements reference deleted files
|
|
||||||
- [ ] Clock plugin works correctly
|
|
||||||
- [ ] News plugin works correctly
|
|
||||||
- [ ] All tests pass (if applicable)
|
|
||||||
- [ ] Documentation is accurate
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
1. **No Code Changes Required**: The deletions are safe because:
|
|
||||||
- Clock functionality exists in `plugins/clock-simple/manager.py`
|
|
||||||
- News functionality exists in `plugins/ledmatrix-news/manager.py`
|
|
||||||
- The plugin system loads these automatically
|
|
||||||
|
|
||||||
2. **README.md Decision**: Keeping plugins version is recommended because:
|
|
||||||
- It accurately describes the current plugin-based architecture
|
|
||||||
- The old "Core Features" section describes the old architecture
|
|
||||||
- Users need current installation/configuration instructions
|
|
||||||
|
|
||||||
3. **Potential Issues**:
|
|
||||||
- If any code in `main` still imports these files, those imports need to be removed
|
|
||||||
- Configuration references to old managers may need updating
|
|
||||||
- Documentation references may need updating
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Related Files to Check (Not Conflicted but Related)
|
|
||||||
|
|
||||||
These files might reference the deleted managers and should be checked:
|
|
||||||
|
|
||||||
- `display_controller.py` - May have references to Clock or NewsManager
|
|
||||||
- `config/config.json` - May have config sections for clock/news_manager
|
|
||||||
- Any test files that might test these managers
|
|
||||||
- Documentation files that reference these managers
|
|
||||||
|
|
||||||
Submodule plugins/soccer-scoreboard updated: b8d4ce1272...e22a16da38
@@ -1385,7 +1385,7 @@ function renderInstalledPlugins(plugins) {
|
|||||||
data-action="configure">
|
data-action="configure">
|
||||||
<i class="fas fa-cog mr-2"></i>Configure
|
<i class="fas fa-cog mr-2"></i>Configure
|
||||||
</button>
|
</button>
|
||||||
<button class="btn bg-gray-600 hover:bg-gray-700 text-white px-4 py-2 rounded-md text-sm flex-1 font-semibold"
|
<button class="btn bg-yellow-600 hover:bg-yellow-700 text-white px-4 py-2 rounded-md text-sm flex-1 font-semibold"
|
||||||
data-plugin-id="${escapedPluginId}"
|
data-plugin-id="${escapedPluginId}"
|
||||||
data-action="update">
|
data-action="update">
|
||||||
<i class="fas fa-sync mr-2"></i>Update
|
<i class="fas fa-sync mr-2"></i>Update
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<!-- Plugin Controls -->
|
<!-- Plugin Controls -->
|
||||||
<div class="flex flex-wrap items-center justify-between gap-4 mb-6">
|
<div class="flex flex-wrap items-center justify-between gap-4 mb-6">
|
||||||
<div class="flex items-center space-x-4">
|
<div class="flex items-center space-x-4">
|
||||||
<button id="refresh-plugins-btn" class="btn bg-gray-600 hover:bg-gray-700 text-white px-4 py-2 rounded-md">
|
<button id="refresh-plugins-btn" class="btn bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-md">
|
||||||
<i class="fas fa-sync-alt mr-2"></i>Refresh Plugins
|
<i class="fas fa-sync-alt mr-2"></i>Refresh Plugins
|
||||||
</button>
|
</button>
|
||||||
<button id="update-all-plugins-btn" class="btn bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded-md flex items-center">
|
<button id="update-all-plugins-btn" class="btn bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded-md flex items-center">
|
||||||
|
|||||||
Reference in New Issue
Block a user