package lists import ( "database/sql" "errors" "fagott.pw/charakterin" "fagott.pw/grilist/frontend" "fagott.pw/grilist/grilist" "fagott.pw/grilist/modules/grils" "fmt" "github.com/julienschmidt/httprouter" "log" "net/http" "strconv" "time" ) // Module und so. type Module struct { g *grilist.Grilist grils *grils.GrilsModule } // List ist eine Liste an DINGEN. type List struct { ID int Name string Description string Owner *charakterin.User ForkOf *int UpdatedAt *time.Time Grils []*ListGril } // ListGril ist ein geranktes Gril type ListGril struct { Gril *grils.Gril Order int } // Name gibt den Namen des Moduls zurück func (m *Module) Name() string { return "Lists" } // Init initialisiert das Modul func (m *Module) Init(g *grilist.Grilist) { m.g = g gm, ok := g.Modules["Grils"] if !ok { log.Fatal("lists: grils module not found") } grilsModule, ok := gm.Interface().(*grils.GrilsModule) if !ok { log.Fatal("lists: error with grils module") } m.grils = grilsModule m.g.Router.GET("/list/:id", m.viewList) } // Interface gibt das Modul zurück func (m *Module) Interface() interface{} { return m } func (m *Module) getListGrils(list *List) error { rows, err := m.g.DB.Query(`SELECT gril_id, "order" FROM grilist.lists_grils WHERE list_id = $1`, list.ID) if err != nil { return err } defer rows.Close() for rows.Next() { var grilID int lg := &ListGril{} if err := rows.Scan(&grilID, &lg.Order); err != nil { log.Println("error scanning row in getListGrils:", err) continue } gril, err := m.grils.FromID(grilID) if err != nil { log.Println("error getting listGril:", err) continue } lg.Gril = gril list.Grils = append(list.Grils, lg) } return nil } func (m *Module) getLists(whereClause string, params ...interface{}) ([]*List, error) { var lists []*List rows, err := m.g.DB.Query(fmt.Sprintf(`SELECT id, name, description, fork_of, updated_at FROM grilist.lists WHERE %s`, whereClause), params...) if err != nil { return nil, err } defer rows.Close() for rows.Next() { list := &List{} if err := rows.Scan(&list.ID, &list.Name, &list.Description, &list.ForkOf, &list.UpdatedAt); err != nil { log.Println("error scanning row in getLists:", err) continue } if err := m.getListGrils(list); err != nil { log.Println(err) continue } lists = append(lists, list) } return lists, nil } // GetUserLists gibt die Listen eines Benutzers zurück. func (m *Module) GetUserLists(u *charakterin.User) []*List { lists, err := m.getLists(`user_id = $1`, u.ID) if err != nil { log.Println(err) } return lists } // FromID sucht nach der Liste mit der gegebenen ID und gibt sie, falls sie existiert, zurück. func (m *Module) FromID(id int) (*List, error) { lists, err := m.getLists(`id = $1`, id) if err != nil { return nil, err } if len(lists) == 0 { return nil, errors.New("no list found") } return lists[0], nil } func mkCard(title, description string, actions ...frontend.Action) frontend.Card { card := frontend.Card{ Title: title, Description: description, Size: "medium", } for _, action := range actions { card.Actions = append(card.Actions, action) } return card } func rowsToCard(rows *sql.Rows) []frontend.Card { var cards []frontend.Card for rows.Next() { var id int var title, description string if err := rows.Scan(&id, &title, &description); err != nil { log.Println("error scanning row", err) continue } cards = append(cards, mkCard(title, description, frontend.Action{"anguckieren", fmt.Sprintf("/list/%d", id)})) } return cards } // ProvideDashboardData gibt Daten für das Dashboard bezogen auf den Benutzer zurück func (m *Module) ProvideDashboardData(user *charakterin.User) []grilist.DashboardCategory { var categories []grilist.DashboardCategory // Listen des Benutzers rows, err := m.g.DB.Query(`SELECT id, name, description FROM grilist.lists WHERE user_id = $1`, user.ID) if err != nil { log.Println(err) return []grilist.DashboardCategory{} } defer rows.Close() categories = append(categories, grilist.DashboardCategory{ Title: "Meine Listen", Cards: rowsToCard(rows), }) // Neue Listen rows, err = m.g.DB.Query(`SELECT id, name, description FROM grilist.lists ORDER BY id DESC LIMIT 5`) if err != nil { log.Println(err) return categories } defer rows.Close() categories = append(categories, grilist.DashboardCategory{ Title: "Neueste Listen", Cards: rowsToCard(rows), }) return categories } func (m *Module) viewList(w http.ResponseWriter, r *http.Request, p httprouter.Params) { loggedIn := false if user, _ := m.g.Charakterin.GetUserFromRequest(r); user != nil { loggedIn = true } sid := p.ByName("id") id, err := strconv.Atoi(sid) if err != nil { http.Redirect(w, r, "/", 302) return } list, err := m.FromID(id) if err != nil { http.Redirect(w, r, "/", 302) return } data := make(map[string]interface{}) data["loggedIn"] = loggedIn data["list"] = list m.g.Renderer.RenderPage("list", w, data) } // New erstellt eine neue Instanz des Modules func New() *Module { return &Module{} }