git-watchtower 1.10.0 → 1.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -273
- package/package.json +1 -1
- package/src/server/web-ui.js +24 -20
package/README.md
CHANGED
|
@@ -4,13 +4,15 @@
|
|
|
4
4
|
[](https://www.npmjs.com/package/git-watchtower)
|
|
5
5
|
[](LICENSE)
|
|
6
6
|
|
|
7
|
-
Monitor and switch between git branches in real-time. Built for working with web
|
|
7
|
+
Monitor and switch between git branches in real-time. Built for working with web-based AI coding agents, like Claude Code Web & Codex.
|
|
8
8
|
|
|
9
|
-
- **Live branch monitoring**
|
|
10
|
-
- **
|
|
11
|
-
- **
|
|
12
|
-
- **
|
|
13
|
-
- **
|
|
9
|
+
- **Live branch monitoring** with activity sparklines and ahead/behind counters
|
|
10
|
+
- **Web dashboard** for browser-based branch management and PR workflows
|
|
11
|
+
- **Instant notifications** with visual and audio alerts when branches update
|
|
12
|
+
- **Quick switching** with preview pane, undo, and stash integration
|
|
13
|
+
- **Auto-pull** when your current branch has remote changes
|
|
14
|
+
- **Optional dev server** with live reload, or run your own command (Next.js, Vite, etc.)
|
|
15
|
+
- **Zero dependencies** — uses only Node.js built-in modules
|
|
14
16
|
|
|
15
17
|

|
|
16
18
|
|
|
@@ -22,27 +24,21 @@ Git Watchtower watches your remote and notifies you when branches are updated. P
|
|
|
22
24
|
|
|
23
25
|
Also works for human collaborators, but the primary use case is keeping tabs on AI agents coding on different branches.
|
|
24
26
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
- **Merge Conflict Detection** - Warns you when auto-pull fails
|
|
41
|
-
- **Flexible Server Modes** - Static site, custom server command, or no server
|
|
42
|
-
- **Server Log View** - Press `l` to view your dev server output (custom server command mode)
|
|
43
|
-
- **Server Restart** - Press `R` to restart your dev server (custom server command mode)
|
|
44
|
-
- **Configurable Remote** - Works with any git remote name (not just `origin`)
|
|
45
|
-
- **Zero Dependencies** - Uses only Node.js built-in modules
|
|
27
|
+
## Web Dashboard
|
|
28
|
+
|
|
29
|
+
Launch a browser-based dashboard alongside the terminal UI with `--web`:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
git-watchtower --web
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+

|
|
36
|
+
|
|
37
|
+
The web dashboard provides real-time branch monitoring, PR workflows, CI status, session statistics, and more — all in a rich browser interface. When running multiple instances across different projects, they coordinate automatically into a single multi-project dashboard.
|
|
38
|
+
|
|
39
|
+
Press `W` in the TUI to toggle the web dashboard on or off at any time.
|
|
40
|
+
|
|
41
|
+
[Full web dashboard documentation →](docs/web-dashboard.md)
|
|
46
42
|
|
|
47
43
|
## Installation
|
|
48
44
|
|
|
@@ -75,186 +71,64 @@ git-watchtower
|
|
|
75
71
|
# Run without dev server (branch monitoring only)
|
|
76
72
|
git-watchtower --no-server
|
|
77
73
|
|
|
78
|
-
#
|
|
79
|
-
git-watchtower --
|
|
74
|
+
# Launch with web dashboard
|
|
75
|
+
git-watchtower --web
|
|
76
|
+
|
|
77
|
+
# Specify custom ports
|
|
78
|
+
git-watchtower --port 8080 --web --web-port 9000
|
|
80
79
|
|
|
81
80
|
# Re-run the configuration wizard
|
|
82
81
|
git-watchtower --init
|
|
83
82
|
|
|
84
|
-
# Show version
|
|
85
|
-
git-watchtower --version
|
|
86
|
-
|
|
87
83
|
# Show help
|
|
88
84
|
git-watchtower --help
|
|
89
85
|
```
|
|
90
86
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
### Static Site Mode (Default)
|
|
94
|
-
Serves static files with automatic live reload. Good for static HTML/CSS/JS sites, projects without a build step, quick prototyping.
|
|
95
|
-
|
|
96
|
-
#### Live Reload
|
|
97
|
-
|
|
98
|
-
The static server includes automatic live reload powered by Server-Sent Events (SSE). When you save a file, all connected browsers refresh instantly.
|
|
99
|
-
|
|
100
|
-
**How it works:**
|
|
101
|
-
1. A small script is automatically injected into HTML pages
|
|
102
|
-
2. The script opens an SSE connection to `/livereload`
|
|
103
|
-
3. When files change in your static directory, the server notifies all browsers
|
|
104
|
-
4. Browsers automatically reload to show your changes
|
|
105
|
-
|
|
106
|
-
**File watching behavior:**
|
|
107
|
-
- Uses Node.js native `fs.watch()` with recursive watching
|
|
108
|
-
- Changes are debounced (100ms) to prevent rapid reloads during saves
|
|
109
|
-
- Press `r` to manually trigger a reload for all connected browsers
|
|
110
|
-
|
|
111
|
-
**Ignored files:**
|
|
87
|
+
[Full CLI reference →](docs/configuration.md#cli-flags)
|
|
112
88
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
| Ignored | Reason |
|
|
116
|
-
|---------|--------|
|
|
117
|
-
| `.git/` directory | Git internals change frequently during commits, fetches, etc. |
|
|
118
|
-
| `.gitignore` patterns | Respects your project's ignore rules |
|
|
119
|
-
|
|
120
|
-
If a `.gitignore` file exists in your static directory (or project root), those patterns are used to filter file change events. This means changes to `node_modules/`, build artifacts, log files, and other ignored paths won't trigger reloads.
|
|
89
|
+
## Server Modes
|
|
121
90
|
|
|
122
|
-
|
|
123
|
-
- Simple filenames: `foo.txt`
|
|
124
|
-
- Wildcards: `*.log`, `file?.txt`
|
|
125
|
-
- Globstar: `**/logs`, `logs/**/*.log`
|
|
126
|
-
- Directory patterns: `node_modules/`, `dist/`
|
|
127
|
-
- Anchored patterns: `/build` (root only)
|
|
128
|
-
- Comments and blank lines are ignored
|
|
91
|
+
Git Watchtower supports three server modes:
|
|
129
92
|
|
|
130
|
-
|
|
131
|
-
|
|
93
|
+
| Mode | Flag | Description |
|
|
94
|
+
|------|------|-------------|
|
|
95
|
+
| **Static Site** | `--mode static` | Built-in server with live reload for HTML/CSS/JS (default) |
|
|
96
|
+
| **Custom Command** | `--mode command -c "npm run dev"` | Run your own dev server (Next.js, Vite, Nuxt, etc.) |
|
|
97
|
+
| **No Server** | `--no-server` | Branch monitoring only |
|
|
132
98
|
|
|
133
|
-
|
|
134
|
-
Branch monitoring only. Use this when watching AI agents push to multiple branches, or when you have your own dev server running separately.
|
|
99
|
+
[Full server modes documentation →](docs/server-modes.md)
|
|
135
100
|
|
|
136
101
|
## Configuration
|
|
137
102
|
|
|
138
|
-
|
|
103
|
+
Settings are saved to `.watchtowerrc.json` in your project directory. Key settings:
|
|
139
104
|
|
|
140
105
|
| Setting | Description | Default |
|
|
141
106
|
|---------|-------------|---------|
|
|
142
107
|
| Server mode | static, command, or none | static |
|
|
143
108
|
| Port | Server port number | 3000 |
|
|
144
|
-
|
|
|
145
|
-
| Command | Dev server command (custom server command mode) | npm run dev |
|
|
146
|
-
| Restart on switch | Restart server on branch switch | true |
|
|
109
|
+
| Web dashboard | Enable browser dashboard | false (use `--web`) |
|
|
147
110
|
| Auto-pull | Auto-pull when current branch has updates | true |
|
|
148
111
|
| Polling interval | How often to check for git updates | 5 seconds |
|
|
149
112
|
| Sound notifications | Audio alerts for updates | true |
|
|
150
113
|
| Visible branches | Number of branches shown in list | 7 |
|
|
151
114
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
### Example Configuration
|
|
155
|
-
|
|
156
|
-
```json
|
|
157
|
-
{
|
|
158
|
-
"server": {
|
|
159
|
-
"mode": "command",
|
|
160
|
-
"command": "npm run dev",
|
|
161
|
-
"port": 3000,
|
|
162
|
-
"restartOnSwitch": true,
|
|
163
|
-
"staticDir": "public"
|
|
164
|
-
},
|
|
165
|
-
"remoteName": "origin",
|
|
166
|
-
"autoPull": true,
|
|
167
|
-
"gitPollInterval": 5000,
|
|
168
|
-
"soundEnabled": true,
|
|
169
|
-
"visibleBranches": 7
|
|
170
|
-
}
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
### Environment Variables
|
|
174
|
-
|
|
175
|
-
You can also use environment variables:
|
|
176
|
-
|
|
177
|
-
```bash
|
|
178
|
-
PORT=8080 git-watchtower
|
|
179
|
-
GIT_POLL_INTERVAL=10000 git-watchtower
|
|
180
|
-
```
|
|
115
|
+
[Full configuration reference →](docs/configuration.md)
|
|
181
116
|
|
|
182
117
|
## Keyboard Controls
|
|
183
118
|
|
|
184
|
-
### Navigation
|
|
185
119
|
| Key | Action |
|
|
186
120
|
|-----|--------|
|
|
187
|
-
|
|
|
188
|
-
| `↓` / `j` | Move selection down |
|
|
121
|
+
| `Up` / `k`, `Down` / `j` | Navigate branch list |
|
|
189
122
|
| `Enter` | Switch to selected branch |
|
|
123
|
+
| `v` | Preview branch (commits & files) |
|
|
190
124
|
| `/` | Search/filter branches |
|
|
191
|
-
| `
|
|
192
|
-
|
|
193
|
-
### Actions
|
|
194
|
-
| Key | Action |
|
|
195
|
-
|-----|--------|
|
|
196
|
-
| `v` | Preview selected branch (commits & files) |
|
|
197
|
-
| `h` | Show switch history |
|
|
125
|
+
| `b` | Branch actions (PR, CI, merge, approve) |
|
|
198
126
|
| `u` | Undo last branch switch |
|
|
199
|
-
| `
|
|
200
|
-
| `
|
|
201
|
-
| `b` | Branch actions modal (see below) |
|
|
202
|
-
|
|
203
|
-
### Branch Actions (`b`)
|
|
204
|
-
|
|
205
|
-
Press `b` on any branch to open an interactive action modal. All actions are always visible — unavailable ones are grayed out with reasons (e.g., "Requires gh CLI", "Run: gh auth login").
|
|
206
|
-
|
|
207
|
-
| Key | Action | Requires |
|
|
208
|
-
|-----|--------|----------|
|
|
209
|
-
| `b` | Open branch on GitHub/GitLab/Bitbucket/Azure DevOps | - |
|
|
210
|
-
| `c` | Open Claude Code session in browser | Claude branch with session URL |
|
|
211
|
-
| `p` | Create PR (or view existing PR) | `gh` or `glab` CLI |
|
|
212
|
-
| `d` | View PR diff on GitHub/GitLab | Open PR |
|
|
213
|
-
| `a` | Approve pull request | `gh` or `glab` CLI + open PR |
|
|
214
|
-
| `m` | Merge pull request (squash + delete branch) | `gh` or `glab` CLI + open PR |
|
|
215
|
-
| `i` | Check CI status | `gh` or `glab` CLI |
|
|
216
|
-
| `Esc` | Close modal | - |
|
|
217
|
-
|
|
218
|
-
The modal opens instantly and loads PR info in the background. Results are cached per branch and invalidated when the branch receives new commits. The modal auto-detects:
|
|
219
|
-
- **Claude Code branches** (`claude/` prefix) and extracts session URLs from commit messages
|
|
220
|
-
- **Git hosting platform** from the remote URL (GitHub, GitLab, Bitbucket, Azure DevOps)
|
|
221
|
-
- **Existing PRs** and their review/CI status
|
|
222
|
-
- **CLI tool availability** — shows install/auth hints when `gh` or `glab` isn't set up
|
|
223
|
-
|
|
224
|
-
### Server Controls
|
|
225
|
-
| Key | Mode | Action |
|
|
226
|
-
|-----|------|--------|
|
|
227
|
-
| `r` | Static site | Force reload all browsers |
|
|
228
|
-
| `l` | Custom server command | View server logs |
|
|
229
|
-
| `R` | Custom server command | Restart dev server |
|
|
230
|
-
|
|
231
|
-
### Display
|
|
232
|
-
| Key | Action |
|
|
233
|
-
|-----|--------|
|
|
234
|
-
| `s` | Toggle sound notifications |
|
|
235
|
-
| `i` | Show server/status info |
|
|
236
|
-
| `1-0` | Set visible branch count (1-10) |
|
|
237
|
-
| `+` / `-` | Increase/decrease visible branches |
|
|
238
|
-
|
|
239
|
-
### Quit
|
|
240
|
-
| Key | Action |
|
|
241
|
-
|-----|--------|
|
|
127
|
+
| `S` | Stash changes |
|
|
128
|
+
| `W` | Toggle web dashboard |
|
|
242
129
|
| `q` | Quit |
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
## Status Indicators
|
|
246
|
-
|
|
247
|
-
| Badge | Meaning |
|
|
248
|
-
|-------|---------|
|
|
249
|
-
| `★ CURRENT` | Currently checked-out branch |
|
|
250
|
-
| `✦ NEW` | Branch created since Watchtower started |
|
|
251
|
-
| `↓ UPDATES` | Remote has new commits to pull |
|
|
252
|
-
| `✗ DELETED` | Branch was deleted from remote |
|
|
253
|
-
| `NO-SERVER` | Running in branch-monitor-only mode |
|
|
254
|
-
| `SERVER CRASHED` | Dev server process crashed (custom server command mode) |
|
|
255
|
-
| `OFFLINE` | Network connectivity issues detected |
|
|
256
|
-
| `DETACHED HEAD` | Not on a branch (commit checkout) |
|
|
257
|
-
| `MERGE CONFLICT` | Auto-pull failed due to conflicts |
|
|
130
|
+
|
|
131
|
+
[Full keyboard reference →](docs/keyboard-controls.md)
|
|
258
132
|
|
|
259
133
|
## Requirements
|
|
260
134
|
|
|
@@ -265,127 +139,41 @@ The modal opens instantly and loads PR info in the background. Results are cache
|
|
|
265
139
|
|
|
266
140
|
## How It Works
|
|
267
141
|
|
|
268
|
-
1. **Polling
|
|
269
|
-
2. **Detection
|
|
270
|
-
3. **Auto-pull
|
|
271
|
-
4. **Server
|
|
272
|
-
5. **Live Reload
|
|
142
|
+
1. **Polling** — Runs `git fetch` periodically to check for updates
|
|
143
|
+
2. **Detection** — Compares commit hashes to detect new commits, branches, and deletions
|
|
144
|
+
3. **Auto-pull** — When your current branch has remote updates, pulls automatically (if enabled)
|
|
145
|
+
4. **Server** — Depending on mode, serves static files, runs your command, or does nothing
|
|
146
|
+
5. **Live Reload** — In static site mode, notifies connected browsers via SSE when files change
|
|
147
|
+
6. **Web Dashboard** — Optional browser UI that mirrors and extends the TUI via SSE
|
|
273
148
|
|
|
274
149
|
## Troubleshooting
|
|
275
150
|
|
|
276
|
-
|
|
277
|
-
Git Watchtower requires Git. Install it from: https://git-scm.com/downloads
|
|
278
|
-
|
|
279
|
-
### "No Git remote configured"
|
|
280
|
-
Git Watchtower requires a remote to watch. Add one with:
|
|
281
|
-
```bash
|
|
282
|
-
git remote add origin <repository-url>
|
|
283
|
-
```
|
|
284
|
-
|
|
285
|
-
### Using a different remote name
|
|
286
|
-
If your remote isn't called `origin`, update your config:
|
|
287
|
-
```json
|
|
288
|
-
{
|
|
289
|
-
"remoteName": "upstream"
|
|
290
|
-
}
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
### Port already in use
|
|
294
|
-
Try a different port:
|
|
295
|
-
```bash
|
|
296
|
-
git-watchtower -p 3001
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
### Slow fetches / High latency
|
|
300
|
-
Git Watchtower will automatically reduce polling frequency on slow networks. You can also increase the interval in your config.
|
|
301
|
-
|
|
302
|
-
### Sound not working
|
|
303
|
-
- **macOS**: Uses system sounds via `afplay`
|
|
304
|
-
- **Linux**: Requires PulseAudio (`paplay`) or ALSA (`aplay`)
|
|
305
|
-
- **Windows**: Uses terminal bell
|
|
306
|
-
|
|
307
|
-
Toggle sound with `s` or set `"soundEnabled": false` in config.
|
|
308
|
-
|
|
309
|
-
### Server crashes immediately (custom server command mode)
|
|
310
|
-
- Check that your command works when run directly
|
|
311
|
-
- View logs with `l` to see error messages
|
|
312
|
-
- Try restarting with `R`
|
|
151
|
+
Common issues and solutions are covered in the [troubleshooting guide](docs/troubleshooting.md).
|
|
313
152
|
|
|
314
153
|
## Contributing
|
|
315
154
|
|
|
316
|
-
Contributions are welcome!
|
|
317
|
-
|
|
318
|
-
### Reporting Bugs
|
|
319
|
-
|
|
320
|
-
If you find a bug, please [open an issue](https://github.com/drummel/git-watchtower/issues/new) on GitHub with:
|
|
321
|
-
- A clear, descriptive title
|
|
322
|
-
- Steps to reproduce the issue
|
|
323
|
-
- Expected vs actual behavior
|
|
324
|
-
- Your environment (OS, Node.js version, terminal)
|
|
325
|
-
- Any relevant error messages or screenshots
|
|
326
|
-
|
|
327
|
-
### Requesting Features
|
|
328
|
-
|
|
329
|
-
Have an idea to improve Git Watchtower? [Submit a feature request](https://github.com/drummel/git-watchtower/issues/new) with:
|
|
330
|
-
- A clear description of the feature
|
|
331
|
-
- The problem it would solve or use case it addresses
|
|
332
|
-
- Any implementation ideas (optional)
|
|
333
|
-
|
|
334
|
-
### Submitting Pull Requests
|
|
335
|
-
|
|
336
|
-
1. Fork the repository
|
|
337
|
-
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
338
|
-
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
339
|
-
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
340
|
-
5. Open a Pull Request
|
|
341
|
-
|
|
342
|
-
Please ensure your PR:
|
|
343
|
-
- Includes a clear description of the changes
|
|
344
|
-
- Maintains the zero-dependency philosophy (Node.js built-ins only)
|
|
345
|
-
- Works across platforms (macOS, Linux, Windows) when applicable
|
|
155
|
+
Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
346
156
|
|
|
347
157
|
## Development
|
|
348
158
|
|
|
349
|
-
### Local Installation
|
|
350
|
-
|
|
351
|
-
For local development and testing:
|
|
352
|
-
|
|
353
159
|
```bash
|
|
354
160
|
# Clone the repository
|
|
355
161
|
git clone https://github.com/drummel/git-watchtower.git
|
|
356
162
|
cd git-watchtower
|
|
357
163
|
|
|
358
|
-
#
|
|
359
|
-
# Creates a global symlink - changes take effect immediately
|
|
164
|
+
# Create a global symlink (changes take effect immediately)
|
|
360
165
|
npm link
|
|
361
166
|
|
|
362
|
-
#
|
|
167
|
+
# Run from any git repository
|
|
363
168
|
git-watchtower
|
|
364
169
|
|
|
365
|
-
#
|
|
366
|
-
|
|
367
|
-
```
|
|
368
|
-
|
|
369
|
-
### After Making Code Changes
|
|
370
|
-
|
|
371
|
-
| Install Method | Update Process |
|
|
372
|
-
|----------------|----------------|
|
|
373
|
-
| `npm link` | Nothing - changes apply immediately |
|
|
374
|
-
| `npm install -g .` | Run `npm install -g .` again |
|
|
375
|
-
| Direct `node bin/...` | Nothing - always runs current code |
|
|
376
|
-
|
|
377
|
-
### Unlinking
|
|
378
|
-
|
|
379
|
-
To remove the global symlink:
|
|
170
|
+
# Run tests
|
|
171
|
+
npm test
|
|
380
172
|
|
|
381
|
-
|
|
382
|
-
|
|
173
|
+
# Run directly without installing
|
|
174
|
+
node bin/git-watchtower.js
|
|
383
175
|
```
|
|
384
176
|
|
|
385
177
|
## License
|
|
386
178
|
|
|
387
179
|
MIT License - see [LICENSE](LICENSE) for details.
|
|
388
|
-
|
|
389
|
-
## Acknowledgments
|
|
390
|
-
|
|
391
|
-
- Built with Node.js built-in modules only (no external dependencies)
|
package/package.json
CHANGED
package/src/server/web-ui.js
CHANGED
|
@@ -283,6 +283,12 @@ function getWebDashboardHtml(port) {
|
|
|
283
283
|
flex-shrink: 0;
|
|
284
284
|
min-width: 60px;
|
|
285
285
|
}
|
|
286
|
+
.branch-badges {
|
|
287
|
+
display: flex;
|
|
288
|
+
gap: 4px;
|
|
289
|
+
justify-content: flex-end;
|
|
290
|
+
flex-wrap: wrap;
|
|
291
|
+
}
|
|
286
292
|
.branch-time {
|
|
287
293
|
font-size: 12px;
|
|
288
294
|
font-family: var(--font-mono);
|
|
@@ -1586,26 +1592,6 @@ function getWebDashboardHtml(port) {
|
|
|
1586
1592
|
html += '</span>';
|
|
1587
1593
|
// Copy branch name button
|
|
1588
1594
|
html += '<button class="copy-btn" data-copy="' + escHtml(b.name) + '" title="Copy branch name" onclick="event.stopPropagation()">📋</button>';
|
|
1589
|
-
if (isCurrent) html += '<span class="branch-current-badge">HEAD</span>';
|
|
1590
|
-
if (isPinned) html += '<span class="branch-new-badge" style="color:var(--orange);background:rgba(219,109,40,0.15)">pinned</span>';
|
|
1591
|
-
if (b.isNew) html += '<span class="branch-new-badge">new</span>';
|
|
1592
|
-
if (b.isDeleted) html += '<span class="branch-deleted-badge">deleted</span>';
|
|
1593
|
-
if (b.justUpdated) html += '<span class="branch-updated-badge">updated</span>';
|
|
1594
|
-
if (prStatus) {
|
|
1595
|
-
var prClass = prStatus.state === 'OPEN' ? 'pr-open' : prStatus.state === 'MERGED' ? 'pr-merged' : 'pr-closed';
|
|
1596
|
-
var prUrl = getPrUrl(prStatus.number);
|
|
1597
|
-
html += '<span class="pr-badge ' + prClass + '">';
|
|
1598
|
-
if (prUrl) {
|
|
1599
|
-
html += '<a href="' + escHtml(prUrl) + '" target="_blank" rel="noopener" onclick="event.stopPropagation()">';
|
|
1600
|
-
}
|
|
1601
|
-
html += (prStatus.state === 'MERGED' ? 'merged' : 'PR #' + prStatus.number);
|
|
1602
|
-
if (prUrl) html += '</a>';
|
|
1603
|
-
html += '</span>';
|
|
1604
|
-
// Copy PR URL
|
|
1605
|
-
if (prUrl) {
|
|
1606
|
-
html += '<button class="copy-btn" data-copy="' + escHtml(prUrl) + '" title="Copy PR URL" onclick="event.stopPropagation()">📋</button>';
|
|
1607
|
-
}
|
|
1608
|
-
}
|
|
1609
1595
|
html += '</div>'; // branch-name-row
|
|
1610
1596
|
|
|
1611
1597
|
html += '<div class="branch-meta">';
|
|
@@ -1628,6 +1614,24 @@ function getWebDashboardHtml(port) {
|
|
|
1628
1614
|
|
|
1629
1615
|
html += '<div class="branch-right">';
|
|
1630
1616
|
html += '<span class="branch-time">' + timeAgo(b.date) + '</span>';
|
|
1617
|
+
// Badges
|
|
1618
|
+
var badges = '';
|
|
1619
|
+
if (isCurrent) badges += '<span class="branch-current-badge">HEAD</span>';
|
|
1620
|
+
if (isPinned) badges += '<span class="branch-new-badge" style="color:var(--orange);background:rgba(219,109,40,0.15)">pinned</span>';
|
|
1621
|
+
if (b.isNew) badges += '<span class="branch-new-badge">new</span>';
|
|
1622
|
+
if (b.isDeleted) badges += '<span class="branch-deleted-badge">deleted</span>';
|
|
1623
|
+
if (b.justUpdated) badges += '<span class="branch-updated-badge">updated</span>';
|
|
1624
|
+
if (prStatus) {
|
|
1625
|
+
var prClass = prStatus.state === 'OPEN' ? 'pr-open' : prStatus.state === 'MERGED' ? 'pr-merged' : 'pr-closed';
|
|
1626
|
+
var prUrl = getPrUrl(prStatus.number);
|
|
1627
|
+
badges += '<span class="pr-badge ' + prClass + '">';
|
|
1628
|
+
if (prUrl) badges += '<a href="' + escHtml(prUrl) + '" target="_blank" rel="noopener" onclick="event.stopPropagation()">';
|
|
1629
|
+
badges += (prStatus.state === 'MERGED' ? 'merged' : 'PR #' + prStatus.number);
|
|
1630
|
+
if (prUrl) badges += '</a>';
|
|
1631
|
+
badges += '</span>';
|
|
1632
|
+
if (prUrl) badges += '<button class="copy-btn" data-copy="' + escHtml(prUrl) + '" title="Copy PR URL" onclick="event.stopPropagation()">📋</button>';
|
|
1633
|
+
}
|
|
1634
|
+
if (badges) html += '<div class="branch-badges">' + badges + '</div>';
|
|
1631
1635
|
if (ab && (ab.ahead || ab.behind)) {
|
|
1632
1636
|
html += '<div class="branch-diff">';
|
|
1633
1637
|
html += '<span class="diff-added">+' + fmtCompact(ab.ahead || 0) + '</span>';
|