Files
sm-quizzes-plugin/models/question.go

147 lines
4.1 KiB
Go

// Code generated by summer make. DO NOT EDIT.
package models
import (
"time"
"git.golem15.com/golem15/summercms/modules/pact"
"gorm.io/gorm"
)
// Question types.
const (
TypeSingle = "single"
TypeMultiple = "multiple"
TypeSelfCheck = "self_check"
)
// QuestionTypes lists the valid values of Question.Type.
var QuestionTypes = []string{TypeSingle, TypeMultiple, TypeSelfCheck}
// Question is one question of a quiz. A self_check question is a flashcard:
// the user reveals AnswerText and marks whether they knew it.
type Question struct {
ID uint `gorm:"column:id;primaryKey"`
QuizID uint `gorm:"column:quiz_id"`
Text string `gorm:"column:text"`
Type string `gorm:"column:type"`
Category *string `gorm:"column:category"`
AnswerText *string `gorm:"column:answer_text"`
Explanation *string `gorm:"column:explanation"`
SortOrder int `gorm:"column:sort_order"`
Points int `gorm:"column:points"`
CreatedAt time.Time `gorm:"column:created_at"`
UpdatedAt time.Time `gorm:"column:updated_at"`
Quiz *Quiz `gorm:"foreignKey:QuizID"`
Answers []Answer `gorm:"foreignKey:QuestionID"`
}
// TableName is the plugin-prefixed table.
func (Question) TableName() string { return "golem15_quizzes_questions" }
// Fillable lists the columns mass assignment may set.
func (Question) Fillable() []string {
return []string{"quiz_id", "text", "type", "category", "answer_text", "explanation", "sort_order", "points"}
}
// Rules are checked by the admin API on every save.
func (Question) Rules() map[string]string {
return map[string]string{
"quiz_id": "required|integer|min:1",
"text": "required",
"type": "required|in:single,multiple,self_check",
"category": "nullable|max:255",
"sort_order": "nullable|integer",
"points": "required|integer|min:0",
}
}
// FilterDB returns the database the admin filter choices are read from. The
// plugin sets it at boot.
//
// TODO: requires SummerCMS change. pact.FilterOptions receives neither a
// context nor a database handle, so a model whose filter choices come from
// the database needs this package-level hook.
var FilterDB func() *gorm.DB
// Filter scopes of the questions admin list.
const (
ScopeByQuiz = "filterByQuiz"
ScopeByCategory = "filterByCategory"
)
// FilterScopes lists the admin list scopes the model answers.
func (Question) FilterScopes() []string { return []string{ScopeByQuiz, ScopeByCategory} }
// FilterScope narrows the admin list to the chosen quizzes or categories.
func (Question) FilterScope(name string, db *gorm.DB, value any) *gorm.DB {
if db == nil {
return db
}
values := filterValues(value)
if len(values) == 0 {
return db
}
switch name {
case ScopeByQuiz:
return db.Where("golem15_quizzes_questions.quiz_id IN ?", values)
case ScopeByCategory:
return db.Where("golem15_quizzes_questions.category IN ?", values)
}
return db
}
// FilterOptions serves the quizzes and the distinct categories as choices.
func (Question) FilterOptions(scope string) []pact.Option {
if FilterDB == nil {
return nil
}
db := FilterDB()
if db == nil {
return nil
}
var out []pact.Option
switch scope {
case ScopeByQuiz:
var quizzes []Quiz
if err := db.Select("id", "title").Order("title").Find(&quizzes).Error; err != nil {
return nil
}
for _, q := range quizzes {
out = append(out, pact.Option{Value: uintString(q.ID), Label: q.Title})
}
case ScopeByCategory:
var cats []string
if err := db.Model(&Question{}).Where("category IS NOT NULL AND category <> ''").
Distinct("category").Order("category").Pluck("category", &cats).Error; err != nil {
return nil
}
for _, c := range cats {
out = append(out, pact.Option{Value: c, Label: c})
}
}
return out
}
func filterValues(value any) []string {
switch v := value.(type) {
case string:
if v == "" {
return nil
}
return []string{v}
case []string:
return v
case []any:
out := make([]string, 0, len(v))
for _, x := range v {
if s, ok := x.(string); ok && s != "" {
out = append(out, s)
}
}
return out
}
return nil
}