package cabana_test import ( "context" "errors" "git.golem15.com/golem15/summercms/modules/cabana" "git.golem15.com/golem15/summercms/modules/pact" ) // Person is the model behind the acme.roster people controller. type Person struct { ID uint `gorm:"column:id;primaryKey"` Name string `gorm:"column:name"` Email string `gorm:"column:email"` Active bool `gorm:"column:active"` Banned bool `gorm:"column:banned"` } func (Person) TableName() string { return "acme_roster_people" } // Fillable lists the columns the admin form may write. func (Person) Fillable() []string { return []string{"name", "email"} } // PeopleController is an admin controller with bulk and record actions. type PeopleController struct{} var ( _ pact.AdminController = PeopleController{} _ pact.AdminRecordSource = PeopleController{} _ pact.HasAdminBulkActions = PeopleController{} _ pact.HasAdminRecordActions = PeopleController{} ) func (PeopleController) ID() string { return "acme.roster.people" } func (PeopleController) ModelName() string { return "Person" } func (PeopleController) ConfigDir() string { return "controllers/people" } func (PeopleController) NewRecord() any { return &Person{} } func (PeopleController) RequiredPermissions() []string { return []string{"acme.roster.access"} } // AdminBulkActions registers the actions config_list.yaml offers under // bulkActions. Run receives the selected records, already loaded and locked // through the list scope, and writes through the request's transaction. func (PeopleController) AdminBulkActions() []pact.AdminBulkAction { return []pact.AdminBulkAction{{ Name: "activate", Label: "acme.roster::lang.people.activate", Confirm: "acme.roster::lang.people.activate_confirm", Permissions: []string{"acme.roster.manage"}, Run: func(ctx context.Context, in pact.AdminBulkActionInput) (pact.AdminBulkActionResult, error) { tx, ok := cabana.TxFromContext(ctx) if !ok { return pact.AdminBulkActionResult{}, errors.New("no transaction") } changed := 0 for _, record := range in.Records { person := record.(*Person) if person.Active { continue } if err := tx.Model(person).Update("active", true).Error; err != nil { return pact.AdminBulkActionResult{}, err } changed++ } return pact.AdminBulkActionResult{Affected: changed}, nil }, }, { Name: "archive", Label: "acme.roster::lang.people.archive", Run: func(ctx context.Context, in pact.AdminBulkActionInput) (pact.AdminBulkActionResult, error) { tx, ok := cabana.TxFromContext(ctx) if !ok { return pact.AdminBulkActionResult{}, errors.New("no transaction") } for _, record := range in.Records { if err := tx.Delete(record).Error; err != nil { return pact.AdminBulkActionResult{}, err } } return pact.AdminBulkActionResult{ Message: "acme.roster::lang.people.archived", Affected: len(in.Records), }, nil }, }} } // AdminRecordActions registers the actions config_form.yaml offers under // recordActions. Applies decides whether an action fits the record's current // state; Run receives the record loaded and locked through the form scope. func (PeopleController) AdminRecordActions() []pact.AdminRecordAction { return []pact.AdminRecordAction{{ Name: "activate", Label: "acme.roster::lang.people.activate", Permissions: []string{"acme.roster.manage"}, Applies: func(_ context.Context, record any) (bool, error) { return !record.(*Person).Active, nil }, Run: func(ctx context.Context, in pact.AdminRecordActionInput) (pact.AdminRecordActionResult, error) { tx, ok := cabana.TxFromContext(ctx) if !ok { return pact.AdminRecordActionResult{}, errors.New("no transaction") } if err := tx.Model(in.Record).Update("active", true).Error; err != nil { return pact.AdminRecordActionResult{}, err } return pact.AdminRecordActionResult{Message: "acme.roster::lang.people.activated"}, nil }, }, { Name: "reinstate", Label: "acme.roster::lang.people.reinstate", Confirm: "acme.roster::lang.people.reinstate_confirm", Applies: func(_ context.Context, record any) (bool, error) { return record.(*Person).Banned, nil }, Run: func(ctx context.Context, in pact.AdminRecordActionInput) (pact.AdminRecordActionResult, error) { tx, ok := cabana.TxFromContext(ctx) if !ok { return pact.AdminRecordActionResult{}, errors.New("no transaction") } if err := tx.Model(in.Record).Update("banned", false).Error; err != nil { return pact.AdminRecordActionResult{}, err } return pact.AdminRecordActionResult{}, nil }, }} }