diff --git a/appview/db/db.go b/appview/db/db.go --- a/appview/db/db.go +++ b/appview/db/db.go @@ -674,6 +674,15 @@ foreign key (vouch_id) references vouches(id) on delete cascade ); + create table if not exists vouch_skips ( + did text not null, + subject_did text not null, + created_at text not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')), + primary key (did, subject_did), + check (did <> subject_did) + ); + + create table if not exists migrations ( id integer primary key autoincrement, name text unique diff --git a/appview/db/vouch.go b/appview/db/vouch.go --- a/appview/db/vouch.go +++ b/appview/db/vouch.go @@ -308,6 +308,14 @@ return batch[subjectDid], nil } +func SkipVouchSuggestion(e Execer, did, subjectDid string) error { + _, err := e.Exec( + `insert or ignore into vouch_skips (did, subject_did) values (?, ?)`, + did, subjectDid, + ) + return err +} + // priority: // 1. collaborator invites sent // 2. knot member invites sent @@ -390,6 +398,8 @@ ) where did not in ( select subject_did from vouches where vouches.did = ? + union + select subject_did from vouch_skips where vouch_skips.did = ? ) group by did order by min(priority) asc, max(created) desc @@ -405,7 +415,7 @@ did, did, // issue_comments did, did, // follows did, did, // stars - did, // vouches exclusion + did, did, // existing vouches + skips exclusion limit, } diff --git a/appview/state/router.go b/appview/state/router.go --- a/appview/state/router.go +++ b/appview/state/router.go @@ -189,6 +189,7 @@ r.With(middleware.AuthMiddleware(s.oauth)).Route("/vouch", func(r chi.Router) { r.Post("/", s.Vouch) + r.Post("/skip", s.SkipVouchSuggestion) }) r.With(middleware.AuthMiddleware(s.oauth)).Route("/star", func(r chi.Router) { diff --git a/appview/state/vouch.go b/appview/state/vouch.go --- a/appview/state/vouch.go +++ b/appview/state/vouch.go @@ -14,6 +14,39 @@ "tangled.org/core/log" ) +func (s *State) SkipVouchSuggestion(w http.ResponseWriter, r *http.Request) { + l := log.SubLogger(s.logger, "skipVouchSuggestion") + currentUser := s.oauth.GetMultiAccountUser(r) + + subject := r.FormValue("subject") + if subject == "" { + l.Warn("missing subject") + s.pages.Notice(w, "error", "Missing subject user.") + return + } + + subjectIdent, err := s.idResolver.ResolveIdent(r.Context(), subject) + if err != nil { + l.Error("failed to resolve subject", "subject", subject, "err", err) + s.pages.Notice(w, "error", "Could not find that user.") + return + } + + if currentUser.Did == subjectIdent.DID.String() { + l.Warn("cannot skip yourself") + s.pages.Notice(w, "error", "You cannot skip yourself.") + return + } + + if err := db.SkipVouchSuggestion(s.db, currentUser.Did, subjectIdent.DID.String()); err != nil { + l.Error("failed to skip vouch suggestion", "err", err) + s.pages.Notice(w, "error", "Failed to skip suggestion.") + return + } + + s.pages.HxRefresh(w) +} + func (s *State) Vouch(w http.ResponseWriter, r *http.Request) { l := log.SubLogger(s.logger, "vouch") l = s.logger.With("handler", "Vouch") diff --git a/appview/pages/templates/user/vouches.html b/appview/pages/templates/user/vouches.html --- a/appview/pages/templates/user/vouches.html +++ b/appview/pages/templates/user/vouches.html @@ -43,7 +43,7 @@ {{ if .Suggestions }}