Skip to content

Commit f687830

Browse files
committed
Refactor dashboard widget drag-and-drop functionality and enhance palette interactions
- Removed drag handle from plugin cards in the dashboard. - Updated CSS for dragging states in the widget palette. - Enhanced the editor.js to support new widget addition from the palette with auto-save functionality. - Implemented loading state for newly added widgets and improved rendering logic. - Added success toast notifications for user feedback on widget addition. - Refactored palette.js to initialize Sortable.js for the widget palette and handle drag events. - Removed legacy drag-and-drop functionality from the plugins page, transitioning to sidebar edit mode for plugin reordering.
1 parent b2ddaec commit f687830

11 files changed

Lines changed: 1185 additions & 224 deletions

File tree

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,17 @@ Gearbox is a general-purpose monitoring and management platform with a plugin-ba
1717

1818
**IMPORTANT:** Gearbox is NOT an HAProxy-specific tool. It is a universal monitoring platform. HAProxy monitoring is just one plugin among many.
1919

20+
## 🚀 Getting Started
21+
22+
**New to Gearbox?** Follow our comprehensive [Getting Started Guide](docs/GETTING_STARTED.md) for step-by-step instructions on:
23+
24+
- Installing the Gearbox dashboard and agent
25+
- Generating and configuring API keys
26+
- Adding your first monitored server
27+
- Enabling plugins and creating dashboards
28+
29+
The guide includes detailed examples, troubleshooting tips, and best practices for production deployments.
30+
2031
## Quick Start
2132

2233
### Prerequisites

