doortts doortts 2017-04-23
index: Make user choose after login page
@ac01ceeeb798397180d9bf3adf681e0f3f35bf1e
app/controllers/Application.java
--- app/controllers/Application.java
+++ app/controllers/Application.java
@@ -10,7 +10,9 @@
 import controllers.annotation.AnonymousCheck;
 import jsmessages.JsMessages;
 import models.Project;
+import models.User;
 import models.UserCredential;
+import models.UserSetting;
 import org.apache.commons.lang3.StringUtils;
 import play.Logger;
 import play.mvc.Controller;
@@ -19,6 +21,7 @@
 import playRepository.RepositoryService;
 import views.html.error.notfound_default;
 import views.html.index.index;
+import views.html.index.notifications;
 
 import static com.feth.play.module.pa.controllers.Authenticate.*;
 
@@ -33,9 +36,19 @@
 
     @AnonymousCheck
     public static Result index() {
+        User user = UserApp.currentUser();
+        UserSetting userSetting = UserSetting.findByUser(user.id);
+        if(!user.isAnonymous() && StringUtils.isNotBlank(userSetting.loginDefaultPage)) {
+            return redirect(userSetting.loginDefaultPage);
+        }
         return ok(index.render(UserApp.currentUser()));
     }
 
+    @AnonymousCheck
+    public static Result notifications() {
+        return ok(notifications.render(UserApp.currentUser()));
+    }
+
     public static Result oAuth(final String provider) {
         return authenticate(provider);
     }
app/controllers/IssueApp.java
--- app/controllers/IssueApp.java
+++ app/controllers/IssueApp.java
@@ -59,6 +59,11 @@
     }
 
     @AnonymousCheck(requiresLogin = true, displaysFlashMessage = true)
+    public static Result userIssuesPage() throws WriteException, IOException {
+        return controllers.IssueApp.userIssues("", "html", 1);
+    }
+
+    @AnonymousCheck(requiresLogin = true, displaysFlashMessage = true)
     public static Result userIssues(String state, String format, int pageNum) throws WriteException, IOException {
         Project project = null;
         // SearchCondition from param
app/controllers/UserApp.java
--- app/controllers/UserApp.java
+++ app/controllers/UserApp.java
@@ -15,6 +15,7 @@
 import com.feth.play.module.mail.Mailer.Mail.Body;
 import com.feth.play.module.pa.PlayAuthenticate;
 import controllers.annotation.AnonymousCheck;
+import jxl.write.WriteException;
 import models.*;
 import models.enumeration.Operation;
 import models.enumeration.UserState;
@@ -44,14 +45,13 @@
 import javax.naming.AuthenticationException;
 import javax.naming.CommunicationException;
 import javax.naming.NamingException;
+import java.io.IOException;
 import java.util.*;
 
 import static com.feth.play.module.mail.Mailer.getEmailName;
-import static com.feth.play.module.pa.controllers.Authenticate.noCache;
 import static play.data.Form.form;
 import static play.libs.Json.toJson;
 import static utils.HtmlUtil.defaultSanitize;
-import org.apache.commons.lang3.StringEscapeUtils;
 
 public class UserApp extends Controller {
     public static final String SESSION_USERID = "userId";
@@ -1215,6 +1215,17 @@
         }
     }
 
+    @AnonymousCheck
+    public static Result setDefaultLoginPage() throws IOException, WriteException {
+        UserSetting userSetting = UserSetting.findByUser(UserApp.currentUser().id);
+        userSetting.loginDefaultPage = request().getQueryString("path");
+        userSetting.save();
+
+        ObjectNode json = Json.newObject();
+        json.put("defaultLoginPage", userSetting.loginDefaultPage);
+        return ok(json);
+    }
+
     public static Result usermenuTabContentList(){
         return ok(views.html.common.usermenu_tab_content_list.render());
     }
 
