232 lines
5.8 KiB
Go
232 lines
5.8 KiB
Go
|
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)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|