320 lines
12 KiB
Markdown
320 lines
12 KiB
Markdown
# TASK.md — v0.13.1 UI Polish Fixes (Round 2)
|
|
|
|
**Version:** v0.13.1
|
|
**Type:** UI polish — 4 fixes
|
|
**Files likely affected:** `deploy.html`, `backups.html`, `dashboard.html`, `monitoring.html`, `layout.html`, `style.css`, `handlers.go`, `alerts.go`, `funcmap.go`
|
|
|
|
Read `CLAUDE.md`, `controller/README.md`, and `CONTEXT.md` before starting.
|
|
|
|
---
|
|
|
|
## Fix 1: Backup section on deploy page needs card/box styling
|
|
|
|
**Problem:** The "Biztonsági mentés" section on app deploy/settings pages (e.g., `/stacks/immich/deploy`) has no visible border or card styling, unlike the "Adattárolás" section above it and other card sections on the page. It looks flat and out of place.
|
|
|
|
**Where:** `deploy.html` line ~96: `<div class="deploy-cross-drive">` and the `.deploy-cross-drive` CSS class in `style.css`.
|
|
|
|
**Solution:** Add card-like styling to `.deploy-cross-drive` in `style.css`. Look at how `.deploy-storage-info` (the "Adattárolás" card above it on the same page) is styled and match it:
|
|
- `border: 1px solid var(--border)`
|
|
- `background: var(--card-bg)`
|
|
- `border-radius: 12px`
|
|
- `padding: 1.5rem`
|
|
|
|
If `.deploy-cross-drive` already exists in CSS, add the missing border/background properties. If it doesn't exist, create it with the above properties.
|
|
|
|
---
|
|
|
|
## Fix 2: Clean up auto-generated env values section on deploy page
|
|
|
|
**Problem:** The "Automatikusan generált értékek" section on the deploy page is cluttered. Each field currently shows: input + "Megjelenítés" button (for passwords) + "Másolás" button + badge. Too many elements stacked together.
|
|
|
|
**Current code location:** `deploy.html` lines ~254-281, inside the `{{if .AutoFields}}` block.
|
|
|
|
**Current structure per field:**
|
|
```html
|
|
<div class="form-group form-group-auto">
|
|
<label>{{.Label}}</label>
|
|
{{if and $isDeployed $val}}
|
|
{{if eq .Type "secret"}}
|
|
<div class="input-with-button">
|
|
<input type="password" ...>
|
|
<button ... onclick="toggleAutoField(...)">Megjelenítés</button>
|
|
<button ... onclick="copyAutoField(...)">Másolás</button>
|
|
</div>
|
|
{{else}}
|
|
<div class="input-with-button">
|
|
<input type="text" ...>
|
|
<button ... onclick="copyAutoField(...)">Másolás</button>
|
|
</div>
|
|
{{end}}
|
|
{{end}}
|
|
<span class="auto-generated-badge">✓ Automatikusan generálva</span>
|
|
</div>
|
|
```
|
|
|
|
**Changes:**
|
|
|
|
1. **Remove ALL "Másolás" buttons** — users can select+copy natively, dedicated button adds clutter
|
|
2. **Keep** the "Megjelenítés"/"Elrejtés" toggle button for secret/password fields (essential)
|
|
3. **Move the badge inline with the label** — instead of on a separate line below the input, put it next to the label text
|
|
|
|
**New structure per field:**
|
|
```html
|
|
<div class="form-group form-group-auto">
|
|
<label>{{.Label}} <span class="auto-generated-badge">✓ Automatikusan generálva</span></label>
|
|
{{if and $isDeployed $val}}
|
|
{{if eq .Type "secret"}}
|
|
<div class="input-with-button">
|
|
<input type="password" id="auto-field-{{.EnvVar}}" class="form-control" value="{{$val}}" readonly>
|
|
<button type="button" class="btn btn-sm btn-outline" onclick="toggleAutoField('auto-field-{{.EnvVar}}', this)">Megjelenítés</button>
|
|
</div>
|
|
{{else}}
|
|
<input type="text" id="auto-field-{{.EnvVar}}" class="form-control" value="{{$val}}" readonly>
|
|
{{end}}
|
|
{{end}}
|
|
</div>
|
|
```
|
|
|
|
4. **Remove the `copyAutoField` JS function** — search for `function copyAutoField` in deploy.html's `<script>` block and remove it entirely.
|
|
|
|
5. **CSS adjustments** in `style.css`:
|
|
- `.form-group-auto label` should use `display: flex; align-items: center; gap: 0.5rem;` so the badge sits inline with the label text
|
|
- `.auto-generated-badge` should be `font-size: 0.75rem` and `font-weight: normal` to not overpower the label
|
|
- Read-only inputs (`.form-group-auto .form-control[readonly]`) could have a slightly muted background (e.g., `background: var(--bg-secondary)`) to visually indicate they're not editable
|
|
|
|
---
|
|
|
|
## Fix 3: Pillanatképek — show 0 instead of n/a
|
|
|
|
**Problem:** In the Pillanatképek table on the backup page, columns "Hozzáadott (új adat)", "Új fájl", "Változott" show `n/a` with a long tooltip when `HasStats` is false. The user wants `0` instead — `n/a` implies "data unavailable", but `0` correctly means "no changes".
|
|
|
|
**Current code** (`backups.html`, in the snapshot table tbody):
|
|
```html
|
|
<td class="mono">{{if .HasStats}}+{{.DataAdded}}{{else}}<span class="col-na" title="A restic pillanatképek nem tartalmaznak méretadatot — csak az utolsó mentés adatai állnak rendelkezésre.">n/a</span>{{end}}</td>
|
|
<td class="mono">{{if .HasStats}}{{.FilesNew}}{{else}}<span class="col-na" title="A restic pillanatképek nem tartalmaznak fájlszámot — csak az utolsó mentés adatai állnak rendelkezésre.">n/a</span>{{end}}</td>
|
|
<td class="mono">{{if .HasStats}}{{.FilesChanged}}{{else}}<span class="col-na" title="A restic pillanatképek nem tartalmaznak fájlszámot — csak az utolsó mentés adatai állnak rendelkezésre.">n/a</span>{{end}}</td>
|
|
```
|
|
|
|
**Replace with:**
|
|
```html
|
|
<td class="mono">{{if .HasStats}}+{{.DataAdded}}{{else}}0{{end}}</td>
|
|
<td class="mono">{{if .HasStats}}{{.FilesNew}}{{else}}0{{end}}</td>
|
|
<td class="mono">{{if .HasStats}}{{.FilesChanged}}{{else}}0{{end}}</td>
|
|
```
|
|
|
|
Remove the `<span class="col-na" title="...">` wrappers entirely. Simple `0` values.
|
|
|
|
Also remove the `.col-na` CSS class from `style.css` if it's no longer used elsewhere.
|
|
|
|
---
|
|
|
|
## Fix 4: Move disk warnings from top banner to inline under storage bars
|
|
|
|
**Problem:** The yellow HDD warning banner ("Az adattároló nem külön meghajtón van...") appears at the very top of the page via `layout.html`, rendered as a full-width alert banner. Even though v0.13.0 added `PageOnly` filtering (only dashboard + monitoring), the warnings are still too prominent and positioned at the top rather than near the relevant storage info.
|
|
|
|
**Goal:**
|
|
1. Disk warnings should NOT appear in the layout.html top banner at all
|
|
2. They should render **inline, under the relevant storage usage bar** on dashboard and monitoring pages
|
|
3. They should be **smaller and more subtle** than the current full-width alert banner
|
|
|
|
### Step 1: Add `Inline` field to Alert struct
|
|
|
|
In `alerts.go`, add an `Inline bool` field to the `Alert` struct:
|
|
|
|
```go
|
|
type Alert struct {
|
|
ID string
|
|
Level string
|
|
Message string
|
|
Link string
|
|
LinkText string
|
|
PageOnly []string
|
|
Inline bool // If true, rendered by page template, not layout
|
|
}
|
|
```
|
|
|
|
### Step 2: Mark disk warnings as inline in Refresh()
|
|
|
|
In `alerts.go` `Refresh()`, where disk warnings get `PageOnly` set (the block checking for "meghajtón" / "adattároló" / "meghajtó"), also set `Inline: true`:
|
|
|
|
```go
|
|
if strings.Contains(w, "meghajtón") || strings.Contains(w, "adattároló") || strings.Contains(w, "meghajtó") {
|
|
alert.ID = "disk-not-separate"
|
|
alert.PageOnly = []string{"dashboard", "monitoring"}
|
|
alert.Inline = true
|
|
}
|
|
```
|
|
|
|
### Step 3: Skip inline alerts in layout.html
|
|
|
|
In `layout.html`, update the alert rendering loop to skip inline alerts:
|
|
|
|
**Current:**
|
|
```html
|
|
{{range .Alerts}}
|
|
{{if or (not .PageOnly) (pageMatch .PageOnly $.Page)}}
|
|
<div class="alert-banner alert-banner-{{.Level}}">
|
|
```
|
|
|
|
**Change to:**
|
|
```html
|
|
{{range .Alerts}}
|
|
{{if and (not .Inline) (or (not .PageOnly) (pageMatch .PageOnly $.Page))}}
|
|
<div class="alert-banner alert-banner-{{.Level}}">
|
|
```
|
|
|
|
### Step 4: Add GetInlineAlerts method to AlertManager
|
|
|
|
In `alerts.go`, add a new method:
|
|
|
|
```go
|
|
// GetInlineAlerts returns alerts marked as Inline for a specific page.
|
|
func (am *AlertManager) GetInlineAlerts(page string) []Alert {
|
|
am.mu.RLock()
|
|
defer am.mu.RUnlock()
|
|
|
|
var result []Alert
|
|
for _, a := range am.alerts {
|
|
if !a.Inline {
|
|
continue
|
|
}
|
|
if len(a.PageOnly) == 0 {
|
|
result = append(result, a)
|
|
continue
|
|
}
|
|
for _, p := range a.PageOnly {
|
|
if p == page {
|
|
result = append(result, a)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
```
|
|
|
|
### Step 5: Pass inline alerts in dashboard and monitoring handlers
|
|
|
|
In `handlers.go`:
|
|
|
|
**In `dashboardHandler`**, after `baseData()` call, add:
|
|
```go
|
|
if s.alertManager != nil {
|
|
data["DiskWarnings"] = s.alertManager.GetInlineAlerts("dashboard")
|
|
}
|
|
```
|
|
|
|
**In `monitoringHandler`**, after `baseData()` call, add:
|
|
```go
|
|
if s.alertManager != nil {
|
|
data["DiskWarnings"] = s.alertManager.GetInlineAlerts("monitoring")
|
|
}
|
|
```
|
|
|
|
### Step 6: Render inline warnings in dashboard.html
|
|
|
|
In `dashboard.html`, inside the `.system-info-card`, right after the second `.system-info-items` block (the one with SSD and HDD bars) — just before the closing `</div>` of `.system-info-card` — add:
|
|
|
|
```html
|
|
{{if .DiskWarnings}}
|
|
<div class="inline-warnings">
|
|
{{range .DiskWarnings}}
|
|
<div class="inline-warning inline-warning-{{.Level}}">
|
|
<span class="inline-warning-dot">●</span>
|
|
<span class="inline-warning-text">{{.Message}}</span>
|
|
{{if .Link}}<a href="{{.Link}}" class="inline-warning-link">{{.LinkText}} →</a>{{end}}
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
{{end}}
|
|
```
|
|
|
|
Place this INSIDE the `{{if .SystemInfo.TotalMemMB}}...{{end}}` block, after the storage bars but before the closing `</div>` of `.system-info-card`.
|
|
|
|
### Step 7: Render inline warnings in monitoring.html
|
|
|
|
In `monitoring.html`, inside the Tárhely `.monitor-card` (currently Section 1.5), right after the `.storage-bars` closing `</div>` but still inside the `.monitor-card`, add the same block:
|
|
|
|
```html
|
|
{{if .DiskWarnings}}
|
|
<div class="inline-warnings">
|
|
{{range .DiskWarnings}}
|
|
<div class="inline-warning inline-warning-{{.Level}}">
|
|
<span class="inline-warning-dot">●</span>
|
|
<span class="inline-warning-text">{{.Message}}</span>
|
|
{{if .Link}}<a href="{{.Link}}" class="inline-warning-link">{{.LinkText}} →</a>{{end}}
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
{{end}}
|
|
```
|
|
|
|
### Step 8: Add CSS for inline warnings
|
|
|
|
In `style.css`, add:
|
|
|
|
```css
|
|
.inline-warnings {
|
|
margin-top: 0.75rem;
|
|
}
|
|
.inline-warning {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
padding: 0.4rem 0.75rem;
|
|
margin-top: 0.25rem;
|
|
font-size: 0.8rem;
|
|
border-radius: 6px;
|
|
}
|
|
.inline-warning-warning {
|
|
color: var(--yellow);
|
|
background: rgba(250, 204, 21, 0.06);
|
|
border: 1px solid rgba(250, 204, 21, 0.15);
|
|
}
|
|
.inline-warning-error {
|
|
color: var(--red);
|
|
background: rgba(218, 54, 51, 0.06);
|
|
border: 1px solid rgba(218, 54, 51, 0.15);
|
|
}
|
|
.inline-warning-dot {
|
|
font-size: 0.6rem;
|
|
flex-shrink: 0;
|
|
}
|
|
.inline-warning-text {
|
|
flex: 1;
|
|
}
|
|
.inline-warning-link {
|
|
color: inherit;
|
|
opacity: 0.8;
|
|
white-space: nowrap;
|
|
text-decoration: none;
|
|
}
|
|
.inline-warning-link:hover {
|
|
opacity: 1;
|
|
text-decoration: underline;
|
|
}
|
|
```
|
|
|
|
This makes the warnings compact (small font, subtle background, thin border) and positioned right under the storage bar they relate to.
|
|
|
|
---
|
|
|
|
## Implementation order
|
|
|
|
1. **Fix 3** — Pillanatképek 0 vs n/a (template-only, 1 min)
|
|
2. **Fix 1** — Deploy page card border (CSS only, 1 min)
|
|
3. **Fix 2** — Auto-generated values cleanup (template + CSS)
|
|
4. **Fix 4** — Disk warnings inline (alerts.go + layout.html + dashboard.html + monitoring.html + handlers.go + style.css)
|
|
|
|
## Build & deploy
|
|
|
|
After all fixes, bump version to **v0.13.1**, then follow the standard build workflow in `CLAUDE.md`:
|
|
|
|
```
|
|
Read TASK.md for the full plan. Apply all code changes described, then build and deploy.
|
|
After all fixes are done:
|
|
1. Run `go build ./...` and `go vet ./...` from the controller/ directory — fix any errors
|
|
2. Update CHANGELOG.md with a new entry at the top (read top 30 lines only for format, then Edit to insert)
|
|
3. Commit, build, and deploy following the workflow in CLAUDE.md
|
|
```
|