Monorepo for Tangled tangled.org
859
fork

Configure Feed

Select the types of activity you want to include in your feed.

appview/pages: nudge users to vouch for a contributor #345

open opened by oppi.li targeting master from op/ryxxuwzqyuuu
Labels

None yet.

assignee

None yet.

Participants 1
AT URI
at://did:plc:qfpnj4og54vl56wngdriaxug/sh.tangled.repo.pull/3mlb3um4dfe22
+100 -29
Diff #1
+9
appview/db/vouch.go
··· 308 308 return batch[subjectDid], nil 309 309 } 310 310 311 + func IsVouchSkipped(e Execer, did, subjectDid string) (bool, error) { 312 + var exists bool 313 + err := e.QueryRow( 314 + `select exists(select 1 from vouch_skips where did = ? and subject_did = ?)`, 315 + did, subjectDid, 316 + ).Scan(&exists) 317 + return exists, err 318 + } 319 + 311 320 func SkipVouchSuggestion(e Execer, did, subjectDid string) error { 312 321 _, err := e.Exec( 313 322 `insert or ignore into vouch_skips (did, subject_did) values (?, ?)`,
+1
appview/pages/pages.go
··· 1384 1384 1385 1385 LabelDefs map[string]*models.LabelDefinition 1386 1386 VouchRelationships map[syntax.DID]*models.VouchRelationship 1387 + VouchSkips map[syntax.DID]bool 1387 1388 } 1388 1389 1389 1390 func (p *Pages) RepoSinglePull(w io.Writer, params RepoSinglePullParams) error {
+38
appview/pages/templates/repo/pulls/fragments/pullVouchNudge.html
··· 1 + {{ define "repo/pulls/fragments/pullVouchNudge" }} 2 + {{ $owner := .Pull.OwnerDid }} 3 + {{ $vr := index .VouchRelationships (did $owner) }} 4 + {{ $skipped := index .VouchSkips (did $owner) }} 5 + 6 + {{ if and 7 + .LoggedInUser 8 + (ne .LoggedInUser.Did $owner) 9 + (or .Pull.State.IsOpen .Pull.State.IsMerged) 10 + (or (not $vr) $vr.IsEmpty) 11 + (not $skipped) }} 12 + 13 + <div class="border border-gray-200 dark:border-gray-700 rounded px-2 pl-4 py-2 flex items-center gap-4 text-sm text-gray-600 dark:text-gray-300 bg-white dark:bg-gray-800"> 14 + <span class="flex-1 flex items-center gap-2 flex-wrap"> 15 + {{ i "shield-question-mark" "size-4" }} 16 + Would you like to vouch for 17 + <a href="/{{ resolve $owner }}" class="inline-flex items-center gap-1 font-medium text-gray-900 dark:text-white hover:underline"> 18 + <img src="{{ tinyAvatar $owner }}" class="rounded-full size-4 inline" /> 19 + {{ resolve $owner }} 20 + </a> 21 + for their contribution? 22 + </span> 23 + <button 24 + hx-post="/vouch/skip?subject={{ $owner }}" 25 + hx-trigger="click" 26 + hx-disabled-elt="this" 27 + title="Skip suggestion" 28 + class="group shrink-0 text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 p-0.5" 29 + > 30 + <span class="group-[.htmx-request]:hidden">dismiss</span> 31 + {{ i "loader-circle" "size-4 animate-spin hidden group-[.htmx-request]:block" }} 32 + </button> 33 + <div class="shrink-0"> 34 + {{ template "user/fragments/vouch" (dict "VouchRelationship" $vr "Evidences" (list .Pull.AtUri.String) "PopoverId" (printf "vouch-nudge-modal-%s" (normalizeForHtmlId $owner))) }} 35 + </div> 36 + </div> 37 + {{ end }} 38 + {{ end }}
+6 -3
appview/pages/templates/repo/pulls/pull.html
··· 80 80 81 81 {{ define "repoContentLayout" }} 82 82 <div class="grid grid-cols-1 md:grid-cols-10 gap-4 w-full"> 83 - <section class="bg-white col-span-1 md:col-span-8 dark:bg-gray-800 p-6 rounded relative w-full mx-auto dark:text-white h-full flex-shrink"> 84 - {{ block "repoContent" . }}{{ end }} 85 - </section> 83 + <div class="col-span-1 md:col-span-8 flex flex-col gap-4"> 84 + <section class="bg-white dark:bg-gray-800 p-6 rounded relative w-full mx-auto dark:text-white h-full flex-shrink"> 85 + {{ block "repoContent" . }}{{ end }} 86 + </section> 87 + {{ template "repo/pulls/fragments/pullVouchNudge" . }} 88 + </div> 86 89 <div class="flex flex-col gap-6 col-span-1 md:col-span-2"> 87 90 {{ template "repo/fragments/labelPanel" 88 91 (dict "RepoInfo" $.RepoInfo
+1 -1
appview/pages/templates/timeline/fragments/vouchSuggestions.html
··· 19 19 <span class="text-xs text-gray-500 dark:text-gray-400 truncate" title="{{ .Reason }}">{{ .Reason }}</span> 20 20 </div> 21 21 <div class="shrink-0"> 22 - {{ template "user/fragments/vouch" . }} 22 + {{ template "user/fragments/vouch" (dict "VouchRelationship" .VouchRelationship) }} 23 23 </div> 24 24 </div> 25 25 {{ end }}
+1 -1
appview/pages/templates/user/fragments/profileCard.html
··· 109 109 </div> 110 110 111 111 {{ if ne .FollowStatus.String "IsSelf" }} 112 - {{ template "user/fragments/vouch" . }} 112 + {{ template "user/fragments/vouch" (dict "VouchRelationship" .VouchRelationship) }} 113 113 114 114 {{ if .VouchRelationship }} 115 115 {{ if .VouchRelationship.IndirectVouches }}
+2 -2
appview/pages/templates/user/fragments/profilePopover.html
··· 39 39 {{ if and .LoggedInUser (ne .FollowStatus.String "IsSelf") }} 40 40 <div class="flex items-center gap-2"> 41 41 {{ template "user/fragments/follow" . }} 42 - {{ template "user/fragments/vouchButton" . }} 42 + {{ template "user/fragments/vouchButton" (dict "VouchRelationship" .VouchRelationship) }} 43 43 </div> 44 44 45 45 {{ if .VouchRelationship }} ··· 54 54 55 55 {{/* render the vouch modal outside the popover content div so the popover api places it in the top layer correctly */}} 56 56 {{ if and .LoggedInUser (ne .FollowStatus.String "IsSelf") }} 57 - {{ template "user/fragments/vouchPopover" . }} 57 + {{ template "user/fragments/vouchPopover" (dict "VouchRelationship" .VouchRelationship) }} 58 58 {{ end }} 59 59 {{ end }}
+4 -1
appview/pages/templates/user/fragments/vouch.html
··· 1 1 {{ define "user/fragments/vouch" }} 2 2 <div class="relative"> 3 + {{ $vr := index . "VouchRelationship" }} 4 + {{ $ev := index . "Evidences" }} 5 + {{ $popoverId := index . "PopoverId" }} 3 6 {{ template "user/fragments/vouchButton" . }} 4 - {{ template "user/fragments/vouchPopover" . }} 7 + {{ template "user/fragments/vouchPopover" (dict "VouchRelationship" $vr "Evidences" $ev "PopoverId" $popoverId) }} 5 8 </div> 6 9 {{ end }}
+3 -1
appview/pages/templates/user/fragments/vouchButton.html
··· 13 13 {{ with .VouchRelationship }} 14 14 {{ $userDid = .SubjectDid.String }} 15 15 {{ end }} 16 + {{ $popoverId := index . "PopoverId" }} 17 + {{ if not $popoverId }}{{ $popoverId = printf "vouch-modal-%s" (normalizeForHtmlId $userDid) }}{{ end }} 16 18 <button 17 19 id="vouch-btn-{{ normalizeForHtmlId $userDid }}" 18 20 type="button" 19 - popovertarget="vouch-modal-{{ normalizeForHtmlId $userDid }}" 21 + popovertarget="{{ $popoverId }}" 20 22 popovertargetaction="toggle" 21 23 class="{{ if $isVouched }}btn-create{{else if $isDenounced}}btn-cancel{{else}}btn{{end}} w-full flex gap-2 items-center justify-center"> 22 24 {{ if $isVouched }}
+26 -19
appview/pages/templates/user/fragments/vouchPopover.html
··· 1 1 {{ define "user/fragments/vouchPopover" }} 2 + {{ $vr := index . "VouchRelationship" }} 3 + {{ $ev := index . "Evidences" }} 2 4 {{ $isVouched := false }} 3 5 {{ $isDenounced := false }} 4 6 {{ $isUndecided := false }} 5 - {{ if .VouchRelationship }} 6 - {{ if .VouchRelationship.IsDirectVouch }} 7 + {{ if $vr }} 8 + {{ if $vr.IsDirectVouch }} 7 9 {{ $isVouched = true }} 8 - {{ else if .VouchRelationship.IsDirectDenounce }} 10 + {{ else if $vr.IsDirectDenounce }} 9 11 {{ $isDenounced = true }} 10 12 {{ else }} 11 13 {{ $isUndecided = true }} ··· 16 18 17 19 {{ $userIdent := "" }} 18 20 {{ $userDid := "" }} 19 - {{ with .VouchRelationship }} 21 + {{ with $vr }} 20 22 {{ $userDid = .SubjectDid.String }} 21 23 {{ $userIdent = resolve .SubjectDid.String }} 22 24 {{ end }} 25 + {{ $popoverId := index . "PopoverId" }} 26 + {{ if not $popoverId }}{{ $popoverId = printf "vouch-modal-%s" (normalizeForHtmlId $userDid) }}{{ end }} 23 27 <div 24 - id="vouch-modal-{{ normalizeForHtmlId $userDid }}" 28 + id="{{ $popoverId }}" 25 29 popover 26 30 class="bg-white w-[95%] md:w-96 dark:bg-gray-800 p-4 rounded border border-gray-200 dark:border-gray-700 drop-shadow dark:text-white backdrop:bg-gray-400/50 dark:backdrop:bg-gray-800/50 space-y-2"> 27 31 ··· 34 38 <div> 35 39 <p class="font-semibold mb-1 text-base">Vouch for {{ $userIdent }}</p> 36 40 <p class="text-gray-600 dark:text-gray-400 text-sm"> 37 - {{ with .VouchRelationship }} 41 + {{ with $vr }} 38 42 {{ with .GetDirectVouch }} 39 43 You {{if $isVouched}}vouched{{else}}denounced{{end}} {{ $userIdent }} {{ relTimeFmt .CreatedAt }}. 40 44 You can change your decision below. ··· 46 50 </p> 47 51 </div> 48 52 49 - {{ if .VouchRelationship }} 50 - {{ if .VouchRelationship.IndirectVouches }} 53 + {{ if $vr }} 54 + {{ if $vr.IndirectVouches }} 51 55 <div> 52 56 <p class="font-semibold mb-1 text-sm">From your network:</p> 53 - {{ template "user/fragments/networkVouches" .VouchRelationship }} 57 + {{ template "user/fragments/networkVouches" $vr }} 54 58 </div> 55 59 {{ end }} 56 60 {{ end }} 57 61 58 62 <input type="hidden" name="subject" value="{{ $userDid }}" /> 63 + {{ range $ev }} 64 + <input type="hidden" name="evidences" value="{{ . }}" /> 65 + {{ end }} 59 66 60 67 {{ $labelClass := "grid grid-cols-[auto_1fr_auto] items-center gap-2 rounded p-2 py- ring-1 ring-gray-200 dark:ring-gray-700 cursor-pointer" }} 61 68 62 69 <div class="grid grid-cols-3 gap-2"> 63 70 <input 64 - id="vouch-{{ normalizeForHtmlId $userDid }}" 71 + id="vouch-{{ $popoverId }}" 65 72 type="radio" 66 73 name="kind" 67 74 value="vouch" 68 75 {{ if $isVouched }}checked{{ end }} 69 76 class="peer/vouch hidden appearance-none" /> 70 77 <input 71 - id="denounce-{{ normalizeForHtmlId $userDid }}" 78 + id="denounce-{{ $popoverId }}" 72 79 type="radio" 73 80 name="kind" 74 81 value="denounce" 75 82 {{ if $isDenounced }}checked{{ end }} 76 83 class="peer/denounce hidden appearance-none" /> 77 84 <input 78 - id="none-{{ normalizeForHtmlId $userDid }}" 85 + id="none-{{ $popoverId }}" 79 86 type="radio" 80 87 name="kind" 81 88 value="none" ··· 83 90 class="peer/none hidden appearance-none" /> 84 91 85 92 <label 86 - for="vouch-{{ normalizeForHtmlId $userDid }}" 93 + for="vouch-{{ $popoverId }}" 87 94 class=" 88 95 {{ $labelClass }} 89 96 hover:bg-gray-100 peer-checked/vouch:bg-green-200 peer-checked/vouch:text-green-800 peer-checked/vouch:ring-green-400 ··· 92 99 <span class="text-sm font-medium">Vouch</span> 93 100 </label> 94 101 <label 95 - for="denounce-{{ normalizeForHtmlId $userDid }}" 102 + for="denounce-{{ $popoverId }}" 96 103 class=" 97 104 {{ $labelClass }} 98 105 hover:bg-gray-100 peer-checked/denounce:bg-red-200 peer-checked/denounce:text-red-800 peer-checked/denounce:ring-red-400 ··· 101 108 <span class="text-sm font-medium">Denounce</span> 102 109 </label> 103 110 <label 104 - for="none-{{ normalizeForHtmlId $userDid }}" 111 + for="none-{{ $popoverId }}" 105 112 class=" 106 113 {{ $labelClass }} 107 114 hover:bg-gray-100 peer-checked/none:bg-gray-200 peer-checked/none:text-gray-800 peer-checked/none:ring-gray-400 ··· 111 118 </label> 112 119 113 120 <textarea 114 - id="reason-{{ normalizeForHtmlId $userDid }}" 121 + id="reason-{{ $popoverId }}" 115 122 name="reason" 116 123 rows="1" 117 124 maxlength="300" 118 125 placeholder="Write a reason..." 119 126 class="w-full resize-none col-span-3 peer-checked/none:hidden"> 120 - {{- with .VouchRelationship -}} 127 + {{- with $vr -}} 121 128 {{- with .GetDirectVouch -}} 122 129 {{- with .Reason -}} 123 130 {{- . -}} ··· 130 137 <div class="flex gap-2"> 131 138 <button 132 139 type="button" 133 - popovertarget="vouch-modal-{{ normalizeForHtmlId $userDid }}" 140 + popovertarget="{{ $popoverId }}" 134 141 popovertargetaction="hide" 135 142 class="btn flex-1 flex items-center justify-center gap-2"> 136 143 {{ i "x" "size-4" }} ··· 141 148 class="btn-create flex-1 flex items-center justify-center gap-2 text-white group"> 142 149 {{ i "check" "size-4 inline group-[.htmx-request]:hidden" }} 143 150 {{ i "loader-circle" "size-4 animate-spin hidden group-[.htmx-request]:inline" }} 144 - {{ if and .VouchRelationship .VouchRelationship.GetDirectVouch }} update {{ else }} save {{end}} 151 + {{ if and $vr $vr.GetDirectVouch }} update {{ else }} save {{end}} 145 152 </button> 146 153 </div> 147 154 </form>
+1 -1
appview/pages/templates/user/vouches.html
··· 50 50 <span class="text-sm text-gray-500 dark:text-gray-400">{{ .Reason }}</span> 51 51 </div> 52 52 <div class="shrink-0 w-32"> 53 - {{ template "user/fragments/vouch" . }} 53 + {{ template "user/fragments/vouch" (dict "VouchRelationship" .VouchRelationship) }} 54 54 </div> 55 55 <button 56 56 hx-post="/vouch/skip?subject={{ .Did.String }}"
+8
appview/pulls/single.go
··· 189 189 } 190 190 191 191 vouchRelationships := make(map[syntax.DID]*models.VouchRelationship) 192 + vouchSkips := make(map[syntax.DID]bool) 192 193 if user != nil { 193 194 participants := pull.Participants() 194 195 vouchRelationships, err = db.GetVouchRelationshipsBatch(s.db, syntax.DID(user.Did), participants) 195 196 if err != nil { 196 197 l.Error("failed to fetch vouch relationships", "err", err) 197 198 } 199 + ownerDid := syntax.DID(pull.OwnerDid) 200 + skipped, err := db.IsVouchSkipped(s.db, user.Did, pull.OwnerDid) 201 + if err != nil { 202 + l.Error("failed to check vouch skip", "err", err) 203 + } 204 + vouchSkips[ownerDid] = skipped 198 205 } 199 206 200 207 patch := pull.Submissions[roundIdInt].CombinedPatch() ··· 239 246 240 247 LabelDefs: defs, 241 248 VouchRelationships: vouchRelationships, 249 + VouchSkips: vouchSkips, 242 250 }) 243 251 if err != nil { 244 252 l.Error("failed to render page", "err", err)

History

2 rounds 0 comments
sign up or login to add to the discussion
1 commit
expand
appview/pages: nudge users to vouch for a contributor
merge conflicts detected
expand
  • api/tangled/cbor_gen.go:2467
  • api/tangled/graphvouch.go:19
  • lexicons/graph/vouch.json:29
expand 0 comments
oppi.li submitted #0
1 commit
expand
appview/pages: nudge users to vouch for a contributor
expand 0 comments