+8
-9
appview/issues/issues.go
+8
-9
appview/issues/issues.go
···
129
}
130
131
rp.pages.RepoSingleIssue(w, pages.RepoSingleIssueParams{
132
-
LoggedInUser: user,
133
-
RepoInfo: rp.repoResolver.GetRepoInfo(r, user),
134
-
Issue: issue,
135
-
CommentList: issue.CommentList(),
136
-
Backlinks: backlinks,
137
-
OrderedReactionKinds: models.OrderedReactionKinds,
138
-
Reactions: reactionMap,
139
-
UserReacted: userReactions,
140
-
LabelDefs: defs,
141
})
142
}
143
···
129
}
130
131
rp.pages.RepoSingleIssue(w, pages.RepoSingleIssueParams{
132
+
LoggedInUser: user,
133
+
RepoInfo: rp.repoResolver.GetRepoInfo(r, user),
134
+
Issue: issue,
135
+
CommentList: issue.CommentList(),
136
+
Backlinks: backlinks,
137
+
Reactions: reactionMap,
138
+
UserReacted: userReactions,
139
+
LabelDefs: defs,
140
})
141
}
142
-15
appview/knots/knots.go
-15
appview/knots/knots.go
···
40
Knotstream *eventconsumer.Consumer
41
}
42
43
-
type tab = map[string]any
44
-
45
-
var (
46
-
knotsTabs []tab = []tab{
47
-
{"Name": "profile", "Icon": "user"},
48
-
{"Name": "keys", "Icon": "key"},
49
-
{"Name": "emails", "Icon": "mail"},
50
-
{"Name": "notifications", "Icon": "bell"},
51
-
{"Name": "knots", "Icon": "volleyball"},
52
-
{"Name": "spindles", "Icon": "spool"},
53
-
}
54
-
)
55
-
56
func (k *Knots) Router() http.Handler {
57
r := chi.NewRouter()
58
···
84
k.Pages.Knots(w, pages.KnotsParams{
85
LoggedInUser: user,
86
Registrations: registrations,
87
-
Tabs: knotsTabs,
88
Tab: "knots",
89
})
90
}
···
148
Members: members,
149
Repos: repoMap,
150
IsOwner: true,
151
-
Tabs: knotsTabs,
152
Tab: "knots",
153
})
154
}
···
40
Knotstream *eventconsumer.Consumer
41
}
42
43
func (k *Knots) Router() http.Handler {
44
r := chi.NewRouter()
45
···
71
k.Pages.Knots(w, pages.KnotsParams{
72
LoggedInUser: user,
73
Registrations: registrations,
74
Tab: "knots",
75
})
76
}
···
134
Members: members,
135
Repos: repoMap,
136
IsOwner: true,
137
Tab: "knots",
138
})
139
}
+22
appview/pages/funcmap.go
+22
appview/pages/funcmap.go
···
32
"tangled.org/core/crypto"
33
)
34
35
+
type tab map[string]string
36
+
37
func (p *Pages) funcMap() template.FuncMap {
38
return template.FuncMap{
39
"split": func(s string) []string {
···
386
return "error"
387
}
388
return fp
389
+
},
390
+
// constant values used to define a template
391
+
"const": func() map[string]any {
392
+
return map[string]any{
393
+
"OrderedReactionKinds": models.OrderedReactionKinds,
394
+
// would be great to have ordered maps right about now
395
+
"UserSettingsTabs": []tab{
396
+
{"Name": "profile", "Icon": "user"},
397
+
{"Name": "keys", "Icon": "key"},
398
+
{"Name": "emails", "Icon": "mail"},
399
+
{"Name": "notifications", "Icon": "bell"},
400
+
{"Name": "knots", "Icon": "volleyball"},
401
+
{"Name": "spindles", "Icon": "spool"},
402
+
},
403
+
"RepoSettingsTabs": []tab{
404
+
{"Name": "general", "Icon": "sliders-horizontal"},
405
+
{"Name": "access", "Icon": "users"},
406
+
{"Name": "pipelines", "Icon": "layers-2"},
407
+
},
408
+
}
409
},
410
}
411
}
+18
-34
appview/pages/pages.go
+18
-34
appview/pages/pages.go
···
336
337
type UserProfileSettingsParams struct {
338
LoggedInUser *oauth.User
339
-
Tabs []map[string]any
340
Tab string
341
}
342
···
375
type UserKeysSettingsParams struct {
376
LoggedInUser *oauth.User
377
PubKeys []models.PublicKey
378
-
Tabs []map[string]any
379
Tab string
380
}
381
···
386
type UserEmailsSettingsParams struct {
387
LoggedInUser *oauth.User
388
Emails []models.Email
389
-
Tabs []map[string]any
390
Tab string
391
}
392
···
397
type UserNotificationSettingsParams struct {
398
LoggedInUser *oauth.User
399
Preferences *models.NotificationPreferences
400
-
Tabs []map[string]any
401
Tab string
402
}
403
···
417
type KnotsParams struct {
418
LoggedInUser *oauth.User
419
Registrations []models.Registration
420
-
Tabs []map[string]any
421
Tab string
422
}
423
···
431
Members []string
432
Repos map[string][]models.Repo
433
IsOwner bool
434
-
Tabs []map[string]any
435
Tab string
436
}
437
···
450
type SpindlesParams struct {
451
LoggedInUser *oauth.User
452
Spindles []models.Spindle
453
-
Tabs []map[string]any
454
Tab string
455
}
456
···
460
461
type SpindleListingParams struct {
462
models.Spindle
463
-
Tabs []map[string]any
464
Tab string
465
}
466
···
473
Spindle models.Spindle
474
Members []string
475
Repos map[string][]models.Repo
476
-
Tabs []map[string]any
477
Tab string
478
}
479
···
881
SubscribedLabels map[string]struct{}
882
ShouldSubscribeAll bool
883
Active string
884
-
Tabs []map[string]any
885
Tab string
886
Branches []types.Branch
887
}
···
895
LoggedInUser *oauth.User
896
RepoInfo repoinfo.RepoInfo
897
Active string
898
-
Tabs []map[string]any
899
Tab string
900
Collaborators []Collaborator
901
}
···
909
LoggedInUser *oauth.User
910
RepoInfo repoinfo.RepoInfo
911
Active string
912
-
Tabs []map[string]any
913
Tab string
914
Spindles []string
915
CurrentSpindle string
···
947
Backlinks []models.RichReferenceLink
948
LabelDefs map[string]*models.LabelDefinition
949
950
-
OrderedReactionKinds []models.ReactionKind
951
-
Reactions map[models.ReactionKind]models.ReactionDisplayData
952
-
UserReacted map[models.ReactionKind]bool
953
}
954
955
func (p *Pages) RepoSingleIssue(w io.Writer, params RepoSingleIssueParams) error {
···
1104
ResubmitCheck ResubmitResult
1105
Pipelines map[string]models.Pipeline
1106
1107
-
OrderedReactionKinds []models.ReactionKind
1108
-
Reactions map[models.ReactionKind]models.ReactionDisplayData
1109
-
UserReacted map[models.ReactionKind]bool
1110
1111
LabelDefs map[string]*models.LabelDefinition
1112
}
···
1117
}
1118
1119
type RepoPullPatchParams struct {
1120
-
LoggedInUser *oauth.User
1121
-
RepoInfo repoinfo.RepoInfo
1122
-
Pull *models.Pull
1123
-
Stack models.Stack
1124
-
Diff *types.NiceDiff
1125
-
Round int
1126
-
Submission *models.PullSubmission
1127
-
OrderedReactionKinds []models.ReactionKind
1128
-
DiffOpts types.DiffOpts
1129
}
1130
1131
// this name is a mouthful
···
1134
}
1135
1136
type RepoPullInterdiffParams struct {
1137
-
LoggedInUser *oauth.User
1138
-
RepoInfo repoinfo.RepoInfo
1139
-
Pull *models.Pull
1140
-
Round int
1141
-
Interdiff *patchutil.InterdiffResult
1142
-
OrderedReactionKinds []models.ReactionKind
1143
-
DiffOpts types.DiffOpts
1144
}
1145
1146
// this name is a mouthful
···
336
337
type UserProfileSettingsParams struct {
338
LoggedInUser *oauth.User
339
Tab string
340
}
341
···
374
type UserKeysSettingsParams struct {
375
LoggedInUser *oauth.User
376
PubKeys []models.PublicKey
377
Tab string
378
}
379
···
384
type UserEmailsSettingsParams struct {
385
LoggedInUser *oauth.User
386
Emails []models.Email
387
Tab string
388
}
389
···
394
type UserNotificationSettingsParams struct {
395
LoggedInUser *oauth.User
396
Preferences *models.NotificationPreferences
397
Tab string
398
}
399
···
413
type KnotsParams struct {
414
LoggedInUser *oauth.User
415
Registrations []models.Registration
416
Tab string
417
}
418
···
426
Members []string
427
Repos map[string][]models.Repo
428
IsOwner bool
429
Tab string
430
}
431
···
444
type SpindlesParams struct {
445
LoggedInUser *oauth.User
446
Spindles []models.Spindle
447
Tab string
448
}
449
···
453
454
type SpindleListingParams struct {
455
models.Spindle
456
Tab string
457
}
458
···
465
Spindle models.Spindle
466
Members []string
467
Repos map[string][]models.Repo
468
Tab string
469
}
470
···
872
SubscribedLabels map[string]struct{}
873
ShouldSubscribeAll bool
874
Active string
875
Tab string
876
Branches []types.Branch
877
}
···
885
LoggedInUser *oauth.User
886
RepoInfo repoinfo.RepoInfo
887
Active string
888
Tab string
889
Collaborators []Collaborator
890
}
···
898
LoggedInUser *oauth.User
899
RepoInfo repoinfo.RepoInfo
900
Active string
901
Tab string
902
Spindles []string
903
CurrentSpindle string
···
935
Backlinks []models.RichReferenceLink
936
LabelDefs map[string]*models.LabelDefinition
937
938
+
Reactions map[models.ReactionKind]models.ReactionDisplayData
939
+
UserReacted map[models.ReactionKind]bool
940
}
941
942
func (p *Pages) RepoSingleIssue(w io.Writer, params RepoSingleIssueParams) error {
···
1091
ResubmitCheck ResubmitResult
1092
Pipelines map[string]models.Pipeline
1093
1094
+
Reactions map[models.ReactionKind]models.ReactionDisplayData
1095
+
UserReacted map[models.ReactionKind]bool
1096
1097
LabelDefs map[string]*models.LabelDefinition
1098
}
···
1103
}
1104
1105
type RepoPullPatchParams struct {
1106
+
LoggedInUser *oauth.User
1107
+
RepoInfo repoinfo.RepoInfo
1108
+
Pull *models.Pull
1109
+
Stack models.Stack
1110
+
Diff *types.NiceDiff
1111
+
Round int
1112
+
Submission *models.PullSubmission
1113
+
DiffOpts types.DiffOpts
1114
}
1115
1116
// this name is a mouthful
···
1119
}
1120
1121
type RepoPullInterdiffParams struct {
1122
+
LoggedInUser *oauth.User
1123
+
RepoInfo repoinfo.RepoInfo
1124
+
Pull *models.Pull
1125
+
Round int
1126
+
Interdiff *patchutil.InterdiffResult
1127
+
DiffOpts types.DiffOpts
1128
}
1129
1130
// this name is a mouthful
+50
appview/pages/templates/repo/fragments/reactions.html
+50
appview/pages/templates/repo/fragments/reactions.html
···
···
1
+
{{ define "repo/fragments/reactions" }}
2
+
<div class="flex flex-wrap items-center gap-2">
3
+
{{- $reactions := .Reactions -}}
4
+
{{- $userReacted := .UserReacted -}}
5
+
{{- $threadAt := .ThreadAt -}}
6
+
7
+
{{ template "reactionsPopup" }}
8
+
{{ range $kind := const.OrderedReactionKinds }}
9
+
{{ $reactionData := index $reactions $kind }}
10
+
{{ template "repo/fragments/reaction"
11
+
(dict
12
+
"Kind" $kind
13
+
"Count" $reactionData.Count
14
+
"IsReacted" (index $userReacted $kind)
15
+
"ThreadAt" $threadAt
16
+
"Users" $reactionData.Users) }}
17
+
{{ end }}
18
+
</div>
19
+
{{ end }}
20
+
21
+
{{ define "reactionsPopup" }}
22
+
<details
23
+
id="reactionsPopUp"
24
+
class="relative inline-block"
25
+
>
26
+
<summary
27
+
class="flex justify-center items-center min-w-8 min-h-8 rounded border border-gray-200 dark:border-gray-700
28
+
hover:bg-gray-50
29
+
hover:border-gray-300
30
+
dark:hover:bg-gray-700
31
+
dark:hover:border-gray-600
32
+
cursor-pointer list-none"
33
+
>
34
+
{{ i "smile" "size-4" }}
35
+
</summary>
36
+
<div
37
+
class="absolute flex left-0 z-10 mt-4 rounded bg-white dark:bg-gray-800 dark:text-white border border-gray-200 dark:border-gray-700 shadow-lg"
38
+
>
39
+
{{ range $kind := const.OrderedReactionKinds }}
40
+
<button
41
+
id="reactBtn-{{ $kind }}"
42
+
class="size-12 hover:bg-gray-100 dark:hover:bg-gray-700"
43
+
hx-on:click="this.parentElement.parentElement.removeAttribute('open')"
44
+
>
45
+
{{ $kind }}
46
+
</button>
47
+
{{ end }}
48
+
</div>
49
+
</details>
50
+
{{ end }}
-30
appview/pages/templates/repo/fragments/reactionsPopUp.html
-30
appview/pages/templates/repo/fragments/reactionsPopUp.html
···
1
-
{{ define "repo/fragments/reactionsPopUp" }}
2
-
<details
3
-
id="reactionsPopUp"
4
-
class="relative inline-block"
5
-
>
6
-
<summary
7
-
class="flex justify-center items-center min-w-8 min-h-8 rounded border border-gray-200 dark:border-gray-700
8
-
hover:bg-gray-50
9
-
hover:border-gray-300
10
-
dark:hover:bg-gray-700
11
-
dark:hover:border-gray-600
12
-
cursor-pointer list-none"
13
-
>
14
-
{{ i "smile" "size-4" }}
15
-
</summary>
16
-
<div
17
-
class="absolute flex left-0 z-10 mt-4 rounded bg-white dark:bg-gray-800 dark:text-white border border-gray-200 dark:border-gray-700 shadow-lg"
18
-
>
19
-
{{ range $kind := . }}
20
-
<button
21
-
id="reactBtn-{{ $kind }}"
22
-
class="size-12 hover:bg-gray-100 dark:hover:bg-gray-700"
23
-
hx-on:click="this.parentElement.parentElement.removeAttribute('open')"
24
-
>
25
-
{{ $kind }}
26
-
</button>
27
-
{{ end }}
28
-
</div>
29
-
</details>
30
-
{{ end }}
···
+5
-21
appview/pages/templates/repo/issues/issue.html
+5
-21
appview/pages/templates/repo/issues/issue.html
···
35
{{ if .Issue.Body }}
36
<article id="body" class="mt-4 prose dark:prose-invert">{{ .Issue.Body | markdown }}</article>
37
{{ end }}
38
-
<div class="flex flex-wrap gap-2 items-stretch mt-4">
39
-
{{ template "issueReactions" . }}
40
</div>
41
</section>
42
{{ end }}
···
106
{{ i "loader-circle" "size-3 animate-spin hidden group-[.htmx-request]:inline" }}
107
</a>
108
{{ end }}
109
-
110
-
{{ define "issueReactions" }}
111
-
<div class="flex items-center gap-2">
112
-
{{ template "repo/fragments/reactionsPopUp" .OrderedReactionKinds }}
113
-
{{ range $kind := .OrderedReactionKinds }}
114
-
{{ $reactionData := index $.Reactions $kind }}
115
-
{{
116
-
template "repo/fragments/reaction"
117
-
(dict
118
-
"Kind" $kind
119
-
"Count" $reactionData.Count
120
-
"IsReacted" (index $.UserReacted $kind)
121
-
"ThreadAt" $.Issue.AtUri
122
-
"Users" $reactionData.Users)
123
-
}}
124
-
{{ end }}
125
-
</div>
126
-
{{ end }}
127
-
128
129
{{ define "repoAfter" }}
130
<div class="flex flex-col gap-4 mt-4">
···
35
{{ if .Issue.Body }}
36
<article id="body" class="mt-4 prose dark:prose-invert">{{ .Issue.Body | markdown }}</article>
37
{{ end }}
38
+
<div class="mt-4">
39
+
{{ template "repo/fragments/reactions"
40
+
(dict "Reactions" .Reactions
41
+
"UserReacted" .UserReacted
42
+
"ThreadAt" .Issue.AtUri) }}
43
</div>
44
</section>
45
{{ end }}
···
109
{{ i "loader-circle" "size-3 animate-spin hidden group-[.htmx-request]:inline" }}
110
</a>
111
{{ end }}
112
113
{{ define "repoAfter" }}
114
<div class="flex flex-col gap-4 mt-4">
+5
-16
appview/pages/templates/repo/pulls/fragments/pullHeader.html
+5
-16
appview/pages/templates/repo/pulls/fragments/pullHeader.html
···
64
</article>
65
{{ end }}
66
67
-
{{ with .OrderedReactionKinds }}
68
-
<div class="flex items-center gap-2 mt-2">
69
-
{{ template "repo/fragments/reactionsPopUp" . }}
70
-
{{ range $kind := . }}
71
-
{{ $reactionData := index $.Reactions $kind }}
72
-
{{
73
-
template "repo/fragments/reaction"
74
-
(dict
75
-
"Kind" $kind
76
-
"Count" $reactionData.Count
77
-
"IsReacted" (index $.UserReacted $kind)
78
-
"ThreadAt" $.Pull.AtUri
79
-
"Users" $reactionData.Users)
80
-
}}
81
-
{{ end }}
82
</div>
83
-
{{ end }}
84
</section>
85
86
+2
-3
appview/pulls/pulls.go
+2
-3
appview/pulls/pulls.go
-14
appview/repo/settings.go
-14
appview/repo/settings.go
···
22
indigoxrpc "github.com/bluesky-social/indigo/xrpc"
23
)
24
25
-
type tab = map[string]any
26
-
27
-
var (
28
-
// would be great to have ordered maps right about now
29
-
settingsTabs []tab = []tab{
30
-
{"Name": "general", "Icon": "sliders-horizontal"},
31
-
{"Name": "access", "Icon": "users"},
32
-
{"Name": "pipelines", "Icon": "layers-2"},
33
-
}
34
-
)
35
-
36
func (rp *Repo) SetDefaultBranch(w http.ResponseWriter, r *http.Request) {
37
l := rp.logger.With("handler", "SetDefaultBranch")
38
···
262
DefaultLabels: defaultLabels,
263
SubscribedLabels: subscribedLabels,
264
ShouldSubscribeAll: shouldSubscribeAll,
265
-
Tabs: settingsTabs,
266
Tab: "general",
267
})
268
}
···
308
rp.pages.RepoAccessSettings(w, pages.RepoAccessSettingsParams{
309
LoggedInUser: user,
310
RepoInfo: rp.repoResolver.GetRepoInfo(r, user),
311
-
Tabs: settingsTabs,
312
Tab: "access",
313
Collaborators: collaborators,
314
})
···
369
rp.pages.RepoPipelineSettings(w, pages.RepoPipelineSettingsParams{
370
LoggedInUser: user,
371
RepoInfo: rp.repoResolver.GetRepoInfo(r, user),
372
-
Tabs: settingsTabs,
373
Tab: "pipelines",
374
Spindles: spindles,
375
CurrentSpindle: f.Spindle,
···
22
indigoxrpc "github.com/bluesky-social/indigo/xrpc"
23
)
24
25
func (rp *Repo) SetDefaultBranch(w http.ResponseWriter, r *http.Request) {
26
l := rp.logger.With("handler", "SetDefaultBranch")
27
···
251
DefaultLabels: defaultLabels,
252
SubscribedLabels: subscribedLabels,
253
ShouldSubscribeAll: shouldSubscribeAll,
254
Tab: "general",
255
})
256
}
···
296
rp.pages.RepoAccessSettings(w, pages.RepoAccessSettingsParams{
297
LoggedInUser: user,
298
RepoInfo: rp.repoResolver.GetRepoInfo(r, user),
299
Tab: "access",
300
Collaborators: collaborators,
301
})
···
356
rp.pages.RepoPipelineSettings(w, pages.RepoPipelineSettingsParams{
357
LoggedInUser: user,
358
RepoInfo: rp.repoResolver.GetRepoInfo(r, user),
359
Tab: "pipelines",
360
Spindles: spindles,
361
CurrentSpindle: f.Spindle,
-17
appview/settings/settings.go
-17
appview/settings/settings.go
···
35
Config *config.Config
36
}
37
38
-
type tab = map[string]any
39
-
40
-
var (
41
-
settingsTabs []tab = []tab{
42
-
{"Name": "profile", "Icon": "user"},
43
-
{"Name": "keys", "Icon": "key"},
44
-
{"Name": "emails", "Icon": "mail"},
45
-
{"Name": "notifications", "Icon": "bell"},
46
-
{"Name": "knots", "Icon": "volleyball"},
47
-
{"Name": "spindles", "Icon": "spool"},
48
-
}
49
-
)
50
-
51
func (s *Settings) Router() http.Handler {
52
r := chi.NewRouter()
53
···
85
86
s.Pages.UserProfileSettings(w, pages.UserProfileSettingsParams{
87
LoggedInUser: user,
88
-
Tabs: settingsTabs,
89
Tab: "profile",
90
})
91
}
···
104
s.Pages.UserNotificationSettings(w, pages.UserNotificationSettingsParams{
105
LoggedInUser: user,
106
Preferences: prefs,
107
-
Tabs: settingsTabs,
108
Tab: "notifications",
109
})
110
}
···
146
s.Pages.UserKeysSettings(w, pages.UserKeysSettingsParams{
147
LoggedInUser: user,
148
PubKeys: pubKeys,
149
-
Tabs: settingsTabs,
150
Tab: "keys",
151
})
152
}
···
161
s.Pages.UserEmailsSettings(w, pages.UserEmailsSettingsParams{
162
LoggedInUser: user,
163
Emails: emails,
164
-
Tabs: settingsTabs,
165
Tab: "emails",
166
})
167
}
···
35
Config *config.Config
36
}
37
38
func (s *Settings) Router() http.Handler {
39
r := chi.NewRouter()
40
···
72
73
s.Pages.UserProfileSettings(w, pages.UserProfileSettingsParams{
74
LoggedInUser: user,
75
Tab: "profile",
76
})
77
}
···
90
s.Pages.UserNotificationSettings(w, pages.UserNotificationSettingsParams{
91
LoggedInUser: user,
92
Preferences: prefs,
93
Tab: "notifications",
94
})
95
}
···
131
s.Pages.UserKeysSettings(w, pages.UserKeysSettingsParams{
132
LoggedInUser: user,
133
PubKeys: pubKeys,
134
Tab: "keys",
135
})
136
}
···
145
s.Pages.UserEmailsSettings(w, pages.UserEmailsSettingsParams{
146
LoggedInUser: user,
147
Emails: emails,
148
Tab: "emails",
149
})
150
}
-15
appview/spindles/spindles.go
-15
appview/spindles/spindles.go
···
39
Logger *slog.Logger
40
}
41
42
-
type tab = map[string]any
43
-
44
-
var (
45
-
spindlesTabs []tab = []tab{
46
-
{"Name": "profile", "Icon": "user"},
47
-
{"Name": "keys", "Icon": "key"},
48
-
{"Name": "emails", "Icon": "mail"},
49
-
{"Name": "notifications", "Icon": "bell"},
50
-
{"Name": "knots", "Icon": "volleyball"},
51
-
{"Name": "spindles", "Icon": "spool"},
52
-
}
53
-
)
54
-
55
func (s *Spindles) Router() http.Handler {
56
r := chi.NewRouter()
57
···
83
s.Pages.Spindles(w, pages.SpindlesParams{
84
LoggedInUser: user,
85
Spindles: all,
86
-
Tabs: spindlesTabs,
87
Tab: "spindles",
88
})
89
}
···
143
Spindle: spindle,
144
Members: members,
145
Repos: repoMap,
146
-
Tabs: spindlesTabs,
147
Tab: "spindles",
148
})
149
}
···
39
Logger *slog.Logger
40
}
41
42
func (s *Spindles) Router() http.Handler {
43
r := chi.NewRouter()
44
···
70
s.Pages.Spindles(w, pages.SpindlesParams{
71
LoggedInUser: user,
72
Spindles: all,
73
Tab: "spindles",
74
})
75
}
···
129
Spindle: spindle,
130
Members: members,
131
Repos: repoMap,
132
Tab: "spindles",
133
})
134
}