This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository coselmar. See http://git.codelutin.com/coselmar.git commit f4d6cdb936ab867d434ba7a50d67aa4d958a1958 Author: Yannick Martel <martel@©odelutin.com> Date: Mon Feb 16 12:25:26 2015 +0100 Add last 5 projects in home page when user is connected. internal-test #6443 --- .../ifremer/coselmar/beans/QuestionSearchBean.java | 19 +++++++ .../persistence/entity/QuestionTopiaDao.java | 47 +++++++++++++---- .../coselmar/services/v1/QuestionsWebService.java | 41 ++++++++------- coselmar-ui/src/main/webapp/i18n/en.js | 1 + coselmar-ui/src/main/webapp/i18n/fr.js | 1 + coselmar-ui/src/main/webapp/index.html | 2 +- .../src/main/webapp/js/coselmar-controllers.js | 17 ++++++- coselmar-ui/src/main/webapp/js/coselmar.js | 1 + coselmar-ui/src/main/webapp/views/home.html | 59 +++++++++++++++++++++- .../src/main/webapp/views/questions/questions.html | 7 +-- 10 files changed, 158 insertions(+), 37 deletions(-) diff --git a/coselmar-persistence/src/main/java/fr/ifremer/coselmar/beans/QuestionSearchBean.java b/coselmar-persistence/src/main/java/fr/ifremer/coselmar/beans/QuestionSearchBean.java index 1e909bf..12d9a82 100644 --- a/coselmar-persistence/src/main/java/fr/ifremer/coselmar/beans/QuestionSearchBean.java +++ b/coselmar-persistence/src/main/java/fr/ifremer/coselmar/beans/QuestionSearchBean.java @@ -38,6 +38,9 @@ public class QuestionSearchBean implements Serializable { protected String status; protected String privacy; + protected Integer limit; + protected Integer page; + public List<String> getKeywords() { return keywords; } @@ -61,4 +64,20 @@ public class QuestionSearchBean implements Serializable { public void setPrivacy(String privacy) { this.privacy = privacy; } + + public Integer getLimit() { + return limit; + } + + public void setLimit(Integer limit) { + this.limit = limit; + } + + public Integer getPage() { + return page; + } + + public void setPage(Integer page) { + this.page = page; + } } diff --git a/coselmar-persistence/src/main/java/fr/ifremer/coselmar/persistence/entity/QuestionTopiaDao.java b/coselmar-persistence/src/main/java/fr/ifremer/coselmar/persistence/entity/QuestionTopiaDao.java index 2152adf..bc02716 100644 --- a/coselmar-persistence/src/main/java/fr/ifremer/coselmar/persistence/entity/QuestionTopiaDao.java +++ b/coselmar-persistence/src/main/java/fr/ifremer/coselmar/persistence/entity/QuestionTopiaDao.java @@ -32,10 +32,11 @@ import fr.ifremer.coselmar.beans.QuestionSearchBean; import fr.ifremer.coselmar.persistence.DaoUtils; import org.apache.commons.lang3.StringUtils; import org.nuiton.topia.persistence.TopiaQueryBuilderAddCriteriaOrRunQueryStep; +import org.nuiton.util.pagination.PaginationParameter; public class QuestionTopiaDao extends AbstractQuestionTopiaDao<Question> { - public List<Question> findForExpert(CoselmarUser expert, QuestionSearchBean searchBean) { + public List<Question> findForExpert(CoselmarUser expert, QuestionSearchBean searchBean, PaginationParameter page) { StringBuilder hqlBuilder = new StringBuilder("SELECT Q FROM " + Question.class.getName() + " Q " + " INNER JOIN Q." + Question.PROPERTY_PARTICIPANTS + " CUG "); @@ -61,7 +62,12 @@ public class QuestionTopiaDao extends AbstractQuestionTopiaDao<Question> { hqlBuilder.append(" AND (" + finerHql + ")" ); - List<Question> questions = forHql(hqlBuilder.toString(), args).findAll(); + List<Question> questions; + if (page != null) { + questions = forHql(hqlBuilder.toString(), args).find(page); + } else { + questions = forHql(hqlBuilder.toString(), args).findAll(); + } return questions; } @@ -93,7 +99,7 @@ public class QuestionTopiaDao extends AbstractQuestionTopiaDao<Question> { return questions; } - public List<Question> findForExpert(CoselmarUser expert, List<String> topiaIds) { + public List<Question> findForExpert(CoselmarUser expert, List<String> topiaIds, PaginationParameter page) { StringBuilder hqlBuilder = new StringBuilder("SELECT Q FROM " + Question.class.getName() + " Q " + " INNER JOIN Q." + Question.PROPERTY_PARTICIPANTS + " CUG "); @@ -118,12 +124,18 @@ public class QuestionTopiaDao extends AbstractQuestionTopiaDao<Question> { String topiaIdsCondition = DaoUtils.andAttributeIn("Q", Question.PROPERTY_TOPIA_ID, args, topiaIds); hqlBuilder.append(topiaIdsCondition); - List<Question> questions = forHql(hqlBuilder.toString(), args).findAll(); + + List<Question> questions; + if (page != null) { + questions = forHql(hqlBuilder.toString(), args).find(page); + } else { + questions = forHql(hqlBuilder.toString(), args).findAll(); + } return questions; } - public List<Question> findForClient(CoselmarUser client, QuestionSearchBean searchBean) { + public List<Question> findForClient(CoselmarUser client, QuestionSearchBean searchBean, PaginationParameter page) { StringBuilder hqlBuilder = new StringBuilder("SELECT Q FROM " + Question.class.getName() + " Q "); @@ -138,22 +150,32 @@ public class QuestionTopiaDao extends AbstractQuestionTopiaDao<Question> { hqlBuilder.append(" AND (" + finerHql + ")" ); } - List<Question> questions = forHql(hqlBuilder.toString(), args).findAll(); + List<Question> questions; + if (page != null) { + questions = forHql(hqlBuilder.toString(), args).find(page); + } else { + questions = forHql(hqlBuilder.toString(), args).findAll(); + } return questions; } - public List<Question> findForClient(CoselmarUser client, List<String> topiaIds) { + public List<Question> findForClient(CoselmarUser client, List<String> topiaIds, PaginationParameter page) { TopiaQueryBuilderAddCriteriaOrRunQueryStep<Question> queryBuilder = forTopiaIdIn(topiaIds); queryBuilder.addContains(Question.PROPERTY_CLIENTS, client); - List<Question> questions = queryBuilder.findAll(); + List<Question> questions; + if (page != null) { + questions = queryBuilder.find(page); + } else { + questions = queryBuilder.findAll(); + } return questions; } - public List<Question> findWithSearchBean(QuestionSearchBean searchBean) { + public List<Question> findWithSearchBean(QuestionSearchBean searchBean, PaginationParameter page) { StringBuilder hqlBuilder = new StringBuilder("SELECT Q FROM " + Question.class.getName() + " Q "); @@ -164,7 +186,12 @@ public class QuestionTopiaDao extends AbstractQuestionTopiaDao<Question> { hqlBuilder.append(" WHERE (" + finerHql + ")" ); } - List<Question> questions = forHql(hqlBuilder.toString(), args).findAll(); + List<Question> questions; + if (page != null) { + questions = forHql(hqlBuilder.toString(), args).find(page); + } else { + questions = forHql(hqlBuilder.toString(), args).findAll(); + } return questions; } diff --git a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/QuestionsWebService.java b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/QuestionsWebService.java index dec1de1..cac8102 100644 --- a/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/QuestionsWebService.java +++ b/coselmar-rest/src/main/java/fr/ifremer/coselmar/services/v1/QuestionsWebService.java @@ -59,6 +59,7 @@ import org.apache.commons.logging.LogFactory; import org.apache.lucene.queryparser.classic.ParseException; import org.nuiton.topia.persistence.TopiaIdFactory; import org.nuiton.topia.persistence.TopiaNoResultException; +import org.nuiton.util.pagination.PaginationParameter; /** * @author ymartel <martel@codelutin.com> @@ -231,13 +232,7 @@ public class QuestionsWebService extends CoselmarWebServiceSupport { // Check authentication String authorization = getContext().getHeader("Authorization"); - UserWebToken userWebToken = checkAuthentication(authorization); - - // Retrieve current user - String fullCurrentUserId = getFullUserIdFromShort(userWebToken.getUserId()); - CoselmarUser currentUser = getCoselmarUserDao().forTopiaIdEquals(fullCurrentUserId).findAnyOrNull(); - - String currentUserRole = userWebToken.getRole().toUpperCase(); + CoselmarUser currentUser = checkUserAuthentication(authorization); List<Question> questionList; @@ -254,7 +249,7 @@ public class QuestionsWebService extends CoselmarWebServiceSupport { TopiaIdFactory topiaIdFactory = getPersistenceContext().getTopiaIdFactory(); QuestionBean questionBean; - if (RESTRICTED_ACCESS_USERS.contains(currentUserRole)) { + if (RESTRICTED_ACCESS_USERS.contains(currentUser.getRole().name())) { questionBean = BeanEntityConverter.toLightBean(topiaIdFactory, question); } else { @@ -930,7 +925,7 @@ public class QuestionsWebService extends CoselmarWebServiceSupport { * @throws UnauthorizedException */ protected List<Question> getAllFilteredQuestions(CoselmarUser currentUser, QuestionSearchBean searchBean) throws UnauthorizedException { - String currentUserRole = currentUser.getRole().name(); + QuestionsIndexationService questionsIndexationService = getServicesContext().newService(QuestionsIndexationService.class); //Try to retrieve corresponding questionIds from the index if searchBean given @@ -949,21 +944,31 @@ public class QuestionsWebService extends CoselmarWebServiceSupport { } } - // classical search with DAO } List<Question> questionList; + String currentUserRole = currentUser.getRole().name(); + Integer limit = searchBean.getLimit(); + PaginationParameter paginationParameter = null; + if (limit != null) { + Integer page = searchBean.getPage(); + int wantedPage = page != null ? page.intValue() : 0; + paginationParameter = PaginationParameter.of(wantedPage, limit.intValue(), Question.PROPERTY_SUBMISSION_DATE, true); + } else { + paginationParameter = PaginationParameter.of(0, Integer.MAX_VALUE, Question.PROPERTY_SUBMISSION_DATE, true); + } + // Supervisor or Admin : access to all questions, no restriction if (StringUtils.equalsIgnoreCase(CoselmarUserRole.ADMIN.name(), currentUserRole) || StringUtils.equalsIgnoreCase(CoselmarUserRole.SUPERVISOR.name(), currentUserRole)) { if (fromIndexQuestionIds != null && !fromIndexQuestionIds.isEmpty()) { - questionList = getQuestionDao().forTopiaIdIn(fromIndexQuestionIds).findAll(); + questionList = getQuestionDao().forTopiaIdIn(fromIndexQuestionIds).find(paginationParameter); // classical search with DAO } else { - questionList = getQuestionDao().findWithSearchBean(searchBean); + questionList = getQuestionDao().findWithSearchBean(searchBean, paginationParameter); } @@ -977,30 +982,30 @@ public class QuestionsWebService extends CoselmarWebServiceSupport { } else { if (fromIndexQuestionIds != null && !fromIndexQuestionIds.isEmpty()) { - questionList = getQuestionDao().forTopiaIdIn(fromIndexQuestionIds).findAll(); + questionList = getQuestionDao().forTopiaIdIn(fromIndexQuestionIds).find(paginationParameter); // classical search with DAO } else { - questionList = getQuestionDao().findWithSearchBean(searchBean); + questionList = getQuestionDao().findWithSearchBean(searchBean, paginationParameter); } } // Expert : access to all public question and private question if he is participant or client } else if (StringUtils.equalsIgnoreCase(CoselmarUserRole.EXPERT.name(), currentUserRole)) { if (fromIndexQuestionIds != null && !fromIndexQuestionIds.isEmpty()) { - questionList = getQuestionDao().findForExpert(currentUser, fromIndexQuestionIds); + questionList = getQuestionDao().findForExpert(currentUser, fromIndexQuestionIds, paginationParameter); } else { - questionList = getQuestionDao().findForExpert(currentUser, searchBean); + questionList = getQuestionDao().findForExpert(currentUser, searchBean, paginationParameter); } // Client : access to question he is client } else if (StringUtils.equalsIgnoreCase(CoselmarUserRole.CLIENT.name(), currentUserRole)) { if (fromIndexQuestionIds != null && !fromIndexQuestionIds.isEmpty()) { - questionList = getQuestionDao().findForClient(currentUser, fromIndexQuestionIds); + questionList = getQuestionDao().findForClient(currentUser, fromIndexQuestionIds, paginationParameter); } else { - questionList = getQuestionDao().findForClient(currentUser, searchBean); + questionList = getQuestionDao().findForClient(currentUser, searchBean, paginationParameter); } } else { diff --git a/coselmar-ui/src/main/webapp/i18n/en.js b/coselmar-ui/src/main/webapp/i18n/en.js index f5f301f..0721a06 100644 --- a/coselmar-ui/src/main/webapp/i18n/en.js +++ b/coselmar-ui/src/main/webapp/i18n/en.js @@ -293,5 +293,6 @@ var translateEN = { <ul>\ <li>make a comprehensive research paper repository / issue and retrieve the results in a usable format.</li>\ </p>", +"home.connected.lastProjects" : "Last projects", } \ No newline at end of file diff --git a/coselmar-ui/src/main/webapp/i18n/fr.js b/coselmar-ui/src/main/webapp/i18n/fr.js index 8796029..29f4708 100644 --- a/coselmar-ui/src/main/webapp/i18n/fr.js +++ b/coselmar-ui/src/main/webapp/i18n/fr.js @@ -294,4 +294,5 @@ var translateFR = { <ul>\ <li>faire une recherche globale sur le référentiel document/question et d'extraire le résultat sous un format exploitable</li>\ </p>", +"home.connected.lastProjects" : "Derniers projets", } \ No newline at end of file diff --git a/coselmar-ui/src/main/webapp/index.html b/coselmar-ui/src/main/webapp/index.html index a6bd6fd..2439101 100644 --- a/coselmar-ui/src/main/webapp/index.html +++ b/coselmar-ui/src/main/webapp/index.html @@ -175,8 +175,8 @@ <div class="header-placeholder"></div> </div> </header> - <div ng-view class="container"></div> + <div ng-view class="container"></div> <footer class="footer"> <div class="container"> diff --git a/coselmar-ui/src/main/webapp/js/coselmar-controllers.js b/coselmar-ui/src/main/webapp/js/coselmar-controllers.js index 48e2458..97a9ac7 100644 --- a/coselmar-ui/src/main/webapp/js/coselmar-controllers.js +++ b/coselmar-ui/src/main/webapp/js/coselmar-controllers.js @@ -48,8 +48,8 @@ coselmarControllers.controller("HomeCtrl", ['$scope', '$http', '$location', '$ro $location.path($location.search()["returnTo"]); delete returnTo; } else { - // Redirect on '/' - $location.path('/'); + // Reload page + $route.reload(); } }) } @@ -103,6 +103,19 @@ coselmarControllers.controller("unauthorizedCtrl", ['$scope', function ($scope) }]); +// Controller for home when user connected, load 5 last projects +coselmarControllers.controller("homeConnectedCtrl", ['$scope', 'questionsService', function ($scope, questionsService) { + + var searchOptions = {'limit' : 5, 'page' : 0}; + + questionsService.getQuestions(searchOptions, function(questions) { + $scope.questions = questions; + }, function(fail) { + $scope.questions = []; + }); + +}]); + ///////////////////////////////////////////////// //////////// Documents Part /////////////////// ///////////////////////////////////////////////// diff --git a/coselmar-ui/src/main/webapp/js/coselmar.js b/coselmar-ui/src/main/webapp/js/coselmar.js index a444191..2f7d749 100644 --- a/coselmar-ui/src/main/webapp/js/coselmar.js +++ b/coselmar-ui/src/main/webapp/js/coselmar.js @@ -94,6 +94,7 @@ coselmarApp.config(['$routeProvider', function($routeProvider) { }).otherwise({ redirectTo: '/', + controller : 'homeConnectedCtrl', templateUrl : 'views/home.html' }); }]); diff --git a/coselmar-ui/src/main/webapp/views/home.html b/coselmar-ui/src/main/webapp/views/home.html index 0afe113..e21988b 100644 --- a/coselmar-ui/src/main/webapp/views/home.html +++ b/coselmar-ui/src/main/webapp/views/home.html @@ -21,7 +21,64 @@ <http://www.gnu.org/licenses/gpl-3.0.html>. #L% --> -<div> +<div ng-if="!currentUser"> <div translate="home.presentation.title"></div> <div style="margin-top : 50px" translate="home.presentation.body"></div> </div> + +<div ng-if="currentUser"> + <!-- In case of user connected, show five last projects --> + <div translate="home.presentation.title"></div> + <div> + <h3>{{ "home.connected.lastProjects" | translate }}</h3> + + <table class="table table-bordered"> + <thead> + <tr> + <th>{{ 'question.metadata.title' | translate }}</th> + <th>{{ 'question.metadata.submissionDate' | translate }}</th> + <th>{{ 'question.metadata.themes' | translate }}</th> + <th>{{ 'question.metadata.deadline' | translate }}</th> + <th ng-if="currentUser.role != 'MEMBER' && currentUser.role != 'CLIENT'">{{ 'question.metadata.clients' | translate }}</th> + <th ng-if="currentUser.role != 'MEMBER' && currentUser.role != 'CLIENT'">{{ 'question.metadata.participants' | translate }}</th> + <th ng-if="currentUser.role != 'MEMBER' && currentUser.role != 'CLIENT'">{{ 'question.metadata.relatedDocuments' | translate }}</th> + </tr> + </thead> + <tbody> + <tr ng-repeat="question in questions" > + <td ng-if="currentUser.role != 'MEMBER'"> + <span class="status-{{question.status|lowercase}}" title="{{question.status | translate}}"></span> + <a href="#/questions/{{question.id}}" class="paddingLeft10" tooltip-placement="bottom" tooltip-html-unsafe="{{question.summary}}">{{question.title}}</a> + </td> + <td ng-if="currentUser.role == 'MEMBER'">{{question.title}}</td> + + <td>{{question.submissionDate | date:'mediumDate'}}</td> + + <td><span ng-repeat="theme in question.themes">{{theme}}, </span></td> + + <td>{{question.deadline | date:'mediumDate'}}</td> + + <!-- clients : we use ng-if for better tooltip management --> + <td ng-if="question.clients && currentUser.role != 'MEMBER' && currentUser.role != 'CLIENT'"> + <span tooltip-placement="bottom" tooltip-html-unsafe="{{getUserNames(question.clients)}}" >{{question.clients.length}}</span> + </td> + <td ng-if="!question.clients && currentUser.role != 'MEMBER' && currentUser.role != 'CLIENT'">0</td> + + <!-- participants --> + <td ng-if="question.participants && currentUser.role != 'MEMBER' && currentUser.role != 'CLIENT'"> + <span tooltip-placement="bottom" tooltip-html-unsafe="{{getUserNames(question.participants)}}" >{{question.participants.length}}</span> + </td> + <td ng-if="!question.participants && currentUser.role != 'MEMBER' && currentUser.role != 'CLIENT'">0</td> + + <!-- related documents --> + <td ng-if="question.relatedDocuments && currentUser.role != 'MEMBER' && currentUser.role != 'CLIENT'"> + <span tooltip-placement="bottom" tooltip-html-unsafe="{{getDocumentTitles(question.relatedDocuments)}}" tooltip-trigger="mouseenter" >{{question.relatedDocuments.length}}</span> + </td> + <td ng-if="!question.relatedDocuments && currentUser.role != 'MEMBER' && currentUser.role != 'CLIENT'">0</td> + + </tr> + </tbody> + </table> + <p ng-if="questions && questions.length == 0" translate="common.search.noResult" class="info"/> + </div> +</div> diff --git a/coselmar-ui/src/main/webapp/views/questions/questions.html b/coselmar-ui/src/main/webapp/views/questions/questions.html index 478a0e5..4899300 100644 --- a/coselmar-ui/src/main/webapp/views/questions/questions.html +++ b/coselmar-ui/src/main/webapp/views/questions/questions.html @@ -55,8 +55,7 @@ <th ng-if="currentUser.role != 'MEMBER' && currentUser.role != 'CLIENT'">{{ 'question.metadata.clients' | translate }}</th> <th ng-if="currentUser.role != 'MEMBER' && currentUser.role != 'CLIENT'">{{ 'question.metadata.participants' | translate }}</th> <th ng-if="currentUser.role != 'MEMBER' && currentUser.role != 'CLIENT'">{{ 'question.metadata.relatedDocuments' | translate }}</th> - <th ng-if="currentUser.role == 'MEMBER' || currentUser.role == 'CLIENT'">{{ 'question.metadata.status' | translate }}</th> - <th></th> + <th ng-if="currentUser.role != 'MEMBER' && currentUser.role != 'CLIENT'"></th> </tr> </thead> <tbody> @@ -91,9 +90,7 @@ </td> <td ng-if="!question.relatedDocuments && currentUser.role != 'MEMBER' && currentUser.role != 'CLIENT'">0</td> - <td ng-if="currentUser.role == 'MEMBER' || currentUser.role == 'CLIENT'">{{question.status}}</td> - - <td> + <td ng-if="currentUser.role != 'MEMBER' && currentUser.role != 'CLIENT'"> <!--<a class="btn btn-action btn-disable" ng-click="closeQuestion(question.id)"--> <!--ng-if="currentUser.role == 'SUPERVISOR'">--> <!--<span class="fa fa-close" aria-hidden="true"></span>Close</a>--> -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.