Jihan Kim 2014-07-25
UserInfo: separate each form tabs into independent page
Userinfo editform tabs like as Profile, Change Password, E-mails
and Notification settings within a same page are separated to independent page.
A link to "Notification settings" page will be appended to notification email.
@9bc6073ceb0aceb772946f18f234b5e2f18d06e7
app/assets/stylesheets/less/_yobiUI.less
--- app/assets/stylesheets/less/_yobiUI.less
+++ app/assets/stylesheets/less/_yobiUI.less
@@ -290,14 +290,14 @@
 .fake-file-wrap {
     position: relative; display:block; clear:both;
     overflow: hidden; cursor:pointer;
-    width:70px; /*margin-top:10px;*/
     &:hover {
         background:darken(@white, 10%);
     }
 
     .file {
         position: absolute; z-index:2; cursor:pointer;
-        top:0; left: 5px; /*-15px;*/ width:100px;
+        top:0; left: 5px; /*-15px;*/
+        min-width:100px; width:100%;
         .opacity(0);
     }
 }
app/controllers/UserApp.java
--- app/controllers/UserApp.java
+++ app/controllers/UserApp.java
@@ -42,10 +42,7 @@
 import play.mvc.*;
 import play.mvc.Http.Cookie;
 import utils.*;
-import views.html.user.edit;
-import views.html.user.login;
-import views.html.user.signup;
-import views.html.user.view;
+import views.html.user.*;
 
 import java.util.*;
 
@@ -563,6 +560,52 @@
     }
 
     @With(AnonymousCheckAction.class)
