mirror of
https://github.com/Dvorinka/PPve.git
synced 2026-06-04 04:22:58 +00:00
ff
This commit is contained in:
+733
@@ -0,0 +1,733 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type GridCard struct {
|
||||
ID string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Icon string `json:"icon"`
|
||||
Link string `json:"link"`
|
||||
Color string `json:"color"`
|
||||
Order int `json:"order"`
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
|
||||
// In-memory storage for grid cards (replace with database in production)
|
||||
var gridCards = []GridCard{
|
||||
{
|
||||
ID: "evidence-aut",
|
||||
Title: "Evidence aut",
|
||||
Description: "Záznam o jízdách služebním autem",
|
||||
Icon: "🚗",
|
||||
Link: "/evidence-aut",
|
||||
Color: "#004990",
|
||||
Order: 1,
|
||||
Enabled: true,
|
||||
},
|
||||
{
|
||||
ID: "kontakt",
|
||||
Title: "Kontakt",
|
||||
Description: "Kontaktní formulář",
|
||||
Icon: "📧",
|
||||
Link: "/kontakt",
|
||||
Color: "#0072b0",
|
||||
Order: 2,
|
||||
Enabled: true,
|
||||
},
|
||||
}
|
||||
|
||||
func HandleAdmin(w http.ResponseWriter, r *http.Request) {
|
||||
user := GetCurrentUser(r)
|
||||
if user == nil {
|
||||
http.Redirect(w, r, "/login", http.StatusFound)
|
||||
return
|
||||
}
|
||||
|
||||
tmpl := `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Administrace</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
background-color: #f5f5f5;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.header {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
padding: 1rem 2rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.logout-btn {
|
||||
background: rgba(255,255,255,0.2);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
transition: background 0.3s;
|
||||
}
|
||||
|
||||
.logout-btn:hover {
|
||||
background: rgba(255,255,255,0.3);
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 2rem auto;
|
||||
padding: 0 2rem;
|
||||
}
|
||||
|
||||
.section {
|
||||
background: white;
|
||||
border-radius: 10px;
|
||||
padding: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.section h2 {
|
||||
color: #333;
|
||||
margin-bottom: 1.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
border-bottom: 2px solid #667eea;
|
||||
}
|
||||
|
||||
.cards-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||
gap: 1rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.card-item {
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 8px;
|
||||
padding: 1rem;
|
||||
background: #f9f9f9;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.card-toggle {
|
||||
width: 50px;
|
||||
height: 24px;
|
||||
background: #ccc;
|
||||
border-radius: 12px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
transition: background 0.3s;
|
||||
}
|
||||
|
||||
.card-toggle.active {
|
||||
background: #667eea;
|
||||
}
|
||||
|
||||
.card-toggle::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
background: white;
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
.card-toggle.active::before {
|
||||
transform: translateX(26px);
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.form-group input,
|
||||
.form-group textarea {
|
||||
width: 100%;
|
||||
padding: 0.5rem;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 5px;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.form-group input:focus,
|
||||
.form-group textarea:focus {
|
||||
outline: none;
|
||||
border-color: #667eea;
|
||||
}
|
||||
|
||||
.btn {
|
||||
background: #667eea;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
transition: background 0.3s;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background: #5a67d8;
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
background: #e53e3e;
|
||||
}
|
||||
|
||||
.btn-danger:hover {
|
||||
background: #c53030;
|
||||
}
|
||||
|
||||
.add-card-btn {
|
||||
background: #38a169;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 0.75rem 1.5rem;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.add-card-btn:hover {
|
||||
background: #2f855a;
|
||||
}
|
||||
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background: white;
|
||||
margin: 5% auto;
|
||||
padding: 2rem;
|
||||
border-radius: 10px;
|
||||
width: 90%;
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
.close {
|
||||
color: #aaa;
|
||||
float: right;
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.close:hover {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.success-message {
|
||||
background: #c6f6d5;
|
||||
color: #22543d;
|
||||
padding: 0.75rem;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 1rem;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
background: #fed7d7;
|
||||
color: #822727;
|
||||
padding: 0.75rem;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 1rem;
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.header {
|
||||
padding: 1rem;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.cards-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
<h1>Administrace</h1>
|
||||
<div class="user-info">
|
||||
<span>Přihlášen jako: <strong>{{.Username}}</strong></span>
|
||||
<button class="logout-btn" onclick="logout()">Odhlásit se</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="section">
|
||||
<h2>Správa karet hlavní stránky</h2>
|
||||
<div class="success-message" id="successMessage"></div>
|
||||
<div class="error-message" id="errorMessage"></div>
|
||||
|
||||
<button class="add-card-btn" onclick="openAddCardModal()">Přidat novou kartu</button>
|
||||
|
||||
<div class="cards-grid" id="cardsGrid">
|
||||
<!-- Cards will be loaded here -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Add/Edit Card Modal -->
|
||||
<div id="cardModal" class="modal">
|
||||
<div class="modal-content">
|
||||
<span class="close" onclick="closeCardModal()">×</span>
|
||||
<h3 id="modalTitle">Přidat kartu</h3>
|
||||
<form id="cardForm">
|
||||
<input type="hidden" id="cardId" name="id">
|
||||
|
||||
<div class="form-group">
|
||||
<label for="cardTitle">Název</label>
|
||||
<input type="text" id="cardTitle" name="title" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="cardDescription">Popis</label>
|
||||
<textarea id="cardDescription" name="description" rows="3"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="cardIcon">Ikona (emoji nebo text)</label>
|
||||
<input type="text" id="cardIcon" name="icon">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="cardLink">Odkaz</label>
|
||||
<input type="text" id="cardLink" name="link" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="cardColor">Barva</label>
|
||||
<input type="color" id="cardColor" name="color" value="#004990">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="cardOrder">Pořadí</label>
|
||||
<input type="number" id="cardOrder" name="order" min="1" value="1">
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn">Uložit</button>
|
||||
<button type="button" class="btn" onclick="closeCardModal()">Zrušit</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let cards = [];
|
||||
|
||||
// Load cards on page load
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
loadCards();
|
||||
});
|
||||
|
||||
async function loadCards() {
|
||||
try {
|
||||
const response = await fetch('/admin/cards', {
|
||||
headers: {
|
||||
'Authorization': localStorage.getItem('authToken') || ''
|
||||
}
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
cards = await response.json();
|
||||
renderCards();
|
||||
} else {
|
||||
showError('Chyba při načítání karet');
|
||||
}
|
||||
} catch (error) {
|
||||
showError('Chyba při načítání karet');
|
||||
}
|
||||
}
|
||||
|
||||
function renderCards() {
|
||||
const grid = document.getElementById('cardsGrid');
|
||||
grid.innerHTML = '';
|
||||
|
||||
cards.sort((a, b) => a.order - b.order).forEach(card => {
|
||||
const cardElement = document.createElement('div');
|
||||
cardElement.className = 'card-item';
|
||||
cardElement.innerHTML = ` + "`" + `
|
||||
<div class="card-header">
|
||||
<div class="card-title">${card.icon} ${card.title}</div>
|
||||
<div class="card-toggle ${card.enabled ? 'active' : ''}"
|
||||
onclick="toggleCard('${card.id}')"></div>
|
||||
</div>
|
||||
<p><strong>Popis:</strong> ${card.description}</p>
|
||||
<p><strong>Odkaz:</strong> ${card.link}</p>
|
||||
<p><strong>Barva:</strong> <span style="background: ${card.color}; padding: 2px 8px; color: white; border-radius: 3px;">${card.color}</span></p>
|
||||
<p><strong>Pořadí:</strong> ${card.order}</p>
|
||||
<div style="margin-top: 1rem;">
|
||||
<button class="btn" onclick="editCard('${card.id}')">Upravit</button>
|
||||
<button class="btn btn-danger" onclick="deleteCard('${card.id}')">Smazat</button>
|
||||
</div>
|
||||
` + "`" + `;
|
||||
grid.appendChild(cardElement);
|
||||
});
|
||||
}
|
||||
|
||||
async function toggleCard(cardId) {
|
||||
try {
|
||||
const response = await fetch(` + "`" + `/admin/cards/${cardId}/toggle` + "`" + `, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': localStorage.getItem('authToken') || ''
|
||||
}
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
await loadCards();
|
||||
showSuccess('Karta byla aktualizována');
|
||||
} else {
|
||||
showError('Chyba při aktualizaci karty');
|
||||
}
|
||||
} catch (error) {
|
||||
showError('Chyba při aktualizaci karty');
|
||||
}
|
||||
}
|
||||
|
||||
function openAddCardModal() {
|
||||
document.getElementById('modalTitle').textContent = 'Přidat kartu';
|
||||
document.getElementById('cardForm').reset();
|
||||
document.getElementById('cardId').value = '';
|
||||
document.getElementById('cardModal').style.display = 'block';
|
||||
}
|
||||
|
||||
function editCard(cardId) {
|
||||
const card = cards.find(c => c.id === cardId);
|
||||
if (!card) return;
|
||||
|
||||
document.getElementById('modalTitle').textContent = 'Upravit kartu';
|
||||
document.getElementById('cardId').value = card.id;
|
||||
document.getElementById('cardTitle').value = card.title;
|
||||
document.getElementById('cardDescription').value = card.description;
|
||||
document.getElementById('cardIcon').value = card.icon;
|
||||
document.getElementById('cardLink').value = card.link;
|
||||
document.getElementById('cardColor').value = card.color;
|
||||
document.getElementById('cardOrder').value = card.order;
|
||||
document.getElementById('cardModal').style.display = 'block';
|
||||
}
|
||||
|
||||
function closeCardModal() {
|
||||
document.getElementById('cardModal').style.display = 'none';
|
||||
}
|
||||
|
||||
document.getElementById('cardForm').addEventListener('submit', async function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const formData = new FormData(e.target);
|
||||
const cardData = {
|
||||
id: formData.get('id') || generateId(),
|
||||
title: formData.get('title'),
|
||||
description: formData.get('description'),
|
||||
icon: formData.get('icon'),
|
||||
link: formData.get('link'),
|
||||
color: formData.get('color'),
|
||||
order: parseInt(formData.get('order')),
|
||||
enabled: true
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch('/admin/cards', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': localStorage.getItem('authToken') || ''
|
||||
},
|
||||
body: JSON.stringify(cardData)
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
closeCardModal();
|
||||
await loadCards();
|
||||
showSuccess('Karta byla uložena');
|
||||
} else {
|
||||
showError('Chyba při ukládání karty');
|
||||
}
|
||||
} catch (error) {
|
||||
showError('Chyba při ukládání karty');
|
||||
}
|
||||
});
|
||||
|
||||
async function deleteCard(cardId) {
|
||||
if (!confirm('Opravdu chcete smazat tuto kartu?')) return;
|
||||
|
||||
try {
|
||||
const response = await fetch(` + "`" + `/admin/cards/${cardId}` + "`" + `, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Authorization': localStorage.getItem('authToken') || ''
|
||||
}
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
await loadCards();
|
||||
showSuccess('Karta byla smazána');
|
||||
} else {
|
||||
showError('Chyba při mazání karty');
|
||||
}
|
||||
} catch (error) {
|
||||
showError('Chyba při mazání karty');
|
||||
}
|
||||
}
|
||||
|
||||
async function logout() {
|
||||
try {
|
||||
await fetch('/logout', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': localStorage.getItem('authToken') || ''
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
// Ignore error
|
||||
}
|
||||
|
||||
localStorage.removeItem('authToken');
|
||||
localStorage.removeItem('userRole');
|
||||
window.location.href = '/login';
|
||||
}
|
||||
|
||||
function generateId() {
|
||||
return 'card-' + Date.now() + '-' + Math.random().toString(36).substr(2, 9);
|
||||
}
|
||||
|
||||
function showSuccess(message) {
|
||||
const successDiv = document.getElementById('successMessage');
|
||||
successDiv.textContent = message;
|
||||
successDiv.style.display = 'block';
|
||||
setTimeout(() => {
|
||||
successDiv.style.display = 'none';
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
function showError(message) {
|
||||
const errorDiv = document.getElementById('errorMessage');
|
||||
errorDiv.textContent = message;
|
||||
errorDiv.style.display = 'block';
|
||||
setTimeout(() => {
|
||||
errorDiv.style.display = 'none';
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
// Close modal when clicking outside
|
||||
window.onclick = function(event) {
|
||||
const modal = document.getElementById('cardModal');
|
||||
if (event.target === modal) {
|
||||
closeCardModal();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>`
|
||||
|
||||
t, err := template.New("admin").Parse(tmpl)
|
||||
if err != nil {
|
||||
http.Error(w, "Template error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
data := struct {
|
||||
Username string
|
||||
Role string
|
||||
}{
|
||||
Username: user.Username,
|
||||
Role: user.Role,
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
t.Execute(w, data)
|
||||
}
|
||||
|
||||
func HandleAdminCards(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
switch r.Method {
|
||||
case "GET":
|
||||
json.NewEncoder(w).Encode(gridCards)
|
||||
|
||||
case "POST":
|
||||
var card GridCard
|
||||
if err := json.NewDecoder(r.Body).Decode(&card); err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
json.NewEncoder(w).Encode(map[string]string{"error": "Invalid JSON"})
|
||||
return
|
||||
}
|
||||
|
||||
// Check if updating existing card
|
||||
found := false
|
||||
for i, existingCard := range gridCards {
|
||||
if existingCard.ID == card.ID {
|
||||
gridCards[i] = card
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
gridCards = append(gridCards, card)
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(map[string]string{"message": "Card saved successfully"})
|
||||
|
||||
default:
|
||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||
json.NewEncoder(w).Encode(map[string]string{"error": "Method not allowed"})
|
||||
}
|
||||
}
|
||||
|
||||
func HandleAdminCardToggle(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if r.Method != "POST" {
|
||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||
json.NewEncoder(w).Encode(map[string]string{"error": "Method not allowed"})
|
||||
return
|
||||
}
|
||||
|
||||
// Extract card ID from URL path
|
||||
path := r.URL.Path
|
||||
parts := strings.Split(path, "/")
|
||||
if len(parts) < 4 {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
json.NewEncoder(w).Encode(map[string]string{"error": "Invalid card ID"})
|
||||
return
|
||||
}
|
||||
|
||||
cardID := parts[3] // /admin/cards/{id}/toggle
|
||||
|
||||
for i, card := range gridCards {
|
||||
if card.ID == cardID {
|
||||
gridCards[i].Enabled = !gridCards[i].Enabled
|
||||
json.NewEncoder(w).Encode(map[string]string{"message": "Card toggled successfully"})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
json.NewEncoder(w).Encode(map[string]string{"error": "Card not found"})
|
||||
}
|
||||
|
||||
func HandleAdminCardDelete(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
if r.Method != "DELETE" {
|
||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||
json.NewEncoder(w).Encode(map[string]string{"error": "Method not allowed"})
|
||||
return
|
||||
}
|
||||
|
||||
// Extract card ID from URL path
|
||||
path := r.URL.Path
|
||||
parts := strings.Split(path, "/")
|
||||
if len(parts) < 4 {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
json.NewEncoder(w).Encode(map[string]string{"error": "Invalid card ID"})
|
||||
return
|
||||
}
|
||||
|
||||
cardID := parts[3] // /admin/cards/{id}
|
||||
|
||||
for i, card := range gridCards {
|
||||
if card.ID == cardID {
|
||||
// Remove card from slice
|
||||
gridCards = append(gridCards[:i], gridCards[i+1:]...)
|
||||
json.NewEncoder(w).Encode(map[string]string{"message": "Card deleted successfully"})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
json.NewEncoder(w).Encode(map[string]string{"error": "Card not found"})
|
||||
}
|
||||
|
||||
func HandleGetCards(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
// Filter only enabled cards and sort by order
|
||||
var enabledCards []GridCard
|
||||
for _, card := range gridCards {
|
||||
if card.Enabled {
|
||||
enabledCards = append(enabledCards, card)
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by order
|
||||
for i := 0; i < len(enabledCards)-1; i++ {
|
||||
for j := i + 1; j < len(enabledCards); j++ {
|
||||
if enabledCards[i].Order > enabledCards[j].Order {
|
||||
enabledCards[i], enabledCards[j] = enabledCards[j], enabledCards[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(enabledCards)
|
||||
}
|
||||
Reference in New Issue
Block a user