diff --git a/common/conversations.go b/common/conversations.go index 9aa13350..908a0f7a 100644 --- a/common/conversations.go +++ b/common/conversations.go @@ -54,6 +54,7 @@ func init() { type Conversation struct { ID int + Link string CreatedBy int CreatedAt time.Time LastReplyBy int @@ -133,6 +134,10 @@ func (co *Conversation) Create() (int, error) { return int(lastID), err } +func BuildConvoURL(coid int) string { + return "/user/convo/" + strconv.Itoa(coid) +} + type ConversationExtra struct { *Conversation Users []*User @@ -141,7 +146,7 @@ type ConversationExtra struct { type ConversationStore interface { Get(id int) (*Conversation, error) GetUser(uid, offset int) (cos []*Conversation, err error) - GetUserExtra(uid int, offset int) (cos []*ConversationExtra, err error) + GetUserExtra(uid, offset int) (cos []*ConversationExtra, err error) GetUserCount(uid int) (count int) Delete(id int) error Count() (count int) @@ -330,7 +335,7 @@ func (s *DefaultConversationStore) Create(content string, createdBy int, partici if len(participants) == 0 { return 0, errors.New("no participants set") } - res, err := s.create.Exec(createdBy,createdBy) + res, err := s.create.Exec(createdBy, createdBy) if err != nil { return 0, err } @@ -346,6 +351,9 @@ func (s *DefaultConversationStore) Create(content string, createdBy int, partici } for _, p := range participants { + if p == createdBy { + continue + } _, err := s.addParticipant.Exec(p, lastID) if err != nil { return 0, err diff --git a/common/pages.go b/common/pages.go index d9fde7a3..c60c9929 100644 --- a/common/pages.go +++ b/common/pages.go @@ -283,9 +283,15 @@ type ResetPage struct { MFA bool } +type ConvoListRow struct { + *ConversationExtra + ShortUsers []*User + OneOnOne bool +} + type ConvoListPage struct { *Header - Convos []*ConversationExtra + Convos []ConvoListRow Paginator } diff --git a/common/template_init.go b/common/template_init.go index 46418ffb..ef6ca731 100644 --- a/common/template_init.go +++ b/common/template_init.go @@ -350,13 +350,17 @@ func compileTemplates(wg *sync.WaitGroup, c *tmpl.CTemplateSet, themeName string t.AddStd("account", "c.Account", accountPage) parti := []*User{&user} - convo := &Conversation{1, user.ID, time.Now(), 0, time.Now()} + convo := &Conversation{1, BuildConvoURL(1), user.ID, time.Now(), 0, time.Now()} convoItems := []ConvoViewRow{ConvoViewRow{&ConversationPost{1, 1, "hey", "", user.ID}, &user, "", 4, true}} convoPage := ConvoViewPage{header, convo, convoItems, parti, true, Paginator{[]int{1}, 1, 1}} t.AddStd("convo", "c.ConvoViewPage", convoPage) convos := []*ConversationExtra{&ConversationExtra{&Conversation{}, []*User{&user}}} - convoListPage := ConvoListPage{header, convos, Paginator{[]int{1}, 1, 1}} + var cRows []ConvoListRow + for _, convo := range convos { + cRows = append(cRows, ConvoListRow{convo, convo.Users, false}) + } + convoListPage := ConvoListPage{header, cRows, Paginator{[]int{1}, 1, 1}} t.AddStd("convos", "c.ConvoListPage", convoListPage) basePage := &BasePanelPage{header, PanelStats{}, "dashboard", ReportForumID} @@ -557,7 +561,7 @@ func compileJSTemplates(wg *sync.WaitGroup, c *tmpl.CTemplateSet, themeName stri t.AddStd("topic_c_poll_input", "c.TopicCPollInput", TopicCPollInput{Index: 0}) parti := []*User{&user} - convo := &Conversation{1, user.ID, time.Now(), 0, time.Now()} + convo := &Conversation{1, BuildConvoURL(1), user.ID, time.Now(), 0, time.Now()} convoItems := []ConvoViewRow{ConvoViewRow{&ConversationPost{1, 1, "hey", "", user.ID}, &user, "", 4, true}} convoPage := ConvoViewPage{header, convo, convoItems, parti, true, Paginator{[]int{1}, 1, 1}} t.AddStd("convo", "c.ConvoViewPage", convoPage) diff --git a/routes/convos.go b/routes/convos.go index 11722770..c03dd4d4 100644 --- a/routes/convos.go +++ b/routes/convos.go @@ -30,7 +30,24 @@ func Convos(w http.ResponseWriter, r *http.Request, user c.User, h *c.Header) c. return c.InternalError(err, w, r) } - pi := c.Account{h, "dashboard", "convos", c.ConvoListPage{h, convos, c.Paginator{pageList, page, lastPage}}} + var cRows []c.ConvoListRow + for _, convo := range convos { + var parti []*c.User + notMe := false + for _, u := range convo.Users { + if u.ID == user.ID { + continue + } + parti = append(parti, u) + notMe = true + } + if !notMe { + parti = convo.Users + } + cRows = append(cRows, c.ConvoListRow{convo, parti, len(parti) == 1}) + } + + pi := c.Account{h, "dashboard", "convos", c.ConvoListPage{h, cRows, c.Paginator{pageList, page, lastPage}}} return renderTemplate("account", w, r, h, pi) } @@ -138,16 +155,29 @@ func ConvosCreateSubmit(w http.ResponseWriter, r *http.Request, user c.User) c.R return c.NoPermissions(w, r, user) } - recps := c.SanitiseSingleLine(r.PostFormValue("recp")) + sRecps := c.SanitiseSingleLine(r.PostFormValue("recp")) body := c.PreparseMessage(r.PostFormValue("body")) rlist := []int{} + + // De-dupe recipients + var recps []string + unames := make(map[string]struct{}) + for _, recp := range strings.Split(sRecps, ",") { + recp = strings.TrimSpace(recp) + _, exists := unames[recp] + if !exists { + recps = append(recps, recp) + unames[recp] = struct{}{} + } + } + max := 10 // max number of recipients that can be added at once - for i, recp := range strings.Split(recps, ",") { + for i, recp := range recps { if i >= max { break } - u, err := c.Users.GetByName(strings.TrimSpace(recp)) + u, err := c.Users.GetByName(recp) if err == sql.ErrNoRows { return c.LocalError("One of the recipients doesn't exist", w, r, user) } else if err != nil { diff --git a/templates/convos.html b/templates/convos.html index aefe6297..749cde72 100644 --- a/templates/convos.html +++ b/templates/convos.html @@ -9,7 +9,7 @@