TASKS.md

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -125,26 +125,51 @@ Framework = Shared services and building blocks (graphs, tables, panels, cards,
125125
- Fetches widgets dynamically from `/api/dashboards/widgets` endpoint
126126
- Responsive design with dark mode support
127127

128-
#### Task 3: Drag-and-Drop from Palette
128+
#### Task 3: Drag-and-Drop from Palette
129129

130-
- [ ] Extend `gearbox/static/js/dashboard/editor.js` drag-drop functionality
131-
- [ ] Use SortableJS `group` option to enable cross-container dragging
132-
- [ ] On drop: generate widget ID, create instance, add to dashboard, save YAML
133-
- [ ] Show loading state while widget content loads via HTMX
130+
- [x] Extend `gearbox/static/js/dashboard/editor.js` drag-drop functionality
131+
- [x] Use SortableJS `group` option to enable cross-container dragging
132+
- [x] On drop: generate widget ID, create instance, add to dashboard, save YAML
133+
- [x] Show loading state while widget content loads via HTMX
134134

135-
#### Task 4: Navigation Updates
135+
**Implementation Details:**
136136

137-
- [ ] Create dynamic plugin navigation
138-
- [ ] Show plugin menu items only when enabled for server
139-
- [ ] Ensure plugin menu items update when plugins are enabled/disabled
137+
- Configured SortableJS with `group` option for cross-container dragging between palette and grid
138+
- Palette widgets use `pull: 'clone'` to allow dragging without removing from palette
139+
- Grid accepts drops from palette via `put: ['widget-palette']`
140+
- `onAdd` handler creates new widget instances with unique IDs when dropped
141+
- Auto-saves dashboard after widget drop with silent save (no page reload)
142+
- Displays loading state during widget creation, then shows placeholder content
143+
- Widget position is automatically calculated based on drop index
144+
- Edit controls (drag handle, delete button) are injected after widget creation
145+
- Success toast notification confirms widget addition
146+
- Built successfully with `make templ-generate && make build`
147+
148+
#### Task 4: Navigation Updates ✅
149+
150+
- [x] Create dynamic plugin navigation
151+
- [x] Show plugin menu items only when enabled for server
152+
- [x] Ensure plugin menu items update when plugins are enabled/disabled
153+
- [x] Left hand nav items can be rearranged by clicking edit icon that is next to the toggle sidebar icon
154+
- [x] When in edit mode user can drag a menu item up or down and other nav items flow around it
155+
- [x] Edit icon becomes save icon while in edit mode
156+
- [x] When a plugin is enabled it generates its default "dashboard" interface yaml file if it does not already exist. Each plugin's default dashboard has a default name and icon as designed by plugin developer. When plugins is enabled it is added to the nav bar
157+
- [x] The rearrangement of left hand nav items will be removed from the plugin screen, all nav rearrangement is now in the nav bar only.
140158

141-
#### Task 5: Left Hand Navigation bar Updates
159+
**Implementation Details:**
142160

143-
- [ ] Items can be rearranged by clicking edit icon that is next to the toggle sidebar icon
144-
- [ ] When in edit mode user can drag a menu item up or down and other nav items flow around it
145-
- [ ] Edit icon becomes save icon
146-
- [ ] When a plugin is enabled it generates its default "dashboard" interface yaml file if it does not already exist. Each plugin's default dashboard has a default name and icon as designed by plugin developer. When plugins is enabled it is added to the nav bar
147-
- [ ] The rearrangement of left hand nav items will be removed from the plugin screen, all nav rearrangement is now in the nav bar only.
161+
- Added edit mode toggle button next to sidebar collapse button in [base.templ](gearbox/internal/framework/templates/layouts/base.templ:1105-1129)
162+
- Edit icon switches to save/checkmark icon when in edit mode
163+
- Created `SidebarLinkDraggable` and `SidebarLinkDraggableWithBadge` templ components with data attributes and drag handles
164+
- Implemented `toggleSidebarEditMode()` JavaScript function for managing edit state
165+
- Used SortableJS for drag-and-drop reordering of navigation items
166+
- Drag handles visible only in edit mode, links disabled during editing
167+
- `saveSidebarOrder()` POSTs new order to `/api/integrations/sort-order` endpoint
168+
- Removed drag handle from plugin cards in [plugins.templ](gearbox/internal/framework/templates/pages/plugins.templ)
169+
- Disabled drag-and-drop in [plugins-page.js](gearbox/static/js/plugins/plugins-page.js) with explanatory comments
170+
- Dynamic navigation already working via `OrderedIntegrationLinks()` and middleware
171+
- Plugin dashboards auto-generate when enabled (completed in Task 1)
172+
- Built successfully with `make templ-generate && make build`
148173

149174
**Testing Checklist:**
150175

@@ -186,20 +211,3 @@ Framework = Shared services and building blocks (graphs, tables, panels, cards,
186211
- **Agent API Docs:** [gearbox-agent/docs/](gearbox-agent/docs/)
187212
- **Plugin Architecture:** [docs/plugins.md](docs/plugins.md)
188213
- **Development Guide:** [gearbox/docs/development.md](gearbox/docs/development.md)
189-
190-
---
191-
192-
## Fresh Start
193-
194-
Code to run for a fresh start (deletes local database and starts dev server):
195-
196-
```bash
197-
# from the gearbox directory
198-
cd ../gearbox-agent
199-
make deploy
200-
cd -
201-
rm -f data/haproxy-monitor.db
202-
rm -rf data/dashboards
203-
make dev-local
204-
```
205-

docs/GETTING_STARTED.md

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
# Getting Started with Gearbox
2+
3+
Welcome to Gearbox! This guide will walk you through setting up your first monitored server or workstation (we call these "Boxes").
4+
5+
## Overview
6+
7+
Gearbox is a plugin-based server monitoring and management platform that consists of two components:
8+
9+
- **Gearbox Dashboard** - Web interface for monitoring multiple servers (port 3000)
10+
- **Gearbox Agent** - Lightweight service installed on each Box you want to monitor (port 8405)
11+
12+
## Prerequisites
13+
14+
- A Linux server or workstation to monitor (the "Box")
15+
- Go 1.21+ installed on the Box (for building the agent)
16+
- Network connectivity between the dashboard and the Box on port 8405
17+
18+
## Quick Start
19+
20+
### Step 1: Install Gearbox Dashboard
21+
22+
The dashboard is where you'll view and manage all your monitored Boxes.
23+
24+
```bash
25+
# Clone the repository
26+
git clone https://github.com/sarg3nt/gearbox.git
27+
cd gearbox/gearbox
28+
29+
# Build the dashboard
30+
make build
31+
32+
# Run the dashboard
33+
./bin/gearbox
34+
```
35+
36+
The dashboard will be available at `http://localhost:3000`
37+
38+
### Step 2: Install Gearbox Agent on Your Box
39+
40+
On the server or workstation you want to monitor:
41+
42+
```bash
43+
# Clone the repository
44+
git clone https://github.com/sarg3nt/gearbox.git
45+
cd gearbox/gearbox-agent
46+
47+
# Build the agent
48+
make build
49+
50+
# The agent binary will be in ./bin/gearbox-agent
51+
```
52+
53+
### Step 3: Generate an API Key
54+
55+
1. Open the Gearbox dashboard at `http://localhost:3000`
56+
2. Navigate to **Settings > Servers** and click **Add Server**
57+
3. Click the **Generate API Key** button
58+
4. Copy the generated API key to your clipboard
59+
5. **Important:** Save this key somewhere safe - you won't be able to see it again!
60+
61+
### Step 4: Configure the Agent
62+
63+
Create a configuration file or set environment variables on your Box:
64+
65+
#### Option A: Environment Variables (Recommended)
66+
67+
```bash
68+
export GEARBOX_API_KEY="your-generated-api-key-here"
69+
export GEARBOX_PORT="8405" # Optional, defaults to 8405
70+
```
71+
72+
Add these to your shell profile (`~/.bashrc`, `~/.zshrc`) or create a systemd service file to make them persistent.
73+
74+
#### Option B: Configuration File
75+
76+
Create `/etc/gearbox-agent/config.yaml`:
77+
78+
```yaml
79+
api_key: "your-generated-api-key-here"
80+
port: 8405
81+
```
82+
83+
### Step 5: Start the Agent
84+
85+
```bash
86+
# Start the agent
87+
cd gearbox-agent
88+
./bin/gearbox-agent
89+
```
90+
91+
The agent will start on port 8405 and begin collecting system metrics.
92+
93+
### Step 6: Add the Box to Your Dashboard
94+
95+
1. Return to the Gearbox dashboard
96+
2. In the **Add Server** form, fill in:
97+
- **Server Name**: A friendly name (e.g., "Production Web Server")
98+
- **Server ID**: A unique identifier (e.g., "web-prod-01")
99+
- **Agent URL**: The URL to your agent (e.g., `http://192.168.1.100:8405`)
100+
- **API Key**: Paste the API key you generated earlier
101+
3. Click **Test Connection** to verify connectivity
102+
4. Click **Add Server** to save
103+
104+
### Step 7: Enable Plugins
105+
106+
After adding your first Box:
107+
108+
1. Navigate to **Settings > Plugins**
109+
2. Enable the plugins you want to use:
110+
- **HAProxy** - HAProxy monitoring and statistics
111+
- **Metrics** - System metrics visualization
112+
- **Services** - Service management and monitoring
113+
- **Certificates** - TLS certificate tracking
114+
- **Logs** - Log aggregation and viewing
115+
- **Traffic** - Traffic analysis and visualization
116+
- **Alerts** - Alert management
117+
- **OS Updates** - OS package updates
118+
119+
When you enable a plugin, its default dashboard will be automatically created and added to the navigation.
120+
121+
## Running as a System Service
122+
123+
### Systemd Service (Linux)
124+
125+
Create `/etc/systemd/system/gearbox-agent.service`:
126+
127+
```ini
128+
[Unit]
129+
Description=Gearbox Agent - Server Monitoring
130+
After=network.target
131+
132+
[Service]
133+
Type=simple
134+
User=gearbox
135+
WorkingDirectory=/opt/gearbox-agent
136+
Environment="GEARBOX_API_KEY=your-api-key-here"
137+
Environment="GEARBOX_PORT=8405"
138+
ExecStart=/opt/gearbox-agent/bin/gearbox-agent
139+
Restart=always
140+
RestartSec=10
141+
142+
[Install]
143+
WantedBy=multi-user.target
144+
```
145+
146+
Enable and start the service:
147+
148+
```bash
149+
sudo systemctl daemon-reload
150+
sudo systemctl enable gearbox-agent
151+
sudo systemctl start gearbox-agent
152+
sudo systemctl status gearbox-agent
153+
```
154+
155+
## Auto-Discovery
156+
157+
Gearbox Agent automatically discovers services running on your Box:
158+
159+
- **HAProxy** - Detects running HAProxy instances and collects stats
160+
- **Docker** - Discovers Docker containers and images
161+
- **System Services** - Monitors systemd services
162+
163+
No manual configuration required! Just enable the relevant plugins in the dashboard.
164+
165+
## Security Considerations
166+
167+
1. **API Key Security**: Treat your API key like a password. Never commit it to version control.
168+
2. **Network Security**: Use a firewall to restrict access to port 8405 to only your dashboard server.
169+
3. **HTTPS**: In production, run both the dashboard and agent behind a reverse proxy with HTTPS.
170+
4. **Authentication**: The dashboard supports password authentication and WebAuthn. Enable it for production use.
171+
172+
## Troubleshooting
173+
174+
### Agent Won't Start
175+
176+
- Verify the `GEARBOX_API_KEY` environment variable is set
177+
- Check if port 8405 is available: `sudo netstat -tulpn | grep 8405`
178+
- Review agent logs for errors
179+
180+
### Connection Test Fails
181+
182+
- Verify the Agent URL is correct and accessible from the dashboard server
183+
- Check firewall rules on both the dashboard and Box
184+
- Confirm the API key matches between dashboard and agent
185+
- Use `curl` to test: `curl http://your-box:8405/health`
186+
187+
### No Data Showing
188+
189+
- Wait 30-60 seconds for the first data collection cycle
190+
- Verify the plugin is enabled in **Settings > Plugins**
191+
- Check that the service you're trying to monitor is actually running on the Box
192+
- Review agent logs for collection errors
193+
194+
## Next Steps
195+
196+
- **Customize Dashboards**: Create custom dashboards with your favorite widgets
197+
- **Configure Alerts**: Set up alert rules for critical metrics
198+
- **Enable GitOps**: Configure git sync for dashboard definitions
199+
- **Add More Boxes**: Repeat the process to monitor additional servers
200+
201+
## Getting Help
202+
203+
- **Documentation**: [GitHub Repository](https://github.com/sarg3nt/gearbox)
204+
- **Issues**: [Report a Bug](https://github.com/sarg3nt/gearbox/issues)
205+
- **Architecture**: See [docs/plugins.md](plugins.md) for plugin architecture details
206+
207+
## What's Next?
208+
209+
Now that you have Gearbox running, explore:
210+
211+
1. **Widget System**: Learn how to create custom widgets
212+
2. **Plugin Development**: Build your own monitoring plugins
213+
3. **Dashboard Layouts**: Customize dashboard arrangements
214+
4. **Advanced Configuration**: Explore environment variables and configuration options
215+
216+
Happy monitoring! 📊

gearbox/internal/framework/handler/haproxy_config.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,14 @@ func (h *Handler) HAProxyServerNewPage(w http.ResponseWriter, r *http.Request) {
5050
return
5151
}
5252

53-
component := pages.HAProxyServerNewPage(user, "")
53+
// Fetch existing servers to determine if we should show sidebar
54+
servers, err := h.db.GetServers()
55+
if err != nil {
56+
h.logger.Error("Failed to fetch servers", "error", err)
57+
servers = []*database.ServerDB{} // Default to empty to show no-sidebar layout
58+
}
59+
60+
component := pages.HAProxyServerNewPage(user, servers, "")
5461
if err := component.Render(r.Context(), w); err != nil {
5562
h.logger.Error("Failed to render new server page", "error", err)
5663
http.Error(w, "Internal server error", http.StatusInternalServerError)
@@ -479,7 +486,14 @@ func (h *Handler) renderServerFormWithError(w http.ResponseWriter, r *http.Reque
479486
http.Error(w, "Internal server error", http.StatusInternalServerError)
480487
}
481488
} else {
482-
component := pages.HAProxyServerNewPage(user, errorMsg)
489+
// Fetch existing servers to determine if we should show sidebar
490+
servers, err := h.db.GetServers()
491+
if err != nil {
492+
h.logger.Error("Failed to fetch servers", "error", err)
493+
servers = []*database.ServerDB{} // Default to empty to show no-sidebar layout
494+
}
495+
496+
component := pages.HAProxyServerNewPage(user, servers, errorMsg)
483497
if err := component.Render(r.Context(), w); err != nil {
484498
h.logger.Error("Failed to render form", "error", err)
485499
http.Error(w, "Internal server error", http.StatusInternalServerError)

0 commit comments

Comments
 (0)