back interdiff of round #1 and #0

appview: add reaction for issues/PRs (close #65) #265

merged
opened by boltless.me targeting master from boltless.me/core: push-uoymosxlmxvl

Add sh.tangled.feed.reaction lexicon and UI to react to issues/PRs close #65 close #113

Signed-off-by: Seongmin Lee boltlessengineer@proton.me

files
api
appview
db
issues
pages
templates
layouts
repo
issues
pulls
fragments
pulls
state
cmd
lexicons
ERROR
api/tangled/cbor_gen.go

Failed to calculate interdiff for this file.

ERROR
api/tangled/feedreaction.go

Failed to calculate interdiff for this file.

ERROR
appview/db/db.go

Failed to calculate interdiff for this file.

ERROR
appview/db/issues.go

Failed to calculate interdiff for this file.

ERROR
appview/db/reaction.go

Failed to calculate interdiff for this file.

ERROR
appview/issues/issues.go

Failed to calculate interdiff for this file.

ERROR
appview/pages/pages.go

Failed to calculate interdiff for this file.

ERROR
appview/pages/templates/layouts/repobase.html

Failed to calculate interdiff for this file.

REVERTED
appview/pages/templates/repo/issues/fragments/reactions.html
···
-
{{ define "repo/issues/fragments/reactions" }}
-
<button
-
id="reactIndi-{{ .Kind }}"
-
class="flex justify-center items-center min-w-8 min-h-8 rounded border
-
leading-4 px-3 gap-1
-
{{ if eq .Count 0 }}
-
hidden
-
{{ end }}
-
{{ if .IsReacted }}
-
bg-sky-100
-
border-sky-400
-
dark:bg-sky-900
-
dark:border-sky-500
-
{{ else }}
-
border-gray-200
-
hover:bg-gray-50
-
hover:border-gray-300
-
dark:border-gray-700
-
dark:hover:bg-gray-700
-
dark:hover:border-gray-600
-
{{ end }}
-
"
-
{{ if .IsReacted }}
-
hx-delete="/react?subject={{ .ThreadAt }}&kind={{ .Kind }}"
-
{{ else }}
-
hx-post="/react?subject={{ .ThreadAt }}&kind={{ .Kind }}"
-
{{ end }}
-
hx-swap="outerHTML"
-
hx-trigger="click from:(#reactBtn-{{ .Kind }}, #reactIndi-{{ .Kind }})"
-
hx-disabled-elt="this"
-
>
-
<span>{{ .Kind }}</span> <span>{{ .Count }}</span>
-
</button>
-
{{ end }}
ERROR
appview/pages/templates/repo/issues/issue.html

Failed to calculate interdiff for this file.

ERROR
appview/pages/templates/repo/pulls/fragments/pullHeader.html

Failed to calculate interdiff for this file.

ERROR
appview/pulls/pulls.go

Failed to calculate interdiff for this file.

REVERTED
appview/state/react.go
···
-
package state
-
-
import (
-
"log"
-
"net/http"
-
"time"
-
-
comatproto "github.com/bluesky-social/indigo/api/atproto"
-
"github.com/bluesky-social/indigo/atproto/syntax"
-
-
lexutil "github.com/bluesky-social/indigo/lex/util"
-
// "github.com/posthog/posthog-go"
-
"tangled.sh/tangled.sh/core/api/tangled"
-
"tangled.sh/tangled.sh/core/appview"
-
"tangled.sh/tangled.sh/core/appview/db"
-
"tangled.sh/tangled.sh/core/appview/pages"
-
)
-
-
func (s *State) React(w http.ResponseWriter, r *http.Request) {
-
currentUser := s.oauth.GetUser(r)
-
-
subject := r.URL.Query().Get("subject")
-
if subject == "" {
-
log.Println("invalid form")
-
return
-
}
-
-
subjectUri, err := syntax.ParseATURI(subject)
-
if err != nil {
-
log.Println("invalid form")
-
return
-
}
-
-
reactionKind, ok := db.ParseReactionKind(r.URL.Query().Get("kind"))
-
if !ok {
-
log.Println("invalid reaction kind")
-
return
-
}
-
-
client, err := s.oauth.AuthorizedClient(r)
-
if err != nil {
-
log.Println("failed to authorize client", err)
-
return
-
}
-
-
switch r.Method {
-
case http.MethodPost:
-
createdAt := time.Now().Format(time.RFC3339)
-
rkey := appview.TID()
-
resp, err := client.RepoPutRecord(r.Context(), &comatproto.RepoPutRecord_Input{
-
Collection: tangled.FeedReactionNSID,
-
Repo: currentUser.Did,
-
Rkey: rkey,
-
Record: &lexutil.LexiconTypeDecoder{
-
Val: &tangled.FeedReaction{
-
Subject: subjectUri.String(),
-
Reaction: reactionKind.String(),
-
CreatedAt: createdAt,
-
},
-
},
-
})
-
if err != nil {
-
log.Println("failed to create atproto record", err)
-
return
-
}
-
-
err = db.AddReaction(s.db, currentUser.Did, subjectUri, reactionKind, rkey)
-
if err != nil {
-
log.Println("failed to react", err)
-
return
-
}
-
-
count, err := db.GetReactionCount(s.db, subjectUri, reactionKind)
-
if err != nil {
-
log.Println("failed to get reaction count for ", subjectUri)
-
}
-
-
log.Println("created atproto record: ", resp.Uri)
-
-
s.pages.ThreadReactionFragment(w, pages.ThreadReactionFragmentParams{
-
ThreadAt: subjectUri,
-
Kind: reactionKind,
-
Count: count,
-
IsReacted: true,
-
})
-
-
return
-
case http.MethodDelete:
-
reaction, err := db.GetReaction(s.db, currentUser.Did, subjectUri, reactionKind)
-
if err != nil {
-
log.Println("failed to get reaction relationship for", currentUser.Did, subjectUri)
-
return
-
}
-
-
_, err = client.RepoDeleteRecord(r.Context(), &comatproto.RepoDeleteRecord_Input{
-
Collection: tangled.FeedReactionNSID,
-
Repo: currentUser.Did,
-
Rkey: reaction.Rkey,
-
})
-
-
if err != nil {
-
log.Println("failed to remove reaction")
-
return
-
}
-
-
err = db.DeleteReactionByRkey(s.db, currentUser.Did, reaction.Rkey)
-
if err != nil {
-
log.Println("failed to delete reaction from DB")
-
// this is not an issue, the firehose event might have already done this
-
}
-
-
count, err := db.GetReactionCount(s.db, subjectUri, reactionKind)
-
if err != nil {
-
log.Println("failed to get reaction count for ", subjectUri)
-
return
-
}
-
-
s.pages.ThreadReactionFragment(w, pages.ThreadReactionFragmentParams{
-
ThreadAt: subjectUri,
-
Kind: reactionKind,
-
Count: count,
-
IsReacted: false,
-
})
-
-
return
-
}
-
}
ERROR
appview/state/router.go

Failed to calculate interdiff for this file.

ERROR
cmd/gen.go

Failed to calculate interdiff for this file.

ERROR
lexicons/feed/reaction.json

Failed to calculate interdiff for this file.

NEW
appview/pages/templates/repo/issues/fragments/reaction.html
···
+
{{ define "repo/issues/fragments/reaction" }}
+
<button
+
id="reactIndi-{{ .Kind }}"
+
class="flex justify-center items-center min-w-8 min-h-8 rounded border
+
leading-4 px-3 gap-1
+
{{ if eq .Count 0 }}
+
hidden
+
{{ end }}
+
{{ if .IsReacted }}
+
bg-sky-100
+
border-sky-400
+
dark:bg-sky-900
+
dark:border-sky-500
+
{{ else }}
+
border-gray-200
+
hover:bg-gray-50
+
hover:border-gray-300
+
dark:border-gray-700
+
dark:hover:bg-gray-700
+
dark:hover:border-gray-600
+
{{ end }}
+
"
+
{{ if .IsReacted }}
+
hx-delete="/react?subject={{ .ThreadAt }}&kind={{ .Kind }}"
+
{{ else }}
+
hx-post="/react?subject={{ .ThreadAt }}&kind={{ .Kind }}"
+
{{ end }}
+
hx-swap="outerHTML"
+
hx-trigger="click from:(#reactBtn-{{ .Kind }}, #reactIndi-{{ .Kind }})"
+
hx-disabled-elt="this"
+
>
+
<span>{{ .Kind }}</span> <span>{{ .Count }}</span>
+
</button>
+
{{ end }}
NEW
appview/state/reaction.go
···
+
package state
+
+
import (
+
"log"
+
"net/http"
+
"time"
+
+
comatproto "github.com/bluesky-social/indigo/api/atproto"
+
"github.com/bluesky-social/indigo/atproto/syntax"
+
+
lexutil "github.com/bluesky-social/indigo/lex/util"
+
"tangled.sh/tangled.sh/core/api/tangled"
+
"tangled.sh/tangled.sh/core/appview"
+
"tangled.sh/tangled.sh/core/appview/db"
+
"tangled.sh/tangled.sh/core/appview/pages"
+
)
+
+
func (s *State) React(w http.ResponseWriter, r *http.Request) {
+
currentUser := s.oauth.GetUser(r)
+
+
subject := r.URL.Query().Get("subject")
+
if subject == "" {
+
log.Println("invalid form")
+
return
+
}
+
+
subjectUri, err := syntax.ParseATURI(subject)
+
if err != nil {
+
log.Println("invalid form")
+
return
+
}
+
+
reactionKind, ok := db.ParseReactionKind(r.URL.Query().Get("kind"))
+
if !ok {
+
log.Println("invalid reaction kind")
+
return
+
}
+
+
client, err := s.oauth.AuthorizedClient(r)
+
if err != nil {
+
log.Println("failed to authorize client", err)
+
return
+
}
+
+
switch r.Method {
+
case http.MethodPost:
+
createdAt := time.Now().Format(time.RFC3339)
+
rkey := appview.TID()
+
resp, err := client.RepoPutRecord(r.Context(), &comatproto.RepoPutRecord_Input{
+
Collection: tangled.FeedReactionNSID,
+
Repo: currentUser.Did,
+
Rkey: rkey,
+
Record: &lexutil.LexiconTypeDecoder{
+
Val: &tangled.FeedReaction{
+
Subject: subjectUri.String(),
+
Reaction: reactionKind.String(),
+
CreatedAt: createdAt,
+
},
+
},
+
})
+
if err != nil {
+
log.Println("failed to create atproto record", err)
+
return
+
}
+
+
err = db.AddReaction(s.db, currentUser.Did, subjectUri, reactionKind, rkey)
+
if err != nil {
+
log.Println("failed to react", err)
+
return
+
}
+
+
count, err := db.GetReactionCount(s.db, subjectUri, reactionKind)
+
if err != nil {
+
log.Println("failed to get reaction count for ", subjectUri)
+
}
+
+
log.Println("created atproto record: ", resp.Uri)
+
+
s.pages.ThreadReactionFragment(w, pages.ThreadReactionFragmentParams{
+
ThreadAt: subjectUri,
+
Kind: reactionKind,
+
Count: count,
+
IsReacted: true,
+
})
+
+
return
+
case http.MethodDelete:
+
reaction, err := db.GetReaction(s.db, currentUser.Did, subjectUri, reactionKind)
+
if err != nil {
+
log.Println("failed to get reaction relationship for", currentUser.Did, subjectUri)
+
return
+
}
+
+
_, err = client.RepoDeleteRecord(r.Context(), &comatproto.RepoDeleteRecord_Input{
+
Collection: tangled.FeedReactionNSID,
+
Repo: currentUser.Did,
+
Rkey: reaction.Rkey,
+
})
+
+
if err != nil {
+
log.Println("failed to remove reaction")
+
return
+
}
+
+
err = db.DeleteReactionByRkey(s.db, currentUser.Did, reaction.Rkey)
+
if err != nil {
+
log.Println("failed to delete reaction from DB")
+
// this is not an issue, the firehose event might have already done this
+
}
+
+
count, err := db.GetReactionCount(s.db, subjectUri, reactionKind)
+
if err != nil {
+
log.Println("failed to get reaction count for ", subjectUri)
+
return
+
}
+
+
s.pages.ThreadReactionFragment(w, pages.ThreadReactionFragmentParams{
+
ThreadAt: subjectUri,
+
Kind: reactionKind,
+
Count: count,
+
IsReacted: false,
+
})
+
+
return
+
}
+
}