feat: publisher, local business and home crumb settings

- Publisher and Local business tabs with the C20 refusals (sameAs lines,
  person as local business, address, times, country, coordinates)
- the publisher node from the settings, as an Organization, a Person or
  the chosen local business type with address, geo and opening hours
- P8 publisher preview with Google's required and recommended findings
  (classes/schema Validate)
- the home crumb name on the General tab; every new key in the settings
  API and seo_update_settings
This commit is contained in:
Jakub Zych
2026-11-04 14:14:59 +01:00
parent ea2ce24954
commit fde5024b5a
13 changed files with 938 additions and 52 deletions

View File

@@ -2,6 +2,7 @@ package classes
import (
"context"
"encoding/json"
"strconv"
"strings"
@@ -220,3 +221,50 @@ func (s *Service) structuredData(ctx context.Context, db *gorm.DB, settings mode
res.JSONLD = graph
return nil
}
// PublisherPreview is the view model of the settings' P8 partial: the
// generated publisher node as indented JSON and its findings as lines, or
// the all-good line.
type PublisherPreview struct {
JSON string
Findings []string
AllGood string
}
// FindingText renders a finding with the graph copy of the request locale.
func (s *Service) FindingText(ctx context.Context, typ string, f schema.Finding) string {
key := "golem15.seo::lang.graph.recommended"
if f.Level == schema.LevelRequired {
key = "golem15.seo::lang.graph.required"
}
return s.PhraseCtx(ctx, key, map[string]string{"property": f.Property, "type": typ})
}
// PublisherPreview builds P8 from the stored settings in the default
// locale (UI-SPEC C20).
func (s *Service) PublisherPreview(ctx context.Context) (PublisherPreview, error) {
db, err := s.DB(ctx)
if err != nil {
return PublisherPreview{}, err
}
settings, err := LoadSettings(db)
if err != nil {
return PublisherPreview{}, err
}
locale := s.DefaultLocale(ctx, db)
node := schema.PublisherNode(s.SiteURL(), s.PublisherOf(ctx, db, settings, locale), s.SiteName(ctx, settings, locale))
out := PublisherPreview{AllGood: s.PhraseCtx(ctx, "golem15.seo::lang.graph.all_good", nil)}
if node == nil {
return out, nil
}
raw, err := json.MarshalIndent(node, "", " ")
if err != nil {
return PublisherPreview{}, err
}
out.JSON = string(raw)
rep := schema.ValidateNode(node)
for _, f := range rep.Findings {
out.Findings = append(out.Findings, s.FindingText(ctx, rep.Type, f))
}
return out, nil
}