ggdgsdbsdbbb / project_routes.v
175 lines · 163 sloc · 7.09 KB · e5cf6929b726be8619b74a869c136696dfea4546
Raw
1// Copyright (c) 2019-2026 Alexander Medvednikov. All rights reserved.
2// Use of this source code is governed by a GPL license that can be found in the LICENSE file.
3module main
4
5import veb
6import validation
7
8struct ProjectColumnView {
9 column ProjectColumn
10 cards []ProjectCard
11}
12
13@['/:username/:repo_name/projects']
14pub fn (mut app App) handle_get_repo_projects(mut ctx Context, username string, repo_name string) veb.Result {
15 repo := app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() }
16 if !app.has_user_repo_read_access(ctx, ctx.user.id, repo.id) && !repo.is_public {
17 return ctx.not_found()
18 }
19 projects := app.list_repo_projects(repo.id)
20 return $veb.html('templates/projects.html')
21}
22
23@['/:username/:repo_name/projects/new']
24pub fn (mut app App) new_project(mut ctx Context, username string, repo_name string) veb.Result {
25 if !ctx.logged_in {
26 return ctx.redirect_to_login()
27 }
28 repo := app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() }
29 if repo.user_id != ctx.user.id {
30 return ctx.redirect('/${username}/${repo_name}/projects')
31 }
32 return $veb.html('templates/new/project.html')
33}
34
35@['/:username/:repo_name/projects'; post]
36pub fn (mut app App) handle_create_project(mut ctx Context, username string, repo_name string) veb.Result {
37 if !ctx.logged_in {
38 return ctx.redirect_to_login()
39 }
40 repo := app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() }
41 if repo.user_id != ctx.user.id {
42 return ctx.redirect('/${username}/${repo_name}/projects')
43 }
44 name := ctx.form['name']
45 desc := ctx.form['description']
46 if validation.is_string_empty(name) {
47 return ctx.redirect('/${username}/${repo_name}/projects/new')
48 }
49 id := app.add_project(repo.id, name, desc) or {
50 ctx.error('Could not create project')
51 return ctx.redirect('/${username}/${repo_name}/projects/new')
52 }
53 return ctx.redirect('/${username}/${repo_name}/projects/${id}')
54}
55
56@['/:username/:repo_name/projects/:id']
57pub fn (mut app App) view_project(mut ctx Context, username string, repo_name string, id string) veb.Result {
58 repo := app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() }
59 if !app.has_user_repo_read_access(ctx, ctx.user.id, repo.id) && !repo.is_public {
60 return ctx.not_found()
61 }
62 project := app.find_project(id.int()) or { return ctx.not_found() }
63 if project.repo_id != repo.id {
64 return ctx.not_found()
65 }
66 columns := app.list_project_columns(project.id)
67 mut views := []ProjectColumnView{}
68 for col in columns {
69 views << ProjectColumnView{
70 column: col
71 cards: app.list_project_cards(col.id)
72 }
73 }
74 can_edit := ctx.logged_in && repo.user_id == ctx.user.id
75 return $veb.html('templates/project.html')
76}
77
78@['/:username/:repo_name/projects/:id/columns'; post]
79pub fn (mut app App) handle_add_project_column(mut ctx Context, username string, repo_name string, id string) veb.Result {
80 if !ctx.logged_in {
81 return ctx.redirect_to_login()
82 }
83 repo := app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() }
84 project := app.find_project(id.int()) or { return ctx.not_found() }
85 if project.repo_id != repo.id || repo.user_id != ctx.user.id {
86 return ctx.redirect('/${username}/${repo_name}/projects/${id}')
87 }
88 name := ctx.form['name']
89 if validation.is_string_empty(name) {
90 return ctx.redirect('/${username}/${repo_name}/projects/${id}')
91 }
92 pos := app.list_project_columns(project.id).len
93 app.add_project_column(project.id, name, pos) or {}
94 return ctx.redirect('/${username}/${repo_name}/projects/${id}')
95}
96
97@['/:username/:repo_name/projects/:id/columns/:col_id/delete'; post]
98pub fn (mut app App) handle_delete_project_column(mut ctx Context, username string, repo_name string, id string, col_id string) veb.Result {
99 if !ctx.logged_in {
100 return ctx.redirect_to_login()
101 }
102 repo := app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() }
103 project := app.find_project(id.int()) or { return ctx.not_found() }
104 if project.repo_id != repo.id || repo.user_id != ctx.user.id {
105 return ctx.redirect('/${username}/${repo_name}/projects/${id}')
106 }
107 app.delete_project_column(col_id.int()) or {}
108 return ctx.redirect('/${username}/${repo_name}/projects/${id}')
109}
110
111@['/:username/:repo_name/projects/:id/columns/:col_id/cards'; post]
112pub fn (mut app App) handle_add_project_card(mut ctx Context, username string, repo_name string, id string, col_id string) veb.Result {
113 if !ctx.logged_in {
114 return ctx.redirect_to_login()
115 }
116 repo := app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() }
117 project := app.find_project(id.int()) or { return ctx.not_found() }
118 if project.repo_id != repo.id || repo.user_id != ctx.user.id {
119 return ctx.redirect('/${username}/${repo_name}/projects/${id}')
120 }
121 col := app.find_project_column(col_id.int()) or { return ctx.not_found() }
122 if col.project_id != project.id {
123 return ctx.not_found()
124 }
125 title := ctx.form['title']
126 note := ctx.form['note']
127 if validation.is_string_empty(title) {
128 return ctx.redirect('/${username}/${repo_name}/projects/${id}')
129 }
130 app.add_project_card(col.id, title, note) or {}
131 return ctx.redirect('/${username}/${repo_name}/projects/${id}')
132}
133
134@['/:username/:repo_name/projects/:id/cards/:card_id/delete'; post]
135pub fn (mut app App) handle_delete_project_card(mut ctx Context, username string, repo_name string, id string, card_id string) veb.Result {
136 if !ctx.logged_in {
137 return ctx.redirect_to_login()
138 }
139 repo := app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() }
140 project := app.find_project(id.int()) or { return ctx.not_found() }
141 if project.repo_id != repo.id || repo.user_id != ctx.user.id {
142 return ctx.redirect('/${username}/${repo_name}/projects/${id}')
143 }
144 app.delete_project_card(card_id.int()) or {}
145 return ctx.redirect('/${username}/${repo_name}/projects/${id}')
146}
147
148@['/:username/:repo_name/projects/:id/cards/:card_id/move'; post]
149pub fn (mut app App) handle_move_project_card(mut ctx Context, username string, repo_name string, id string, card_id string) veb.Result {
150 if !ctx.logged_in {
151 return ctx.redirect_to_login()
152 }
153 repo := app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() }
154 project := app.find_project(id.int()) or { return ctx.not_found() }
155 if project.repo_id != repo.id || repo.user_id != ctx.user.id {
156 return ctx.redirect('/${username}/${repo_name}/projects/${id}')
157 }
158 new_col := ctx.form['column_id'].int()
159 app.move_project_card(card_id.int(), new_col) or {}
160 return ctx.redirect('/${username}/${repo_name}/projects/${id}')
161}
162
163@['/:username/:repo_name/projects/:id/delete'; post]
164pub fn (mut app App) handle_delete_project(mut ctx Context, username string, repo_name string, id string) veb.Result {
165 if !ctx.logged_in {
166 return ctx.redirect_to_login()
167 }
168 repo := app.find_repo_by_name_and_username(repo_name, username) or { return ctx.not_found() }
169 project := app.find_project(id.int()) or { return ctx.not_found() }
170 if project.repo_id != repo.id || repo.user_id != ctx.user.id {
171 return ctx.redirect('/${username}/${repo_name}/projects/${id}')
172 }
173 app.delete_project(project.id) or {}
174 return ctx.redirect('/${username}/${repo_name}/projects')
175}
176