app/models/UserSetting.java (added)
+++ app/models/UserSetting.java
@@ -0,0 +1,41 @@
+/**
+ * Yona, 21st Century Project Hosting SW
+ * <p>
+ * Copyright Yona & Yobi Authors & NAVER Corp.
+ * https://yona.io
+ **/
+package models;
+
+import play.db.ebean.Model;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.OneToOne;
+
+@Entity
+public class UserSetting extends Model {
+    private static final long serialVersionUID = -2377215889638087516L;
+
+    public static final Model.Finder<Long, UserSetting> find = new Finder<>(Long.class, UserSetting.class);
+
+    @Id
+    public Long id;
+
+    @OneToOne
+    public User user;
+
+    public String loginDefaultPage;
+
+    public UserSetting(User user) {
+        this.user = user;
+    }
+
+    public static UserSetting findByUser(Long id){
+        UserSetting userSetting = find.where().eq("user.id", id).findUnique();
+        if (userSetting == null) {
+            userSetting = new UserSetting(User.find.byId(id));
+        }
+        return userSetting;
+    }
+
+}
app/views/common/mySeriesMenuTab.scala.html
--- app/views/common/mySeriesMenuTab.scala.html
+++ app/views/common/mySeriesMenuTab.scala.html
@@ -13,8 +13,14 @@
     }
     active
 }
+
 <ul class="nav nav-tabs">
-    <li @isActive(viewType, TAB_NOTI)><a href="@routes.Application.index()">@Messages("notification")</a></li>
+    <li @isActive(viewType, TAB_NOTI)><a href="@routes.Application.notifications()">@Messages("notification")</a></li>
     <li @isActive(viewType, TAB_MY_ISSUES)><a href="@routes.IssueApp.userIssues()">@Messages("issue.myIssue")</a></li>
     <li @isActive(viewType, TAB_MY_FILES)><a href="@routes.UserApp.userFiles()">@Messages("user.files")</a></li>
+    <li>@if(isActive(viewType, TAB_NOTI) || isActive(viewType, TAB_MY_ISSUES)){
+        @if(!requestHeader.path.equals("/") && !requestHeader.path.substring(1).equals(UserSetting.findByUser(UserApp.currentUser().id).loginDefaultPage)){
+            <button id="setDefaultLoginPage" type="button" class="ybtn hide-in-mobile" data-url="@requestHeader.path.substring(1)" title="@Messages("button.setDefaultLoginPage")" data-trigger="hover"  data-placement="bottom" data-toggle="popover" data-content="@Messages("button.setDefaultLoginPage.desc")">@Messages("button.setDefaultLoginPage")</button>
+        }
+    }</li>
 </ul>
