···
243
-
func GetIssueAt(e Execer, repoAt syntax.ATURI, issueId int) (string, error) {
245
-
err := e.QueryRow(`select issue_at from issues where repo_at = ? and issue_id = ?`, repoAt, issueId).Scan(&issueAt)
246
-
return issueAt, err
243
+
func GetIssuesPaginated(e Execer, page pagination.Page, filters ...filter) ([]Issue, error) {
244
+
issueMap := make(map[string]*Issue) // at-uri -> issue
249
-
func GetIssueOwnerDid(e Execer, repoAt syntax.ATURI, issueId int) (string, error) {
250
-
var ownerDid string
251
-
err := e.QueryRow(`select owner_did from issues where repo_at = ? and issue_id = ?`, repoAt, issueId).Scan(&ownerDid)
252
-
return ownerDid, err
246
+
var conditions []string
255
-
func GetIssuesPaginated(e Execer, repoAt syntax.ATURI, isOpen bool, page pagination.Page) ([]Issue, error) {
249
+
for _, filter := range filters {
250
+
conditions = append(conditions, filter.Condition())
251
+
args = append(args, filter.Arg()...)
262
-
rows, err := e.Query(
255
+
if conditions != nil {
256
+
whereClause = " where " + strings.Join(conditions, " and ")
259
+
pLower := FilterGte("row_num", page.Offset+1)
260
+
pUpper := FilterLte("row_num", page.Offset+page.Limit)
262
+
args = append(args, pLower.Arg()...)
263
+
args = append(args, pUpper.Arg()...)
264
+
pagination := " where " + pLower.Condition() + " and " + pUpper.Condition()
266
+
query := fmt.Sprintf(
264
-
with numbered_issue as (
274
-
count(c.id) as comment_count,
275
-
row_number() over (order by i.created desc) as row_num
281
+
row_number() over (order by created desc) as row_num
279
-
comments c on i.repo_at = c.repo_at and i.issue_id = c.issue_id
281
-
i.repo_at = ? and i.open = ?
283
-
i.id, i.owner_did, i.issue_id, i.created, i.title, i.body, i.open
298
-
row_num between ? and ?`,
299
-
repoAt, openValue, page.Offset+1, page.Offset+page.Limit)
292
+
rows, err := e.Query(query, args...)
294
+
return nil, fmt.Errorf("failed to query issues table: %w", err)
308
-
var metadata IssueMetadata
309
-
err := rows.Scan(&issue.ID, &issue.OwnerDid, &issue.Rkey, &issue.IssueId, &createdAt, &issue.Title, &issue.Body, &issue.Open, &metadata.CommentCount)
301
+
var editedAt, deletedAt sql.Null[string]
318
+
return nil, fmt.Errorf("failed to scan issue: %w", err)
321
+
if t, err := time.Parse(time.RFC3339, createdAt); err == nil {
325
+
if editedAt.Valid {
326
+
if t, err := time.Parse(time.RFC3339, editedAt.V); err == nil {
314
-
createdTime, err := time.Parse(time.RFC3339, createdAt)
331
+
if deletedAt.Valid {
332
+
if t, err := time.Parse(time.RFC3339, deletedAt.V); err == nil {
318
-
issue.Created = createdTime
319
-
issue.Metadata = &metadata
337
+
atUri := issue.AtUri().String()
338
+
issueMap[atUri] = &issue
341
+
// collect reverse repos
342
+
repoAts := make([]string, 0, len(issueMap)) // or just []string{}
343
+
for _, issue := range issueMap {
344
+
repoAts = append(repoAts, string(issue.RepoAt))
347
+
repos, err := GetRepos(e, 0, FilterIn("at_uri", repoAts))
349
+
return nil, fmt.Errorf("failed to build repo mappings: %w", err)
352
+
repoMap := make(map[string]*Repo)
353
+
for i := range repos {
354
+
repoMap[string(repos[i].RepoAt())] = &repos[i]
357
+
for issueAt := range issueMap {
358
+
i := issueMap[issueAt]
359
+
r := repoMap[string(i.RepoAt)]
321
-
issues = append(issues, issue)
363
+
// collect comments
364
+
issueAts := slices.Collect(maps.Keys(issueMap))
365
+
comments, err := GetIssueComments(e, FilterIn("issue_at", issueAts))
367
+
return nil, fmt.Errorf("failed to query comments: %w", err)
324
-
if err := rows.Err(); err != nil {
370
+
for i := range comments {
371
+
issueAt := comments[i].IssueAt
372
+
if issue, ok := issueMap[issueAt]; ok {
373
+
issue.Comments = append(issue.Comments, comments[i])
378
+
for _, i := range issueMap {
379
+
issues = append(issues, *i)
382
+
sort.Slice(issues, func(i, j int) bool {
383
+
return issues[i].Created.After(issues[j].Created)
···
var issueCreatedAt string
···
func GetIssues(e Execer, filters ...filter) ([]Issue, error) {
408
-
return GetIssuesWithLimit(e, 0, filters...)
466
+
return GetIssuesPaginated(e, pagination.FirstPage(), filters...)
// timeframe here is directly passed into the sql query filter, and any
···
var issueCreatedAt, repoCreatedAt string
···
repo.Created = repoCreatedTime
482
-
issue.Metadata = &IssueMetadata{
issues = append(issues, issue)
···
502
-
err := row.Scan(&issue.ID, &issue.OwnerDid, &issue.Rkey, &createdAt, &issue.Title, &issue.Body, &issue.Open)
556
+
err := row.Scan(&issue.Id, &issue.Did, &issue.Rkey, &createdAt, &issue.Title, &issue.Body, &issue.Open)
···
516
-
func GetIssueWithComments(e Execer, repoAt syntax.ATURI, issueId int) (*Issue, []Comment, error) {
517
-
query := `select id, owner_did, rkey, issue_id, created, title, body, open from issues where repo_at = ? and issue_id = ?`
518
-
row := e.QueryRow(query, repoAt, issueId)
521
-
var createdAt string
522
-
err := row.Scan(&issue.ID, &issue.OwnerDid, &issue.Rkey, &issue.IssueId, &createdAt, &issue.Title, &issue.Body, &issue.Open)
570
+
func AddIssueComment(e Execer, c IssueComment) (int64, error) {
571
+
result, err := e.Exec(
572
+
`insert into issue_comments (
581
+
values (?, ?, ?, ?, ?, ?, null)
582
+
on conflict(did, rkey) do update set
583
+
issue_at = excluded.issue_at,
584
+
body = excluded.body,
587
+
issue_comments.issue_at != excluded.issue_at
588
+
or issue_comments.body != excluded.body
589
+
or issue_comments.reply_to != excluded.reply_to
591
+
else issue_comments.edited
598
+
c.Created.Format(time.RFC3339),
599
+
time.Now().Format(time.RFC3339),
524
-
return nil, nil, err
527
-
createdTime, err := time.Parse(time.RFC3339, createdAt)
605
+
id, err := result.LastInsertId()
529
-
return nil, nil, err
531
-
issue.Created = createdTime
533
-
comments, err := GetComments(e, repoAt, issueId)
535
-
return nil, nil, err
613
+
func DeleteIssueComments(e Execer, filters ...filter) error {
614
+
var conditions []string
616
+
for _, filter := range filters {
617
+
conditions = append(conditions, filter.Condition())
618
+
args = append(args, filter.Arg()...)
538
-
return &issue, comments, nil
622
+
if conditions != nil {
623
+
whereClause = " where " + strings.Join(conditions, " and ")
541
-
func NewIssueComment(e Execer, comment *Comment) error {
542
-
query := `insert into comments (owner_did, repo_at, rkey, issue_id, comment_id, body) values (?, ?, ?, ?, ?, ?)`
626
+
query := fmt.Sprintf(`update issue_comments set body = "", deleted = strftime('%%Y-%%m-%%dT%%H:%%M:%%SZ', 'now') %s`, whereClause)
628
+
_, err := e.Exec(query, args...)
555
-
func GetComments(e Execer, repoAt syntax.ATURI, issueId int) ([]Comment, error) {
556
-
var comments []Comment
632
+
func GetIssueComments(e Execer, filters ...filter) ([]IssueComment, error) {
633
+
var comments []IssueComment
635
+
var conditions []string
637
+
for _, filter := range filters {
638
+
conditions = append(conditions, filter.Condition())
639
+
args = append(args, filter.Arg()...)
558
-
rows, err := e.Query(`
643
+
if conditions != nil {
644
+
whereClause = " where " + strings.Join(conditions, " and ")
647
+
query := fmt.Sprintf(`
571
-
repo_at = ? and issue_id = ?
577
-
if err == sql.ErrNoRows {
578
-
return []Comment{}, nil
663
+
rows, err := e.Query(query, args...)
586
-
var comment Comment
587
-
var createdAt string
588
-
var deletedAt, editedAt, rkey sql.NullString
589
-
err := rows.Scan(&comment.OwnerDid, &comment.Issue, &comment.CommentId, &rkey, &comment.Body, &createdAt, &editedAt, &deletedAt)
669
+
var comment IssueComment
671
+
var rkey, edited, deleted, replyTo sql.Null[string]
594
-
createdAtTime, err := time.Parse(time.RFC3339, createdAt)
687
+
// this is a remnant from old times, newer comments always have rkey
689
+
comment.Rkey = rkey.V
598
-
comment.Created = &createdAtTime
692
+
if t, err := time.Parse(time.RFC3339, created); err == nil {
693
+
comment.Created = t
600
-
if deletedAt.Valid {
601
-
deletedTime, err := time.Parse(time.RFC3339, deletedAt.String)
697
+
if t, err := time.Parse(time.RFC3339, edited.V); err == nil {
698
+
comment.Edited = &t
605
-
comment.Deleted = &deletedTime
608
-
if editedAt.Valid {
609
-
editedTime, err := time.Parse(time.RFC3339, editedAt.String)
703
+
if t, err := time.Parse(time.RFC3339, deleted.V); err == nil {
704
+
comment.Deleted = &t
613
-
comment.Edited = &editedTime
617
-
comment.Rkey = rkey.String
709
+
comment.ReplyTo = &replyTo.V
comments = append(comments, comment)
623
-
if err := rows.Err(); err != nil {
715
+
if err = rows.Err(); err != nil {
630
-
func GetComment(e Execer, repoAt syntax.ATURI, issueId, commentId int) (*Comment, error) {
633
-
owner_did, body, rkey, created, deleted, edited
635
-
comments where repo_at = ? and issue_id = ? and comment_id = ?
637
-
row := e.QueryRow(query, repoAt, issueId, commentId)
639
-
var comment Comment
640
-
var createdAt string
641
-
var deletedAt, editedAt, rkey sql.NullString
642
-
err := row.Scan(&comment.OwnerDid, &comment.Body, &rkey, &createdAt, &deletedAt, &editedAt)
722
+
func DeleteIssues(e Execer, filters ...filter) error {
723
+
var conditions []string
725
+
for _, filter := range filters {
726
+
conditions = append(conditions, filter.Condition())
727
+
args = append(args, filter.Arg()...)
647
-
createdTime, err := time.Parse(time.RFC3339, createdAt)
731
+
if conditions != nil {
732
+
whereClause = " where " + strings.Join(conditions, " and ")
651
-
comment.Created = &createdTime
653
-
if deletedAt.Valid {
654
-
deletedTime, err := time.Parse(time.RFC3339, deletedAt.String)
658
-
comment.Deleted = &deletedTime
735
+
query := fmt.Sprintf(`delete from issues %s`, whereClause)
736
+
_, err := e.Exec(query, args...)
661
-
if editedAt.Valid {
662
-
editedTime, err := time.Parse(time.RFC3339, editedAt.String)
666
-
comment.Edited = &editedTime
740
+
func CloseIssues(e Execer, filters ...filter) error {
741
+
var conditions []string
743
+
for _, filter := range filters {
744
+
conditions = append(conditions, filter.Condition())
745
+
args = append(args, filter.Arg()...)
670
-
comment.Rkey = rkey.String
749
+
if conditions != nil {
750
+
whereClause = " where " + strings.Join(conditions, " and ")
673
-
comment.RepoAt = repoAt
674
-
comment.Issue = issueId
675
-
comment.CommentId = commentId
677
-
return &comment, nil
680
-
func EditComment(e Execer, repoAt syntax.ATURI, issueId, commentId int, newBody string) error {
685
-
edited = strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
686
-
where repo_at = ? and issue_id = ? and comment_id = ?
687
-
`, newBody, repoAt, issueId, commentId)
753
+
query := fmt.Sprintf(`update issues set open = 0 %s`, whereClause)
754
+
_, err := e.Exec(query, args...)
691
-
func DeleteComment(e Execer, repoAt syntax.ATURI, issueId, commentId int) error {
696
-
deleted = strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
697
-
where repo_at = ? and issue_id = ? and comment_id = ?
698
-
`, repoAt, issueId, commentId)
702
-
func UpdateCommentByRkey(e Execer, ownerDid, rkey, newBody string) error {
707
-
edited = strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
708
-
where owner_did = ? and rkey = ?
709
-
`, newBody, ownerDid, rkey)
713
-
func DeleteCommentByRkey(e Execer, ownerDid, rkey string) error {
718
-
deleted = strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
719
-
where owner_did = ? and rkey = ?
758
+
func ReopenIssues(e Execer, filters ...filter) error {
759
+
var conditions []string
761
+
for _, filter := range filters {
762
+
conditions = append(conditions, filter.Condition())
763
+
args = append(args, filter.Arg()...)
724
-
func UpdateIssueByRkey(e Execer, ownerDid, rkey, title, body string) error {
725
-
_, err := e.Exec(`update issues set title = ?, body = ? where owner_did = ? and rkey = ?`, title, body, ownerDid, rkey)
767
+
if conditions != nil {
768
+
whereClause = " where " + strings.Join(conditions, " and ")
729
-
func DeleteIssueByRkey(e Execer, ownerDid, rkey string) error {
730
-
_, err := e.Exec(`delete from issues where owner_did = ? and rkey = ?`, ownerDid, rkey)
734
-
func CloseIssue(e Execer, repoAt syntax.ATURI, issueId int) error {
735
-
_, err := e.Exec(`update issues set open = 0 where repo_at = ? and issue_id = ?`, repoAt, issueId)
739
-
func ReopenIssue(e Execer, repoAt syntax.ATURI, issueId int) error {
740
-
_, err := e.Exec(`update issues set open = 1 where repo_at = ? and issue_id = ?`, repoAt, issueId)
771
+
query := fmt.Sprintf(`update issues set open = 1 %s`, whereClause)
772
+
_, err := e.Exec(query, args...)