feat: page registry with its admin screen and signpost type
- golem15_seo_pages (migration 202610280002): the site's own frontend pages
with an address and a name per locale, kind, origin, parent, content date
and note; settings routes_reported_at
- SEO > Pages (golem15.seo.pages) after URL rules: list with kind, origin
and missing filters and the missing row state, form with the P9 partial;
the plugin's form extension saves the address and name per locale and
refuses url_required, url_invalid, url_taken and url_owned
- menu item type seo-page with a content descriptor, so each page gets
the SEO tab, resolves ok and is listed in the sitemaps grouped by kind
(pages, offers, services, landing-pages, titled per locale)
- management API GET/POST /_seo/api/v1/pages, PUT/DELETE /pages/{id} and
the MCP tools seo_list_pages, seo_create_page, seo_update_page,
seo_delete_page (in this commit because the operations parity test maps
every Pages operation to its tool)
This commit is contained in:
56
updates/202610280002_create_golem15_seo_pages.go
Normal file
56
updates/202610280002_create_golem15_seo_pages.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package updates
|
||||
|
||||
import (
|
||||
"github.com/go-gormigrate/gormigrate/v2"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// createPages creates golem15_seo_pages, the page registry (D-33): the
|
||||
// site's own frontend pages with their address per locale (url is the
|
||||
// default locale's, urls the others'), name per locale, kind, origin,
|
||||
// parent, content date, last report and note, one row per default-locale
|
||||
// address. The settings get routes_reported_at, the time of the newest
|
||||
// route report, against which a reported page shows as missing.
|
||||
var createPages = []*gormigrate.Migration{
|
||||
{
|
||||
ID: "202610280002_create_golem15_seo_pages",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.Exec(`CREATE TABLE golem15_seo_pages (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
url TEXT NOT NULL,
|
||||
urls JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
title TEXT NOT NULL DEFAULT '',
|
||||
titles JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
kind TEXT NOT NULL DEFAULT 'page',
|
||||
origin TEXT NOT NULL DEFAULT 'manual',
|
||||
parent_id BIGINT NULL REFERENCES golem15_seo_pages (id) ON DELETE SET NULL,
|
||||
content_updated_at DATE NULL,
|
||||
reported_at TIMESTAMPTZ NULL,
|
||||
note TEXT NOT NULL DEFAULT '',
|
||||
created_at TIMESTAMP(0) NULL,
|
||||
updated_at TIMESTAMP(0) NULL
|
||||
)`).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
// One page per default-locale address; a row being created holds
|
||||
// '' only inside its own save transaction.
|
||||
if err := tx.Exec(`CREATE UNIQUE INDEX golem15_seo_pages_url ON golem15_seo_pages (url) WHERE url <> ''`).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Exec(`CREATE INDEX golem15_seo_pages_urls ON golem15_seo_pages USING gin (urls jsonb_path_ops)`).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Exec(`ALTER TABLE golem15_seo_settings ADD COLUMN routes_reported_at TIMESTAMPTZ NULL`).Error
|
||||
},
|
||||
Rollback: func(tx *gorm.DB) error {
|
||||
if err := tx.Exec(`ALTER TABLE golem15_seo_settings DROP COLUMN IF EXISTS routes_reported_at`).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Exec(`DROP TABLE IF EXISTS golem15_seo_pages`).Error
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
Register(createPages...)
|
||||
}
|
||||
Reference in New Issue
Block a user