package models import ( "database/sql" "errors" "net/http" "strconv" "strings" "brainminder.speedtech.it/internal/database" "brainminder.speedtech.it/internal/funcs" ) type TypeModel struct { DB *database.DB } type Type struct { Id int64 `db:"id"` Title string `db:"title"` Icon string `db:"icon"` Description string `db:"description"` Notebooks string `db:"notebooks"` Show_summary int `db:"show_summary"` Show_description int `db:"show_description"` Sections string `db:"sections"` } func (model *TypeModel) One(id int64) (*Type, bool, error) { ctx, cancel := database.GetContext() defer cancel() var row Type query := `SELECT * FROM bm_type WHERE id = $1` err := model.DB.GetContext(ctx, &row, query, id) if errors.Is(err, sql.ErrNoRows) { return nil, false, nil } return &row, true, err } func (model *TypeModel) Find(criteria map[string]any) ([]Type, bool, error) { ctx, cancel := database.GetContext() defer cancel() var params []interface{} var conditions []string var cond string query := "SELECT DISTINCT bmt.* FROM bm_type bmt " for field, value := range criteria { switch field { case "Title": valstr := value.(string) if len(valstr) > 0 { params = append(params, valstr) conditions = append(conditions, "bmt.title LIKE '%' || ? || '%'") } case "notebook_id": if value != nil { valint := value.(int64) if valint > 0 { valstr := "|" + strconv.FormatInt(valint, 10) + "|" params = append(params, valstr) conditions = append(conditions, "INSTR(notebooks, ?) > 0") } } } } for _, condition := range conditions { if len(cond) > 0 { cond = cond + " AND " } cond = cond + condition } if len(cond) > 0 { query = query + "WHERE " + cond + " " } query = query + `ORDER BY bmt.title` var rows []Type err := model.DB.SelectContext(ctx, &rows, query, params...) if errors.Is(err, sql.ErrNoRows) { return nil, false, nil } return rows, true, err } func (model *TypeModel) FindAsOptions(criteria map[string]any) []funcs.WidgetOption { Types, _, _ := model.Find(criteria) var selectOptions []funcs.WidgetOption for _, Type := range Types { selectOptions = append(selectOptions, funcs.WidgetOption{Key: strconv.FormatInt(Type.Id, 10), Value: Type.Title}) } return selectOptions } func (model *TypeModel) Delete(id int) (bool, error) { ctx, cancel := database.GetContext() defer cancel() query := `DELETE FROM bm_type WHERE id = $1` _, err := model.DB.ExecContext(ctx, query, id) if errors.Is(err, sql.ErrNoRows) { return false, nil } return true, err } func (model *TypeModel) Create(Type *Type) (int64, error) { ctx, cancel := database.GetContext() defer cancel() query := `INSERT INTO bm_type (title, icon, description, notebooks, sections, show_summary, show_description) VALUES (:title, :icon, :description, :notebooks, :sections, :show_summary, :show_description)` result, err := model.DB.NamedExecContext(ctx, query, Type) if err != nil { return 0, err } id, err := result.LastInsertId() if err != nil { return 0, err } return id, err } func (model *TypeModel) Update(Type *Type) error { ctx, cancel := database.GetContext() defer cancel() query := `UPDATE bm_type SET title=:title, icon=:icon, description=:description, notebooks=:notebooks, sections=:sections, show_summary=:show_summary, show_description=:show_description WHERE id = :id` _, err := model.DB.NamedExecContext(ctx, query, Type) return err } func (model *TypeModel) SaveField(type_field_id int64, field *Field) error { ctx, cancel := database.GetContext() defer cancel() query := `UPDATE bm_type_fields SET widget_id=:widget_id, title=:title, position=:position, valid_values=:valid_values, show_on_list=:show_on_list, show_on_view=:show_on_view, ui_section=:ui_section, is_multiple=:is_multiple WHERE id =:type_field_id` _, err := model.DB.NamedExecContext(ctx, query, field) return err } func (model *TypeModel) RemoveField(type_field_id int64) error { ctx, cancel := database.GetContext() defer cancel() //Check here if it is used query := "DELETE FROM bm_type_fields WHERE id=$1" _, err := model.DB.ExecContext(ctx, query, type_field_id) return err } func (model *TypeModel) AddField(bmField *Field) error { ctx, cancel := database.GetContext() defer cancel() query := `INSERT INTO bm_type_fields (type_id, widget_id, title, position, valid_values, show_on_list, show_on_view, ui_section, is_multiple) VALUES (:type_id, :widget_id, :title, :position, :valid_values, :show_on_list, :show_on_view, :ui_section, :is_multiple)` _, err := model.DB.NamedExecContext(ctx, query, bmField) return err } func (model *TypeModel) AddFields(TypeId int64, r *http.Request) { fieldsNew := make(map[int64]Field) for name, values := range r.PostForm { s, found := strings.CutPrefix(name, "Fields-New-") if found { parts := strings.Split(s, "-") if len(parts) == 2 { counter, _ := strconv.ParseInt(parts[0], 10, 64) type_field_attribute := parts[1] field, found := fieldsNew[counter] if !found { field := &Field{Type_id: TypeId} fieldsNew[counter] = *field } field = fieldsNew[counter] switch type_field_attribute { case "Widget_id": field.Widget_id, _ = strconv.ParseInt(values[0], 10, 64) case "Title": field.Title = values[0] case "Valid_values": field.Valid_values = values[0] case "Ui_section": field.Ui_section = values[0] case "Is_multiple": field.Is_multiple, _ = strconv.ParseInt(values[0], 10, 64) case "Show_on_list": field.Show_on_list, _ = strconv.ParseInt(values[0], 10, 64) case "Show_on_view": field.Show_on_view, _ = strconv.ParseInt(values[0], 10, 64) } fieldsNew[counter] = field } } } for _, field := range fieldsNew { if len(field.Title) > 0 { model.AddField(&field) } } }