gitlyx / issue_routes.v
215 lines · 202 sloc · 6.81 KB · 03ce80574e9d3cb5892de161e92055e76b30af1c
Raw
1module main
2
3import veb
4import validation
5import api
6
7struct ItemWithUser[T] {
8 item T
9 user User
10}
11
12type IssueWithUser = ItemWithUser[Issue]
13type CommentWithUser = ItemWithUser[Comment]
14
15@['/api/v1/:username/:repo_name/issues/count']
16fn (mut app App) handle_issues_count(username string, repo_name string) veb.Result {
17 has_access := app.has_user_repo_read_access_by_repo_name(ctx, ctx.user.id, username, repo_name)
18 if !has_access {
19 return ctx.json_error('Not found')
20 }
21 repo := app.find_repo_by_name_and_username(repo_name, username) or {
22 return ctx.json_error('Not found')
23 }
24 count := app.get_repo_issue_count(repo.id)
25 return ctx.json(api.ApiIssueCount{
26 success: true
27 result: count
28 })
29}
30
31@['/:username/:repo_name/issues/new']
32pub fn (mut app App) new_issue(mut ctx Context, username string, repo_name string) veb.Result {
33 if !ctx.logged_in {
34 return ctx.not_found()
35 }
36 repo := app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() }
37 ctx.set_page_title(['New issue', '${repo.user_name}/${repo.name}'])
38 return $veb.html()
39}
40
41@['/:username/issues']
42pub fn (mut app App) handle_get_user_issues(mut ctx Context, username string) veb.Result {
43 return app.user_issues(mut ctx, username, 'created')
44}
45
46@['/:username/:repo_name/issues'; post]
47pub fn (mut app App) handle_add_repo_issue(mut ctx Context, username string, repo_name string) veb.Result {
48 // TODO: use captcha instead of user restrictions
49 if !ctx.logged_in || (ctx.logged_in && ctx.user.posts_count >= posts_per_day) {
50 return ctx.redirect_to_index()
51 }
52 repo := app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() }
53 title := ctx.form['title']
54 text := ctx.form['text']
55 is_title_empty := validation.is_string_empty(title)
56 is_text_empty := validation.is_string_empty(text)
57 if is_title_empty || is_text_empty {
58 return ctx.redirect('/${username}/${repo_name}/issues/new')
59 }
60 app.increment_user_post(mut ctx.user) or { app.info(err.str()) }
61 app.add_issue(repo.id, ctx.user.id, title, text) or { app.info(err.str()) }
62 app.increment_repo_issues(repo.id) or { app.info(err.str()) }
63 app.dispatch_webhook(repo.id, 'issue', WebhookIssuePayload{
64 action: 'opened'
65 repo: '${username}/${repo_name}'
66 title: title
67 author: ctx.user.username
68 })
69 has_first_issue_activity := app.has_activity(ctx.user.id, 'first_issue')
70 if !has_first_issue_activity {
71 app.add_activity(ctx.user.id, 'first_issue') or { app.info(err.str()) }
72 }
73 return ctx.redirect('/${username}/${repo_name}/issues')
74}
75
76@['/:username/:repo_name/issues']
77pub fn (mut app App) handle_get_repo_issues(mut ctx Context, username string, repo_name string) veb.Result {
78 return app.issues(mut ctx, username, repo_name, '0')
79}
80
81@['/:username/:repo_name/issues/:page']
82pub fn (mut app App) issues(mut ctx Context, username string, repo_name string, page string) veb.Result {
83 repo := app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() }
84 page_i := page.int()
85 mut issues_with_users := []IssueWithUser{}
86 mut issue := Issue{}
87 mut user := User{}
88 repo_issues := app.find_repo_issues_as_page(repo.id, page_i)
89 mut i := 0
90 for i = 0; i < repo_issues.len; i++ {
91 issue = repo_issues[i]
92 user = app.get_user_by_id(issue.author_id) or { continue }
93 issue.labels = app.get_issue_labels(issue.id)
94 issue.repo_author = repo.user_name
95 issue.repo_name = repo.name
96 issues_with_users << IssueWithUser{
97 item: issue
98 user: user
99 }
100 }
101 show_repo_link := false
102 mut first := false
103 mut last := false
104 if repo.nr_open_issues > commits_per_page {
105 offset := page_i * commits_per_page
106 delta := repo.nr_open_issues - offset
107 if delta > 0 {
108 if delta == repo.nr_open_issues && page_i == 0 {
109 first = true
110 } else {
111 last = true
112 }
113 }
114 } else {
115 last = true
116 first = true
117 }
118 page_count := calculate_pages(repo.nr_open_issues, commits_per_page)
119 prev_page, next_page := generate_prev_next_pages(page_i)
120 ctx.set_page_title(['Issues', '${repo.user_name}/${repo.name}'])
121 return $veb.html()
122}
123
124@['/:username/:repo_name/issue/:id']
125pub fn (mut app App) issue(mut ctx Context, username string, repo_name string, id string) veb.Result {
126 repo := app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() }
127 issue := app.find_issue_by_id(id.int()) or { return ctx.not_found() }
128 issue_author := app.get_user_by_id(issue.author_id) or { return ctx.not_found() }
129 ctx.set_page_title(['${issue.title} #${issue.id}', '${repo.user_name}/${repo.name}'])
130 mut comments_with_users := []CommentWithUser{}
131 mut comment := Comment{}
132 mut comment_author := User{}
133 issue_comments := app.get_all_issue_comments(issue.id)
134 mut i := 0
135 for i = 0; i < issue_comments.len; i++ {
136 comment = issue_comments[i]
137 comment_author = app.get_user_by_id(comment.author_id) or { continue }
138 comments_with_users << CommentWithUser{
139 item: comment
140 user: comment_author
141 }
142 }
143 return $veb.html()
144}
145
146@['/:username/issues/:tab']
147pub fn (mut app App) user_issues(mut ctx Context, username string, tab string) veb.Result {
148 if !ctx.logged_in {
149 return ctx.not_found()
150 }
151 if ctx.user.username != username {
152 return ctx.not_found()
153 }
154 exists, user := app.check_username(username)
155 if !exists {
156 return ctx.not_found()
157 }
158 current_tab := if tab in ['assigned', 'created', 'mentioned', 'activity'] {
159 tab
160 } else {
161 'created'
162 }
163 mut issues := match current_tab {
164 'assigned' { []Issue{} }
165 'mentioned' { app.find_user_mentioned_issues(user.username) }
166 'activity' { app.find_user_recent_issues(user.id) }
167 else { app.find_user_issues(user.id) }
168 }
169
170 mut issue_repo := Repo{}
171 for mut issue in issues {
172 issue_repo = app.find_repo_by_id(issue.repo_id) or { continue }
173 issue.repo_author = issue_repo.user_name
174 issue.repo_name = issue_repo.name
175 issue.labels = app.get_issue_labels(issue.id)
176 }
177 mut issues_with_users := []IssueWithUser{}
178 for issue in issues {
179 issue_author := app.get_user_by_id(issue.author_id) or { continue }
180 issues_with_users << IssueWithUser{
181 item: issue
182 user: issue_author
183 }
184 }
185 tab_assigned_class := if current_tab == 'assigned' {
186 'user-issues-sidebar__item user-issues-sidebar__item--active'
187 } else {
188 'user-issues-sidebar__item'
189 }
190 tab_created_class := if current_tab == 'created' {
191 'user-issues-sidebar__item user-issues-sidebar__item--active'
192 } else {
193 'user-issues-sidebar__item'
194 }
195 tab_mentioned_class := if current_tab == 'mentioned' {
196 'user-issues-sidebar__item user-issues-sidebar__item--active'
197 } else {
198 'user-issues-sidebar__item'
199 }
200 tab_activity_class := if current_tab == 'activity' {
201 'user-issues-sidebar__item user-issues-sidebar__item--active'
202 } else {
203 'user-issues-sidebar__item'
204 }
205 show_repo_link := true
206 tab_title := match current_tab {
207 'assigned' { 'Assigned issues' }
208 'mentioned' { 'Mentioned issues' }
209 'activity' { 'Issue activity' }
210 else { 'Created issues' }
211 }
212
213 ctx.set_page_title([tab_title, user.username])
214 return $veb.html()
215}
216