mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-04 02:32:57 +00:00
dev day #62
This commit is contained in:
@@ -2093,6 +2093,10 @@ func (bc *BaseController) SetupInitialize(c *gin.Context) {
|
||||
}
|
||||
logger.Info("Initial settings saved: club_id=%s club_name=%s gallery_url=%s gallery_label=%s", s.ClubID, s.ClubName, s.GalleryURL, s.GalleryLabel)
|
||||
|
||||
// Seed default homepage page elements with all available sections
|
||||
bc.seedDefaultHomePageElements()
|
||||
logger.Info("Default homepage page elements seeded")
|
||||
|
||||
// Run all setup operations asynchronously in background to provide immediate response
|
||||
scheme := "http"
|
||||
if c.Request.TLS != nil {
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"fotbal-club/internal/models"
|
||||
"fotbal-club/pkg/logger"
|
||||
)
|
||||
|
||||
// seedDefaultHomePageElements creates default page element configurations for the homepage
|
||||
// with all major sections visible by default (videos, gallery, matches, news, etc.)
|
||||
func (bc *BaseController) seedDefaultHomePageElements() {
|
||||
// Check if any homepage elements already exist
|
||||
var count int64
|
||||
if err := bc.DB.Model(&models.PageElementConfig{}).Where("page_type = ?", "homepage").Count(&count).Error; err != nil {
|
||||
logger.Error("Failed to check existing page elements: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if count > 0 {
|
||||
logger.Info("Homepage page elements already exist, skipping seed")
|
||||
return
|
||||
}
|
||||
|
||||
// Define default homepage elements with all major sections visible
|
||||
defaultElements := []models.PageElementConfig{
|
||||
// Hero section - main featured content
|
||||
{PageType: "homepage", ElementName: "hero", Variant: "grid", Visible: true, DisplayOrder: 1},
|
||||
|
||||
// News/Articles - latest articles
|
||||
{PageType: "homepage", ElementName: "news", Variant: "grid", Visible: true, DisplayOrder: 2},
|
||||
|
||||
// Matches - upcoming and recent matches
|
||||
{PageType: "homepage", ElementName: "matches", Variant: "compact", Visible: true, DisplayOrder: 3},
|
||||
|
||||
// Table - league standings
|
||||
{PageType: "homepage", ElementName: "table", Variant: "split_news", Visible: true, DisplayOrder: 4},
|
||||
|
||||
// Videos - YouTube videos and highlights
|
||||
{PageType: "homepage", ElementName: "videos", Variant: "grid", Visible: true, DisplayOrder: 5},
|
||||
|
||||
// Gallery - photo gallery
|
||||
{PageType: "homepage", ElementName: "gallery", Variant: "grid", Visible: true, DisplayOrder: 6},
|
||||
|
||||
// Team - players and squad
|
||||
{PageType: "homepage", ElementName: "team", Variant: "grid", Visible: true, DisplayOrder: 7},
|
||||
|
||||
// Activities - upcoming events
|
||||
{PageType: "homepage", ElementName: "activities", Variant: "list", Visible: true, DisplayOrder: 8},
|
||||
|
||||
// Sponsors - partners and sponsors
|
||||
{PageType: "homepage", ElementName: "sponsors", Variant: "grid", Visible: true, DisplayOrder: 9},
|
||||
|
||||
// Newsletter - newsletter signup
|
||||
{PageType: "homepage", ElementName: "newsletter", Variant: "default", Visible: true, DisplayOrder: 10},
|
||||
|
||||
// Contact - contact information and map
|
||||
{PageType: "homepage", ElementName: "contact", Variant: "combined", Visible: true, DisplayOrder: 11},
|
||||
}
|
||||
|
||||
// Insert all default elements in a single transaction
|
||||
tx := bc.DB.Begin()
|
||||
for _, element := range defaultElements {
|
||||
if err := tx.Create(&element).Error; err != nil {
|
||||
logger.Error("Failed to create page element %s: %v", element.ElementName, err)
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err := tx.Commit().Error; err != nil {
|
||||
logger.Error("Failed to commit page elements transaction: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
logger.Info("Successfully seeded %d default homepage page elements", len(defaultElements))
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type DocsController struct {
|
||||
DocsPath string
|
||||
}
|
||||
|
||||
func NewDocsController(docsPath string) *DocsController {
|
||||
return &DocsController{
|
||||
DocsPath: docsPath,
|
||||
}
|
||||
}
|
||||
|
||||
// GetDocFile serves a specific documentation file
|
||||
func (dc *DocsController) GetDocFile(c *gin.Context) {
|
||||
// Get the requested file path from the URL
|
||||
docPath := c.Param("filepath")
|
||||
|
||||
// Security: Prevent directory traversal
|
||||
if strings.Contains(docPath, "..") {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid file path"})
|
||||
return
|
||||
}
|
||||
|
||||
// Build full path
|
||||
fullPath := filepath.Join(dc.DocsPath, docPath)
|
||||
|
||||
// Check if file exists and is a markdown file
|
||||
if !strings.HasSuffix(fullPath, ".md") {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Only markdown files are allowed"})
|
||||
return
|
||||
}
|
||||
|
||||
// Read the file
|
||||
content, err := ioutil.ReadFile(fullPath)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Documentation file not found"})
|
||||
return
|
||||
}
|
||||
|
||||
// Return the content as plain text
|
||||
c.Header("Content-Type", "text/markdown; charset=utf-8")
|
||||
c.String(http.StatusOK, string(content))
|
||||
}
|
||||
|
||||
// ListDocFiles returns a list of available documentation files
|
||||
func (dc *DocsController) ListDocFiles(c *gin.Context) {
|
||||
files, err := ioutil.ReadDir(dc.DocsPath)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to read documentation directory"})
|
||||
return
|
||||
}
|
||||
|
||||
var docFiles []map[string]interface{}
|
||||
|
||||
for _, file := range files {
|
||||
if !file.IsDir() && strings.HasSuffix(file.Name(), ".md") {
|
||||
docFiles = append(docFiles, map[string]interface{}{
|
||||
"name": file.Name(),
|
||||
"path": "/DOCS/" + file.Name(),
|
||||
"size": file.Size(),
|
||||
"modified_at": file.ModTime(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"files": docFiles,
|
||||
"total": len(docFiles),
|
||||
})
|
||||
}
|
||||
|
||||
// SearchDocs searches through documentation files
|
||||
func (dc *DocsController) SearchDocs(c *gin.Context) {
|
||||
query := c.Query("q")
|
||||
if query == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Search query is required"})
|
||||
return
|
||||
}
|
||||
|
||||
query = strings.ToLower(query)
|
||||
files, err := ioutil.ReadDir(dc.DocsPath)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to read documentation directory"})
|
||||
return
|
||||
}
|
||||
|
||||
var results []map[string]interface{}
|
||||
|
||||
for _, file := range files {
|
||||
if file.IsDir() || !strings.HasSuffix(file.Name(), ".md") {
|
||||
continue
|
||||
}
|
||||
|
||||
fullPath := filepath.Join(dc.DocsPath, file.Name())
|
||||
content, err := ioutil.ReadFile(fullPath)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
contentLower := strings.ToLower(string(content))
|
||||
nameLower := strings.ToLower(file.Name())
|
||||
|
||||
// Check if query matches filename or content
|
||||
if strings.Contains(nameLower, query) || strings.Contains(contentLower, query) {
|
||||
// Find context around match
|
||||
index := strings.Index(contentLower, query)
|
||||
start := 0
|
||||
end := len(content)
|
||||
|
||||
if index > 100 {
|
||||
start = index - 100
|
||||
}
|
||||
if index+len(query)+200 < len(content) {
|
||||
end = index + len(query) + 200
|
||||
}
|
||||
|
||||
excerpt := string(content[start:end])
|
||||
|
||||
results = append(results, map[string]interface{}{
|
||||
"name": file.Name(),
|
||||
"path": "/DOCS/" + file.Name(),
|
||||
"excerpt": excerpt,
|
||||
"matches": strings.Count(contentLower, query),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"results": results,
|
||||
"total": len(results),
|
||||
"query": query,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user