... | ... |
@@ -431,7 +431,8 @@ sub startup { |
431 | 431 |
$r->get('/issues' => sub { shift->render_maybe('/issues') })->to(tab => 'issues'); |
432 | 432 |
|
433 | 433 |
# New issue |
434 |
- $r->get('/issues/new' => sub { shift->render_maybe('/issues/new') })->to(tab => 'issues'); |
|
434 |
+ $r->any('/issues/new' => sub { shift->render_maybe('/issues/new') })->to(tab => 'issues'); |
|
435 |
+ $r->get('/issues/:number' => sub { shift->render_maybe('/issue') })->to(tab => 'issues'); |
|
435 | 436 |
|
436 | 437 |
# Pull requests |
437 | 438 |
$r->get('/pulls' => sub { shift->render_maybe('/pulls') })->to(tab => 'pulls'); |
... | ... |
@@ -124,7 +124,7 @@ |
124 | 124 |
<li class="<%= $tab eq 'issues' ? 'active' : '' %>"> |
125 | 125 |
<a href="<%= url_for("/$user_id/$project_id/issues") %>"> |
126 | 126 |
<i class="icon-tasks"></i> |
127 |
- Issue |
|
127 |
+ Issues |
|
128 | 128 |
</a> |
129 | 129 |
</li> |
130 | 130 |
<li class="<%= $tab eq 'pulls' ? 'active' : '' %>"> |
... | ... |
@@ -0,0 +1,18 @@ |
1 |
+<% |
|
2 |
+ # API |
|
3 |
+ my $api = gitprep_api; |
|
4 |
+ |
|
5 |
+ # Parameters |
|
6 |
+ my $user_id = param('user'); |
|
7 |
+ my $project_id = param('project'); |
|
8 |
+ my $issue_number = param('number'); |
|
9 |
+ |
|
10 |
+ layout 'common', title => "Issue - $user_id/$project_id #$issue_number"; |
|
11 |
+%> |
|
12 |
+ |
|
13 |
+%= include '/include/header'; |
|
14 |
+ |
|
15 |
+<div class="container"> |
|
16 |
+</div> |
|
17 |
+ |
|
18 |
+%= include '/include/footer'; |
... | ... |
@@ -75,7 +75,7 @@ |
75 | 75 |
%> |
76 | 76 |
<li> |
77 | 77 |
<div class="pulls-title"> |
78 |
- <a href="<%= "/$user_id/$project_id/pull/$issue->{number}" %>"> |
|
78 |
+ <a href="<%= "/$user_id/$project_id/issues/$issue->{number}" %>"> |
|
79 | 79 |
<b><%= $issue->{title} %></b> |
80 | 80 |
</a> |
81 | 81 |
</div> |
... | ... |
@@ -6,20 +6,114 @@ |
6 | 6 |
my $user_id = param('user'); |
7 | 7 |
my $project_id = param('project'); |
8 | 8 |
my $issue_number = param('number'); |
9 |
+ |
|
10 |
+ my $errors; |
|
11 |
+ if (lc $self->req->method eq 'post') { |
|
12 |
+ my $op = param('op'); |
|
9 | 13 |
|
14 |
+ if ($op eq 'create') { |
|
15 |
+ |
|
16 |
+ # Parameters |
|
17 |
+ my $title = param('title'); |
|
18 |
+ my $message = param('message'); |
|
19 |
+ |
|
20 |
+ # Validation |
|
21 |
+ my $vc = app->vc; |
|
22 |
+ my $validation = $vc->validation; |
|
23 |
+ |
|
24 |
+ # Check title |
|
25 |
+ if (!(defined $title && length $title)) { |
|
26 |
+ $validation->add_failed(title => 'title is empty'); |
|
27 |
+ } |
|
28 |
+ elsif (length $title > 300) { |
|
29 |
+ $validation->add_failed(title => 'title is too long'); |
|
30 |
+ } |
|
31 |
+ |
|
32 |
+ # Message |
|
33 |
+ if (!(defined $message && length $message)) { |
|
34 |
+ $message = ''; |
|
35 |
+ if (length $message > 1000) { |
|
36 |
+ $validation->add_failed(message => 'message is too long'); |
|
37 |
+ } |
|
38 |
+ } |
|
39 |
+ |
|
40 |
+ if ($validation->is_valid) { |
|
41 |
+ my $project_row_id = app->dbi->model('project')->select( |
|
42 |
+ 'project.row_id', |
|
43 |
+ where => {'user.id' => $user_id, 'project.id' => $project_id} |
|
44 |
+ )->value; |
|
45 |
+ |
|
46 |
+ my $issue; |
|
47 |
+ my $now_tm = Time::Moment->now_utc; |
|
48 |
+ my $now_epoch = $now_tm->epoch; |
|
49 |
+ my $session_user_row_id = $api->session_user_row_id; |
|
50 |
+ my $issue_number; |
|
51 |
+ |
|
52 |
+ app->dbi->connector->txn(sub { |
|
53 |
+ |
|
54 |
+ # issue number |
|
55 |
+ $issue_number = app->dbi->model('issue')->select( |
|
56 |
+ 'max(number)', |
|
57 |
+ where => {project => $project_row_id}, |
|
58 |
+ append => 'group by project' |
|
59 |
+ )->value; |
|
60 |
+ $issue_number++; |
|
61 |
+ |
|
62 |
+ # New issue |
|
63 |
+ my $new_issue = { |
|
64 |
+ title => $title, |
|
65 |
+ open => 1, |
|
66 |
+ open_time => $now_epoch, |
|
67 |
+ open_user => $session_user_row_id, |
|
68 |
+ pull_request => 0, |
|
69 |
+ project => $project_row_id, |
|
70 |
+ number => $issue_number |
|
71 |
+ }; |
|
72 |
+ app->dbi->model('issue')->insert($new_issue); |
|
73 |
+ my $new_issue_row_id = app->dbi->execute("select LAST_INSERT_ROWID()")->value; |
|
74 |
+ |
|
75 |
+ # New issue message |
|
76 |
+ my $new_issue_message = { |
|
77 |
+ issue => $new_issue_row_id, |
|
78 |
+ number => 1, |
|
79 |
+ message => $message, |
|
80 |
+ create_time => $now_epoch, |
|
81 |
+ update_time => $now_epoch, |
|
82 |
+ user => $session_user_row_id |
|
83 |
+ }; |
|
84 |
+ |
|
85 |
+ app->dbi->model('issue_message')->insert($new_issue_message); |
|
86 |
+ }); |
|
87 |
+ |
|
88 |
+ $self->redirect_to("/$user_id/$project_id/issues/$issue_number"); |
|
89 |
+ return; |
|
90 |
+ } |
|
91 |
+ else { |
|
92 |
+ $errors = $validation->messages; |
|
93 |
+ } |
|
94 |
+ } |
|
95 |
+ } |
|
96 |
+ |
|
10 | 97 |
layout 'common', title => "New issue - $user_id/$project_id"; |
11 | 98 |
%> |
12 |
- <div class="compare-open-pull-request"> |
|
13 |
- <form action="<%= url_for %>" method="post"> |
|
14 |
- <%= hidden_field op => 'create-pull-request' %> |
|
15 |
- <div class="compare-open-pull-request-title"> |
|
16 |
- <%= text_field 'title' %> |
|
17 |
- </div> |
|
18 |
- <div class="compare-open-pull-request-message"> |
|
19 |
- <%= text_area 'message' %> |
|
20 |
- </div> |
|
21 |
- <div class="compare-open-pull-request-button"> |
|
22 |
- <%= submit_button 'Create pull request', class => 'btn btn-success' %> |
|
23 |
- </div> |
|
24 |
- </form> |
|
25 |
- </div> |
|
99 |
+ |
|
100 |
+%= include '/include/header'; |
|
101 |
+<div class="container"> |
|
102 |
+ %= include '/include/errors', errors => $errors; |
|
103 |
+ <div class="compare-open-pull-request"> |
|
104 |
+ <form action="<%= url_for %>" method="post"> |
|
105 |
+ <%= hidden_field op => 'create' %> |
|
106 |
+ <div class="compare-open-pull-request-title"> |
|
107 |
+ <%= text_field 'title' %> |
|
108 |
+ </div> |
|
109 |
+ <div class="compare-open-pull-request-message"> |
|
110 |
+ <%= text_area 'message' %> |
|
111 |
+ </div> |
|
112 |
+ <div class="compare-open-pull-request-button"> |
|
113 |
+ <%= submit_button 'Submit new issue', class => 'btn btn-success' %> |
|
114 |
+ </div> |
|
115 |
+ </form> |
|
116 |
+ </div> |
|
117 |
+</div> |
|
118 |
+ |
|
119 |
+%= include '/include/footer'; |