feat: SEO field types and the complete SEO tab

This commit is contained in:
2026-10-27 11:04:03 +01:00
parent deebd9aa65
commit 93ddbcc9ef
26 changed files with 1827 additions and 50 deletions

View File

@@ -93,6 +93,47 @@ func (c rulesAdminController) ListExtendRecords(ctx context.Context, _ *gorm.DB,
return nil
}
// service returns the SEO service of the booted app, nil before boot.
func (c rulesAdminController) service() *classes.Service {
svc, err := classes.NewService(appOf(c.app))
if err != nil {
return nil
}
return svc
}
// AdminJS loads the SEO element bundle on the rules screens (the result
// preview widget).
func (rulesAdminController) AdminJS() []string { return []string{"assets/dist/seo.js"} }
// AdminCSS loads the SEO element styles on the rules screens.
func (rulesAdminController) AdminCSS() []string { return []string{"assets/dist/seo.css"} }
// AdminActions registers the result preview's widget action (E3).
func (c rulesAdminController) AdminActions() []pact.AdminAction {
return []pact.AdminAction{classes.RuleSnippetAction(c.service, "golem15.seo::lang.snippet.action", PermissionManage)}
}
// PartialData serves P1 seo_status (canonical warnings) and P2
// seo_effective of a rule.
func (c rulesAdminController) PartialData(ctx context.Context, name string, record any) (any, error) {
svc := c.service()
r, ok := record.(*models.Rule)
if svc == nil || !ok || r == nil {
if name == "seo_effective" {
return classes.EffectiveView{}, nil
}
return classes.StatusView{}, nil
}
switch name {
case "seo_status":
return svc.RuleStatus(ctx, *r), nil
case "seo_effective":
return svc.RuleEffective(ctx, *r)
}
return nil, nil
}
// FilterOptions serves the match filter's two choices.
func (rulesAdminController) FilterOptions(scope string) []pact.Option {
if scope != models.FilterMatch {
@@ -113,4 +154,7 @@ var (
_ pact.ListExtendRecords = rulesAdminController{}
_ pact.FilterOptions = rulesAdminController{}
_ pact.FormAfterDelete = rulesAdminController{}
_ pact.HasAdminActions = rulesAdminController{}
_ pact.AdminPartialData = rulesAdminController{}
_ pact.AdminClientAssets = rulesAdminController{}
)