first commit
This commit is contained in:
538
views/admin/partials/settings.html
Normal file
538
views/admin/partials/settings.html
Normal file
@@ -0,0 +1,538 @@
|
||||
<div class="container-fluid" hx-trigger="heroListChanged from:body" hx-get="/admin/content/settings" hx-target="this"
|
||||
hx-swap="outerHTML">
|
||||
<h2 class="mb-4">Ayarlar & Banner Yönetimi</h2>
|
||||
|
||||
<ul class="nav nav-tabs mb-4" id="settingsTab" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link active" id="general-tab" data-bs-toggle="tab" data-bs-target="#general"
|
||||
type="button" role="tab">Genel Ayarlar</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="security-tab" data-bs-toggle="tab" data-bs-target="#security" type="button" role="tab">Güvenlik</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="hero-tab" data-bs-toggle="tab" data-bs-target="#hero" type="button"
|
||||
role="tab">Banner (Hero) Yönetimi</button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content" id="settingsTabContent">
|
||||
<!-- General Settings Tab -->
|
||||
<div class="tab-pane fade show active" id="general" role="tabpanel">
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card-body">
|
||||
<form action="/admin/settings" method="POST" enctype="multipart/form-data">
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="title" class="form-label">Site Başlığı</label>
|
||||
<input type="text" class="form-control" id="title" name="title"
|
||||
value="{{ .Setting.Title }}">
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="meta_title" class="form-label">Meta Başlık</label>
|
||||
<input type="text" class="form-control" id="meta_title" name="meta_title"
|
||||
value="{{ .Setting.MetaTitle }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="meta_description" class="form-label">Meta Açıklama</label>
|
||||
<textarea class="form-control" id="meta_description" name="meta_description"
|
||||
rows="2">{{ .Setting.MetaDescription }}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="email" class="form-label">E-posta</label>
|
||||
<input type="email" class="form-control" id="email" name="email"
|
||||
value="{{ .Setting.Email }}">
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="phone" class="form-label">Telefon</label>
|
||||
<input type="text" class="form-control" id="phone" name="phone"
|
||||
value="{{ .Setting.Phone }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="address" class="form-label">Adres</label>
|
||||
<textarea class="form-control" id="address" name="address"
|
||||
rows="2">{{ .Setting.Address }}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="url" class="form-label">Site URL</label>
|
||||
<input type="text" class="form-control" id="url" name="url" value="{{ .Setting.URL }}">
|
||||
</div>
|
||||
|
||||
<h5 class="mt-4">Logo Ayarları</h5>
|
||||
<div class="row">
|
||||
<!-- White Logo (WLogo) -->
|
||||
<div class="col-md-6">
|
||||
<div class="card border p-3 mb-3">
|
||||
<h6 class="mb-3">Beyaz Logo (Genellikle Koyu Zemin İçin)</h6>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Logo Yükle</label>
|
||||
<input type="file" class="form-control" name="w_logo" accept="image/*">
|
||||
{{ if .Setting.WLogo }}
|
||||
<div class="mt-2 text-center p-2 logo-preview logo-preview-light border rounded">
|
||||
<img src="{{ .Setting.WLogo }}" alt="WLogo" style="max-height: 50px;">
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="row g-2">
|
||||
<div class="col-6">
|
||||
<label class="form-label small text-muted mb-0">Genişlik</label>
|
||||
<input type="number" class="form-control form-control-sm" name="w_width"
|
||||
placeholder="Otomatik" value="{{ .Setting.WWidth }}">
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label class="form-label small text-muted mb-0">Yükseklik</label>
|
||||
<input type="number" class="form-control form-control-sm" name="w_height"
|
||||
placeholder="Otomatik" value="{{ .Setting.WHeight }}">
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label class="form-label small text-muted mb-0">Kalite (1-100)</label>
|
||||
<input type="number" class="form-control form-control-sm" name="w_quality"
|
||||
placeholder="80" value="{{ .Setting.WQuality }}">
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label class="form-label small text-muted mb-0">Format</label>
|
||||
<select class="form-select form-select-sm" name="w_format">
|
||||
<option value="avif" {{ if eq .Setting.WFormat "avif" }}selected{{ end
|
||||
}}>AVIF (Önerilen)</option>
|
||||
<option value="webp" {{ if eq .Setting.WFormat "webp" }}selected{{ end
|
||||
}}>WebP</option>
|
||||
<option value="png" {{ if eq .Setting.WFormat "png" }}selected{{ end }}>
|
||||
PNG</option>
|
||||
<option value="jpg" {{ if eq .Setting.WFormat "jpg" }}selected{{ end }}>
|
||||
JPG</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Black Logo (BLogo) -->
|
||||
<div class="col-md-6">
|
||||
<div class="card border p-3 mb-3">
|
||||
<h6 class="mb-3">Siyah Logo (Genellikle Beyaz Zemin İçin)</h6>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Logo Yükle</label>
|
||||
<input type="file" class="form-control" name="b_logo" accept="image/*">
|
||||
{{ if .Setting.BLogo }}
|
||||
<div class="mt-2 text-center p-2 logo-preview logo-preview-light border rounded">
|
||||
<img src="{{ .Setting.BLogo }}" alt="BLogo" style="max-height: 50px;">
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="row g-2">
|
||||
<div class="col-6">
|
||||
<label class="form-label small text-muted mb-0">Genişlik</label>
|
||||
<input type="number" class="form-control form-control-sm" name="b_width"
|
||||
placeholder="Otomatik" value="{{ .Setting.BWidth }}">
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label class="form-label small text-muted mb-0">Yükseklik</label>
|
||||
<input type="number" class="form-control form-control-sm" name="b_height"
|
||||
placeholder="Otomatik" value="{{ .Setting.BHeight }}">
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label class="form-label small text-muted mb-0">Kalite (1-100)</label>
|
||||
<input type="number" class="form-control form-control-sm" name="b_quality"
|
||||
placeholder="80" value="{{ .Setting.BQuality }}">
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label class="form-label small text-muted mb-0">Format</label>
|
||||
<select class="form-select form-select-sm" name="b_format">
|
||||
<option value="avif" {{ if eq .Setting.BFormat "avif" }}selected{{ end
|
||||
}}>AVIF (Önerilen)</option>
|
||||
<option value="webp" {{ if eq .Setting.BFormat "webp" }}selected{{ end
|
||||
}}>WebP</option>
|
||||
<option value="png" {{ if eq .Setting.BFormat "png" }}selected{{ end }}>
|
||||
PNG</option>
|
||||
<option value="jpg" {{ if eq .Setting.BFormat "jpg" }}selected{{ end }}>
|
||||
JPG</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- CORS and Rate Limit moved to Güvenlik tab -->
|
||||
|
||||
<h5 class="mt-4">Sosyal Medya</h5>
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Instagram</label>
|
||||
<input type="text" class="form-control" name="instagram"
|
||||
value="{{ .Setting.Instagram }}">
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Twitter (X)</label>
|
||||
<input type="text" class="form-control" name="x" value="{{ .Setting.X }}">
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Facebook</label>
|
||||
<input type="text" class="form-control" name="facebook" value="{{ .Setting.Facebook }}">
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Whatsapp</label>
|
||||
<input type="text" class="form-control" name="whatsapp" value="{{ .Setting.Whatsapp }}">
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Linkedin</label>
|
||||
<input type="text" class="form-control" name="linkedin" value="{{ .Setting.Linkedin }}">
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label">Pinterest</label>
|
||||
<input type="text" class="form-control" name="pinterest"
|
||||
value="{{ .Setting.Pinterest }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3 form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="is_active" name="is_active" {{ if
|
||||
.Setting.IsActive }}checked{{ end }}>
|
||||
<label class="form-check-label" for="is_active">Site Aktif</label>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary">Kaydet</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Security Tab (CORS / Rate Limits) -->
|
||||
<div class="tab-pane fade" id="security" role="tabpanel">
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h5 class="mb-0">CORS Yönetimi</h5>
|
||||
<div class="btn-group">
|
||||
<a href="/admin/content/settings" class="btn btn-outline-primary {{ if not .ShowDeleted }}active{{ end }}">Aktif</a>
|
||||
<a href="/admin/content/settings?deleted=true" class="btn btn-outline-danger {{ if .ShowDeleted }}active{{ end }}">Silinenler</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<div class="card border p-3 mb-3">
|
||||
<h6 class="mb-3">Whitelist (İzinli Origin'ler)</h6>
|
||||
{{ if .EditWhitelist.ID }}
|
||||
<form action="/admin/settings/cors/whitelist/{{ .EditWhitelist.ID }}/update" method="POST" class="mb-3">
|
||||
<div class="input-group mb-2">
|
||||
<input type="text" name="origin" class="form-control" placeholder="https://example.com" required value="{{ .EditWhitelist.Origin }}">
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<input type="text" name="description" class="form-control" placeholder="Açıklama (opsiyonel)" value="{{ .EditWhitelist.Description }}">
|
||||
</div>
|
||||
<div class="form-check form-switch mb-2">
|
||||
<input class="form-check-input" type="checkbox" id="wl_active" name="is_active" {{ if .EditWhitelist.IsActive }}checked{{ end }}>
|
||||
<label class="form-check-label" for="wl_active">Aktif</label>
|
||||
</div>
|
||||
<div class="d-flex gap-2 justify-content-end">
|
||||
<a href="/admin/content/settings" class="btn btn-sm btn-secondary">İptal</a>
|
||||
<button class="btn btn-sm btn-primary" type="submit">Güncelle</button>
|
||||
</div>
|
||||
</form>
|
||||
{{ else }}
|
||||
<form action="/admin/settings/cors/whitelist/create" method="POST" class="mb-3">
|
||||
<div class="input-group mb-2">
|
||||
<input type="text" name="origin" class="form-control" placeholder="https://example.com" required>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<input type="text" name="description" class="form-control" placeholder="Açıklama (opsiyonel)">
|
||||
</div>
|
||||
<div class="d-flex gap-2 justify-content-end">
|
||||
<button class="btn btn-sm btn-primary" type="submit">Ekle</button>
|
||||
</div>
|
||||
</form>
|
||||
{{ end }}
|
||||
<div>
|
||||
<ul class="list-group list-group-flush">
|
||||
{{ if .CorsWhitelist }}
|
||||
{{ range .CorsWhitelist }}
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<strong>{{ .Origin }}</strong>
|
||||
<div class="small text-muted">{{ .Description }}</div>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
{{ if $.ShowDeleted }}
|
||||
<form action="/admin/settings/cors/whitelist/{{ .ID }}/restore" method="POST">
|
||||
<button class="btn btn-sm btn-success">Geri Yükle</button>
|
||||
</form>
|
||||
{{ else }}
|
||||
<a href="/admin/content/settings?edit_whitelist={{ .ID }}" class="btn btn-sm btn-outline-secondary">Düzenle</a>
|
||||
<form action="/admin/settings/cors/whitelist/{{ .ID }}/delete" method="POST" onsubmit="return confirmDelete(event, this);">
|
||||
<button class="btn btn-sm btn-outline-danger">Sil</button>
|
||||
</form>
|
||||
{{ end }}
|
||||
</div>
|
||||
</li>
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
<li class="list-group-item">Kayıt yok</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="card border p-3 mb-3">
|
||||
<h6 class="mb-3">Blacklist (Yasaklı Origin'ler)</h6>
|
||||
{{ if .EditBlacklist.ID }}
|
||||
<form action="/admin/settings/cors/blacklist/{{ .EditBlacklist.ID }}/update" method="POST" class="mb-3">
|
||||
<div class="input-group mb-2">
|
||||
<input type="text" name="origin" class="form-control" placeholder="https://bad.com" required value="{{ .EditBlacklist.Origin }}">
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<input type="text" name="reason" class="form-control" placeholder="Sebep (opsiyonel)" value="{{ .EditBlacklist.Reason }}">
|
||||
</div>
|
||||
<div class="form-check form-switch mb-2">
|
||||
<input class="form-check-input" type="checkbox" id="bl_active" name="is_active" {{ if .EditBlacklist.IsActive }}checked{{ end }}>
|
||||
<label class="form-check-label" for="bl_active">Aktif</label>
|
||||
</div>
|
||||
<div class="d-flex gap-2 justify-content-end">
|
||||
<a href="/admin/content/settings" class="btn btn-sm btn-secondary">İptal</a>
|
||||
<button class="btn btn-sm btn-primary" type="submit">Güncelle</button>
|
||||
</div>
|
||||
</form>
|
||||
{{ else }}
|
||||
<form action="/admin/settings/cors/blacklist/create" method="POST" class="mb-3">
|
||||
<div class="input-group mb-2">
|
||||
<input type="text" name="origin" class="form-control" placeholder="https://bad.com" required>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<input type="text" name="reason" class="form-control" placeholder="Sebep (opsiyonel)">
|
||||
</div>
|
||||
<div class="d-flex gap-2 justify-content-end">
|
||||
<button class="btn btn-sm btn-primary" type="submit">Ekle</button>
|
||||
</div>
|
||||
</form>
|
||||
{{ end }}
|
||||
<div>
|
||||
<ul class="list-group list-group-flush">
|
||||
{{ if .CorsBlacklist }}
|
||||
{{ range .CorsBlacklist }}
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<strong>{{ .Origin }}</strong>
|
||||
<div class="small text-muted">{{ .Reason }}</div>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
{{ if $.ShowDeleted }}
|
||||
<form action="/admin/settings/cors/blacklist/{{ .ID }}/restore" method="POST">
|
||||
<button class="btn btn-sm btn-success">Geri Yükle</button>
|
||||
</form>
|
||||
{{ else }}
|
||||
<a href="/admin/content/settings?edit_blacklist={{ .ID }}" class="btn btn-sm btn-outline-secondary">Düzenle</a>
|
||||
<form action="/admin/settings/cors/blacklist/{{ .ID }}/delete" method="POST" onsubmit="return confirmDelete(event, this);">
|
||||
<button class="btn btn-sm btn-outline-danger">Sil</button>
|
||||
</form>
|
||||
{{ end }}
|
||||
</div>
|
||||
</li>
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
<li class="list-group-item">Kayıt yok</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h5 class="mb-3">Rate Limit Ayarları</h5>
|
||||
<div class="card border p-3 mb-3">
|
||||
{{ if .EditRateLimit.ID }}
|
||||
<form action="/admin/settings/rate-limit/{{ .EditRateLimit.ID }}/update" method="POST" class="row g-2 mb-3">
|
||||
<div class="col-md-3">
|
||||
<input type="text" name="name" class="form-control" placeholder="İsim (ör. login)" required value="{{ .EditRateLimit.Name }}">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<input type="number" name="max_requests" class="form-control" placeholder="Max istek" required value="{{ .EditRateLimit.MaxRequests }}">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<input type="number" name="window_seconds" class="form-control" placeholder="Pencere (s)" required value="{{ .EditRateLimit.WindowSeconds }}">
|
||||
</div>
|
||||
<div class="col-md-3 d-flex gap-2">
|
||||
<a href="/admin/content/settings" class="btn btn-secondary">İptal</a>
|
||||
<button class="btn btn-primary" type="submit">Güncelle</button>
|
||||
</div>
|
||||
</form>
|
||||
{{ else }}
|
||||
<form action="/admin/settings/rate-limit/create" method="POST" class="row g-2 mb-3">
|
||||
<div class="col-md-3">
|
||||
<input type="text" name="name" class="form-control" placeholder="İsim (ör. login)" required>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<input type="number" name="max_requests" class="form-control" placeholder="Max istek" required>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<input type="number" name="window_seconds" class="form-control" placeholder="Pencere (s)" required>
|
||||
</div>
|
||||
<div class="col-md-3 d-flex gap-2">
|
||||
<button class="btn btn-primary" type="submit">Ekle</button>
|
||||
</div>
|
||||
</form>
|
||||
{{ end }}
|
||||
|
||||
<div>
|
||||
<ul class="list-group list-group-flush">
|
||||
{{ if .RateLimits }}
|
||||
{{ range .RateLimits }}
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<strong>{{ .Name }}</strong>
|
||||
<div class="small text-muted">{{ .MaxRequests }} req / {{ .WindowSeconds }}s</div>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
{{ if $.ShowDeleted }}
|
||||
<form action="/admin/settings/rate-limit/{{ .ID }}/restore" method="POST">
|
||||
<button class="btn btn-sm btn-success">Geri Yükle</button>
|
||||
</form>
|
||||
{{ else }}
|
||||
<a href="/admin/content/settings?edit_ratelimit={{ .ID }}" class="btn btn-sm btn-outline-secondary">Düzenle</a>
|
||||
<form action="/admin/settings/rate-limit/{{ .ID }}/delete" method="POST" onsubmit="return confirmDelete(event, this);">
|
||||
<button class="btn btn-sm btn-outline-danger">Sil</button>
|
||||
</form>
|
||||
{{ end }}
|
||||
</div>
|
||||
</li>
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
<li class="list-group-item">Kayıt yok</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hero Management Tab -->
|
||||
<div class="tab-pane fade" id="hero" role="tabpanel">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<div class="btn-group" role="group">
|
||||
<a href="/admin/content/settings"
|
||||
class="btn btn-outline-primary {{ if not .ShowDeleted }}active{{ end }}">Aktif</a>
|
||||
<a href="/admin/content/settings?deleted=true"
|
||||
class="btn btn-outline-danger {{ if .ShowDeleted }}active{{ end }}">Silinenler</a>
|
||||
</div>
|
||||
<a href="/admin/heroes/new" class="btn btn-primary">
|
||||
<i class="bi bi-plus-lg"></i> Yeni Banner Ekle
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Görsel/Renk</th>
|
||||
<th>Başlık</th>
|
||||
<th>Alt Başlık</th>
|
||||
<th>Durum</th>
|
||||
<th>İşlemler</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{ range .Heroes }}
|
||||
<tr>
|
||||
<td>
|
||||
<div style="width: 50px; height: 30px; background-color: {{ .Color }}; border-radius: 4px; border: 1px solid #ddd;"
|
||||
title="{{ .Color }}"></div>
|
||||
</td>
|
||||
<td>{{ .Title }}</td>
|
||||
<td>{{ .Text1 }}</td>
|
||||
<td>
|
||||
{{ if .IsActive }}
|
||||
<span class="badge bg-success">Aktif</span>
|
||||
{{ else }}
|
||||
<span class="badge bg-secondary">Pasif</span>
|
||||
{{ end }}
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex gap-2">
|
||||
{{ if $.ShowDeleted }}
|
||||
<form action="/admin/heroes/{{ .ID }}/restore" method="POST"
|
||||
onsubmit="return confirmRestore(event, this);">
|
||||
<button type="submit" class="btn btn-sm btn-success" title="Geri Yükle">
|
||||
<i class="bi bi-arrow-counterclockwise"></i>
|
||||
</button>
|
||||
</form>
|
||||
{{ else }}
|
||||
<a href="/admin/heroes/{{ .ID }}/edit"
|
||||
class="btn btn-sm btn-outline-secondary" title="Düzenle">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</a>
|
||||
<form action="/admin/heroes/{{ .ID }}/delete" method="POST"
|
||||
onsubmit="return confirmDelete(event, this);">
|
||||
<button type="submit" class="btn btn-sm btn-outline-danger" title="Sil">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
{{ end }}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Simple tab state preservation using URL hash or local storage is complex with HTMX
|
||||
// For now, let's just make sure tabs work via Bootstrap JS
|
||||
// The tabs might reset to first tab on HTMX swap/update if we are not careful.
|
||||
// Since we reload the whole #settings-container (this file) on update, tabs will reset.
|
||||
// We can add a small script to check URL param or sessionStorage to activate correct tab.
|
||||
(function(){
|
||||
const STORAGE_KEY = 'admin.settings.activeTab';
|
||||
|
||||
// Save active tab id when clicked
|
||||
document.querySelectorAll('#settingsTab button[data-bs-toggle="tab"]').forEach(btn => {
|
||||
btn.addEventListener('shown.bs.tab', (e) => {
|
||||
try { sessionStorage.setItem(STORAGE_KEY, e.target.id); } catch(e){}
|
||||
});
|
||||
});
|
||||
|
||||
// Restore on load
|
||||
function restoreTab(){
|
||||
try{
|
||||
const id = sessionStorage.getItem(STORAGE_KEY);
|
||||
if(id){
|
||||
const btn = document.getElementById(id);
|
||||
if(btn){
|
||||
const tab = new bootstrap.Tab(btn);
|
||||
tab.show();
|
||||
}
|
||||
}
|
||||
}catch(e){}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', restoreTab);
|
||||
|
||||
// HTMX: after swapping settings container, restore the tab
|
||||
document.addEventListener('htmx:afterSwap', function(evt){
|
||||
if(evt.detail.target && evt.detail.target.id === undefined){ return; }
|
||||
const tgt = evt.detail.target;
|
||||
if(tgt && (tgt.id === 'users-container' || tgt.id === 'main-content' || tgt.id === 'modal-area')){
|
||||
// not our container
|
||||
return;
|
||||
}
|
||||
// if settings container was swapped, restore
|
||||
if(tgt && tgt.closest && tgt.closest('.container-fluid') && tgt.closest('.container-fluid').querySelector('#settingsTab')){
|
||||
restoreTab();
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
Reference in New Issue
Block a user