[Notice] Announcing the End of Demo Server [Read me]

issue,posting: refactoring.
Between controllers for issue and posting, * Make them be similar to each other. * Remove duplication
@0d498b808cd85ab3d18f499be6b503b5d83feedf
--- app/controllers/AbstractPostingApp.java
+++ app/controllers/AbstractPostingApp.java
... | ... | @@ -1,8 +1,13 @@ |
1 | 1 |
package controllers; |
2 | 2 |
|
3 |
+import play.db.ebean.Model; |
|
4 |
+ |
|
5 |
+import models.resource.Resource; |
|
6 |
+ |
|
3 | 7 |
import models.*; |
4 | 8 |
import models.enumeration.Direction; |
5 | 9 |
import models.enumeration.Operation; |
10 |
+import models.enumeration.ResourceType; |
|
6 | 11 |
|
7 | 12 |
import play.data.Form; |
8 | 13 |
import play.mvc.Call; |
... | ... | @@ -33,11 +38,8 @@ |
33 | 38 |
} |
34 | 39 |
} |
35 | 40 |
|
36 |
- public static Result newComment(Comment comment, Form<? extends Comment> commentForm, Call redirectTo, Callback updateCommentContainer) throws IOException { |
|
37 |
- if (session(UserApp.SESSION_USERID) == null) { |
|
38 |
- flash(Constants.WARNING, "user.login.alert"); |
|
39 |
- return redirect(redirectTo); |
|
40 |
- } |
|
41 |
+ public static Result newComment(Comment comment, Form<? extends Comment> commentForm, Call redirectTo, Callback containerUpdater) throws IOException { |
|
42 |
+ Project project = comment.asResource().getProject(); |
|
41 | 43 |
|
42 | 44 |
if (commentForm.hasErrors()) { |
43 | 45 |
flash(Constants.WARNING, "board.comment.empty"); |
... | ... | @@ -45,8 +47,7 @@ |
45 | 47 |
} |
46 | 48 |
|
47 | 49 |
comment.setAuthor(UserApp.currentUser()); |
48 |
- updateCommentContainer.run(); // this updates comment.issue or comment.posting; |
|
49 |
- Project project = comment.asResource().getProject(); |
|
50 |
+ containerUpdater.run(); // this updates comment.issue or comment.posting; |
|
50 | 51 |
comment.save(); |
51 | 52 |
|
52 | 53 |
// Attach all of the files in the current user's temporary storage. |
... | ... | @@ -55,26 +56,12 @@ |
55 | 56 |
return redirect(redirectTo); |
56 | 57 |
} |
57 | 58 |
|
58 |
- public static Result deletePosting(AbstractPosting posting, Call redirectTo) { |
|
59 |
- if (!AccessControl.isAllowed(UserApp.currentUser(), posting.asResource(), Operation.DELETE)) { |
|
59 |
+ protected static Result delete(Model target, Resource resource, Call redirectTo) { |
|
60 |
+ if (!AccessControl.isAllowed(UserApp.currentUser(), resource, Operation.DELETE)) { |
|
60 | 61 |
return forbidden(); |
61 | 62 |
} |
62 | 63 |
|
63 |
- posting.delete(); |
|
64 |
- |
|
65 |
- Attachment.deleteAll(posting.asResource().getType(), posting.id); |
|
66 |
- |
|
67 |
- return redirect(redirectTo); |
|
68 |
- } |
|
69 |
- |
|
70 |
- public static Result deleteComment(Comment comment, Call redirectTo) { |
|
71 |
- if (!AccessControl.isAllowed(UserApp.currentUser(), comment.asResource(), Operation.DELETE)) { |
|
72 |
- return forbidden(); |
|
73 |
- } |
|
74 |
- |
|
75 |
- comment.delete(); |
|
76 |
- |
|
77 |
- Attachment.deleteAll(comment.asResource().getType(), comment.id); |
|
64 |
+ target.delete(); |
|
78 | 65 |
|
79 | 66 |
return redirect(redirectTo); |
80 | 67 |
} |
--- app/controllers/BoardApp.java
+++ app/controllers/BoardApp.java
... | ... | @@ -14,8 +14,11 @@ |
14 | 14 |
import models.enumeration.Direction; |
15 | 15 |
import models.enumeration.Matching; |
16 | 16 |
import views.html.board.editPost; |
17 |
+import views.html.board.post; |
|
17 | 18 |
import views.html.board.newPost; |
18 | 19 |
import views.html.board.postList; |
20 |
+import views.html.board.notExistingPage; |
|
21 |
+import views.html.project.unauthorized; |
|
19 | 22 |
|
20 | 23 |
import utils.AccessControl; |
21 | 24 |
import utils.Callback; |
... | ... | @@ -49,14 +52,15 @@ |
49 | 52 |
} |
50 | 53 |
|
51 | 54 |
public static Result posts(String userName, String projectName, int pageNum) { |
52 |
- Form<SearchCondition> postParamForm = new Form<SearchCondition>(SearchCondition.class); |
|
53 |
- SearchCondition searchCondition = postParamForm.bindFromRequest().get(); |
|
54 |
- searchCondition.pageNum = pageNum - 1; |
|
55 | 55 |
Project project = ProjectApp.getProject(userName, projectName); |
56 | 56 |
|
57 | 57 |
if (!AccessControl.isAllowed(UserApp.currentUser(), project.asResource(), Operation.READ)) { |
58 | 58 |
return unauthorized(views.html.project.unauthorized.render(project)); |
59 | 59 |
} |
60 |
+ |
|
61 |
+ Form<SearchCondition> postParamForm = new Form<SearchCondition>(SearchCondition.class); |
|
62 |
+ SearchCondition searchCondition = postParamForm.bindFromRequest().get(); |
|
63 |
+ searchCondition.pageNum = pageNum - 1; |
|
60 | 64 |
|
61 | 65 |
ExpressionList<Posting> el = searchCondition.asExpressionList(project); |
62 | 66 |
Page<Posting> posts = el.findPagingList(ITEMS_PER_PAGE).getPage(searchCondition.pageNum); |
... | ... | @@ -81,21 +85,21 @@ |
81 | 85 |
public static Result newPost(String userName, String projectName) { |
82 | 86 |
Form<Posting> postForm = new Form<Posting>(Posting.class).bindFromRequest(); |
83 | 87 |
Project project = ProjectApp.getProject(userName, projectName); |
88 |
+ |
|
84 | 89 |
if (postForm.hasErrors()) { |
85 |
- flash(Constants.WARNING, "board.post.empty"); |
|
86 |
- |
|
87 |
- return redirect(routes.BoardApp.newPost(userName, projectName)); |
|
88 |
- } else { |
|
89 |
- Posting post = postForm.get(); |
|
90 |
- post.createdDate = JodaDateUtil.now(); |
|
91 |
- post.setAuthor(UserApp.currentUser()); |
|
92 |
- post.project = project; |
|
93 |
- |
|
94 |
- post.save(); |
|
95 |
- |
|
96 |
- // Attach all of the files in the current user's temporary storage. |
|
97 |
- Attachment.attachFiles(UserApp.currentUser().id, post.asResource()); |
|
90 |
+ boolean isAllowedToNotice = ProjectUser.isAllowedToNotice(UserApp.currentUser(), project); |
|
91 |
+ return badRequest(newPost.render(postForm.errors().toString(), postForm, project, isAllowedToNotice)); |
|
98 | 92 |
} |
93 |
+ |
|
94 |
+ Posting post = postForm.get(); |
|
95 |
+ post.createdDate = JodaDateUtil.now(); |
|
96 |
+ post.setAuthor(UserApp.currentUser()); |
|
97 |
+ post.project = project; |
|
98 |
+ |
|
99 |
+ post.save(); |
|
100 |
+ |
|
101 |
+ // Attach all of the files in the current user's temporary storage. |
|
102 |
+ Attachment.attachFiles(UserApp.currentUser().id, post.asResource()); |
|
99 | 103 |
|
100 | 104 |
return redirect(routes.BoardApp.posts(project.owner, project.name, 1)); |
101 | 105 |
} |
... | ... | @@ -109,51 +113,27 @@ |
109 | 113 |
} |
110 | 114 |
|
111 | 115 |
if (post == null) { |
112 |
- flash(Constants.WARNING, "board.post.notExist"); |
|
113 |
- return redirect(routes.BoardApp.posts(project.owner, project.name, 1)); |
|
114 |
- } else { |
|
115 |
- Form<PostingComment> commentForm = new Form<PostingComment>(PostingComment.class); |
|
116 |
- return ok(views.html.board.post.render(post, commentForm, project)); |
|
116 |
+ return notFound(notExistingPage.render("title.post.notExistingPage", project)); |
|
117 | 117 |
} |
118 |
- } |
|
119 | 118 |
|
120 |
- public static Result newComment(String userName, String projectName, Long postId) throws IOException { |
|
121 |
- final Posting post = Posting.finder.byId(postId); |
|
122 |
- Project project = post.project; |
|
123 |
- Call redirectTo = routes.BoardApp.post(project.owner, project.name, postId); |
|
124 |
- Form<PostingComment> commentForm = new Form<PostingComment>(PostingComment.class) |
|
125 |
- .bindFromRequest(); |
|
119 |
+ Form<PostingComment> commentForm = new Form<PostingComment>(PostingComment.class); |
|
126 | 120 |
|
127 |
- final PostingComment comment = commentForm.get(); |
|
128 |
- |
|
129 |
- return newComment(comment, commentForm, redirectTo, new Callback() { |
|
130 |
- @Override |
|
131 |
- public void run() { |
|
132 |
- comment.posting = post; |
|
133 |
- } |
|
134 |
- }); |
|
135 |
- } |
|
136 |
- |
|
137 |
- public static Result deletePost(String userName, String projectName, Long postId) { |
|
138 |
- Posting posting = Posting.finder.byId(postId); |
|
139 |
- Project project = posting.project; |
|
140 |
- |
|
141 |
- return deletePosting(posting, |
|
142 |
- routes.BoardApp.posts(project.owner, project.name, 1)); |
|
121 |
+ return ok(views.html.board.post.render(post, commentForm, project)); |
|
143 | 122 |
} |
144 | 123 |
|
145 | 124 |
public static Result editPostForm(String userName, String projectName, Long postId) { |
146 |
- Posting existPost = Posting.finder.byId(postId); |
|
147 |
- Form<Posting> editForm = new Form<Posting>(Posting.class).fill(existPost); |
|
125 |
+ Posting posting = Posting.finder.byId(postId); |
|
148 | 126 |
Project project = ProjectApp.getProject(userName, projectName); |
149 | 127 |
|
150 |
- if (AccessControl.isAllowed(UserApp.currentUser(), existPost.asResource(), Operation.UPDATE)) { |
|
151 |
- boolean isAllowedToNotice = ProjectUser.isAllowedToNotice(UserApp.currentUser(), project); |
|
152 |
- return ok(editPost.render("board.post.modify", editForm, postId, project, isAllowedToNotice)); |
|
153 |
- } else { |
|
128 |
+ if (!AccessControl.isAllowed(UserApp.currentUser(), posting.asResource(), Operation.UPDATE)) { |
|
154 | 129 |
flash(Constants.WARNING, "board.notAuthor"); |
155 | 130 |
return redirect(routes.BoardApp.post(project.owner, project.name, postId)); |
156 | 131 |
} |
132 |
+ |
|
133 |
+ Form<Posting> editForm = new Form<Posting>(Posting.class).fill(posting); |
|
134 |
+ boolean isAllowedToNotice = ProjectUser.isAllowedToNotice(UserApp.currentUser(), project); |
|
135 |
+ |
|
136 |
+ return ok(editPost.render("board.post.modify", editForm, postId, project, isAllowedToNotice)); |
|
157 | 137 |
} |
158 | 138 |
|
159 | 139 |
public static Result editPost(String userName, String projectName, Long postId) { |
... | ... | @@ -170,12 +150,43 @@ |
170 | 150 |
return editPosting(original, post, postForm, redirectTo, doNothing); |
171 | 151 |
} |
172 | 152 |
|
153 |
+ public static Result deletePost(String userName, String projectName, Long postingId) { |
|
154 |
+ Posting posting = Posting.finder.byId(postingId); |
|
155 |
+ Project project = posting.project; |
|
156 |
+ Call redirectTo = routes.BoardApp.posts(project.owner, project.name, 1); |
|
157 |
+ |
|
158 |
+ return delete(posting, posting.asResource(), redirectTo); |
|
159 |
+ } |
|
160 |
+ |
|
161 |
+ |
|
162 |
+ public static Result newComment(String userName, String projectName, Long postId) throws IOException { |
|
163 |
+ final Posting posting = Posting.finder.byId(postId); |
|
164 |
+ Project project = posting.project; |
|
165 |
+ Call redirectTo = routes.BoardApp.post(project.owner, project.name, postId); |
|
166 |
+ Form<PostingComment> commentForm = new Form<PostingComment>(PostingComment.class) |
|
167 |
+ .bindFromRequest(); |
|
168 |
+ |
|
169 |
+ if (commentForm.hasErrors()) { |
|
170 |
+ return badRequest(commentForm.errors().toString()); |
|
171 |
+ } |
|
172 |
+ |
|
173 |
+ final PostingComment comment = commentForm.get(); |
|
174 |
+ |
|
175 |
+ return newComment(comment, commentForm, redirectTo, new Callback() { |
|
176 |
+ @Override |
|
177 |
+ public void run() { |
|
178 |
+ comment.posting = posting; |
|
179 |
+ } |
|
180 |
+ }); |
|
181 |
+ } |
|
182 |
+ |
|
173 | 183 |
public static Result deleteComment(String userName, String projectName, Long postId, |
174 | 184 |
Long commentId) { |
175 | 185 |
Comment comment = PostingComment.find.byId(commentId); |
176 | 186 |
Project project = comment.asResource().getProject(); |
187 |
+ Call redirectTo = |
|
188 |
+ routes.BoardApp.post(project.owner, project.name, comment.getParent().id); |
|
177 | 189 |
|
178 |
- return deleteComment(comment, |
|
179 |
- routes.BoardApp.post(project.owner, project.name, comment.getParent().id)); |
|
190 |
+ return delete(comment, comment.asResource(), redirectTo); |
|
180 | 191 |
} |
181 | 192 |
} |
--- app/controllers/IssueApp.java
+++ app/controllers/IssueApp.java
... | ... | @@ -13,6 +13,7 @@ |
13 | 13 |
import views.html.issue.issueList; |
14 | 14 |
import views.html.issue.newIssue; |
15 | 15 |
import views.html.issue.notExistingPage; |
16 |
+import views.html.project.unauthorized; |
|
16 | 17 |
|
17 | 18 |
import utils.AccessControl; |
18 | 19 |
import utils.Callback; |
... | ... | @@ -34,6 +35,7 @@ |
34 | 35 |
import java.util.ArrayList; |
35 | 36 |
import java.util.List; |
36 | 37 |
import java.util.Set; |
38 |
+import java.util.Map; |
|
37 | 39 |
|
38 | 40 |
import static com.avaje.ebean.Expr.contains; |
39 | 41 |
import static com.avaje.ebean.Expr.icontains; |
... | ... | @@ -125,26 +127,26 @@ |
125 | 127 |
} |
126 | 128 |
|
127 | 129 |
Form<SearchCondition> issueParamForm = new Form<SearchCondition>(SearchCondition.class); |
128 |
- SearchCondition issueParam = issueParamForm.bindFromRequest().get(); |
|
129 |
- issueParam.state = state; |
|
130 |
- issueParam.pageNum = pageNum - 1; |
|
130 |
+ SearchCondition searchCondition = issueParamForm.bindFromRequest().get(); |
|
131 |
+ searchCondition.pageNum = pageNum - 1; |
|
132 |
+ searchCondition.state = state; |
|
131 | 133 |
|
132 | 134 |
String[] labelIds = request().queryString().get("labelIds"); |
133 | 135 |
if (labelIds != null) { |
134 | 136 |
for (String labelId : labelIds) { |
135 |
- issueParam.labelIds.add(Long.valueOf(labelId)); |
|
137 |
+ searchCondition.labelIds.add(Long.valueOf(labelId)); |
|
136 | 138 |
} |
137 | 139 |
} |
138 | 140 |
|
139 |
- ExpressionList<Issue> el = issueParam.asExpressionList(project); |
|
141 |
+ ExpressionList<Issue> el = searchCondition.asExpressionList(project); |
|
140 | 142 |
|
141 | 143 |
if (format.equals("xls")) { |
142 | 144 |
return issuesAsExcel(el, project); |
143 | 145 |
} else { |
144 | 146 |
Page<Issue> issues = el |
145 |
- .findPagingList(ITEMS_PER_PAGE).getPage(issueParam.pageNum); |
|
147 |
+ .findPagingList(ITEMS_PER_PAGE).getPage(searchCondition.pageNum); |
|
146 | 148 |
|
147 |
- return ok(issueList.render("title.issueList", issues, issueParam, project)); |
|
149 |
+ return ok(issueList.render("title.issueList", issues, searchCondition, project)); |
|
148 | 150 |
} |
149 | 151 |
} |
150 | 152 |
|
... | ... | @@ -169,16 +171,17 @@ |
169 | 171 |
} |
170 | 172 |
|
171 | 173 |
if (issueInfo == null) { |
172 |
- return ok(notExistingPage.render("title.post.notExistingPage", project)); |
|
173 |
- } else { |
|
174 |
- for (IssueLabel label: issueInfo.labels) { |
|
175 |
- label.refresh(); |
|
176 |
- } |
|
177 |
- Form<Comment> commentForm = new Form<Comment>(Comment.class); |
|
178 |
- Issue targetIssue = Issue.finder.byId(issueId); |
|
179 |
- Form<Issue> editForm = new Form<Issue>(Issue.class).fill(targetIssue); |
|
180 |
- return ok(issue.render("title.issueDetail", issueInfo, editForm, commentForm, project)); |
|
174 |
+ return notFound(notExistingPage.render("title.post.notExistingPage", project)); |
|
181 | 175 |
} |
176 |
+ |
|
177 |
+ for (IssueLabel label: issueInfo.labels) { |
|
178 |
+ label.refresh(); |
|
179 |
+ } |
|
180 |
+ |
|
181 |
+ Form<Comment> commentForm = new Form<Comment>(Comment.class); |
|
182 |
+ Form<Issue> editForm = new Form<Issue>(Issue.class).fill(Issue.finder.byId(issueId)); |
|
183 |
+ |
|
184 |
+ return ok(issue.render("title.issueDetail", issueInfo, editForm, commentForm, project)); |
|
182 | 185 |
} |
183 | 186 |
|
184 | 187 |
public static Result newIssueForm(String userName, String projectName) { |
... | ... | @@ -195,36 +198,26 @@ |
195 | 198 |
public static Result newIssue(String ownerName, String projectName) throws IOException { |
196 | 199 |
Form<Issue> issueForm = new Form<Issue>(Issue.class).bindFromRequest(); |
197 | 200 |
Project project = ProjectApp.getProject(ownerName, projectName); |
201 |
+ |
|
198 | 202 |
if (issueForm.hasErrors()) { |
199 | 203 |
return badRequest(newIssue.render(issueForm.errors().toString(), issueForm, project)); |
200 |
- } else { |
|
201 |
- Issue newIssue = issueForm.get(); |
|
202 |
- newIssue.createdDate = JodaDateUtil.now(); |
|
203 |
- newIssue.setAuthor(UserApp.currentUser()); |
|
204 |
- newIssue.project = project; |
|
205 |
- |
|
206 |
- newIssue.state = State.OPEN; |
|
207 |
- addLabels(newIssue.labels, request()); |
|
208 |
- |
|
209 |
- newIssue.save(); |
|
210 |
- |
|
211 |
- // Attach all of the files in the current user's temporary storage. |
|
212 |
- Attachment.attachFiles(UserApp.currentUser().id, newIssue.asResource()); |
|
213 | 204 |
} |
205 |
+ |
|
206 |
+ Issue newIssue = issueForm.get(); |
|
207 |
+ newIssue.createdDate = JodaDateUtil.now(); |
|
208 |
+ newIssue.setAuthor(UserApp.currentUser()); |
|
209 |
+ newIssue.project = project; |
|
210 |
+ |
|
211 |
+ newIssue.state = State.OPEN; |
|
212 |
+ addLabels(newIssue.labels, request()); |
|
213 |
+ |
|
214 |
+ newIssue.save(); |
|
215 |
+ |
|
216 |
+ // Attach all of the files in the current user's temporary storage. |
|
217 |
+ Attachment.attachFiles(UserApp.currentUser().id, newIssue.asResource()); |
|
214 | 218 |
|
215 | 219 |
return redirect(routes.IssueApp.issues(project.owner, project.name, |
216 | 220 |
State.OPEN.state(), "html", 1)); |
217 |
- } |
|
218 |
- |
|
219 |
- public static Result editIssueForm(String userName, String projectName, Long id) { |
|
220 |
- Issue targetIssue = Issue.finder.byId(id); |
|
221 |
- Form<Issue> editForm = new Form<Issue>(Issue.class).fill(targetIssue); |
|
222 |
- Project project = ProjectApp.getProject(userName, projectName); |
|
223 |
- if (!AccessControl.isAllowed(UserApp.currentUser(), targetIssue.asResource(), Operation.UPDATE)) { |
|
224 |
- return unauthorized(views.html.project.unauthorized.render(project)); |
|
225 |
- } |
|
226 |
- |
|
227 |
- return ok(editIssue.render("title.editIssue", editForm, targetIssue, project)); |
|
228 | 221 |
} |
229 | 222 |
|
230 | 223 |
public static void addLabels(Set<IssueLabel> labels, Http.Request request) { |
... | ... | @@ -236,6 +229,19 @@ |
236 | 229 |
} |
237 | 230 |
} |
238 | 231 |
}; |
232 |
+ |
|
233 |
+ public static Result editIssueForm(String userName, String projectName, Long id) { |
|
234 |
+ Issue issue = Issue.finder.byId(id); |
|
235 |
+ Project project = ProjectApp.getProject(userName, projectName); |
|
236 |
+ |
|
237 |
+ if (!AccessControl.isAllowed(UserApp.currentUser(), issue.asResource(), Operation.UPDATE)) { |
|
238 |
+ return unauthorized(views.html.project.unauthorized.render(project)); |
|
239 |
+ } |
|
240 |
+ |
|
241 |
+ Form<Issue> editForm = new Form<Issue>(Issue.class).fill(issue); |
|
242 |
+ |
|
243 |
+ return ok(editIssue.render("title.editIssue", editForm, issue, project)); |
|
244 |
+ } |
|
239 | 245 |
|
240 | 246 |
public static Result editIssue(String userName, String projectName, Long id) throws IOException { |
241 | 247 |
Form<Issue> issueForm = new Form<Issue>(Issue.class).bindFromRequest(); |
... | ... | @@ -261,9 +267,10 @@ |
261 | 267 |
public static Result deleteIssue(String userName, String projectName, Long issueId) { |
262 | 268 |
Issue issue = Issue.finder.byId(issueId); |
263 | 269 |
Project project = issue.project; |
270 |
+ Call redirectTo = |
|
271 |
+ routes.IssueApp.issues(project.owner, project.name, State.OPEN.state(), "html", 1); |
|
264 | 272 |
|
265 |
- return deletePosting(issue, routes.IssueApp.issues(project.owner, project.name, |
|
266 |
- State.OPEN.state(), "html", 1)); |
|
273 |
+ return delete(issue, issue.asResource(), redirectTo); |
|
267 | 274 |
} |
268 | 275 |
|
269 | 276 |
public static Result newComment(String userName, String projectName, Long issueId) throws IOException { |
... | ... | @@ -291,8 +298,9 @@ |
291 | 298 |
Long commentId) { |
292 | 299 |
Comment comment = IssueComment.find.byId(commentId); |
293 | 300 |
Project project = comment.asResource().getProject(); |
301 |
+ Call redirectTo = |
|
302 |
+ routes.IssueApp.issue(project.owner, project.name, comment.getParent().id); |
|
294 | 303 |
|
295 |
- return deleteComment(comment, |
|
296 |
- routes.IssueApp.issue(project.owner, project.name, comment.getParent().id)); |
|
304 |
+ return delete(comment, comment.asResource(), redirectTo); |
|
297 | 305 |
} |
298 | 306 |
} |
--- app/models/AbstractPosting.java
+++ app/models/AbstractPosting.java
... | ... | @@ -134,4 +134,9 @@ |
134 | 134 |
authorLoginId = user.loginId; |
135 | 135 |
authorName = user.name; |
136 | 136 |
} |
137 |
+ |
|
138 |
+ public void delete() { |
|
139 |
+ Attachment.deleteAll(asResource().getType(), id); |
|
140 |
+ super.delete(); |
|
141 |
+ } |
|
137 | 142 |
} |
+++ app/views/board/notExistingPage.scala.html
... | ... | @@ -0,0 +1,10 @@ |
1 | +@(title:String, project:Project) | |
2 | + | |
3 | +@import helper.twitterBootstrap._ | |
4 | + | |
5 | +@main(title, project, utils.MenuType.NONE) { | |
6 | +<div class="page"> | |
7 | + <h1>존재하지 않는 게시물 입니다.</h1> | |
8 | + <a href="@routes.BoardApp.posts(project.owner, project.name)" class="btn">목록으로 가기</a> | |
9 | +</div> | |
10 | +} |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?