feat(15-02): add Categories, Tags, and journal settings admin
Register the remaining YAML admin screens and the settings singleton so a host can boot Posts, Categories, Tags, and Code journal. Posts update and delete refuse other authors without access_other_posts. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -12,6 +12,8 @@ import (
|
||||
func AdminControllers(app func() *backpack.App) []pact.AdminController {
|
||||
return []pact.AdminController{
|
||||
postsAdminController{app: app},
|
||||
categoriesAdminController{app: app},
|
||||
tagsAdminController{app: app},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,5 +27,15 @@ func init() {
|
||||
var _ pact.FilterOptions = postsAdminController{}
|
||||
var _ pact.FormBeforeCreate = postsAdminController{}
|
||||
var _ pact.FormBeforeUpdate = postsAdminController{}
|
||||
var _ pact.FormBeforeDelete = postsAdminController{}
|
||||
var _ cabana.FieldRelationProvider = postsAdminController{}
|
||||
|
||||
var _ pact.AdminController = categoriesAdminController{}
|
||||
var _ pact.AdminPermissioned = categoriesAdminController{}
|
||||
var _ pact.AdminRecordSource = categoriesAdminController{}
|
||||
var _ cabana.FieldRelationProvider = categoriesAdminController{}
|
||||
|
||||
var _ pact.AdminController = tagsAdminController{}
|
||||
var _ pact.AdminPermissioned = tagsAdminController{}
|
||||
var _ pact.AdminRecordSource = tagsAdminController{}
|
||||
}
|
||||
|
||||
48
controllers/categories.go
Normal file
48
controllers/categories.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"git.golem15.com/golem15/sm-journal-plugin/models"
|
||||
"git.golem15.com/golem15/summercms/modules/backpack"
|
||||
"git.golem15.com/golem15/summercms/modules/cabana"
|
||||
"git.golem15.com/golem15/summercms/modules/pact"
|
||||
)
|
||||
|
||||
const (
|
||||
// CategoriesControllerID is the cabana controller id of the Categories screen.
|
||||
CategoriesControllerID = "golem15.journal.categories"
|
||||
// PermissionAccessCategories is Categories::$requiredPermissions.
|
||||
PermissionAccessCategories = "golem15.journal.access_categories"
|
||||
)
|
||||
|
||||
type categoriesAdminController struct {
|
||||
app func() *backpack.App
|
||||
}
|
||||
|
||||
func (categoriesAdminController) ID() string { return CategoriesControllerID }
|
||||
|
||||
func (categoriesAdminController) ModelName() string { return `Golem15\Journal\Models\Category` }
|
||||
|
||||
func (categoriesAdminController) ConfigDir() string { return "controllers/categories" }
|
||||
|
||||
func (categoriesAdminController) RequiredPermissions() []string {
|
||||
return []string{PermissionAccessCategories}
|
||||
}
|
||||
|
||||
func (categoriesAdminController) NewRecord() any { return &models.Category{} }
|
||||
|
||||
func (categoriesAdminController) AdminFieldRelations() []cabana.FieldRelationContract {
|
||||
return []cabana.FieldRelationContract{{
|
||||
Field: "parent",
|
||||
Kind: "belongsTo",
|
||||
NewRelated: func() any { return &models.Category{} },
|
||||
ForeignKey: "parent_id",
|
||||
LabelColumn: "name",
|
||||
}}
|
||||
}
|
||||
|
||||
var (
|
||||
_ pact.AdminController = categoriesAdminController{}
|
||||
_ pact.AdminPermissioned = categoriesAdminController{}
|
||||
_ pact.AdminRecordSource = categoriesAdminController{}
|
||||
_ cabana.FieldRelationProvider = categoriesAdminController{}
|
||||
)
|
||||
19
controllers/categories/config_form.yaml
Normal file
19
controllers/categories/config_form.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
name: golem15.journal::lang.journal.create_category
|
||||
form: ~/plugins/golem15/journal/models/category/fields.yaml
|
||||
modelClass: Golem15\Journal\Models\Category
|
||||
defaultRedirect: golem15/journal/categories
|
||||
|
||||
create:
|
||||
redirect: golem15/journal/categories/update/:id
|
||||
redirectClose: golem15/journal/categories
|
||||
|
||||
update:
|
||||
redirect: golem15/journal/categories
|
||||
redirectClose: golem15/journal/categories
|
||||
|
||||
messages:
|
||||
create: golem15.journal::lang.journal.create_category
|
||||
update: backend::lang.messages.form.update
|
||||
saved: backend::lang.messages.form.saved
|
||||
deleteConfirm: golem15.journal::lang.category.delete_confirm
|
||||
deleted: backend::lang.messages.form.deleted
|
||||
19
controllers/categories/config_list.yaml
Normal file
19
controllers/categories/config_list.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
list: ~/plugins/golem15/journal/models/category/columns.yaml
|
||||
modelClass: Golem15\Journal\Models\Category
|
||||
title: golem15.journal::lang.category.label_plural
|
||||
recordUrl: golem15/journal/categories/update/:id
|
||||
noRecordsMessage: backend::lang.list.no_records
|
||||
recordsPerPage: 20
|
||||
showCheckboxes: true
|
||||
showSetup: true
|
||||
|
||||
toolbar:
|
||||
buttons: [create, delete]
|
||||
search:
|
||||
prompt: backend::lang.list.search_prompt
|
||||
|
||||
messages:
|
||||
create: golem15.journal::lang.journal.create_category
|
||||
empty: backend::lang.list.no_records
|
||||
deleteConfirm: golem15.journal::lang.category.delete_confirm
|
||||
deleted: backend::lang.messages.list.deleted
|
||||
@@ -174,9 +174,28 @@ func (c postsAdminController) FormBeforeUpdate(ctx context.Context, model any) e
|
||||
if !ok || post == nil {
|
||||
return errors.New("posts admin: form model is not a post")
|
||||
}
|
||||
if err := refuseOtherAuthor(ctx, post); err != nil {
|
||||
return err
|
||||
}
|
||||
return preparePostWrite(ctx, post)
|
||||
}
|
||||
|
||||
func (c postsAdminController) FormBeforeDelete(ctx context.Context, model any) error {
|
||||
post, ok := model.(*models.Post)
|
||||
if !ok || post == nil {
|
||||
return errors.New("posts admin: form model is not a post")
|
||||
}
|
||||
return refuseOtherAuthor(ctx, post)
|
||||
}
|
||||
|
||||
func refuseOtherAuthor(ctx context.Context, post *models.Post) error {
|
||||
principal, _ := bouncer.User(ctx)
|
||||
if post.CanEdit(principal) {
|
||||
return nil
|
||||
}
|
||||
return &cabana.ForbiddenError{Message: "golem15.journal::lang.journal.access_other_posts"}
|
||||
}
|
||||
|
||||
func preparePostWrite(ctx context.Context, post *models.Post) error {
|
||||
if err := refuseUnpublishedWrite(ctx, post); err != nil {
|
||||
return err
|
||||
|
||||
36
controllers/tags.go
Normal file
36
controllers/tags.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"git.golem15.com/golem15/sm-journal-plugin/models"
|
||||
"git.golem15.com/golem15/summercms/modules/backpack"
|
||||
"git.golem15.com/golem15/summercms/modules/pact"
|
||||
)
|
||||
|
||||
const (
|
||||
// TagsControllerID is the cabana controller id of the Tags screen.
|
||||
TagsControllerID = "golem15.journal.tags"
|
||||
// PermissionAccessTags is Tags::$requiredPermissions.
|
||||
PermissionAccessTags = "golem15.journal.access_tags"
|
||||
)
|
||||
|
||||
type tagsAdminController struct {
|
||||
app func() *backpack.App
|
||||
}
|
||||
|
||||
func (tagsAdminController) ID() string { return TagsControllerID }
|
||||
|
||||
func (tagsAdminController) ModelName() string { return `Golem15\Journal\Models\Tag` }
|
||||
|
||||
func (tagsAdminController) ConfigDir() string { return "controllers/tags" }
|
||||
|
||||
func (tagsAdminController) RequiredPermissions() []string {
|
||||
return []string{PermissionAccessTags}
|
||||
}
|
||||
|
||||
func (tagsAdminController) NewRecord() any { return &models.Tag{} }
|
||||
|
||||
var (
|
||||
_ pact.AdminController = tagsAdminController{}
|
||||
_ pact.AdminPermissioned = tagsAdminController{}
|
||||
_ pact.AdminRecordSource = tagsAdminController{}
|
||||
)
|
||||
19
controllers/tags/config_form.yaml
Normal file
19
controllers/tags/config_form.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
name: golem15.journal::lang.journal.create_tag
|
||||
form: ~/plugins/golem15/journal/models/tag/fields.yaml
|
||||
modelClass: Golem15\Journal\Models\Tag
|
||||
defaultRedirect: golem15/journal/tags
|
||||
|
||||
create:
|
||||
redirect: golem15/journal/tags/update/:id
|
||||
redirectClose: golem15/journal/tags
|
||||
|
||||
update:
|
||||
redirect: golem15/journal/tags
|
||||
redirectClose: golem15/journal/tags
|
||||
|
||||
messages:
|
||||
create: golem15.journal::lang.journal.create_tag
|
||||
update: backend::lang.messages.form.update
|
||||
saved: backend::lang.messages.form.saved
|
||||
deleteConfirm: golem15.journal::lang.tag.delete_confirm
|
||||
deleted: backend::lang.messages.form.deleted
|
||||
19
controllers/tags/config_list.yaml
Normal file
19
controllers/tags/config_list.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
list: ~/plugins/golem15/journal/models/tag/columns.yaml
|
||||
modelClass: Golem15\Journal\Models\Tag
|
||||
title: golem15.journal::lang.tag.label_plural
|
||||
recordUrl: golem15/journal/tags/update/:id
|
||||
noRecordsMessage: backend::lang.list.no_records
|
||||
recordsPerPage: 20
|
||||
showCheckboxes: true
|
||||
showSetup: true
|
||||
|
||||
toolbar:
|
||||
buttons: [create, delete]
|
||||
search:
|
||||
prompt: backend::lang.list.search_prompt
|
||||
|
||||
messages:
|
||||
create: golem15.journal::lang.journal.create_tag
|
||||
empty: backend::lang.list.no_records
|
||||
deleteConfirm: golem15.journal::lang.tag.delete_confirm
|
||||
deleted: backend::lang.messages.list.deleted
|
||||
Reference in New Issue
Block a user