mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-03 18:22:57 +00:00
330 lines
8.1 KiB
Go
330 lines
8.1 KiB
Go
package controllers
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type MyUIbrixController struct {
|
|
DB *gorm.DB
|
|
}
|
|
|
|
// PageElementConfigRequest represents element configuration
|
|
type PageElementConfigRequest struct {
|
|
PageType string `json:"page_type" binding:"required"`
|
|
ElementName string `json:"element_name" binding:"required"`
|
|
Variant string `json:"variant"`
|
|
Visible bool `json:"visible"`
|
|
DisplayOrder int `json:"display_order"`
|
|
CustomStyles map[string]interface{} `json:"custom_styles"`
|
|
}
|
|
|
|
// ValidateElementConfig validates and optimizes element configuration
|
|
func (ctrl *MyUIbrixController) ValidateElementConfig(c *gin.Context) {
|
|
var req PageElementConfigRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
// Validate element name (alphanumeric, underscore, hyphen only)
|
|
if !isValidElementName(req.ElementName) {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid element name"})
|
|
return
|
|
}
|
|
|
|
// Optimize custom styles by removing redundant properties
|
|
optimizedStyles := optimizeStyles(req.CustomStyles)
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"valid": true,
|
|
"optimized_styles": optimizedStyles,
|
|
"suggestions": generateStyleSuggestions(req.ElementName, optimizedStyles),
|
|
})
|
|
}
|
|
|
|
// GetElementPreview generates server-side preview data
|
|
func (ctrl *MyUIbrixController) GetElementPreview(c *gin.Context) {
|
|
elementName := c.Query("element")
|
|
variant := c.Query("variant")
|
|
viewport := c.Query("viewport") // desktop, tablet, mobile
|
|
|
|
if elementName == "" {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "element required"})
|
|
return
|
|
}
|
|
|
|
// Generate preview metadata
|
|
preview := generatePreviewMetadata(elementName, variant, viewport)
|
|
|
|
c.JSON(http.StatusOK, preview)
|
|
}
|
|
|
|
// BatchValidateConfigs validates multiple configs at once
|
|
func (ctrl *MyUIbrixController) BatchValidateConfigs(c *gin.Context) {
|
|
var configs []PageElementConfigRequest
|
|
if err := c.ShouldBindJSON(&configs); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
|
|
results := make([]map[string]interface{}, 0, len(configs))
|
|
|
|
for _, config := range configs {
|
|
if !isValidElementName(config.ElementName) {
|
|
results = append(results, map[string]interface{}{
|
|
"element_name": config.ElementName,
|
|
"valid": false,
|
|
"error": "Invalid element name",
|
|
})
|
|
continue
|
|
}
|
|
|
|
optimizedStyles := optimizeStyles(config.CustomStyles)
|
|
results = append(results, map[string]interface{}{
|
|
"element_name": config.ElementName,
|
|
"valid": true,
|
|
"optimized_styles": optimizedStyles,
|
|
"display_order": config.DisplayOrder,
|
|
})
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"results": results,
|
|
"timestamp": time.Now().Unix(),
|
|
})
|
|
}
|
|
|
|
// OptimizePageLayout analyzes and optimizes page element layout
|
|
func (ctrl *MyUIbrixController) OptimizePageLayout(c *gin.Context) {
|
|
pageType := c.Query("page_type")
|
|
if pageType == "" {
|
|
pageType = "homepage"
|
|
}
|
|
|
|
// Load current configurations from database
|
|
var configs []map[string]interface{}
|
|
|
|
query := `
|
|
SELECT element_name, variant, visible, display_order, settings
|
|
FROM page_element_configs
|
|
WHERE page_type = ?
|
|
ORDER BY display_order ASC
|
|
`
|
|
|
|
rows, err := ctrl.DB.Raw(query, pageType).Rows()
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to load configs"})
|
|
return
|
|
}
|
|
defer rows.Close()
|
|
|
|
for rows.Next() {
|
|
var elementName, variant string
|
|
var visible bool
|
|
var displayOrder int
|
|
var settingsJSON []byte
|
|
|
|
if err := rows.Scan(&elementName, &variant, &visible, &displayOrder, &settingsJSON); err != nil {
|
|
continue
|
|
}
|
|
|
|
// settings is a JSON object; we expect optional nested key "styles"
|
|
var settings map[string]interface{}
|
|
if len(settingsJSON) > 0 {
|
|
_ = json.Unmarshal(settingsJSON, &settings)
|
|
}
|
|
|
|
var customStyles map[string]interface{}
|
|
if settings != nil {
|
|
if st, ok := settings["styles"]; ok {
|
|
if m, ok2 := st.(map[string]interface{}); ok2 {
|
|
customStyles = m
|
|
}
|
|
}
|
|
}
|
|
|
|
configs = append(configs, map[string]interface{}{
|
|
"element_name": elementName,
|
|
"variant": variant,
|
|
"visible": visible,
|
|
"display_order": displayOrder,
|
|
// Keep API field name as custom_styles for compatibility
|
|
"custom_styles": customStyles,
|
|
})
|
|
}
|
|
|
|
// Generate optimization suggestions
|
|
suggestions := generateLayoutSuggestions(configs)
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"current_layout": configs,
|
|
"suggestions": suggestions,
|
|
"performance_score": calculatePerformanceScore(configs),
|
|
})
|
|
}
|
|
|
|
// Helper functions
|
|
|
|
func isValidElementName(name string) bool {
|
|
if name == "" || len(name) > 100 {
|
|
return false
|
|
}
|
|
for _, r := range name {
|
|
if !((r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') ||
|
|
(r >= '0' && r <= '9') || r == '_' || r == '-') {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func optimizeStyles(styles map[string]interface{}) map[string]interface{} {
|
|
if styles == nil {
|
|
return make(map[string]interface{})
|
|
}
|
|
|
|
optimized := make(map[string]interface{})
|
|
|
|
// Remove redundant or default values
|
|
for key, value := range styles {
|
|
// Skip empty values
|
|
if value == nil || value == "" || value == 0 {
|
|
continue
|
|
}
|
|
|
|
// Skip defaults
|
|
if isDefaultValue(key, value) {
|
|
continue
|
|
}
|
|
|
|
optimized[key] = value
|
|
}
|
|
|
|
return optimized
|
|
}
|
|
|
|
func isDefaultValue(key string, value interface{}) bool {
|
|
defaults := map[string]interface{}{
|
|
"margin": "0",
|
|
"padding": "0",
|
|
"border": "none",
|
|
"background": "transparent",
|
|
"opacity": 1,
|
|
"display": "block",
|
|
}
|
|
|
|
if defaultVal, exists := defaults[key]; exists {
|
|
return value == defaultVal
|
|
}
|
|
return false
|
|
}
|
|
|
|
func generateStyleSuggestions(elementName string, styles map[string]interface{}) []string {
|
|
suggestions := []string{}
|
|
|
|
// Check for performance-heavy properties
|
|
if _, hasBoxShadow := styles["box-shadow"]; hasBoxShadow {
|
|
if _, hasFilter := styles["filter"]; hasFilter {
|
|
suggestions = append(suggestions, "Multiple shadows and filters may impact performance")
|
|
}
|
|
}
|
|
|
|
// Check for conflicting properties
|
|
if position, ok := styles["position"].(string); ok {
|
|
if position == "fixed" || position == "sticky" {
|
|
suggestions = append(suggestions, "Fixed/sticky positioning may cause layout issues on mobile")
|
|
}
|
|
}
|
|
|
|
return suggestions
|
|
}
|
|
|
|
func generatePreviewMetadata(elementName, variant, viewport string) map[string]interface{} {
|
|
// Generate viewport-specific metadata
|
|
dimensions := map[string]map[string]int{
|
|
"desktop": {"width": 1920, "height": 1080},
|
|
"tablet": {"width": 768, "height": 1024},
|
|
"mobile": {"width": 375, "height": 667},
|
|
}
|
|
|
|
dim := dimensions["desktop"]
|
|
if d, ok := dimensions[viewport]; ok {
|
|
dim = d
|
|
}
|
|
|
|
return map[string]interface{}{
|
|
"element_name": elementName,
|
|
"variant": variant,
|
|
"viewport": viewport,
|
|
"dimensions": dim,
|
|
"render_hints": map[string]interface{}{
|
|
"use_gpu_acceleration": true,
|
|
"optimize_images": true,
|
|
"lazy_load": viewport == "mobile",
|
|
},
|
|
}
|
|
}
|
|
|
|
func generateLayoutSuggestions(configs []map[string]interface{}) []string {
|
|
suggestions := []string{}
|
|
|
|
visibleCount := 0
|
|
for _, config := range configs {
|
|
if visible, ok := config["visible"].(bool); ok && visible {
|
|
visibleCount++
|
|
}
|
|
}
|
|
|
|
if visibleCount > 15 {
|
|
suggestions = append(suggestions, "Consider hiding some elements to improve page load time")
|
|
}
|
|
|
|
if visibleCount < 3 {
|
|
suggestions = append(suggestions, "Page may look empty - consider adding more visible elements")
|
|
}
|
|
|
|
return suggestions
|
|
}
|
|
|
|
func calculatePerformanceScore(configs []map[string]interface{}) int {
|
|
score := 100
|
|
|
|
// Deduct for too many visible elements
|
|
visibleCount := 0
|
|
for _, config := range configs {
|
|
if visible, ok := config["visible"].(bool); ok && visible {
|
|
visibleCount++
|
|
}
|
|
}
|
|
|
|
if visibleCount > 15 {
|
|
score -= (visibleCount - 15) * 2
|
|
}
|
|
|
|
// Deduct for heavy custom styles
|
|
heavyStyleCount := 0
|
|
for _, config := range configs {
|
|
if styles, ok := config["custom_styles"].(map[string]interface{}); ok {
|
|
if len(styles) > 10 {
|
|
heavyStyleCount++
|
|
}
|
|
}
|
|
}
|
|
|
|
score -= heavyStyleCount * 5
|
|
|
|
if score < 0 {
|
|
score = 0
|
|
}
|
|
if score > 100 {
|
|
score = 100
|
|
}
|
|
|
|
return score
|
|
}
|