194 lines
4.3 KiB
Go
194 lines
4.3 KiB
Go
package sections
|
|
|
|
import (
|
|
"encoding/json"
|
|
"sort"
|
|
)
|
|
|
|
// Resolve merges admin sections with profile overrides, producing the final ordered list.
|
|
func Resolve(admin []*PageSection, overrides []ProfileSectionOverride) []ResolvedSection {
|
|
overrideBySection := make(map[string]*ProfileSectionOverride)
|
|
var userAdded []ProfileSectionOverride
|
|
for i := range overrides {
|
|
o := &overrides[i]
|
|
if o.SectionID != "" {
|
|
overrideBySection[o.SectionID] = o
|
|
} else {
|
|
userAdded = append(userAdded, *o)
|
|
}
|
|
}
|
|
|
|
var result []ResolvedSection
|
|
|
|
for _, s := range admin {
|
|
o, hasOverride := overrideBySection[s.ID]
|
|
|
|
if hasOverride && o.Removed {
|
|
continue
|
|
}
|
|
if hasOverride && o.Hidden {
|
|
continue
|
|
}
|
|
|
|
rs := ResolvedSection{
|
|
ID: s.ID,
|
|
SectionType: s.SectionType,
|
|
Title: s.Title,
|
|
Featured: s.Featured,
|
|
ItemLimit: s.ItemLimit,
|
|
Config: s.Config,
|
|
Position: s.Position,
|
|
}
|
|
|
|
if hasOverride {
|
|
rs.Customized = true
|
|
if o.Position != nil {
|
|
rs.Position = *o.Position
|
|
}
|
|
if o.Title != "" {
|
|
rs.Title = o.Title
|
|
}
|
|
if o.Featured != nil {
|
|
rs.Featured = *o.Featured
|
|
}
|
|
if o.ItemLimit != nil {
|
|
rs.ItemLimit = *o.ItemLimit
|
|
}
|
|
if len(o.Config) > 0 && string(o.Config) != "" && string(o.Config) != "null" {
|
|
rs.Config = o.Config
|
|
}
|
|
}
|
|
|
|
result = append(result, rs)
|
|
}
|
|
|
|
for _, o := range userAdded {
|
|
if o.Removed {
|
|
continue
|
|
}
|
|
result = append(result, resolveUserAdded(o))
|
|
}
|
|
|
|
sort.Slice(result, func(i, j int) bool {
|
|
return result[i].Position < result[j].Position
|
|
})
|
|
|
|
return result
|
|
}
|
|
|
|
// ResolveForSettings is like Resolve but includes hidden sections with Hidden=true.
|
|
// Used by the settings UI so users can toggle visibility.
|
|
func ResolveForSettings(admin []*PageSection, overrides []ProfileSectionOverride) []ResolvedSection {
|
|
overrideBySection := make(map[string]*ProfileSectionOverride)
|
|
var userAdded []ProfileSectionOverride
|
|
for i := range overrides {
|
|
o := &overrides[i]
|
|
if o.SectionID != "" {
|
|
overrideBySection[o.SectionID] = o
|
|
} else {
|
|
userAdded = append(userAdded, *o)
|
|
}
|
|
}
|
|
|
|
var result []ResolvedSection
|
|
|
|
for _, s := range admin {
|
|
o, hasOverride := overrideBySection[s.ID]
|
|
|
|
if hasOverride && o.Removed {
|
|
continue
|
|
}
|
|
rs := ResolvedSection{
|
|
ID: s.ID,
|
|
SectionType: s.SectionType,
|
|
Title: s.Title,
|
|
Featured: s.Featured,
|
|
ItemLimit: s.ItemLimit,
|
|
Config: s.Config,
|
|
Position: s.Position,
|
|
}
|
|
|
|
if hasOverride {
|
|
rs.Customized = true
|
|
rs.Hidden = o.Hidden
|
|
if o.Position != nil {
|
|
rs.Position = *o.Position
|
|
}
|
|
if o.Title != "" {
|
|
rs.Title = o.Title
|
|
}
|
|
if o.Featured != nil {
|
|
rs.Featured = *o.Featured
|
|
}
|
|
if o.ItemLimit != nil {
|
|
rs.ItemLimit = *o.ItemLimit
|
|
}
|
|
if len(o.Config) > 0 && string(o.Config) != "" && string(o.Config) != "null" {
|
|
rs.Config = o.Config
|
|
}
|
|
}
|
|
|
|
result = append(result, rs)
|
|
}
|
|
|
|
for _, o := range userAdded {
|
|
if o.Removed {
|
|
continue
|
|
}
|
|
result = append(result, resolveUserAdded(o))
|
|
}
|
|
|
|
sort.Slice(result, func(i, j int) bool {
|
|
return result[i].Position < result[j].Position
|
|
})
|
|
|
|
return result
|
|
}
|
|
|
|
// resolveUserAdded converts a user-added ProfileSectionOverride into a
|
|
// ResolvedSection. When IsUserAdded is true the explicit User* fields take
|
|
// precedence; the legacy SectionType / Title / Config fields are used as a
|
|
// fallback for backward compatibility with existing data.
|
|
func resolveUserAdded(o ProfileSectionOverride) ResolvedSection {
|
|
pos := 0
|
|
if o.Position != nil {
|
|
pos = *o.Position
|
|
}
|
|
limit := 20
|
|
if o.ItemLimit != nil {
|
|
limit = *o.ItemLimit
|
|
}
|
|
featured := false
|
|
if o.Featured != nil {
|
|
featured = *o.Featured
|
|
}
|
|
|
|
// Prefer the explicit user-added fields when present; fall back to the
|
|
// legacy fields for backward compatibility with existing data.
|
|
sectionType := o.SectionType
|
|
if o.IsUserAdded && o.UserSectionType != "" {
|
|
sectionType = o.UserSectionType
|
|
}
|
|
title := o.Title
|
|
if o.IsUserAdded && o.UserTitle != "" {
|
|
title = o.UserTitle
|
|
}
|
|
cfg := json.RawMessage(`{}`)
|
|
if o.IsUserAdded && len(o.UserConfig) > 0 {
|
|
cfg = o.UserConfig
|
|
} else if len(o.Config) > 0 {
|
|
cfg = o.Config
|
|
}
|
|
|
|
return ResolvedSection{
|
|
ID: o.ID,
|
|
SectionType: sectionType,
|
|
Title: title,
|
|
Featured: featured,
|
|
ItemLimit: limit,
|
|
Config: cfg,
|
|
Position: pos,
|
|
IsCustom: true,
|
|
}
|
|
}
|