package web import ( "context" "net/http" "github.com/yourusername/caldav-server/internal/db" "github.com/yourusername/caldav-server/internal/web/templates" ) func (s *Server) handleDashboard(w http.ResponseWriter, r *http.Request) { username := userFromContext(r.Context()) user, ok := s.cfg.Users[username] if !ok { http.Error(w, "user not found in configuration", http.StatusInternalServerError) return } var resources []templates.ResourceCard for _, calName := range user.Calendars { card := templates.ResourceCard{Kind: "calendar", Name: calName} if s.dbase != nil { shares, err := s.dbase.SharesOfCalendar(username, calName) if err != nil { s.logger.Warn("listing calendar shares", "error", err) } for _, sh := range shares { card.Shares = append(card.Shares, templates.ShareRow{ ResourceName: calName, SharedWith: sh.SharedWith, Permission: string(sh.Permission), }) } } resources = append(resources, card) } for _, bookName := range user.AddressBooks { card := templates.ResourceCard{Kind: "addressbook", Name: bookName} if s.dbase != nil { shares, err := s.dbase.SharesOfAddressBook(username, bookName) if err != nil { s.logger.Warn("listing address book shares", "error", err) } for _, sh := range shares { card.Shares = append(card.Shares, templates.ShareRow{ ResourceName: bookName, SharedWith: sh.SharedWith, Permission: string(sh.Permission), }) } } resources = append(resources, card) } var sharedWithMe []templates.SharedWithMeItem if s.dbase != nil { calShares, err := s.dbase.CalendarsSharedWith(username) if err != nil { s.logger.Warn("listing calendars shared with user", "error", err) } for _, sh := range calShares { sharedWithMe = append(sharedWithMe, templates.SharedWithMeItem{ Kind: "calendar", Owner: sh.Owner, Name: sh.CalendarName, Permission: string(sh.Permission), }) } bookShares, err := s.dbase.AddressBooksSharedWith(username) if err != nil { s.logger.Warn("listing address books shared with user", "error", err) } for _, sh := range bookShares { sharedWithMe = append(sharedWithMe, templates.SharedWithMeItem{ Kind: "addressbook", Owner: sh.Owner, Name: sh.AddressBookName, Permission: string(sh.Permission), }) } } w.Header().Set("Content-Type", "text/html; charset=utf-8") _ = templates.Dashboard(username, resources, sharedWithMe).Render(context.Background(), w) } // resourceCardFor rebuilds a single ResourceCard (used to re-render just // the card an htmx request just changed, for partial updates). func (s *Server) resourceCardFor(username, kind, name string) (templates.ResourceCard, error) { card := templates.ResourceCard{Kind: kind, Name: name} if s.dbase == nil { return card, nil } var shares []templates.ShareRow if kind == "calendar" { rows, err := s.dbase.SharesOfCalendar(username, name) if err != nil { return card, err } for _, sh := range rows { shares = append(shares, templates.ShareRow{ResourceName: name, SharedWith: sh.SharedWith, Permission: string(sh.Permission)}) } } else { rows, err := s.dbase.SharesOfAddressBook(username, name) if err != nil { return card, err } for _, sh := range rows { shares = append(shares, templates.ShareRow{ResourceName: name, SharedWith: sh.SharedWith, Permission: string(sh.Permission)}) } } card.Shares = shares return card, nil } func isValidPermission(p string) (db.Permission, bool) { switch db.Permission(p) { case db.PermRead, db.PermWrite: return db.Permission(p), true } return "", false }