package quizzes import ( "context" "embed" "io/fs" "git.golem15.com/golem15/sm-quizzes-plugin/console" "git.golem15.com/golem15/sm-quizzes-plugin/models" "git.golem15.com/golem15/summercms/modules/backpack" "git.golem15.com/golem15/summercms/modules/bonfire" "git.golem15.com/golem15/summercms/modules/lagoon" "git.golem15.com/golem15/summercms/modules/pact" "git.golem15.com/golem15/summercms/modules/party" "github.com/go-gormigrate/gormigrate/v2" "gorm.io/gorm" ) var ( _ pact.HasConfig = (*Plugin)(nil) _ pact.HasLang = (*Plugin)(nil) _ pact.HasMailTemplates = (*Plugin)(nil) _ pact.HasModels = (*Plugin)(nil) _ pact.HasMigrations = (*Plugin)(nil) _ pact.HasCommands = (*Plugin)(nil) _ pact.HasJobs = (*Plugin)(nil) _ pact.HasAdminControllers = (*Plugin)(nil) _ pact.AdminAssets = (*Plugin)(nil) _ pact.HasPermissions = (*Plugin)(nil) _ pact.HasNavigation = (*Plugin)(nil) ) //go:embed config var configFS embed.FS //go:embed lang var langFS embed.FS //go:embed views/mail var mailFS embed.FS //go:embed controllers/*/*.yaml models/*/*.yaml var adminFS embed.FS // Plugin is the golem15.quizzes plugin. type Plugin struct { app *backpack.App } func (p *Plugin) ID() string { return "golem15.quizzes" } // Requires golem15.user: the API runs behind its jwt.auth middleware and // attempts reference its users table. func (p *Plugin) Requires() []string { return []string{"golem15.user"} } // Register keeps the application, so route handlers and commands can reach // its services, such as the database, when they run. func (p *Plugin) Register(app *backpack.App) error { p.app = app return nil } // Boot keeps the application and points the admin filter choices at its // database. func (p *Plugin) Boot(app *backpack.App) error { p.app = app models.FilterDB = func() *gorm.DB { if app == nil { return nil } gdb, _ := app.Lookup[*gorm.DB]() return gdb } return nil } func (p *Plugin) ConfigFS() fs.FS { return configFS } func (p *Plugin) LangFS() fs.FS { return langFS } func (p *Plugin) MailTemplatesFS() fs.FS { return mailFS } func (p *Plugin) MailTemplates() []string { return nil } func (p *Plugin) MailLayouts() map[string]string { return nil } func (p *Plugin) Models() []any { return generatedModels() } func (p *Plugin) Migrations() []*gormigrate.Migration { return generatedMigrations() } func (p *Plugin) Jobs() []pact.Job { return generatedJobs() } func (p *Plugin) AdminControllers() []pact.AdminController { return generatedAdminControllers() } // Commands returns the generated commands plus quizzes:import, which needs // the database and so is built here with the plugin's withDB. func (p *Plugin) Commands() []bonfire.Command { return append(generatedCommands(), console.ImportCommand(p.withDB)) } // withDB runs fn with the application's database: the one the serve command // published, or, when a console command runs, one opened from the config for // the duration of fn. func (p *Plugin) withDB(ctx context.Context, fn func(*gorm.DB) error) error { if gdb, ok := p.app.Lookup[*gorm.DB](); ok && gdb != nil { return fn(gdb) } sqlDB, gdb, err := lagoon.OpenFromApp(ctx, p.app) if err != nil { return err } defer sqlDB.Close() return fn(gdb) } // AdminFS is the admin YAML the controllers read. func (p *Plugin) AdminFS() fs.FS { return adminFS } // Permissions declares the admin permissions. func (p *Plugin) Permissions() []pact.Permission { return []pact.Permission{ {Code: "golem15.quizzes.access_quizzes", Tab: "golem15.quizzes::lang.plugin.name", Label: "golem15.quizzes::lang.permissions.access_quizzes"}, {Code: "golem15.quizzes.access_attempts", Tab: "golem15.quizzes::lang.plugin.name", Label: "golem15.quizzes::lang.permissions.access_attempts"}, } } // Navigation declares the "Quizzes" admin menu with its side menu. func (p *Plugin) Navigation() []pact.NavigationItem { return []pact.NavigationItem{{ Code: "quizzes", Label: "golem15.quizzes::lang.plugin.name", Icon: "icon-question-circle", Permissions: []string{"golem15.quizzes.access_quizzes", "golem15.quizzes.access_attempts"}, Controller: "golem15.quizzes.quizzes", SideMenu: []pact.NavigationItem{ {Code: "quizzes", Label: "golem15.quizzes::lang.quizzes.title", Icon: "icon-list", Controller: "golem15.quizzes.quizzes", Permissions: []string{"golem15.quizzes.access_quizzes"}}, {Code: "questions", Label: "golem15.quizzes::lang.questions.title", Icon: "icon-question", Controller: "golem15.quizzes.questions", Permissions: []string{"golem15.quizzes.access_quizzes"}}, {Code: "answers", Label: "golem15.quizzes::lang.answers.title", Icon: "icon-check-square", Controller: "golem15.quizzes.answers", Permissions: []string{"golem15.quizzes.access_quizzes"}}, {Code: "attempts", Label: "golem15.quizzes::lang.attempts.title", Icon: "icon-bar-chart", Controller: "golem15.quizzes.attempts", Permissions: []string{"golem15.quizzes.access_attempts"}}, }, }} } func init() { party.Register(&Plugin{}) }