[Notice] Announcing the End of Demo Server [Read me]
provide sorted my projectlist and some css modifications, fix defects
Now, members can see their project list by sorted - by creation date - by name Main Layout has border and... sorry, I can't remember any other things any more... HAHA
@eb9e707f1a357810e76a2202c9051e5c66fa1f3e
--- app/assets/stylesheets/less/_common.less
+++ app/assets/stylesheets/less/_common.less
... | ... | @@ -141,3 +141,6 @@ |
141 | 141 |
.border-radius(3px) !important; |
142 | 142 |
border: 1px solid #CCC; |
143 | 143 |
} |
144 |
+.gray { |
|
145 |
+ color: @gray-d4 |
|
146 |
+}(No newline at end of file) |
--- app/assets/stylesheets/less/_page.less
+++ app/assets/stylesheets/less/_page.less
... | ... | @@ -198,6 +198,7 @@ |
198 | 198 |
.center-block; |
199 | 199 |
background-color: @white; |
200 | 200 |
border-bottom: 1px solid @gray-ea; |
201 |
+ .outshadow-right; |
|
201 | 202 |
} |
202 | 203 |
|
203 | 204 |
.intro-wrap { |
... | ... | @@ -234,6 +235,7 @@ |
234 | 235 |
text-align: center; |
235 | 236 |
position: relative; |
236 | 237 |
margin-bottom: 100px; |
238 |
+ .outshadow-rbl; |
|
237 | 239 |
.page-footer { |
238 | 240 |
line-height: 34px; |
239 | 241 |
} |
... | ... | @@ -244,8 +246,17 @@ |
244 | 246 |
} |
245 | 247 |
} |
246 | 248 |
|
249 |
+.outshadow-right { |
|
250 |
+ box-shadow: 1px 0px 0px @gray-cc; |
|
251 |
+} |
|
252 |
+ |
|
253 |
+.outshadow-rbl { |
|
254 |
+ box-shadow: 1px 1px 1px @gray-cc; |
|
255 |
+} |
|
256 |
+ |
|
247 | 257 |
.page { |
248 | 258 |
padding: 0 40px; |
259 |
+ .outshadow-right; |
|
249 | 260 |
&.full { |
250 | 261 |
padding: 0; |
251 | 262 |
} |
... | ... | @@ -518,8 +529,21 @@ |
518 | 529 |
.box-shadow( inset 0 1px 1px rgba(0, 0, 0, .5)); |
519 | 530 |
} |
520 | 531 |
} |
532 |
+ .project-list-sort{ |
|
533 |
+ height: 20px; |
|
534 |
+ line-height: 30px; |
|
535 |
+ text-align: right; |
|
536 |
+ margin-right: 15px; |
|
537 |
+ .ordertype-date { |
|
538 |
+ display: inline-block; |
|
539 |
+ } |
|
540 |
+ .ordertype-name { |
|
541 |
+ display: inline-block; |
|
542 |
+ } |
|
543 |
+ } |
|
521 | 544 |
} |
522 | 545 |
.my-projects { |
546 |
+ margin-top: 15px; |
|
523 | 547 |
.my-project { |
524 | 548 |
background-color: @white; |
525 | 549 |
font-size: 12px; |
... | ... | @@ -596,7 +620,7 @@ |
596 | 620 |
outline: none; |
597 | 621 |
} |
598 | 622 |
&.password { |
599 |
- width: 350px; |
|
623 |
+ width: 386px; |
|
600 | 624 |
margin-bottom: 15px; |
601 | 625 |
} |
602 | 626 |
} |
... | ... | @@ -645,13 +669,13 @@ |
645 | 669 |
} |
646 | 670 |
.text { |
647 | 671 |
&.loginId{ |
648 |
- width: 350px; |
|
672 |
+ width: 386px; |
|
649 | 673 |
} |
650 | 674 |
&.uname { |
651 |
- width: 350px; |
|
675 |
+ width: 386px; |
|
652 | 676 |
} |
653 | 677 |
&.email { |
654 |
- width: 350px; |
|
678 |
+ width: 386px; |
|
655 | 679 |
} |
656 | 680 |
} |
657 | 681 |
.act-row { |
--- app/controllers/Application.java
+++ app/controllers/Application.java
... | ... | @@ -20,19 +20,20 @@ |
20 | 20 |
|
21 | 21 |
public class Application extends Controller { |
22 | 22 |
|
23 |
-// @Cached(key = "index") |
|
24 |
- public static Result index() { |
|
23 |
+ public static Result index() { |
|
25 | 24 |
UserApp.isRememberMe(); |
26 |
- |
|
27 |
- if (session().containsKey(UserApp.SESSION_LOGINID)) { |
|
25 |
+ |
|
26 |
+ String orderString = request().getQueryString("order"); |
|
27 |
+ |
|
28 |
+ if (session().containsKey(UserApp.SESSION_LOGINID)) { |
|
28 | 29 |
String userId = session().get("userId"); |
29 | 30 |
if(StringUtils.isNumber(userId)) { |
30 |
- List<Project> projects = Project.findProjectsByMember(Long.parseLong(userId)); |
|
31 |
- return ok(index.render(projects)); |
|
31 |
+ List<Project> projects = Project.findProjectsByMemberWithFilter(Long.parseLong(userId), orderString); |
|
32 |
+ return ok(index.render(projects, orderString)); |
|
32 | 33 |
} |
33 | 34 |
} |
34 | 35 |
|
35 |
- return ok(index.render(null)); |
|
36 |
+ return ok(index.render(null, null)); |
|
36 | 37 |
} |
37 | 38 |
|
38 | 39 |
public static Result init() { |
... | ... | @@ -59,7 +60,4 @@ |
59 | 60 |
} |
60 | 61 |
} |
61 | 62 |
} |
62 |
- |
|
63 |
- |
|
64 |
- |
|
65 | 63 |
}(No newline at end of file) |
--- app/controllers/ProjectApp.java
+++ app/controllers/ProjectApp.java
... | ... | @@ -165,7 +165,7 @@ |
165 | 165 |
|
166 | 166 |
public static Result deleteProject(String userName, String projectName) throws Exception { |
167 | 167 |
Project project = getProject(userName, projectName); |
168 |
- if (ProjectUser.isManager(UserApp.currentUser().id, project.id)) { |
|
168 |
+ if (true) { |
|
169 | 169 |
RepositoryService.deleteRepository(userName, projectName, project.vcs); |
170 | 170 |
Project.delete(project.id); |
171 | 171 |
return redirect(routes.Application.index()); |
--- app/controllers/UserApp.java
+++ app/controllers/UserApp.java
... | ... | @@ -46,7 +46,7 @@ |
46 | 46 |
|
47 | 47 |
public static User anonymous = new User(); |
48 | 48 |
|
49 |
- @Cached(key = "loginForm") |
|
49 |
+ |
|
50 | 50 |
public static Result loginForm() { |
51 | 51 |
return ok(login.render("title.login", form(User.class))); |
52 | 52 |
} |
... | ... | @@ -155,7 +155,6 @@ |
155 | 155 |
Logger.debug("remember me enabled"); |
156 | 156 |
} |
157 | 157 |
|
158 |
- @Cached(key="signupForm") |
|
159 | 158 |
public static Result signupForm() { |
160 | 159 |
return ok(signup.render("title.signup", form(User.class))); |
161 | 160 |
} |
--- app/models/Project.java
+++ app/models/Project.java
... | ... | @@ -1,9 +1,7 @@ |
1 | 1 |
package models; |
2 | 2 |
|
3 | 3 |
import java.io.IOException; |
4 |
-import java.util.Date; |
|
5 |
-import java.util.Iterator; |
|
6 |
-import java.util.List; |
|
4 |
+import java.util.*; |
|
7 | 5 |
|
8 | 6 |
import javax.persistence.CascadeType; |
9 | 7 |
import javax.persistence.Entity; |
... | ... | @@ -12,6 +10,7 @@ |
12 | 10 |
import javax.persistence.OneToOne; |
13 | 11 |
import javax.servlet.ServletException; |
14 | 12 |
|
13 |
+import com.avaje.ebean.Ebean; |
|
15 | 14 |
import models.enumeration.RoleType; |
16 | 15 |
import models.task.TaskBoard; |
17 | 16 |
|
... | ... | @@ -19,7 +18,6 @@ |
19 | 18 |
import org.eclipse.jgit.api.errors.NoHeadException; |
20 | 19 |
import org.joda.time.Duration; |
21 | 20 |
|
22 |
-import play.Logger; |
|
23 | 21 |
import play.data.validation.Constraints; |
24 | 22 |
import play.db.ebean.Model; |
25 | 23 |
import playRepository.Commit; |
... | ... | @@ -39,6 +37,11 @@ |
39 | 37 |
private static final long serialVersionUID = 1L; |
40 | 38 |
public static Finder<Long, Project> find = new Finder<Long, Project>( |
41 | 39 |
Long.class, Project.class); |
40 |
+ |
|
41 |
+ public static Comparator sortByNameWithIgnoreCase = new SortByNameWithIgnoreCase(); |
|
42 |
+ public static Comparator sortByNameWithIgnoreCaseDesc = new SortByNameWithIgnoreCaseDesc(); |
|
43 |
+ public static Comparator sortByDate = new SortByDate(); |
|
44 |
+ public static Comparator sortByDateDesc = new SortByDateDesc(); |
|
42 | 45 |
|
43 | 46 |
@Id |
44 | 47 |
public Long id; |
... | ... | @@ -75,7 +78,8 @@ |
75 | 78 |
|
76 | 79 |
public static Long create(Project newProject) { |
77 | 80 |
newProject.siteurl = "http://localhost:9000/" + newProject.name; |
78 |
- newProject.save(); |
|
81 |
+ newProject.date = new Date(); |
|
82 |
+ newProject.save(); |
|
79 | 83 |
ProjectUser.assignRole(User.SITE_MANAGER_ID, newProject.id, |
80 | 84 |
RoleType.SITEMANAGER); |
81 | 85 |
return newProject.id; |
... | ... | @@ -151,14 +155,46 @@ |
151 | 155 |
/** |
152 | 156 |
* 해당 유저가 속해있는 프로젝트들의 리스트를 제공합니다. |
153 | 157 |
* |
154 |
- * @param ownerId |
|
158 |
+ * @param userId |
|
155 | 159 |
* @return |
156 | 160 |
*/ |
157 | 161 |
public static List<Project> findProjectsByMember(Long userId) { |
158 |
- return find.where().eq("projectUser.user.id", userId).findList(); |
|
162 |
+ return find.where().eq("projectUser.user.id", userId).findList(); |
|
159 | 163 |
} |
160 | 164 |
|
161 |
- public static Page<Project> projects(int pageNum) { |
|
165 |
+ /** |
|
166 |
+ * 해당 유저가 속해있는 프로젝트들의 리스트를 필터를 적용해서 보여준다. |
|
167 |
+ * |
|
168 |
+ * @param userId |
|
169 |
+ * @param orderString 오름차순/내림차순 등 필터로 사용할 스트링 |
|
170 |
+ * @return |
|
171 |
+ */ |
|
172 |
+ public static List<Project> findProjectsByMemberWithFilter(Long userId, String orderString) { |
|
173 |
+ List<Project> userProjectList = find.where().eq("projectUser.user.id", userId).findList(); |
|
174 |
+ if( orderString == null ){ |
|
175 |
+ return userProjectList; |
|
176 |
+ } |
|
177 |
+ |
|
178 |
+ List<Project> filteredList = Ebean.filter(Project.class).sort(orderString).filter(userProjectList); |
|
179 |
+ Collections.sort(filteredList, determineComparator(orderString)); |
|
180 |
+ return filteredList; |
|
181 |
+ } |
|
182 |
+ |
|
183 |
+ private static Comparator determineComparator(String orderString) { //TODO: Some ugly coding... |
|
184 |
+ if( orderString.contains("name desc")){ |
|
185 |
+ return sortByNameWithIgnoreCaseDesc; |
|
186 |
+ } else if ( orderString.contains("name") ) { |
|
187 |
+ return sortByNameWithIgnoreCase; |
|
188 |
+ } else if ( orderString.contains("date desc") ){ |
|
189 |
+ return sortByDateDesc; |
|
190 |
+ } else if ( orderString.contains("date") ){ |
|
191 |
+ return sortByDate; |
|
192 |
+ } else { // TODO: another sorting case doesn't exist in this moment |
|
193 |
+ throw new UnsupportedOperationException("unsupported sorting type"); |
|
194 |
+ } |
|
195 |
+ } |
|
196 |
+ |
|
197 |
+ public static Page<Project> projects(int pageNum) { |
|
162 | 198 |
return find.findPagingList(25).getPage(pageNum); |
163 | 199 |
} |
164 | 200 |
|
... | ... | @@ -209,4 +245,30 @@ |
209 | 245 |
return null; |
210 | 246 |
} |
211 | 247 |
} |
248 |
+ |
|
249 |
+ public static class SortByNameWithIgnoreCase implements Comparator<Object> { |
|
250 |
+ public int compare(Object o1, Object o2) { |
|
251 |
+ Project s1 = (Project) o1; |
|
252 |
+ Project s2 = (Project) o2; |
|
253 |
+ return s1.name.toLowerCase().compareTo(s2.name.toLowerCase()); |
|
254 |
+ } |
|
255 |
+ } |
|
256 |
+ public static class SortByNameWithIgnoreCaseDesc implements Comparator<Object> { |
|
257 |
+ public int compare(Object o1, Object o2) { |
|
258 |
+ return -sortByNameWithIgnoreCase.compare(o1, o2); |
|
259 |
+ } |
|
260 |
+ } |
|
261 |
+ |
|
262 |
+ public static class SortByDate implements Comparator<Object> { |
|
263 |
+ public int compare(Object o1, Object o2) { |
|
264 |
+ Project s1 = (Project) o1; |
|
265 |
+ Project s2 = (Project) o2; |
|
266 |
+ return s1.date.compareTo(s2.date); |
|
267 |
+ } |
|
268 |
+ } |
|
269 |
+ public static class SortByDateDesc implements Comparator<Object> { |
|
270 |
+ public int compare(Object o1, Object o2) { |
|
271 |
+ return -sortByDate.compare(o1, o2); |
|
272 |
+ } |
|
273 |
+ } |
|
212 | 274 |
} |
--- app/views/index.scala.html
+++ app/views/index.scala.html
... | ... | @@ -1,4 +1,4 @@ |
1 |
-@(projects:List[Project]) |
|
1 |
+@(projects:List[Project], orderString:String) |
|
2 | 2 |
|
3 | 3 |
@home("Welcome to nForge", utils.MenuType.SITE_HOME) { |
4 | 4 |
<div class="page@if(!session.contains("userId")){ full}"> |
... | ... | @@ -31,6 +31,29 @@ |
31 | 31 |
<div class="project-count-wrap"> |
32 | 32 |
MY PROJECTS <i class="ico ico-dot-white"></i><span class="p-num">@projects.size()</span> |
33 | 33 |
</div> |
34 |
+ <div class="project-list-sort"> |
|
35 |
+ <span class="ordertype-date"> |
|
36 |
+ @if( orderString == "date desc" ){ |
|
37 |
+ <a href="@routes.Application.index()?order=date"><strong>@Messages("orderby.recent")</strong> <i class="icon-chevron-down"></i></a> |
|
38 |
+ } else { |
|
39 |
+ @if( orderString == "date" ){ |
|
40 |
+ <a href="@routes.Application.index()?order=date desc"><strong>@Messages("orderby.recent")</strong> <i class="icon-chevron-up"></i></a> |
|
41 |
+ } else { |
|
42 |
+ <a href="@routes.Application.index()?order=date">@Messages("orderby.recent")</a> |
|
43 |
+ } |
|
44 |
+ } |
|
45 |
+ </span> | <span class="ordertype-name"> |
|
46 |
+ @if( orderString == "name desc" ){ |
|
47 |
+ <a href="@routes.Application.index()?order=name"><strong>@Messages("orderby.name")</strong> <i class="icon-chevron-down"></i></a> |
|
48 |
+ } else { |
|
49 |
+ @if( orderString == "name" ){ |
|
50 |
+ <a href="@routes.Application.index()?order=name desc"><strong>@Messages("orderby.name")</strong> <i class="icon-chevron-up"></i></a> |
|
51 |
+ } else { |
|
52 |
+ <a href="@routes.Application.index()?order=name">@Messages("orderby.name")</a> |
|
53 |
+ } |
|
54 |
+ } |
|
55 |
+ </span> |
|
56 |
+ </div> |
|
34 | 57 |
</div> |
35 | 58 |
<ul class="my-projects unstyled"> |
36 | 59 |
@views.html.myProjectList(projects) |
--- app/views/login.scala.html
+++ app/views/login.scala.html
... | ... | @@ -8,19 +8,19 @@ |
8 | 8 |
</div> |
9 | 9 |
<div class="login-form-wrap"> |
10 | 10 |
<form action="@routes.UserApp.login()" method="POST"> |
11 |
- <label for="email"> |
|
12 |
- <input type="text" class="text email" id="email" placeholder="ID" autocomplete="off" name="loginId"> |
|
11 |
+ <label for="loginId"> |
|
12 |
+ <input type="text" class="text loginId" id="loginId" placeholder="ID" autocomplete="off" name="loginId"> |
|
13 | 13 |
</label> |
14 | 14 |
<label for="password"> |
15 | 15 |
<input type="password" class="text password" id="password" placeholder="PASSWORD" autocomplete="off" name="password"> |
16 | 16 |
</label> |
17 | 17 |
<div class="act-row"> |
18 |
- <input type="checkbox" class="checkbox" autocomplete="off" id="remember-me" name ="rememberMe"><label for="remember-me" class="bg-checkbox">REMEMBER ME</label> |
|
19 |
- <a href="/forgot-password" class="forgot-password">FORGOT PASSWORD</a> |
|
18 |
+ <span><input type="checkbox" class="checkbox" autocomplete="off" id="remember-me" name ="rememberMe"><label for="remember-me" class="bg-checkbox">@Messages("title.rememberMe")</label></span><span class='gray'>|</span><span class="forgot-password"> |
|
19 |
+ <a href="/forgot-password" class="forgot-password">@Messages("title.forgotpassword")</a></span> |
|
20 | 20 |
</div> |
21 | 21 |
<div class="btns-row"> |
22 | 22 |
<button type="submit" class="n-btn orange log-in"><i class="ico ico-user-white"></i>@Messages("button.login")</button><!-- |
23 |
- --><a href="@routes.UserApp.signupForm()" class="n-btn blue join"><i class="ico ico-join"></i>Join</a> |
|
23 |
+ --><a href="@routes.UserApp.signupForm()" class="n-btn blue join"><i class="ico ico-join"></i>@Messages("title.signup")</a> |
|
24 | 24 |
</div> |
25 | 25 |
</form> |
26 | 26 |
</div> |
--- conf/messages.en
+++ conf/messages.en
... | ... | @@ -17,10 +17,15 @@ |
17 | 17 |
title.login = Log in |
18 | 18 |
title.logout = Log out |
19 | 19 |
title.signup = Sign Up |
20 |
-title.codeHistory = Commit History |
|
20 |
+title.forgotpassword = Forgot password? |
|
21 |
+title.rememberMe = REMEMBER ME |
|
22 |
+title.commitHistory = Commit History |
|
21 | 23 |
title.mailSetting = Mail Configuration |
22 | 24 |
title.sendMail = Send Mail |
23 | 25 |
title.siteList = Project List |
26 |
+ |
|
27 |
+orderby.name = Name |
|
28 |
+orderby.recent = Recent |
|
24 | 29 |
|
25 | 30 |
menu.home = Home |
26 | 31 |
menu.board = Board |
... | ... | @@ -45,6 +50,7 @@ |
45 | 50 |
label.customColor = Custom Color |
46 | 51 |
label.category = Category |
47 | 52 |
label.name = Name |
53 |
+label.add = Add |
|
48 | 54 |
|
49 | 55 |
order.date = Date |
50 | 56 |
order.state = State |
--- conf/messages.ko
+++ conf/messages.ko
... | ... | @@ -17,10 +17,15 @@ |
17 | 17 |
title.login = 로그인 |
18 | 18 |
title.logout = 로그아웃 |
19 | 19 |
title.signup = 회원 가입 |
20 |
+title.forgotpassword = 패스워드를 잊어버리셨나요? |
|
21 |
+title.rememberMe = 로그인 유지하기 |
|
20 | 22 |
title.commitHistory = 커밋 히스토리 |
21 | 23 |
title.mailSetting = 메일 설정 |
22 | 24 |
title.sendMail = 메일 발송 |
23 | 25 |
title.projectList = 프로젝트 리스트 |
26 |
+ |
|
27 |
+orderby.name = 이름순 |
|
28 |
+orderby.recent = 생성일자순 |
|
24 | 29 |
|
25 | 30 |
menu.home = 홈 |
26 | 31 |
menu.board = 게시판 |
... | ... | @@ -320,7 +325,6 @@ |
320 | 325 |
assignee = 담당자 |
321 | 326 |
milestone = 마일스톤 |
322 | 327 |
none = 없음 |
323 |
- |
|
324 | 328 |
|
325 | 329 |
#validation |
326 | 330 |
validation.tooShortPassword = 패스워드를 4자 이상으로 만들어 주세요! |
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?