- POST /_seo/api/v1/batch runs changes in one transaction: dry_run answers the diff and the conflicts (loops, chains, noindex on a published record, canonicals to redirected or noindex addresses) and rolls back; a refused change refuses the batch (D-12) - undo of a change or a whole batch from History and through MCP, with the undo_stale, undo_loop and undo_gone refusals (D-13) - CSV export and import of redirects, rules and records by URL: BOM, comma or semicolon, formula cells escaped, a dry-run preview, all or nothing with via import; the screen's apply token is HMAC-SHA256 over the file and a fingerprint of the data (transfer.stale) - Import and export singleton with the seo_transfer widget action, History record actions undo and undo_batch, navigation entry - MCP tools undo_change, undo_batch, apply_batch, export_csv, import_csv - TestBatch, TestUndo, TestCSVTransfer, TestLoopRefused mcp and import
67 lines
2.0 KiB
Go
67 lines
2.0 KiB
Go
package seo
|
|
|
|
import (
|
|
"git.golem15.com/golem15/sm-seo-plugin/controllers"
|
|
"git.golem15.com/golem15/summercms/modules/pact"
|
|
)
|
|
|
|
// Navigation registers the SEO main item (UI-SPEC C2) behind
|
|
// golem15.seo.manage. It lands on Redirects; each side-menu entry is added
|
|
// when its controller exists, in the C2 order.
|
|
func (*Plugin) Navigation() []pact.NavigationItem {
|
|
return []pact.NavigationItem{{
|
|
Code: "seo",
|
|
Label: "golem15.seo::lang.nav.seo",
|
|
Icon: "search",
|
|
Permissions: []string{controllers.PermissionManage},
|
|
Order: 600,
|
|
Controller: controllers.RedirectsControllerID,
|
|
SideMenu: []pact.NavigationItem{
|
|
{
|
|
Code: "redirects",
|
|
Label: "golem15.seo::lang.nav.redirects",
|
|
Icon: "arrow-right",
|
|
Permissions: []string{controllers.PermissionManage},
|
|
Controller: controllers.RedirectsControllerID,
|
|
},
|
|
{
|
|
Code: "notfound",
|
|
Label: "golem15.seo::lang.nav.notfound",
|
|
Icon: "triangle-alert",
|
|
Permissions: []string{controllers.PermissionManage},
|
|
Controller: controllers.NotFoundControllerID,
|
|
},
|
|
{
|
|
Code: "rules",
|
|
Label: "golem15.seo::lang.nav.rules",
|
|
Icon: "link",
|
|
Permissions: []string{controllers.PermissionManage},
|
|
Controller: controllers.RulesControllerID,
|
|
},
|
|
{
|
|
Code: "robots",
|
|
Label: "golem15.seo::lang.nav.robots",
|
|
Icon: "file-text",
|
|
Permissions: []string{controllers.PermissionManage},
|
|
Controller: controllers.RobotsControllerID,
|
|
},
|
|
{
|
|
Code: "history",
|
|
Label: "golem15.seo::lang.nav.history",
|
|
Icon: "clock",
|
|
Permissions: []string{controllers.PermissionManage},
|
|
Controller: controllers.HistoryControllerID,
|
|
},
|
|
{
|
|
Code: "transfer",
|
|
Label: "golem15.seo::lang.nav.transfer",
|
|
Icon: "download",
|
|
Permissions: []string{controllers.PermissionManage},
|
|
Controller: controllers.TransferControllerID,
|
|
},
|
|
},
|
|
}}
|
|
}
|
|
|
|
var _ pact.HasNavigation = (*Plugin)(nil)
|