app/views/common/usermenu.scala.html
--- app/views/common/usermenu.scala.html
+++ app/views/common/usermenu.scala.html
@@ -67,7 +67,7 @@
 <ul class="gnb-usermenu">
     @if( !UserApp.currentUser().isAnonymous()) {
        <li class="gnb-usermenu-item hide-in-mobile">
-          <a href="@routes.Application.index()" class="user-item-btn loggged-in">@Messages("notification")</a>
+          <a href="@routes.Application.notifications()" class="user-item-btn loggged-in">@Messages("notification")</a>
        </li>
        <li class="divider hide-in-mobile"></li>
        <li class="gnb-usermenu-item">
app/views/index/index.scala.html
--- app/views/index/index.scala.html
+++ app/views/index/index.scala.html
@@ -10,131 +10,4 @@
 @import utils.JodaDateUtil
 @import utils.MenuType._
 
-@siteLayout(utils.Config.getSiteName, utils.MenuType.SITE_HOME) {
-    @if(currentUser == User.anonymous){
-    @partial_intro()
-    } else {
-    <div class="page-wrap-outer">
-        <div class="page-wrap">
-            <div class="site-guide-outer hide">
-                <h3>
-                    <span>@Messages("app.welcome",utils.Config.getSiteName) - @Messages("app.description")</span>
-                </h3>
-                <table class="welcome-table table borderless">
-                    <tr>
-                        <td>
-                            <a href="@routes.ProjectApp.newProjectForm()" class="ybtn ybtn-success">
-                            @Messages("button.newProject")
-                            </a>
-                        </td>
-                        <td>@Messages("app.welcome.project.desc")</td>
-                    </tr>
-                    <tr>
-                        <td>
-                            <a href="@routes.OrganizationApp.newForm()" class="ybtn ybtn-success">
-                            @Messages("title.newOrganization")
-                            </a>
-                        </td>
-                        <td>@Messages("app.welcome.group.desc")</td>
-                    </tr>
-                    <tr>
-                        <td>
-                            <a href="@routes.ProjectApp.projects()" class="ybtn ybtn-success">
-                            @Messages("title.projectList")
-                            </a>
-                        </td>
-                        <td>@Messages("app.welcome.searchProject.desc")</td>
-                    </tr>
-                </table>
-            </div>
-            <div class="guide-toggle">
-                <button class="btn-transparent" id="toggleIntro"><i class="yobicon-resizev"></i></button>
-            </div>
-            <div class="page on-fold-intro">
-                <div class="row-fluid content-container">
-                    <div class="span8 main-stream">
-                        @views.html.common.mySeriesMenuTab(TAB_NOTI)
-                        <ul class="activity-streams notification-wrap unstyled">
-                            @partial_notifications(0, 20)
-                        </ul>
-        	        </div>
-                    <div class="span4 index-menu right-menu span-hard-wrap">
-        	       </div>
-                </div>
-            </div>
-        </div>
-    </div>
-    }
-    <script type="text/javascript">
-        $(document).ready(function(){
-            $("#toggleIntro").click(function(){
-                var $outerGuide = $(".site-guide-outer");
-                $outerGuide.toggleClass("hide");
-                localStorage.setItem("yobi-intro", !$outerGuide.hasClass("hide"));
-            });
-
-            if(localStorage.getItem("yobi-intro") != "false"){
-                $(".site-guide-outer").removeClass("hide");
-            }
-
-            $('.notification-wrap').on('click','[data-toggle="learnmore"]',function(event) {
-                var $this = $(this);
-                $this.find(".more").toggle();
-                var sTargetId = $this.data('target'),
-                    welMessage = $('#'+sTargetId),
-                    nHeight;
-
-                if(event.target.localName =='a' || event.target.localName =='img') {
-                    return ;
-                }
-
-                welMessage.toggleClass('nowrap');
-
-                nHeight = (welMessage.hasClass('nowrap')) ? '' : $(welMessage).find('.message').height();
-
-                $(welMessage).css('min-height',nHeight);
-            });
-
-            function checkOverflow(el) {
-                var curOverflow = el.style.overflow;
-
-                if (!curOverflow || curOverflow === "visible")
-                    el.style.overflow = "hidden";
-
-                var isOverflowing = el.clientWidth < el.scrollWidth
-                        || el.clientHeight < el.scrollHeight;
-
-                el.style.overflow = curOverflow;
-
-                return isOverflowing;
-            }
-
-            $(".message-wrap").each(function(index, value){
-                var $this = $(this);
-                if(checkOverflow($this[0])){
-                    $this.after("<div class='more'>...</div>");
-                }
-            });
-
-            // Show side bar menu default and focus to search box
-            // Also, see layout.scala.html for normal user menu click !!
-            var requiredLoggedIn = $("#required-logged-in").length === 1;
-            if(!requiredLoggedIn){
-                var viewSize = $(window).width();
-                if( viewSize > 720) {
-                    $("#mySidenav").width("420px").css("border", "1px solid #ccc");
-                    setTimeout(function () {
-                        $("#main").off("click");
-                    }, 1000);
-                    $(".search-input").focus();
-                } else {
-                    $("#mySidenav").width("100vw").css("border", "1px solid #ccc");
-                }
-            }
-
-            if ($(".admin-logged-in-affix").length === 1) {
-                $(".sidenav").css("top", "84px");
-            }
-        });
-    </script>
-}
+@views.html.index.notifications(currentUser)
 
app/views/index/notifications.scala.html (added)
+++ app/views/index/notifications.scala.html
@@ -0,0 +1,153 @@
+@**
+* Yona, 21st Century Project Hosting SW
+*
+* Copyright Yona & Yobi Authors & NAVER Corp.
+* https://yona.io
+**@
+@(currentUser:models.User)
+
+@import utils.TemplateHelper._
+@import utils.JodaDateUtil
+@import utils.MenuType._
+
+@siteLayout(utils.Config.getSiteName, utils.MenuType.SITE_HOME) {
+    @if(currentUser == User.anonymous){
+    @partial_intro()
+    } else {
+    <div class="page-wrap-outer">
+        <div class="page-wrap">
+            <div class="site-guide-outer hide">
+                <h3>
+                    <span>@Messages("app.welcome",utils.Config.getSiteName) - @Messages("app.description")</span>
+                </h3>
+                <table class="welcome-table table borderless">
+                    <tr>
+                        <td>
+                            <a href="@routes.ProjectApp.newProjectForm()" class="ybtn ybtn-success">
+                            @Messages("button.newProject")
+                            </a>
+                        </td>
+                        <td>@Messages("app.welcome.project.desc")</td>
+                    </tr>
+                    <tr>
+                        <td>
+                            <a href="@routes.OrganizationApp.newForm()" class="ybtn ybtn-success">
+                            @Messages("title.newOrganization")
+                            </a>
+                        </td>
+                        <td>@Messages("app.welcome.group.desc")</td>
+                    </tr>
+                    <tr>
+                        <td>
+                            <a href="@routes.ProjectApp.projects()" class="ybtn ybtn-success">
+                            @Messages("title.projectList")
+                            </a>
+                        </td>
+                        <td>@Messages("app.welcome.searchProject.desc")</td>
+                    </tr>
+                </table>
+            </div>
+            <div class="guide-toggle">
+                <button class="btn-transparent" id="toggleIntro"><i class="yobicon-resizev"></i></button>
+            </div>
+            <div class="page on-fold-intro">
+                <div class="row-fluid content-container">
+                    <div class="span8 main-stream">
+                        @views.html.common.mySeriesMenuTab(TAB_NOTI)
+                        <ul class="activity-streams notification-wrap unstyled">
+                            @partial_notifications(0, 20)
+                        </ul>
+        	        </div>
+                    <div class="span4 index-menu right-menu span-hard-wrap">
+        	       </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    }
+    <script type="text/javascript">
+        $(document).ready(function(){
+            $("#toggleIntro").click(function(){
+                var $outerGuide = $(".site-guide-outer");
+                $outerGuide.toggleClass("hide");
+                localStorage.setItem("yobi-intro", !$outerGuide.hasClass("hide"));
+            });
+
+            if(localStorage.getItem("yobi-intro") != "false"){
+                $(".site-guide-outer").removeClass("hide");
+            }
+
+            $('.notification-wrap').on('click','[data-toggle="learnmore"]',function(event) {
+                var $this = $(this);
+                $this.find(".more").toggle();
+                var sTargetId = $this.data('target'),
+                    welMessage = $('#'+sTargetId),
+                    nHeight;
+
+                if(event.target.localName =='a' || event.target.localName =='img') {
+                    return ;
+                }
+
+                welMessage.toggleClass('nowrap');
+
+                nHeight = (welMessage.hasClass('nowrap')) ? '' : $(welMessage).find('.message').height();
+
+                $(welMessage).css('min-height',nHeight);
+            });
+
+            function checkOverflow(el) {
+                var curOverflow = el.style.overflow;
+
+                if (!curOverflow || curOverflow === "visible")
+                    el.style.overflow = "hidden";
+
+                var isOverflowing = el.clientWidth < el.scrollWidth
+                        || el.clientHeight < el.scrollHeight;
+
+                el.style.overflow = curOverflow;
+
+                return isOverflowing;
+            }
+
+            $(".message-wrap").each(function(index, value){
+                var $this = $(this);
+                if(checkOverflow($this[0])){
+                    $this.after("<div class='more'>...</div>");
+                }
+            });
+
+            // Show side bar menu default and focus to search box
+            // Also, see layout.scala.html for normal user menu click !!
+            var requiredLoggedIn = $("#required-logged-in").length === 1;
+            if(!requiredLoggedIn){
+                var viewSize = $(window).width();
+                if( viewSize > 720) {
+                    $("#mySidenav").width("420px").css("border", "1px solid #ccc");
+                    setTimeout(function () {
+                        $("#main").off("click");
+                    }, 1000);
+                    $(".search-input").focus();
+                } else {
+                    $("#mySidenav").width("100vw").css("border", "1px solid #ccc");
+                }
+            }
+
+            if ($(".admin-logged-in-affix").length === 1) {
+                $(".sidenav").css("top", "84px");
+            }
+
+            var $setDefaultLoginPage = $("#setDefaultLoginPage");
+            $setDefaultLoginPage.popover();
+            $setDefaultLoginPage.on('click', function(){
+                $.post("@routes.UserApp.setDefaultLoginPage()?path=" + $setDefaultLoginPage.data("url"))
+                        .done(function (data) {
+                            $yobi.notify("Set to default: " + data.defaultLoginPage, 3000);
+                            $setDefaultLoginPage.hide();
+                        })
+                        .fail(function (data) {
+                            $yobi.alert("set Default page failed: " + data);
+                        });
+            });
+        });
+    </script>
+}
app/views/issue/my_list.scala.html
--- app/views/issue/my_list.scala.html
+++ app/views/issue/my_list.scala.html
@@ -25,7 +25,17 @@
       $(function(){
           $yobi.loadModule("issue.List");
 
-
+          var $setDefaultLoginPage = $("#setDefaultLoginPage");
+          $setDefaultLoginPage.on('click', function(){
+              $.post("@routes.UserApp.setDefaultLoginPage()?path=" + $setDefaultLoginPage.data("url"))
+                      .done(function (data) {
+                          $yobi.notify("Set to default: " + data.defaultLoginPage, 3000);
+                          $setDefaultLoginPage.hide();
+                      })
+                      .fail(function (data) {
+                          $yobi.alert("set Default page failed: " + data);
+                      });
+          });
       });
     </script>
 }
 
