alpha
Login
or
Join now
tangled.org
/
core
Star
12
Fork
68
Atom
Configure Feed
Issues
Pull Requests
Commits
Tags
Feed URL
Select the types of activity you want to include in your feed.
Monorepo for Tangled
tangled.org
Star
12
Fork
68
Atom
Configure Feed
Issues
Pull Requests
Commits
Tags
Feed URL
Select the types of activity you want to include in your feed.
Overview
Issues
17
Pulls
28
Pipelines
appview: render single pull
author
Anirudh Oppiliappan
committer
Akshay
date
1 year ago
(Mar 17, 2025, 7:23 PM UTC)
commit
cc07f50b
cc07f50b4874936bede1be922e9b4a89f1074a39
parent
2b49f260
2b49f26017efc7f455cb44b525f2c9f3bca79acc
+302
-186
10 changed files
Expand all
Collapse all
Unified
Split
appview
db
pulls.go
pages
pages.go
templates
repo
pulls
new.html
pull.html
settings.html
state
repo.go
router.go
state.go
input.css
knotserver
routes.go
+5
appview/db/pulls.go
Reviewed
···
233
233
return err
234
234
}
235
235
236
236
+
func MergePull(e Execer, repoAt syntax.ATURI, pullId int) error {
237
237
+
_, err := e.Exec(`update pulls set open = 2 where repo_at = ? and pull_id = ?`, repoAt, pullId)
238
238
+
return err
239
239
+
}
240
240
+
236
241
type PullCount struct {
237
242
Open int
238
243
Closed int
+17
-6
appview/pages/pages.go
Reviewed
···
531
531
}
532
532
533
533
type RepoSinglePullParams struct {
534
534
-
LoggedInUser *auth.User
535
535
-
RepoInfo RepoInfo
536
536
-
DidHandleMap map[string]string
537
537
-
Pull db.Pull
538
538
-
Comments []db.PullComment
539
539
-
Active string
534
534
+
LoggedInUser *auth.User
535
535
+
RepoInfo RepoInfo
536
536
+
DidHandleMap map[string]string
537
537
+
Pull db.Pull
538
538
+
State string
539
539
+
PullOwnerHandle string
540
540
+
Comments []db.PullComment
541
541
+
Active string
542
542
+
MergeCheck types.MergeCheckResponse
540
543
}
541
544
542
545
func (p *Pages) RepoSinglePull(w io.Writer, params RepoSinglePullParams) error {
546
546
+
switch params.Pull.Open {
547
547
+
case 0:
548
548
+
params.State = "close"
549
549
+
case 1:
550
550
+
params.State = "open"
551
551
+
case 2:
552
552
+
params.State = "merged"
553
553
+
}
543
554
params.Active = "pulls"
544
555
return p.executeRepo("repo/pulls/pull", w, params)
545
556
}
+16
-7
appview/pages/templates/repo/pulls/new.html
Reviewed
···
10
10
<div>
11
11
<label for="title">title</label>
12
12
<input type="text" name="title" id="title" class="w-full" />
13
13
+
14
14
+
<label for="targetBranch">target branch</label>
15
15
+
<p class="text-gray-500">
16
16
+
The branch you want to make your change against.
17
17
+
</p>
13
18
<input type="text" name="targetBranch" id="targetBranch" />
14
19
</div>
15
20
<div>
···
21
26
class="w-full resize-y"
22
27
placeholder="Describe your change. Markdown is supported."
23
28
></textarea>
24
24
-
<textarea
25
25
-
name="patch"
26
26
-
id="patch"
27
27
-
rows="10"
28
28
-
class="w-full resize-y font-mono"
29
29
-
placeholder="Paste your git-format-patch output here."
30
30
-
></textarea>
29
29
+
30
30
+
<div class="mt-4">
31
31
+
<label for="patch">paste your patch here</label>
32
32
+
<textarea
33
33
+
name="patch"
34
34
+
id="patch"
35
35
+
rows="10"
36
36
+
class="w-full resize-y font-mono"
37
37
+
placeholder="Paste your git-format-patch output here."
38
38
+
></textarea>
39
39
+
</div>
31
40
</div>
32
41
<div>
33
42
<button type="submit" class="btn">create</button>
+47
-2
appview/pages/templates/repo/pulls/pull.html
Reviewed
···
1
1
{{ define "title" }}
2
2
-
{{ .Pull.Title }} ·
2
2
+
{{ .Pull.Title }} · pull #{{ .Pull.PullId }} ·
3
3
{{ .RepoInfo.FullName }}
4
4
{{ end }}
5
5
···
8
8
{{ .Pull.Title }}
9
9
<span class="text-gray-400">#{{ .Pull.PullId }}</span>
10
10
</h1>
11
11
-
12
11
{{ $bgColor := "bg-gray-800" }}
13
12
{{ $icon := "ban" }}
14
13
{{ if eq .State "open" }}
15
14
{{ $bgColor = "bg-green-600" }}
16
15
{{ $icon = "circle-dot" }}
16
16
+
{{ else if eq .State "merged" }}
17
17
+
{{ $bgColor = "bg-purple-600" }}
18
18
+
{{ $icon = "git-merge" }}
17
19
{{ end }}
18
20
19
21
···
46
48
</article>
47
49
{{ end }}
48
50
</section>
51
51
+
52
52
+
<div>
53
53
+
<details>
54
54
+
<summary
55
55
+
class="list-none cursor-pointer sticky top-0 bg-white rounded-sm px-3 py-2 border border-gray-200 flex items-center text-gray-700 hover:bg-gray-50 transition-colors"
56
56
+
>
57
57
+
<i data-lucide="code" class="w-4 h-4 mr-2"></i>
58
58
+
<span>patch</span>
59
59
+
</summary>
60
60
+
<pre class="font-mono overflow-x-scroll bg-gray-50 p-4 rounded-b border border-gray-200 text-sm">
61
61
+
{{- .Pull.Patch -}}
62
62
+
</pre>
63
63
+
</details>
64
64
+
</div>
65
65
+
66
66
+
<div class="mt-4">
67
67
+
{{ if .MergeCheck }}
68
68
+
<div class="rounded-sm border p-4 {{ if .MergeCheck.IsConflicted }}bg-red-50 border-red-200{{ else }}bg-green-50 border-green-200{{ end }}">
69
69
+
<div class="flex items-center gap-2 rounded-sm {{ if .MergeCheck.IsConflicted }}text-red-500{{ else }}text-green-500 {{ end }}">
70
70
+
{{ if .MergeCheck.IsConflicted }}
71
71
+
<i data-lucide="alert-triangle" class="w-4 h-4"></i>
72
72
+
<span class="font-medium">merge conflicts detected</span>
73
73
+
{{ else }}
74
74
+
<i data-lucide="check-circle" class="w-4 h-4"></i>
75
75
+
<span class="font-medium">ready to merge</span>
76
76
+
{{ end }}
77
77
+
</div>
78
78
+
79
79
+
{{ if .MergeCheck.IsConflicted }}
80
80
+
<div class="mt-2">
81
81
+
<ul class="text-sm space-y-1">
82
82
+
{{ range .MergeCheck.Conflicts }}
83
83
+
<li class="flex items-center">
84
84
+
<i data-lucide="file-warning" class="w-3 h-3 mr-1.5 text-red-500"></i>
85
85
+
<span class="font-mono">{{ slice .Filename 0 (sub (len .Filename) 2) }}</span>
86
86
+
</li>
87
87
+
{{ end }}
88
88
+
</ul>
89
89
+
</div>
90
90
+
{{ end }}
91
91
+
</div>
92
92
+
{{ end }}
93
93
+
</div>
49
94
{{ end }}
50
95
51
96
{{ define "repoAfter" }}
+4
-2
appview/pages/templates/settings.html
Reviewed
···
12
12
{{ end }}
13
13
14
14
{{ define "profile" }}
15
15
-
<header class="text-sm font-bold py-2 px-6 uppercase">profile</header>
15
15
+
<<<<<<< HEAD
16
16
+
<h2 class="text-sm font-bold py-2 px-6 uppercase">profile</h2>
16
17
<section class="rounded bg-white drop-shadow-sm px-6 py-4 mb-6 w-full lg:w-fit">
17
18
<dl class="grid grid-cols-[auto_1fr] gap-x-4">
18
19
{{ if .LoggedInUser.Handle }}
···
28
29
{{ end }}
29
30
30
31
{{ define "keys" }}
31
31
-
<header class="text-sm font-bold py-2 px-6 uppercase">ssh keys</header>
32
32
+
<<<<<<< HEAD
33
33
+
<h2 class="text-sm font-bold py-2 px-6 uppercase">ssh keys</h2>
32
34
<section class="rounded bg-white drop-shadow-sm px-6 py-4 mb-6 w-full lg:w-fit">
33
35
<div id="key-list" class="flex flex-col gap-6 mb-8">
34
36
{{ range .PubKeys }}
+40
-6
appview/state/repo.go
Reviewed
···
404
404
return
405
405
}
406
406
407
407
+
pullOwnerIdent, err := s.resolver.ResolveIdent(r.Context(), pr.OwnerDid)
408
408
+
if err != nil {
409
409
+
log.Println("failed to resolve pull owner", err)
410
410
+
}
411
411
+
407
412
identsToResolve := make([]string, len(comments))
408
413
for i, comment := range comments {
409
414
identsToResolve[i] = comment.OwnerDid
···
418
423
}
419
424
}
420
425
421
421
-
s.pages.RepoSinglePull(w, pages.RepoSinglePullParams{
422
422
-
LoggedInUser: user,
423
423
-
RepoInfo: f.RepoInfo(s, user),
424
424
-
Pull: *pr,
425
425
-
Comments: comments,
426
426
+
secret, err := db.GetRegistrationKey(s.db, f.Knot)
427
427
+
if err != nil {
428
428
+
log.Printf("failed to get registration key for %s", f.Knot)
429
429
+
s.pages.Notice(w, "pull", "Failed to load pull request. Try again later.")
430
430
+
return
431
431
+
}
426
432
427
427
-
DidHandleMap: didHandleMap,
433
433
+
var mergeCheckResponse types.MergeCheckResponse
434
434
+
ksClient, err := NewSignedClient(f.Knot, secret, s.config.Dev)
435
435
+
if err == nil {
436
436
+
resp, err := ksClient.MergeCheck([]byte(pr.Patch), pr.OwnerDid, f.RepoName, pr.TargetBranch)
437
437
+
if err != nil {
438
438
+
log.Println("failed to check for mergeability:", err)
439
439
+
} else {
440
440
+
respBody, err := io.ReadAll(resp.Body)
441
441
+
if err != nil {
442
442
+
log.Println("failed to read merge check response body")
443
443
+
} else {
444
444
+
err = json.Unmarshal(respBody, &mergeCheckResponse)
445
445
+
if err != nil {
446
446
+
log.Println("failed to unmarshal merge check response", err)
447
447
+
}
448
448
+
}
449
449
+
}
450
450
+
} else {
451
451
+
log.Printf("failed to setup signed client for %s; ignoring...", f.Knot)
452
452
+
}
453
453
+
454
454
+
s.pages.RepoSinglePull(w, pages.RepoSinglePullParams{
455
455
+
LoggedInUser: user,
456
456
+
RepoInfo: f.RepoInfo(s, user),
457
457
+
Pull: *pr,
458
458
+
Comments: comments,
459
459
+
PullOwnerHandle: pullOwnerIdent.Handle.String(),
460
460
+
DidHandleMap: didHandleMap,
461
461
+
MergeCheck: mergeCheckResponse,
428
462
})
429
463
}
430
464
+164
appview/state/router.go
Reviewed
···
1
1
+
package state
2
2
+
3
3
+
import (
4
4
+
"net/http"
5
5
+
"strings"
6
6
+
7
7
+
"github.com/go-chi/chi/v5"
8
8
+
)
9
9
+
10
10
+
func (s *State) Router() http.Handler {
11
11
+
router := chi.NewRouter()
12
12
+
13
13
+
router.HandleFunc("/*", func(w http.ResponseWriter, r *http.Request) {
14
14
+
pat := chi.URLParam(r, "*")
15
15
+
if strings.HasPrefix(pat, "did:") || strings.HasPrefix(pat, "@") {
16
16
+
s.UserRouter().ServeHTTP(w, r)
17
17
+
} else {
18
18
+
s.StandardRouter().ServeHTTP(w, r)
19
19
+
}
20
20
+
})
21
21
+
22
22
+
return router
23
23
+
}
24
24
+
25
25
+
func (s *State) UserRouter() http.Handler {
26
26
+
r := chi.NewRouter()
27
27
+
28
28
+
// strip @ from user
29
29
+
r.Use(StripLeadingAt)
30
30
+
31
31
+
r.With(ResolveIdent(s)).Route("/{user}", func(r chi.Router) {
32
32
+
r.Get("/", s.ProfilePage)
33
33
+
r.With(ResolveRepoKnot(s)).Route("/{repo}", func(r chi.Router) {
34
34
+
r.Get("/", s.RepoIndex)
35
35
+
r.Get("/commits/{ref}", s.RepoLog)
36
36
+
r.Route("/tree/{ref}", func(r chi.Router) {
37
37
+
r.Get("/", s.RepoIndex)
38
38
+
r.Get("/*", s.RepoTree)
39
39
+
})
40
40
+
r.Get("/commit/{ref}", s.RepoCommit)
41
41
+
r.Get("/branches", s.RepoBranches)
42
42
+
r.Get("/tags", s.RepoTags)
43
43
+
r.Get("/blob/{ref}/*", s.RepoBlob)
44
44
+
45
45
+
r.Route("/issues", func(r chi.Router) {
46
46
+
r.Get("/", s.RepoIssues)
47
47
+
r.Get("/{issue}", s.RepoSingleIssue)
48
48
+
49
49
+
r.Group(func(r chi.Router) {
50
50
+
r.Use(AuthMiddleware(s))
51
51
+
r.Get("/new", s.NewIssue)
52
52
+
r.Post("/new", s.NewIssue)
53
53
+
r.Post("/{issue}/comment", s.IssueComment)
54
54
+
r.Post("/{issue}/close", s.CloseIssue)
55
55
+
r.Post("/{issue}/reopen", s.ReopenIssue)
56
56
+
})
57
57
+
})
58
58
+
59
59
+
r.Route("/pulls", func(r chi.Router) {
60
60
+
r.Get("/", s.RepoPulls)
61
61
+
r.Get("/{pull}", s.RepoSinglePull)
62
62
+
63
63
+
r.Group(func(r chi.Router) {
64
64
+
r.Use(AuthMiddleware(s))
65
65
+
r.Get("/new", s.NewPull)
66
66
+
r.Post("/new", s.NewPull)
67
67
+
// r.Post("/{pull}/comment", s.PullComment)
68
68
+
// r.Post("/{pull}/close", s.ClosePull)
69
69
+
// r.Post("/{pull}/reopen", s.ReopenPull)
70
70
+
// r.Post("/{pull}/merge", s.MergePull)
71
71
+
})
72
72
+
})
73
73
+
74
74
+
// These routes get proxied to the knot
75
75
+
r.Get("/info/refs", s.InfoRefs)
76
76
+
r.Post("/git-upload-pack", s.UploadPack)
77
77
+
78
78
+
// settings routes, needs auth
79
79
+
r.Group(func(r chi.Router) {
80
80
+
r.Use(AuthMiddleware(s))
81
81
+
// repo description can only be edited by owner
82
82
+
r.With(RepoPermissionMiddleware(s, "repo:owner")).Route("/description", func(r chi.Router) {
83
83
+
r.Put("/", s.RepoDescription)
84
84
+
r.Get("/", s.RepoDescription)
85
85
+
r.Get("/edit", s.RepoDescriptionEdit)
86
86
+
})
87
87
+
r.With(RepoPermissionMiddleware(s, "repo:settings")).Route("/settings", func(r chi.Router) {
88
88
+
r.Get("/", s.RepoSettings)
89
89
+
r.With(RepoPermissionMiddleware(s, "repo:invite")).Put("/collaborator", s.AddCollaborator)
90
90
+
})
91
91
+
})
92
92
+
})
93
93
+
})
94
94
+
95
95
+
r.NotFound(func(w http.ResponseWriter, r *http.Request) {
96
96
+
s.pages.Error404(w)
97
97
+
})
98
98
+
99
99
+
return r
100
100
+
}
101
101
+
102
102
+
func (s *State) StandardRouter() http.Handler {
103
103
+
r := chi.NewRouter()
104
104
+
105
105
+
r.Handle("/static/*", s.pages.Static())
106
106
+
107
107
+
r.Get("/", s.Timeline)
108
108
+
109
109
+
r.With(AuthMiddleware(s)).Get("/logout", s.Logout)
110
110
+
111
111
+
r.Route("/login", func(r chi.Router) {
112
112
+
r.Get("/", s.Login)
113
113
+
r.Post("/", s.Login)
114
114
+
})
115
115
+
116
116
+
r.Route("/knots", func(r chi.Router) {
117
117
+
r.Use(AuthMiddleware(s))
118
118
+
r.Get("/", s.Knots)
119
119
+
r.Post("/key", s.RegistrationKey)
120
120
+
121
121
+
r.Route("/{domain}", func(r chi.Router) {
122
122
+
r.Post("/init", s.InitKnotServer)
123
123
+
r.Get("/", s.KnotServerInfo)
124
124
+
r.Route("/member", func(r chi.Router) {
125
125
+
r.Use(RoleMiddleware(s, "server:owner"))
126
126
+
r.Get("/", s.ListMembers)
127
127
+
r.Put("/", s.AddMember)
128
128
+
r.Delete("/", s.RemoveMember)
129
129
+
})
130
130
+
})
131
131
+
})
132
132
+
133
133
+
r.Route("/repo", func(r chi.Router) {
134
134
+
r.Route("/new", func(r chi.Router) {
135
135
+
r.Use(AuthMiddleware(s))
136
136
+
r.Get("/", s.NewRepo)
137
137
+
r.Post("/", s.NewRepo)
138
138
+
})
139
139
+
// r.Post("/import", s.ImportRepo)
140
140
+
})
141
141
+
142
142
+
r.With(AuthMiddleware(s)).Route("/follow", func(r chi.Router) {
143
143
+
r.Post("/", s.Follow)
144
144
+
r.Delete("/", s.Follow)
145
145
+
})
146
146
+
147
147
+
r.With(AuthMiddleware(s)).Route("/star", func(r chi.Router) {
148
148
+
r.Post("/", s.Star)
149
149
+
r.Delete("/", s.Star)
150
150
+
})
151
151
+
152
152
+
r.Route("/settings", func(r chi.Router) {
153
153
+
r.Use(AuthMiddleware(s))
154
154
+
r.Get("/", s.Settings)
155
155
+
r.Put("/keys", s.SettingsKeys)
156
156
+
})
157
157
+
158
158
+
r.Get("/keys/{user}", s.Keys)
159
159
+
160
160
+
r.NotFound(func(w http.ResponseWriter, r *http.Request) {
161
161
+
s.pages.Error404(w)
162
162
+
})
163
163
+
return r
164
164
+
}
-157
appview/state/state.go
Reviewed
···
829
829
830
830
return fmt.Sprintf("https://cdn.bsky.app/img/feed_thumbnail/plain/%s/%s", did, link), nil
831
831
}
832
832
-
833
833
-
func (s *State) Router() http.Handler {
834
834
-
router := chi.NewRouter()
835
835
-
836
836
-
router.HandleFunc("/*", func(w http.ResponseWriter, r *http.Request) {
837
837
-
pat := chi.URLParam(r, "*")
838
838
-
if strings.HasPrefix(pat, "did:") || strings.HasPrefix(pat, "@") {
839
839
-
s.UserRouter().ServeHTTP(w, r)
840
840
-
} else {
841
841
-
s.StandardRouter().ServeHTTP(w, r)
842
842
-
}
843
843
-
})
844
844
-
845
845
-
return router
846
846
-
}
847
847
-
848
848
-
func (s *State) UserRouter() http.Handler {
849
849
-
r := chi.NewRouter()
850
850
-
851
851
-
// strip @ from user
852
852
-
r.Use(StripLeadingAt)
853
853
-
854
854
-
r.With(ResolveIdent(s)).Route("/{user}", func(r chi.Router) {
855
855
-
r.Get("/", s.ProfilePage)
856
856
-
r.With(ResolveRepoKnot(s)).Route("/{repo}", func(r chi.Router) {
857
857
-
r.Get("/", s.RepoIndex)
858
858
-
r.Get("/commits/{ref}", s.RepoLog)
859
859
-
r.Route("/tree/{ref}", func(r chi.Router) {
860
860
-
r.Get("/", s.RepoIndex)
861
861
-
r.Get("/*", s.RepoTree)
862
862
-
})
863
863
-
r.Get("/commit/{ref}", s.RepoCommit)
864
864
-
r.Get("/branches", s.RepoBranches)
865
865
-
r.Get("/tags", s.RepoTags)
866
866
-
r.Get("/blob/{ref}/*", s.RepoBlob)
867
867
-
868
868
-
r.Route("/issues", func(r chi.Router) {
869
869
-
r.Get("/", s.RepoIssues)
870
870
-
r.Get("/{issue}", s.RepoSingleIssue)
871
871
-
872
872
-
r.Group(func(r chi.Router) {
873
873
-
r.Use(AuthMiddleware(s))
874
874
-
r.Get("/new", s.NewIssue)
875
875
-
r.Post("/new", s.NewIssue)
876
876
-
r.Post("/{issue}/comment", s.IssueComment)
877
877
-
r.Post("/{issue}/close", s.CloseIssue)
878
878
-
r.Post("/{issue}/reopen", s.ReopenIssue)
879
879
-
})
880
880
-
})
881
881
-
882
882
-
r.Route("/pulls", func(r chi.Router) {
883
883
-
r.Get("/", s.RepoPulls)
884
884
-
r.Get("/{pull}", s.RepoSinglePull)
885
885
-
886
886
-
r.Group(func(r chi.Router) {
887
887
-
r.Use(AuthMiddleware(s))
888
888
-
r.Get("/new", s.NewPull)
889
889
-
r.Post("/new", s.NewPull)
890
890
-
// r.Post("/{pull}/comment", s.PullComment)
891
891
-
// r.Post("/{pull}/close", s.ClosePull)
892
892
-
// r.Post("/{pull}/reopen", s.ReopenPull)
893
893
-
// r.Post("/{pull}/merge", s.MergePull)
894
894
-
})
895
895
-
})
896
896
-
897
897
-
// These routes get proxied to the knot
898
898
-
r.Get("/info/refs", s.InfoRefs)
899
899
-
r.Post("/git-upload-pack", s.UploadPack)
900
900
-
901
901
-
// settings routes, needs auth
902
902
-
r.Group(func(r chi.Router) {
903
903
-
r.Use(AuthMiddleware(s))
904
904
-
// repo description can only be edited by owner
905
905
-
r.With(RepoPermissionMiddleware(s, "repo:owner")).Route("/description", func(r chi.Router) {
906
906
-
r.Put("/", s.RepoDescription)
907
907
-
r.Get("/", s.RepoDescription)
908
908
-
r.Get("/edit", s.RepoDescriptionEdit)
909
909
-
})
910
910
-
r.With(RepoPermissionMiddleware(s, "repo:settings")).Route("/settings", func(r chi.Router) {
911
911
-
r.Get("/", s.RepoSettings)
912
912
-
r.With(RepoPermissionMiddleware(s, "repo:invite")).Put("/collaborator", s.AddCollaborator)
913
913
-
})
914
914
-
})
915
915
-
})
916
916
-
})
917
917
-
918
918
-
r.NotFound(func(w http.ResponseWriter, r *http.Request) {
919
919
-
s.pages.Error404(w)
920
920
-
})
921
921
-
922
922
-
return r
923
923
-
}
924
924
-
925
925
-
func (s *State) StandardRouter() http.Handler {
926
926
-
r := chi.NewRouter()
927
927
-
928
928
-
r.Handle("/static/*", s.pages.Static())
929
929
-
930
930
-
r.Get("/", s.Timeline)
931
931
-
932
932
-
r.With(AuthMiddleware(s)).Get("/logout", s.Logout)
933
933
-
934
934
-
r.Route("/login", func(r chi.Router) {
935
935
-
r.Get("/", s.Login)
936
936
-
r.Post("/", s.Login)
937
937
-
})
938
938
-
939
939
-
r.Route("/knots", func(r chi.Router) {
940
940
-
r.Use(AuthMiddleware(s))
941
941
-
r.Get("/", s.Knots)
942
942
-
r.Post("/key", s.RegistrationKey)
943
943
-
944
944
-
r.Route("/{domain}", func(r chi.Router) {
945
945
-
r.Post("/init", s.InitKnotServer)
946
946
-
r.Get("/", s.KnotServerInfo)
947
947
-
r.Route("/member", func(r chi.Router) {
948
948
-
r.Use(RoleMiddleware(s, "server:owner"))
949
949
-
r.Get("/", s.ListMembers)
950
950
-
r.Put("/", s.AddMember)
951
951
-
r.Delete("/", s.RemoveMember)
952
952
-
})
953
953
-
})
954
954
-
})
955
955
-
956
956
-
r.Route("/repo", func(r chi.Router) {
957
957
-
r.Route("/new", func(r chi.Router) {
958
958
-
r.Use(AuthMiddleware(s))
959
959
-
r.Get("/", s.NewRepo)
960
960
-
r.Post("/", s.NewRepo)
961
961
-
})
962
962
-
// r.Post("/import", s.ImportRepo)
963
963
-
})
964
964
-
965
965
-
r.With(AuthMiddleware(s)).Route("/follow", func(r chi.Router) {
966
966
-
r.Post("/", s.Follow)
967
967
-
r.Delete("/", s.Follow)
968
968
-
})
969
969
-
970
970
-
r.With(AuthMiddleware(s)).Route("/star", func(r chi.Router) {
971
971
-
r.Post("/", s.Star)
972
972
-
r.Delete("/", s.Star)
973
973
-
})
974
974
-
975
975
-
r.Route("/settings", func(r chi.Router) {
976
976
-
r.Use(AuthMiddleware(s))
977
977
-
r.Get("/", s.Settings)
978
978
-
r.Put("/keys", s.SettingsKeys)
979
979
-
r.Delete("/keys", s.SettingsKeys)
980
980
-
})
981
981
-
982
982
-
r.Get("/keys/{user}", s.Keys)
983
983
-
984
984
-
r.NotFound(func(w http.ResponseWriter, r *http.Request) {
985
985
-
s.pages.Error404(w)
986
986
-
})
987
987
-
return r
988
988
-
}
+5
-5
input.css
Reviewed
···
110
110
font-size: 14px;
111
111
}
112
112
a {
113
113
-
@apply no-underline text-black hover:underline hover:text-gray-800;
113
113
+
@apply no-underline text-black hover:underline hover:text-gray-800;
114
114
}
115
115
116
116
label {
117
117
-
@apply block text-sm text-black;
117
117
+
@apply block mb-2 text-gray-900 text-sm font-bold py-2 uppercase;
118
118
}
119
119
input {
120
120
-
@apply bg-white border border-gray-400 rounded-sm focus:ring-black p-2;
120
120
+
@apply bg-white border border-gray-400 rounded-sm focus:ring-black p-3;
121
121
}
122
122
textarea {
123
123
-
@apply bg-white border border-gray-400 rounded-sm focus:ring-black p-2;
123
123
+
@apply bg-white border border-gray-400 rounded-sm focus:ring-black p-3;
124
124
}
125
125
details summary::-webkit-details-marker {
126
126
-
display: none;
126
126
+
display: none;
127
127
}
128
128
}
129
129
+4
-1
knotserver/routes.go
Reviewed
···
628
628
629
629
err = gr.MergeCheck([]byte(patch), branch)
630
630
if err == nil {
631
631
-
w.WriteHeader(http.StatusOK)
631
631
+
response := types.MergeCheckResponse{
632
632
+
IsConflicted: false,
633
633
+
}
634
634
+
writeJSON(w, response)
632
635
return
633
636
}
634
637