Monorepo for Tangled
0
fork

Configure Feed

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

vouch panel in profiles

Signed-off-by: oppiliappan <me@oppi.li>

+111 -85
+1 -1
appview/models/vouch.go
··· 19 19 case "vouch": 20 20 return VouchKindVouch, nil 21 21 case "denounce": 22 - return VouchKindVouch, nil 22 + return VouchKindDenounce, nil 23 23 default: 24 24 return VouchKindVouch, fmt.Errorf("invalid vouch kind: %s", v) 25 25 }
-3
appview/pages/templates/user/fragments/picLink.html
··· 10 10 /> 11 11 </a> 12 12 {{ end }} 13 - 14 - 15 -
+71 -1
appview/pages/templates/user/fragments/profileCard.html
··· 39 39 </div> 40 40 </div> 41 41 <div class="col-span-3 md:col-span-full"> 42 - <div id="profile-bio" class="text-sm"> 42 + <div id="profile-bio" class="text-sm space-y-2"> 43 43 {{ $profile := .Profile }} 44 44 {{ with .Profile }} 45 45 ··· 110 110 111 111 {{ if ne .FollowStatus.String "IsSelf" }} 112 112 {{ template "user/fragments/vouch" . }} 113 + 114 + {{ if .VouchRelationship }} 115 + {{ if .VouchRelationship.IndirectVouches }} 116 + <div class="flex flex-col gap-2"> 117 + {{ template "networkVouches" . }} 118 + </div> 119 + {{ end }} 120 + {{ end }} 113 121 {{ end }} 114 122 115 123 </div> ··· 131 139 </div> 132 140 {{ end }} 133 141 {{ end }} 142 + 143 + {{ define "networkVouches" }} 144 + {{ $vouches := (list) }} 145 + {{ $denounces := (list) }} 146 + {{ range .VouchRelationship.IndirectVouches }} 147 + {{ if .IsVouch }} 148 + {{ $vouches = append $vouches .Did }} 149 + {{ else if .IsDenounce }} 150 + {{ $denounces = append $denounces .Did }} 151 + {{ end }} 152 + {{ end }} 153 + 154 + <div class="rounded overflow-hidden"> 155 + {{ if $vouches }} 156 + <div class=" 157 + bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200 158 + p-2 flex items-center justify-between gap-3 159 + border-x border-green-600/25 dark:border-green-400/25 160 + {{ if $denounces }} border-t {{ else }} border-y {{ end }} 161 + "> 162 + <span class="text-sm font-medium">vouched for by {{ len $vouches }} {{ if eq (len $vouches) 1 }}user{{ else }}users{{ end }}</span> 163 + {{ template "fragments/tinyAvatarList" (dict "all" $vouches "classes" "size-6") }} 164 + </div> 165 + {{ end }} 166 + 167 + {{ if $denounces }} 168 + <div class=" 169 + bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200 170 + p-2 flex items-center justify-between gap-3 171 + border-x border-red-600/25 dark:border-red-400/25 172 + {{ if $vouches }} border-b {{ else }} border-y {{ end }} 173 + "> 174 + <span class="text-sm font-medium">denounced by {{ len $denounces }} {{ if eq (len $denounces) 1 }}user{{ else }}users{{ end }}</span> 175 + {{ template "fragments/tinyAvatarList" (dict "all" $denounces "classes" "size-6") }} 176 + </div> 177 + {{ end }} 178 + </div> 179 + {{ end }} 180 + 181 + {{ define "networkVouchItem" }} 182 + <div class="flex items-center gap-2 p-2 group/item"> 183 + <div class="flex-shrink-0 h-fit relative"> 184 + {{ template "user/fragments/picLink" (list .Did "size-8") }} 185 + </div> 186 + <div class="flex-1 min-w-0 flex items-center gap-2"> 187 + <div class="text-sm font-medium flex-shrink-0 text-green-900 dark:text-green-100"> 188 + {{ resolve .Did }} 189 + </div> 190 + <div class="flex-1 min-w-0 text-sm text-green-700 dark:text-green-300 truncate"> 191 + {{ .Reason | description }} 192 + </div> 193 + </div> 194 + <div class="flex-shrink-0 relative min-w-12 text-center"> 195 + <div class="text-xs text-green-600 dark:text-green-400 group-hover/item:opacity-0 transition-opacity"> 196 + {{ template "repo/fragments/shortTime" .CreatedAt }} 197 + </div> 198 + <div class="absolute inset-0 flex items-center gap-1 justify-center opacity-0 group-hover/item:opacity-100 transition-opacity text-xs font-medium text-green-900 dark:text-green-100"> 199 + view {{ i "arrow-right" "size-3" }} 200 + </div> 201 + </div> 202 + </div> 203 + {{ end }}
+32 -73
appview/pages/templates/user/fragments/vouch.html
··· 1 1 {{ define "user/fragments/vouch" }} 2 - {{ $userIdent := resolve .UserDid }} 3 2 {{ $isVouched := false }} 4 3 {{ $isDenounced := false }} 5 4 {{ $isUndecided := false }} ··· 14 13 {{ else }} 15 14 {{ $isUndecided = true }} 16 15 {{ end }} 16 + 17 + {{ $userIdent := "" }} 18 + {{ $userDid := "" }} 19 + {{ with .VouchRelationship }} 20 + {{ $userIdent = .SubjectDid }} 21 + {{ $userIdent = resolve .SubjectDid }} 22 + {{ end }} 17 23 <div class="relative"> 18 24 <button 19 - id="vouch-btn-{{ normalizeForHtmlId .UserDid }}" 25 + id="vouch-btn-{{ normalizeForHtmlId $userDid }}" 20 26 type="button" 21 - popovertarget="vouch-modal-{{ normalizeForHtmlId .UserDid }}" 27 + popovertarget="vouch-modal-{{ normalizeForHtmlId $userDid }}" 22 28 popovertargetaction="toggle" 23 29 class="{{ if $isVouched }}btn-create{{else if $isDenounced}}btn-cancel{{else}}btn{{end}} w-full flex gap-2 items-center justify-center"> 24 30 {{ if $isVouched }} ··· 31 37 </button> 32 38 33 39 <div 34 - id="vouch-modal-{{ normalizeForHtmlId .UserDid }}" 40 + id="vouch-modal-{{ normalizeForHtmlId $userDid }}" 35 41 popover 36 42 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"> 37 43 ··· 41 47 class="flex flex-col gap-4 group"> 42 48 43 49 <h3 class="text-lg font-semibold">Vouch for {{ $userIdent }}</h3> 44 - {{ with .VouchRelationship }} 45 - {{ with .GetDirectVouch }} 46 - <p class="text-gray-700 dark:text-gray-300"> 47 - You {{if $isVouched}}vouched{{else}}denounced{{end}} {{ $userIdent }} {{ relTimeFmt .CreatedAt }}. 48 - You can change your descision below. 49 - </p> 50 + <p class="text-gray-700 dark:text-gray-300"> 51 + {{ with .VouchRelationship }} 52 + {{ with .GetDirectVouch }} 53 + You {{if $isVouched}}vouched{{else}}denounced{{end}} {{ $userIdent }} {{ relTimeFmt .CreatedAt }}. 54 + You can change your descision below. 55 + {{ else }} 56 + Vouching builds a web-of-trust across Tangled. Vouch for users you 57 + have had positive interactions with. 58 + {{ end }} 50 59 {{ end }} 51 - {{ end }} 60 + </p> 52 61 53 - {{ if .VouchRelationship }} 54 - {{ if .VouchRelationship.IndirectVouches }} 55 - <h3 class="text-md font-semibold">Vouches from your network</h3> 56 - {{ template "networkVouches" . }} 57 - {{ end }} 58 - {{ end }} 59 - 60 - <input type="hidden" name="subject" value="{{ .UserDid }}" /> 62 + <input type="hidden" name="subject" value="{{ $userDid }}" /> 61 63 62 64 {{ $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" }} 63 65 64 66 <div class="grid grid-cols-3 gap-2"> 65 67 <input 66 - id="vouch-{{ normalizeForHtmlId .UserDid }}" 68 + id="vouch-{{ normalizeForHtmlId $userDid }}" 67 69 type="radio" 68 70 name="kind" 69 71 value="vouch" 70 72 {{ if $isVouched }}checked{{ end }} 71 73 class="peer/vouch hidden appearance-none" /> 72 74 <input 73 - id="denounce-{{ normalizeForHtmlId .UserDid }}" 75 + id="denounce-{{ normalizeForHtmlId $userDid }}" 74 76 type="radio" 75 77 name="kind" 76 78 value="denounce" 77 79 {{ if $isDenounced }}checked{{ end }} 78 80 class="peer/denounce hidden appearance-none" /> 79 81 <input 80 - id="none-{{ normalizeForHtmlId .UserDid }}" 82 + id="none-{{ normalizeForHtmlId $userDid }}" 81 83 type="radio" 82 84 name="kind" 83 85 value="none" ··· 85 87 class="peer/none hidden appearance-none" /> 86 88 87 89 <label 88 - for="vouch-{{ normalizeForHtmlId .UserDid }}" 90 + for="vouch-{{ normalizeForHtmlId $userDid }}" 89 91 class=" 90 92 {{ $labelClass }} 91 93 hover:bg-gray-100 peer-checked/vouch:bg-green-200 peer-checked/vouch:text-green-800 peer-checked/vouch:ring-green-400 ··· 94 96 <span class="text-sm font-medium">Vouch</span> 95 97 </label> 96 98 <label 97 - for="denounce-{{ normalizeForHtmlId .UserDid }}" 99 + for="denounce-{{ normalizeForHtmlId $userDid }}" 98 100 class=" 99 101 {{ $labelClass }} 100 102 hover:bg-gray-100 peer-checked/denounce:bg-red-200 peer-checked/denounce:text-red-800 peer-checked/denounce:ring-red-400 ··· 103 105 <span class="text-sm font-medium">Denounce</span> 104 106 </label> 105 107 <label 106 - for="none-{{ normalizeForHtmlId .UserDid }}" 108 + for="none-{{ normalizeForHtmlId $userDid }}" 107 109 class=" 108 110 {{ $labelClass }} 109 111 hover:bg-gray-100 peer-checked/none:bg-gray-200 peer-checked/none:text-gray-800 peer-checked/none:ring-gray-400 ··· 113 115 </label> 114 116 115 117 <textarea 116 - id="reason-{{ normalizeForHtmlId .UserDid }}" 118 + id="reason-{{ normalizeForHtmlId $userDid }}" 117 119 name="reason" 118 120 rows="3" 119 121 maxlength="300" ··· 121 123 class="w-full resize-none col-span-3 peer-checked/none:hidden"> 122 124 {{- with .VouchRelationship -}} 123 125 {{- with .GetDirectVouch -}} 124 - {{- .Reason -}} 126 + {{- with .Reason -}} 127 + {{- . -}} 128 + {{- end -}} 125 129 {{- end -}} 126 130 {{- end -}} 127 131 </textarea> ··· 130 134 <div class="flex gap-2"> 131 135 <button 132 136 type="button" 133 - popovertarget="vouch-modal-{{ normalizeForHtmlId .UserDid }}" 137 + popovertarget="vouch-modal-{{ normalizeForHtmlId $userDid }}" 134 138 popovertargetaction="hide" 135 139 class="btn flex-1 flex items-center justify-center gap-2"> 136 140 {{ i "x" "size-4" }} ··· 150 154 </div> 151 155 </div> 152 156 {{ end }} 153 - 154 - {{ define "networkVouches" }} 155 - {{ $style := "flex flex-col border divide-y rounded" }} 156 - {{ $indirectVouches := .VouchRelationship.IndirectVouches }} 157 - 158 - {{ $bg := "bg-green-200 dark:bg-green-700" }} 159 - {{ $fg := "text-green-800 dark:text-green-200" }} 160 - {{ $border := "border-green-400 dark:border-green-600" }} 161 - <div class="{{ $style }} {{ $bg }} {{ $fg }} {{ $border }}"> 162 - {{ range .VouchRelationship.IndirectVouches }} 163 - {{ if .IsVouch }} 164 - {{ template "networkVouchItem" . }} 165 - {{ end }} 166 - {{ end }} 167 - </div> 168 - 169 - {{ $bg = "bg-red-200 dark:bg-red-700" }} 170 - {{ $fg = "text-red-800 dark:text-red-200" }} 171 - {{ $border = "border-red-400 dark:border-red-600" }} 172 - <div class="{{ $style }} {{ $bg }} {{ $fg }} {{ $border }}"> 173 - {{ range .VouchRelationship.IndirectVouches }} 174 - {{ if .IsDenounce }} 175 - {{ template "networkVouchItem" . }} 176 - {{ end }} 177 - {{ end }} 178 - </div> 179 - {{ end }} 180 - 181 - {{ define "networkVouchItem" }} 182 - <div class="flex items-center gap-2 p-2"> 183 - <div class="flex-shrink-0 h-fit relative"> 184 - {{ template "user/fragments/picLink" (list .Did "size-8") }} 185 - </div> 186 - <div class="flex-1 min-w-0"> 187 - <div class="text-sm flex items-center gap-1 group-target/comment:bg-yellow-200/30 group-target/comment:dark:bg-yellow-600/30"> 188 - {{ resolve .Did }} 189 - <span class="before:content-['·']"></span> 190 - {{ template "repo/fragments/shortTime" .CreatedAt }} 191 - </div> 192 - <div class="line-clamp-1"> 193 - {{ .Reason | description }} 194 - </div> 195 - </div> 196 - </div> 197 - {{ end }}
+7 -7
appview/state/vouch.go
··· 35 35 return 36 36 } 37 37 38 - if currentUser.Active.Did == subjectIdent.DID.String() { 38 + if currentUser.Did == subjectIdent.DID.String() { 39 39 l.Warn("cant vouch or denounce yourself") 40 40 s.pages.Notice(w, "error", "You cannot vouch for yourself.") 41 41 return ··· 58 58 59 59 // handle "none" by deleting any existing vouch 60 60 if r.FormValue("kind") == "none" { 61 - _, err := db.GetVouch(s.db, currentUser.Active.Did, subjectDid) 61 + _, err := db.GetVouch(s.db, currentUser.Did, subjectDid) 62 62 if err != nil { 63 63 l.Info("no existing vouch to delete") 64 64 s.pages.HxRefresh(w) ··· 67 67 68 68 _, err = comatproto.RepoDeleteRecord(r.Context(), client, &comatproto.RepoDeleteRecord_Input{ 69 69 Collection: tangled.GraphVouchNSID, 70 - Repo: currentUser.Active.Did, 70 + Repo: currentUser.Did, 71 71 Rkey: subjectDid, 72 72 }) 73 73 ··· 77 77 return 78 78 } 79 79 80 - err = db.DeleteVouch(s.db, currentUser.Active.Did, subjectDid) 80 + err = db.DeleteVouch(s.db, currentUser.Did, subjectDid) 81 81 if err != nil { 82 82 l.Warn("failed to delete vouch from DB", "err", err) 83 83 } ··· 103 103 } 104 104 105 105 var swapCid *string 106 - existingVouch, err := db.GetVouch(s.db, currentUser.Active.Did, subjectDid) 106 + existingVouch, err := db.GetVouch(s.db, currentUser.Did, subjectDid) 107 107 if err == nil { 108 108 cidStr := existingVouch.Cid.String() 109 109 swapCid = &cidStr ··· 111 111 112 112 resp, err := comatproto.RepoPutRecord(r.Context(), client, &comatproto.RepoPutRecord_Input{ 113 113 Collection: tangled.GraphVouchNSID, 114 - Repo: currentUser.Active.Did, 114 + Repo: currentUser.Did, 115 115 Rkey: subjectDid, 116 116 SwapRecord: swapCid, 117 117 Record: &lexutil.LexiconTypeDecoder{ ··· 137 137 } 138 138 139 139 vouch := &models.Vouch{ 140 - Did: currentUser.Active.Did, 140 + Did: currentUser.Did, 141 141 SubjectDid: subjectDid, 142 142 Cid: newCid, 143 143 Kind: kind,