conf/evolutions/default/14.sql (added)
+++ conf/evolutions/default/14.sql
@@ -0,0 +1,14 @@
+# --- !Ups
+CREATE TABLE user_setting (
+  id                        BIGINT AUTO_INCREMENT NOT NULL,
+  user_id                   BIGINT,
+  login_default_page        VARCHAR(255),
+  CONSTRAINT pk_user_setting PRIMARY KEY (id),
+  CONSTRAINT fk_user_setting_user FOREIGN KEY (user_id) REFERENCES n4user (id) on DELETE CASCADE
+)
+row_format=compressed, key_block_size=8;
+
+CREATE index ix_user_setting_user_1 ON user_setting (user_id);
+
+# --- !Downs
+DROP TABLE user_setting;
conf/messages.ko-KR
--- conf/messages.ko-KR
+++ conf/messages.ko-KR
@@ -71,6 +71,8 @@
 button.save = 저장
 button.selectAll = 전체 선택
 button.selectFile = 파일 선택
+button.setDefaultLoginPage = 기본 페이지로 지정
+button.setDefaultLoginPage.desc = 현재 페이지를 로그인 후 표시되는 기본 인덱스 페이지로 지정합니다
 button.show.original = 원문 보기
 button.signup = {0} 시작 하기
 button.submitForm = 폼 전송