+    public static Result editUserInfoByTabForm(String tabId) {
+        User user = UserApp.currentUser();
+        Form<User> userForm = new Form<>(User.class);
+        userForm = userForm.fill(user);
+
+        switch(UserInfoFormTabType.fromString(tabId)){
+            case PASSWORD:
+                return ok(edit_password.render(userForm, user));
+            case NOTIFICATIONS:
+                return ok(edit_notifications.render(userForm, user));
+            case EMAILS:
+                return ok(edit_emails.render(userForm, user));
+            default:
+            case PROFILE:
+                return ok(edit.render(userForm, user));
+        }
+    }
+
+    private enum UserInfoFormTabType {
+        PROFILE("profile"),
+        PASSWORD("password"),
+        NOTIFICATIONS("notifications"),
+        EMAILS("emails");
+
+        private String tabId;
+
+        UserInfoFormTabType(String tabId) {
+            this.tabId = tabId;
+        }
+
+        public String value(){
+            return tabId;
+        }
+
+        public static UserInfoFormTabType fromString(String text)
+            throws IllegalArgumentException {
+            for(UserInfoFormTabType tab : UserInfoFormTabType.values()){
+                if (tab.value().equalsIgnoreCase(text)) {
+                    return tab;
+                }
+            }
+            throw new IllegalArgumentException("Invalid tabId");
+        }
+    }
+
+    @With(AnonymousCheckAction.class)
     @Transactional
     public static Result editUserInfo() {
         Form<User> userForm = new Form<>(User.class).bindFromRequest("name", "email");
app/views/user/edit.scala.html
--- app/views/user/edit.scala.html
+++ app/views/user/edit.scala.html
@@ -31,30 +31,61 @@
 </div>
 <div class="page-wrap-outer">
     <div class="page-wrap">
-        <ul id="editUserinfo" class="nav nav-tabs mt20">
-            <li class="active"><a href="#profile" data-toggle="tab">@Messages("userinfo.editProfile")</a></li>
-            <li><a href="#changePassword" data-toggle="tab">@Messages("userinfo.changePassword")</a></li>
-            <li><a href="#watch" data-toggle="tab">@Messages("userinfo.changeNotifications")</a></li>
-            <li><a href="#email" data-toggle="tab">@Messages("userinfo.changeEmails")</a></li>
-        </ul>
+        @partial_edit_tabmenu("profile")
 
-        <div class="tab-content">
-            <div id="profile" class="tab-pane active">
-                @partial_edit_profile(user)
-            </div>
+        <form id="frmBasic" method="post" action="@routes.UserApp.editUserInfo" class="pull-left">
+        <dl>
+          <dt>@Messages("user.name")</dt>
+          <dd class="mt10">
+            <input type="text" name="name" class="text" value="@user.name">
+          </dd>
+          <dt>@Messages("user.email")</dt>
+          <dd class="mt10">
+            <input type="email" name="email" class="text" value="@user.email">
+          </dd>
+          <dd>
+            <button type="submit" class="ybtn ybtn-success">@Messages("userinfo.editProfile")</button>
+          </dd>
+        </dl>
+        </form>
 
-            <div id="email" class="tab-pane">
-                @partial_edit_email(user)
-            </div>
+        <form method="post" action="@routes.UserApp.editUserInfo" class="pull-left" style="margin-left:50px; padding-left:50px; border-left:1px solid #ddd;">
+          <input type="hidden" name="name" value="@user.name">
+          <input type="hidden" name="email" value="@user.email">
 
-            <div id="changePassword" class="tab-pane">
-                @partial_edit_password(user)
+          <div class="avatar-frm">
+            <div class="avatar-wrap xlarge">
+              <img src="@user.avatarUrl" style="width:128px; max-width:none;" />
+              <div class="progress"></div>
             </div>
+            <div class="btn-wrap mt10 center-txt">
+              <div class="ybtn ybtn-small fake-file-wrap btnUploadAvatar">
+                @Messages("userinfo.changeAvatar")<!--
+                --><input id="avatarFile" type="file" class="file" name="filePath" accept="image/*">
+              </div>
+            </div>
+          </div>
+        </form>
 
-            <div id="watch" class="tab-pane">
-                @partial_edit_watch(user)
+        <div id="avatarCropWrap" class="modal hide" role="dialog" data-backdrop="static">
+          <div class="modal-header center-txt">
+            <div class="avatar-wrap xlarge">
+              <img style="width:128px; max-width:none;"/>
             </div>
+          </div>
+          <div class="modal-body">
+            <img style="max-width:500px;">
+            <canvas width="128" height="128" class="hide"></canvas>
+          </div>
+          <div class="modal-footer">
+            <button type="button" class="ybtn ybtn-default" data-dismiss="modal">@Messages("button.cancel")</button>
+            <button type="button" class="ybtn ybtn-success btnSubmitCrop">@Messages("button.save")</button>
+          </div>
         </div>
+
+        <link rel="stylesheet" type="text/css" href="@routes.Assets.at("stylesheets/jcrop/jquery.Jcrop.css")" />
+        <script type="text/javascript" src="@routes.Assets.at("javascripts/lib/jquery/jquery.Jcrop.min.js")"></script>
+        <script type="text/javascript" src="@routes.Assets.at("javascripts/lib/canvas-to-blob.js")"></script>
     </div>
 </div>
 <script type="text/javascript">
 
app/views/user/edit_emails.scala.html (added)
+++ app/views/user/edit_emails.scala.html
@@ -0,0 +1,90 @@
+@**
+* Yobi, Project Hosting SW
+*
+* Copyright 2014 NAVER Corp.
+* http://yobi.io
+*
+* @Author Jihan Kim
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+**@
+@(userForm:Form[User], user:User)
+
+@import helper._
+@import utils.TemplateHelper._
+@import utils.GravatarUtil._
+
+@siteLayout(user.loginId, utils.MenuType.USER) {
+<div class="site-breadcrumb-outer">
+  <div class="site-breadcrumb-inner">
+    <h3>@Messages("userinfo.accountSetting")</h3>
+  </div>
+</div>
+<div class="page-wrap-outer">
+  <div class="page-wrap">
+    @partial_edit_tabmenu("emails")
+
+    <form action="@routes.UserApp.addEmail" method="post" class="form-inline inner-bubble">
+      <input type="text" placeholder="@Messages("user.email.new")" name="email" class="text uname">
+      <button type="submit" class="ybtn ybtn-success">@Messages("button.add")</button>
+    </form>
+
+    <hr>
+
+    <p>
+      @Messages("emails.main.email.descr")<br>
+      @Messages("emails.sub.email.descr")
+    </p>
+
+    <table class="table mt20">
+      <tr>
+        <td>
+          <img src="@getAvatar(user.email, 40)" width="40" height="40">
+          <strong class="ml10">@user.email</strong>
+          <span class="label-head vmiddle ml10">@Messages("emails.main.email")</span>
+        </td>
+        <td style="text-align:right;">
+        </td>
+      </tr>
+
+      @for(mail <- user.emails){
+      <tr>
+        <td>
+          <img src="@getAvatar(mail.email, 40)" width="40" height="40">
+          <span class="ml10">@mail.email</span>
+        </td>
+        <td style="text-align:right; vertical-align: middle;">
+          <button type="button" data-request-method="delete" data-request-uri="@routes.UserApp.deleteEmail(mail.id)" class="ybtn ybtn-small ybtn-danger">
+            @Messages("button.delete")
+          </button>
+          @if(mail.valid) {
+          <button type="button" data-request-method="put" href="@routes.UserApp.setAsMainEmail(mail.id)" class="ybtn ybtn-small" style="width:150px;">
+            @Messages("emails.set.as.main")
+          </button>
+          } else {
+          <button type="button" data-request-method="post" href="@routes.UserApp.sendValidationEmail(mail.id)" class="ybtn ybtn-small" style="width:150px;">
+            <i class="yobicon-error2 orange-txt mr5" style="vertical-align: bottom;"></i>@Messages("emails.send.validatino.mail")
+          </button>
+          }
+        </td>
+      </tr>
+      }
+    </table>
+  </div>
+</div>
+<script type="text/javascript">
+    $(function(){
+        $yobi.loadModule("user.Setting");
+    });
+</script>
+}
 
app/views/user/edit_notifications.scala.html (added)
+++ app/views/user/edit_notifications.scala.html
@@ -0,0 +1,82 @@
+@**
+* Yobi, Project Hosting SW
+*
+* Copyright 2014 NAVER Corp.
+* http://yobi.io
+*
+* @Author Jihan Kim
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+**@
+@(userForm:Form[User], user:User)
+
+@import helper._
+@import utils.TemplateHelper._
+
+@siteLayout(user.loginId, utils.MenuType.USER) {
+<div class="site-breadcrumb-outer">
+  <div class="site-breadcrumb-inner">
+    <h3>@Messages("userinfo.accountSetting")</h3>
+  </div>
+</div>
+<div class="page-wrap-outer">
+  <div class="page-wrap">
+    @partial_edit_tabmenu("notifications")
+
+    <div>
+      @defining(UserProjectNotification.getProjectNotifications(user)) { notiMap =>
+      <ul id="notification-projects" class="unstyled lst-stacked span3 mr20">
+        @defining(Watch.findBy(user, ResourceType.PROJECT)) { watches =>
+          @if(watches.size > 0) {
+            @for(i <- 0 until watches.size) {
+              @defining(Project.find.byId(watches.get(i).resourceId.toLong)) { project =>
+                <li @if(i == 0){class="active"}><a href="#@project.id" data-toggle="tab">@project.owner / @project.name</a></li>
+              }
+            }
+          }
+        }
+      </ul>
+      <div class="tab-content">
+        @defining(Watch.findBy(user, ResourceType.PROJECT)) { watches =>
+          @if(watches.size > 0) {
+            @for(i <- 0 until watches.size) {
+              @defining(Project.find.byId(watches.get(i).resourceId.toLong)) { project =>
+                <div id="@project.id" class="tab-pane @if(i == 0){active}">
+                  <table class="table table-striped table-bordered">
+                    @for(notiType <- models.enumeration.EventType.notiTypes) {
+                    <tr>
+                      <th>@notiType.getDescr</th>
+                      <td>
+                        <div class="switch" data-on-label="On" data-off-label="Off">
+                          <input class="notiUpdate" data-href="@routes.WatchProjectApp.toggle(project.id, notiType.name())" type="checkbox" data-toggle="switch" @if(UserProjectNotification.isEnabledNotiType(notiMap, project, notiType)){ checked="checked" }>
+                        </div>
+                      </td>
+                    </tr>
+                    }
+                  </table>
+                </div>
+              }
+            }
+          }
+        }
+      </div>
+      }
+    </div>
+  </div>
+</div>
+<script type="text/javascript">
+    $(function(){
+        $yobi.loadModule("user.Setting");
+    });
+</script>
+}
 
app/views/user/edit_password.scala.html (added)
+++ app/views/user/edit_password.scala.html
@@ -0,0 +1,63 @@
+@**
+* Yobi, Project Hosting SW
+*
+* Copyright 2014 NAVER Corp.
+* http://yobi.io
+*
+* @Author Jihan Kim
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+**@
+@(userForm:Form[User], user:User)
+
+@import helper._
+@import utils.TemplateHelper._
+
+@siteLayout(user.loginId, utils.MenuType.USER) {
+<div class="site-breadcrumb-outer">
+  <div class="site-breadcrumb-inner">
+    <h3>@Messages("userinfo.accountSetting")</h3>
+  </div>
+</div>
+<div class="page-wrap-outer">
+  <div class="page-wrap">
+    @partial_edit_tabmenu("password")
+
+    <form id="frmPassword" method="post" action="@routes.UserApp.resetUserPassword">
+      <input type="hidden" name="loginId" value="@user.loginId" />
+      <dl>
+        <dt>@Messages("user.currentPassword")</dt>
+        <dd class="mt10">
+          <input type="password" id="oldPassword" name="oldPassword" value="" autocomplete="off" />
+        </dd>
+        <dt>@Messages("user.newPassword")</dt>
+        <dd class="mt10">
+          <input type="password" id="password" name="password" value="" autocomplete="off" />
+        </dd>
+        <dt>@Messages("validation.retypePassword")</dt>
+        <dd class="mt10">
+          <input type="password" id="retypedPassword" name="retypedPassword" value="" autocomplete="off" />
+        </dd>
+        <dd>
+          <button type="submit" class="ybtn ybtn-success">@Messages("userinfo.changePassword")</button>
+        </dd>
+      </dl>
+    </form>
+  </div>
+</div>
+<script type="text/javascript">
+    $(function(){
+        $yobi.loadModule("user.Setting");
+    });
+</script>
+}
 
app/views/user/partial_edit_email.scala.html (deleted)
--- app/views/user/partial_edit_email.scala.html
@@ -1,70 +0,0 @@
-@**
-* Yobi, Project Hosting SW
-*
-* Copyright 2014 NAVER Corp.
-* http://yobi.io
-*
-* @Author Jihan Kim
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*   http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-**@
-@(user:User)
-
-@import utils.GravatarUtil._
-
-<form action="@routes.UserApp.addEmail" method="post" class="form-inline inner-bubble">
-  <input type="text" placeholder="@Messages("user.email.new")" name="email" class="text uname">
-  <button type="submit" class="ybtn ybtn-success">@Messages("button.add")</button>
-</form>
-
-<hr>
-
-<p>
-  @Messages("emails.main.email.descr")<br>
-  @Messages("emails.sub.email.descr")
-</p>
-
-<table class="table mt20">
-  <tr>
-    <td>
-      <img src="@getAvatar(user.email, 40)" width="40" height="40">
-      <strong class="ml10">@user.email</strong>
-      <span class="label-head vmiddle ml10">@Messages("emails.main.email")</span>
-    </td>
-    <td style="text-align:right;">
-    </td>
-  </tr>
-
-  @for(mail <- user.emails){
-  <tr>
-    <td>
-      <img src="@getAvatar(mail.email, 40)" width="40" height="40">
-      <span class="ml10">@mail.email</span>
-    </td>
-    <td style="text-align:right; vertical-align: middle;">
-      <button type="button" data-request-method="delete" data-request-uri="@routes.UserApp.deleteEmail(mail.id)" class="ybtn ybtn-small ybtn-danger">
-        @Messages("button.delete")
-      </button>
-      @if(mail.valid) {
-      <button type="button" data-request-method="put" href="@routes.UserApp.setAsMainEmail(mail.id)" class="ybtn ybtn-small" style="width:150px;">
-        @Messages("emails.set.as.main")
-      </button>
-      } else {
-      <button type="button" data-request-method="post" href="@routes.UserApp.sendValidationEmail(mail.id)" class="ybtn ybtn-small" style="width:150px;">
-        <i class="yobicon-error2 orange-txt mr5" style="vertical-align: bottom;"></i>@Messages("emails.send.validatino.mail")
-      </button>
-      }
-    </td>
-  </tr>
-  }
-</table>
 
app/views/user/partial_edit_password.scala.html (deleted)
--- app/views/user/partial_edit_password.scala.html
@@ -1,42 +0,0 @@
-@**
-* Yobi, Project Hosting SW
-*
-* Copyright 2014 NAVER Corp.
-* http://yobi.io
-*
-* @Author Jihan Kim
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*   http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-**@
-@(user:User)
-
-<form id="frmPassword" method="post" action="@routes.UserApp.resetUserPassword">
-  <input type="hidden" name="loginId" value="@user.loginId" />
-  <dl>
-    <dt>@Messages("user.currentPassword")</dt>
-    <dd class="mt10">
-      <input type="password" id="oldPassword" name="oldPassword" value="" autocomplete="off" />
-    </dd>
-    <dt>@Messages("user.newPassword")</dt>
-    <dd class="mt10">
-      <input type="password" id="password" name="password" value="" autocomplete="off" />
-    </dd>
-    <dt>@Messages("validation.retypePassword")</dt>
-    <dd class="mt10">
-      <input type="password" id="retypedPassword" name="retypedPassword" value="" autocomplete="off" />
-    </dd>
-    <dd>
-      <button type="submit" class="ybtn ybtn-success">@Messages("userinfo.changePassword")</button>
-    </dd>
-  </dl>
-</form>
 
app/views/user/partial_edit_profile.scala.html (deleted)
--- app/views/user/partial_edit_profile.scala.html
@@ -1,75 +0,0 @@
-@**
-* Yobi, Project Hosting SW
-*
-* Copyright 2014 NAVER Corp.
-* http://yobi.io
-*
-* @Author Jihan Kim
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*   http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-**@
-@(user:User)
-
-<form id="frmBasic" method="post" action="@routes.UserApp.editUserInfo" class="pull-left">
-<dl>
-  <dt>@Messages("user.name")</dt>
-  <dd class="mt10">
-    <input type="text" name="name" class="text" value="@user.name">
-  </dd>
-  <dt>@Messages("user.email")</dt>
-  <dd class="mt10">
-    <input type="email" name="email" class="text" value="@user.email">
-  </dd>
-  <dd>
-    <button type="submit" class="ybtn ybtn-success">@Messages("userinfo.editProfile")</button>
-  </dd>
-</dl>
-</form>
-
-<form method="post" action="@routes.UserApp.editUserInfo" class="pull-left" style="margin-left:50px; padding-left:50px; border-left:1px solid #ddd;">
-  <input type="hidden" name="name" value="@user.name">
-  <input type="hidden" name="email" value="@user.email">
-
-  <div class="avatar-frm">
-    <div class="avatar-wrap xlarge">
-      <img src="@user.avatarUrl" style="width:128px; max-width:none;" />
-      <div class="progress"></div>
-    </div>
-    <div class="btn-wrap mt10 center-txt">
-      <div class="ybtn ybtn-small fake-file-wrap btnUploadAvatar">
-        @Messages("userinfo.changeAvatar")<!--
-        --><input id="avatarFile" type="file" class="file" name="filePath" accept="image/*">
-      </div>
-    </div>
-  </div>
-</form>
-
-<div id="avatarCropWrap" class="modal hide" role="dialog" data-backdrop="static">
-  <div class="modal-header center-txt">
-    <div class="avatar-wrap xlarge">
-      <img style="width:128px; max-width:none;"/>
-    </div>
-  </div>
-  <div class="modal-body">
-    <img style="max-width:500px;">
-    <canvas width="128" height="128" class="hide"></canvas>
-  </div>
-  <div class="modal-footer">
-    <button type="button" class="ybtn ybtn-default" data-dismiss="modal">@Messages("button.cancel")</button>
-    <button type="button" class="ybtn ybtn-success btnSubmitCrop">@Messages("button.save")</button>
-  </div>
-</div>
-
-<link rel="stylesheet" type="text/css" href="@routes.Assets.at("stylesheets/jcrop/jquery.Jcrop.css")" />
-<script type="text/javascript" src="@routes.Assets.at("javascripts/lib/jquery/jquery.Jcrop.min.js")"></script>
-<script type="text/javascript" src="@routes.Assets.at("javascripts/lib/canvas-to-blob.js")"></script>
 
app/views/user/partial_edit_tabmenu.scala.html (added)
+++ app/views/user/partial_edit_tabmenu.scala.html
@@ -0,0 +1,43 @@
+@**
+* Yobi, Project Hosting SW
+*
+* Copyright 2014 NAVER Corp.
+* http://yobi.io
+*
+* @Author Jihan Kim
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+**@
+@(tabId:String = "profile")
+<ul class="nav nav-tabs mt20">
+  <li @if(tabId == "profile"){ class="active" }>
+    <a href="@routes.UserApp.editUserInfoForm">
+      @Messages("userinfo.editProfile")
+    </a>
+  </li>
+  <li @if(tabId == "password"){ class="active" }>
+    <a href="@routes.UserApp.editUserInfoByTabForm("password")">
+    @Messages("userinfo.changePassword")
+    </a>
+  </li>
+  <li @if(tabId == "notifications"){ class="active" }>
+    <a href="@routes.UserApp.editUserInfoByTabForm("notifications")">
+    @Messages("userinfo.changeNotifications")
+    </a>
+  </li>
+  <li @if(tabId == "emails"){ class="active" }>
+    <a href="@routes.UserApp.editUserInfoByTabForm("emails")">
+    @Messages("userinfo.changeEmails")
+    </a>
+  </li>
+</ul>
 
app/views/user/partial_edit_watch.scala.html (deleted)
--- app/views/user/partial_edit_watch.scala.html
@@ -1,61 +0,0 @@
-@**
-* Yobi, Project Hosting SW
-*
-* Copyright 2014 NAVER Corp.
-* http://yobi.io
-*
-* @Author Jihan Kim
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*   http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-**@
-@(user:User)
-
-@import utils.TemplateHelper._
-
-@defining(UserProjectNotification.getProjectNotifications(user)) { notiMap =>
-<ul class="unstyled lst-stacked span3" style="margin-right: 20px;">
-  @defining(Watch.findBy(user, ResourceType.PROJECT)) { watches =>
-    @if(watches.size > 0) {
-      @for(i <- 0 until watches.size) {
-        @defining(Project.find.byId(watches.get(i).resourceId.toLong)) { project =>
-          <li @if(i == 0){class="active"}><a href="#@project.id" data-toggle="tab">@project.owner / @project.name</a></li>
-        }
-      }
-    }
-  }
-</ul>
-<div class="tab-content">
-  @defining(Watch.findBy(user, ResourceType.PROJECT)) { watches =>
-    @if(watches.size > 0) {
-      @for(i <- 0 until watches.size) {
-        @defining(Project.find.byId(watches.get(i).resourceId.toLong)) { project =>
-          <div class="tab-pane @if(i == 0){active}" id="@project.id">
-            <table class="table table-striped table-bordered">
-              @for(notiType <- models.enumeration.EventType.notiTypes) {
-              <tr>
-                <th>@notiType.getDescr</th>
-                <td>
-                  <div class="switch" data-on-label="On" data-off-label="Off">
-                    <input class="notiUpdate" data-href="@routes.WatchProjectApp.toggle(project.id, notiType.name())" type="checkbox" data-toggle="switch" @if(UserProjectNotification.isEnabledNotiType(notiMap, project, notiType)){ checked="checked" }>
-                  </div>
-                </td>
-              </tr>
-              }
-            </table>
-          </div>
-        }
-      }
-    }
-  }
-</div>
-}
conf/routes
--- conf/routes
+++ conf/routes
@@ -49,6 +49,7 @@
 GET            /users/signupform                                                      controllers.UserApp.signupForm()
 POST           /users/signup                                                          controllers.UserApp.newUser()
 GET            /user/editform                                                         controllers.UserApp.editUserInfoForm()
+GET            /user/editform/:tabId                                                  controllers.UserApp.editUserInfoByTabForm(tabId: String)
 POST           /user/edit                                                             controllers.UserApp.editUserInfo()
 POST           /user/resetPassword                                                    controllers.UserApp.resetUserPassword()
 GET            /user/isUsed                                                           controllers.UserApp.isUsed(name:String)
public/javascripts/service/yobi.user.Setting.js
--- public/javascripts/service/yobi.user.Setting.js
+++ public/javascripts/service/yobi.user.Setting.js
@@ -37,6 +37,7 @@
 
             _initFormValidator();
             _initAvatarUploader();
+            _showNotificationTab();
         }
 
         /**
@@ -396,6 +397,10 @@
             })
         }
 
+        function _showNotificationTab(){
+            $('#notification-projects a[href="' + location.hash + '"]').tab("show");
+        }
+
         _init(htOptions || {});
     };
 })("yobi.user.Setting");
Add a comment
List