conf/routes
--- conf/routes
+++ conf/routes
@@ -7,6 +7,7 @@
 
 # Home page
 GET            /                                                                      controllers.Application.index()
+GET            /notifications                                                         controllers.Application.notifications()
 
 # Play!Authenticate
 GET     /logout                            controllers.Application.oAuthLogout
@@ -48,6 +49,7 @@
 GET            /-_-api/v1/favoriteOrganizations                                        controllers.api.UserApi.getFoveriteOrganizations
 POST           /-_-api/v1/favoriteOrganizations/:organizationId                        controllers.api.UserApi.toggleFoveriteOrganization(organizationId:String)
 GET            /-_-api/v1/users                                                        controllers.UserApp.users(query: String ?= "")
+POST           /-_-api/v1/user/defultLoginPage                                         controllers.UserApp.setDefaultLoginPage()
 
 
 
@@ -80,6 +82,7 @@
 POST           /noti/toggle/:projectId/:notiType                                      controllers.WatchProjectApp.toggle(projectId: Long, notiType)
 
 # User
+GET            /user/issues                                                           controllers.IssueApp.userIssuesPage()
 GET            /user/issues                                                           controllers.IssueApp.userIssues(state:String ?= "", format:String ?= "html", pageNum: Int ?= 1)
 GET            /user/files                                                            controllers.UserApp.userFiles()
 GET            /users/loginform                                                       controllers.UserApp.loginForm()
Add a comment
List