This is an automated email from the git hooks/post-receive script. New commit to branch feature/7858-advanced-search-project in repository coselmar. See http://git.codelutin.com/coselmar.git commit df9dc2b149ee38040a315889ed83dd58f4b9c5a1 Author: Yannick Martel <martel@©odelutin.com> Date: Thu Dec 24 14:51:49 2015 +0100 fixes #7858 add advanced search on project in ui --- .../persistence/entity/QuestionTopiaDao.java | 8 +- .../coselmar/services/v1/QuestionsWebService.java | 2 +- coselmar-ui/src/main/webapp/i18n/en.js | 5 + coselmar-ui/src/main/webapp/i18n/fr.js | 5 + .../src/main/webapp/js/coselmar-controllers.js | 46 ++++++ .../src/main/webapp/views/questions/questions.html | 15 +- .../src/main/webapp/views/questions/toolsPart.html | 166 +++++++++++++++++++++ 7 files changed, 231 insertions(+), 16 deletions(-) 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 b23f1e3..68f1417 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 @@ -239,8 +239,14 @@ public class QuestionTopiaDao extends AbstractQuestionTopiaDao<Question> { finerHqlBuilder.append(statusHql); } + String type = example.getType(); + if (StringUtils.isNotBlank(type)) { + String statusHql = DaoUtils.andAttributeEquals(alias, Question.PROPERTY_TYPE, args, type); + finerHqlBuilder.append(statusHql); + } + if (StringUtils.isNotBlank(example.getTitle())) { - String titleHql = DaoUtils.andAttributeEquals(alias, Question.PROPERTY_TITLE, args, example.getTitle()); + String titleHql = DaoUtils.andAttributeLike(alias, Question.PROPERTY_TITLE, args, example.getTitle()); finerHqlBuilder.append(titleHql); } 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 0ce8299..d264076 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 @@ -1005,7 +1005,7 @@ public class QuestionsWebService extends CoselmarWebServiceSupport { //Try to retrieve corresponding questionIds from the index if searchBean given List<String> fromIndexQuestionIds = null; - if (searchBean != null) { + if (searchBean != null && searchBean.getFullTextSearch() != null && !searchBean.getFullTextSearch().isEmpty()) { try { List<String> questionIds = questionsIndexationService.searchQuestion(searchBean); fromIndexQuestionIds = getQuestionsFullId(questionIds); diff --git a/coselmar-ui/src/main/webapp/i18n/en.js b/coselmar-ui/src/main/webapp/i18n/en.js index 1c8811a..cde94dd 100644 --- a/coselmar-ui/src/main/webapp/i18n/en.js +++ b/coselmar-ui/src/main/webapp/i18n/en.js @@ -159,6 +159,11 @@ var translateEN = { "question.metadata.childrenPhrase" : "Has produced or inspired", "question.metadata.participants" : "Participants", +"question.metadata.submitBefore" : "Submit before", +"question.metadata.submitAfter" : "Submit after", +"question.metadata.deadlineBefore" : "Deadline before", +"question.metadata.deadlineAfter" : "Deadline after", + "question.message.requiredTitle" : "Title is required, minimum 10 characters.", "question.message.requiredType" : "Type is required.", "question.message.requiredSummary" : "A summary is required.", diff --git a/coselmar-ui/src/main/webapp/i18n/fr.js b/coselmar-ui/src/main/webapp/i18n/fr.js index 412f946..8a344c6 100644 --- a/coselmar-ui/src/main/webapp/i18n/fr.js +++ b/coselmar-ui/src/main/webapp/i18n/fr.js @@ -159,6 +159,11 @@ var translateFR = { "question.metadata.childrenPhrase" : "A provoqué ou inspiré", "question.metadata.participants" : "Participants", +"question.metadata.submitBefore" : "Soumis avant le", +"question.metadata.submitAfter" : "Soumis après le", +"question.metadata.deadlineBefore" : "Date limite avant le", +"question.metadata.deadlineAfter" : "Date limite après le", + "question.message.requiredTitle" : "Le titre est requis, avec au minimum 10 caractères.", "question.message.requiredType" : "Le type est requis..", "question.message.requiredSummary" : "Un résumé est requis.", diff --git a/coselmar-ui/src/main/webapp/js/coselmar-controllers.js b/coselmar-ui/src/main/webapp/js/coselmar-controllers.js index 39c6537..1255517 100644 --- a/coselmar-ui/src/main/webapp/js/coselmar-controllers.js +++ b/coselmar-ui/src/main/webapp/js/coselmar-controllers.js @@ -912,6 +912,13 @@ coselmarControllers.controller("QuestionsCtrl", ['$scope', '$route', '$routePara $scope.searchOptions = { 'privacy' : '', 'status' : '', 'fullTextSearch' : []}; + var advancedSearch = $routeParams.advancedSearch; + if (advancedSearch) { + $scope.advanced = advancedSearch; + } else { + $scope.advanced = false; + } + questionsService.getQuestions($scope.searchOptions, function(questions) { // success : just get the questions $scope.questions = questions; @@ -925,6 +932,45 @@ coselmarControllers.controller("QuestionsCtrl", ['$scope', '$route', '$routePara }; + $scope.searchMode = function(type) { + if (type == 'advanced') { + $location.search('advancedSearch'); + $scope.advanced = true; + } else { + $location.search(""); + $scope.advanced = false; + } + }; + + $scope.advancedSearchQuestions = function() { + + //Convert Dates to timestamp + if (angular.isDate($scope.searchOptions.submissionAfterDate)) { + $scope.searchOptions.submissionAfterDate = $scope.searchOptions.submissionAfterDate.getTime(); + } + + if (angular.isDate($scope.searchOptions.submissionBeforeDate)) { + $scope.searchOptions.submissionBeforeDate = $scope.searchOptions.submissionBeforeDate.getTime(); + } + + if (angular.isDate($scope.searchOptions.deadlineAfterDate)) { + $scope.searchOptions.deadlineAfterDate = $scope.searchOptions.deadlineAfterDate.getTime(); + } + + if (angular.isDate($scope.searchOptions.deadlineBeforeDate)) { + $scope.searchOptions.deadlineBeforeDate = $scope.searchOptions.deadlineBeforeDate.getTime(); + } + + questionsService.getQuestions($scope.searchOptions, function(questions){ + $scope.questions = questions; + }, errorService.defaultFailOnCall); + + }; + + $scope.openDatePicker = function(datePickerParam) { + datePickerParam = true; + } + $scope.deleteQuestion = function(questionId) { questionsService.deleteQuestion(questionId, function(questions) { diff --git a/coselmar-ui/src/main/webapp/views/questions/questions.html b/coselmar-ui/src/main/webapp/views/questions/questions.html index 9d0da29..15373f3 100644 --- a/coselmar-ui/src/main/webapp/views/questions/questions.html +++ b/coselmar-ui/src/main/webapp/views/questions/questions.html @@ -31,20 +31,7 @@ </div> <div> - <div> - <div class="form-group" ng-if="context.currentUser.role == 'SUPERVISOR'"> - <a href="#/questions/new" class="form-inline navbar-left btn btn-primary">{{ 'question.button.add' | translate }}</a> - </div> - <form class="form-inline pull-right search-zone" role="questionOptions" ng-submit="searchQuestions()"> - <div class="form-group"> - <span class="fa fa-info-circle" tooltip-placement="bottom" tooltip-html-unsafe="{{ 'common.message.info.searchKeywords' | translate }}"></span> - <input type="search" class="form-control" placeholder="keyword1,keyword2,..." ng-model="searchOptions.fullTextSearch" ng-list /> - </div> - <div class="form-group"> - <button type="submit" class="btn btn-primary glyphicon glyphicon-search"></button> - </div> - </form> - </div> + <div ng-include="src='views/questions/toolsPart.html'"></div> <div class="clear table-responsive paddingLeft10"> <table class="table table-bordered"> <thead> diff --git a/coselmar-ui/src/main/webapp/views/questions/toolsPart.html b/coselmar-ui/src/main/webapp/views/questions/toolsPart.html new file mode 100644 index 0000000..55881be --- /dev/null +++ b/coselmar-ui/src/main/webapp/views/questions/toolsPart.html @@ -0,0 +1,166 @@ +<!-- + #%L + Coselmar :: UI + $Id:$ + $HeadURL:$ + %% + Copyright (C) 2014 - 2015 Ifremer, Code Lutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program. If not, see + <http://www.gnu.org/licenses/gpl-3.0.html>. + #L% + --> + +<div> + <!-- New Document --> + <div class="form-group"> + <div class="form-group" ng-if="context.currentUser.role == 'SUPERVISOR'"> + <a href="#/questions/new" class="form-inline navbar-left btn btn-primary">{{ 'question.button.add' | translate }}</a> + </div> + + <!-- Simple search part --> + + <form class="form-inline pull-right search-zone" role="questionOptions" ng-submit="searchQuestions()" ng-show="!advanced"> + <div class="form-group"> + <span class="fa fa-info-circle" tooltip-placement="bottom" tooltip-html-unsafe="{{ 'common.message.info.searchKeywords' | translate }}"></span> + <input type="search" class="form-control" placeholder="keyword1,keyword2,..." ng-model="searchOptions.fullTextSearch" ng-list /> + </div> + <div class="form-group"> + <button type="submit" class="btn btn-primary glyphicon glyphicon-search"></button> + </div> + <div class="form-group" ng-show="!advanced"> + <a ng-click="searchMode('advanced')" class="btn btn-action"> + <span class="fa fa-expand" aria-hidden="true"></span> + {{'common.button.advanceSearch' | translate }} + </a> + </div> + </form> + + </div> +</div> + +<div class="text-right clear"> +</div> + +<!-- Advanced Search part --> +<div ng-show="advanced" class="search-zone marginVertical20"> + <div class="form-group text-right"> + <a ng-click="searchMode('simple')" class="btn btn-action"><span class="fa fa-compress" aria-hidden="true"></span> {{ 'common.button.simpleSearch' | translate }}</a> + </div> + <form class="form-horizontal" name="questionFullOption" ng-submit="advancedSearchQuestions()"> + + <div class="form-group row"> + + <label class="col-md-1 control-label">{{ 'question.metadata.title' | translate }}</label> + <div class="col-md-2"> + <input class="form-control" type="search" class="form-control" placeholder="Titre" ng-model="searchOptions.title" /> + </div> + + <label class="col-md-1 control-label">{{ 'question.metadata.type' | translate }}</label> + <div class="col-md-2"> + <select class="form-control" name="type" ng-model="searchOptions.type"> + <option value=""></option> + <option value="REUNION">{{ 'question.metadata.type.reunion' | translate }}</option> + <option value="EXPERTISE">{{ 'question.metadata.type.expertise' | translate }}</option> + <option value="PROJECT">{{ 'question.metadata.type.project' | translate }}</option> + </select> + </div> + + <label class="col-md-1 control-label">{{ 'question.metadata.privacy' | translate }}</label> + <div class="col-md-2"> + <select class="form-control" name="privacy" ng-model="searchOptions.privacy"> + <option value=""></option> + <option value="PRIVATE">{{ 'common.privacy.private' | translate }}</option> + <option value="PUBLIC">{{ 'common.privacy.public' | translate }}</option> + </select> + </div> + + <label class="col-md-1 control-label">{{ 'question.metadata.status' | translate }}</label> + <div class="col-md-2"> + <select class="form-control" name="privacy" ng-model="searchOptions.status"> + <option value=""></option> + <option value="OPEN">{{ 'OPEN' | translate }}</option> + <option value="IN_PROGRESS">{{ 'IN_PROGRESS' | translate }}</option> + <option value="CLOSED">{{ 'CLOSED' | translate }}</option> + <option value="ADJOURNED">{{ 'ADJOURNED' | translate }}</option> + </select> + </div> + + </div> + + <div class="form-group row"> + + + <label class="col-md-2 control-label">{{ 'question.metadata.submitAfter' | translate }}</label> + <div class="col-md-3"> + <div class="input-group"> + <input type="text" class="form-control" name="submitAfterDate" + placeholder="dd/MM/yyyy" + ng-model="searchOptions.submissionAfterDate" + uib-datepicker-popup="dd/MM/yyyy" is-open="submitAfterDateOpened" + ng-click="submitAfterDateOpened = true"/> + <span class="input-group-addon"><span class="fa fa-calendar" aria-hidden="true" ng-click="openDatePicker(submitAfterDate)"></span></span> + </div> + </div> + + <label class="col-md-2 control-label">{{ 'question.metadata.submitBefore' | translate }}</label> + <div class="col-md-3"> + <div class="input-group"> + <input type="text" class="form-control" name="submitBeforeDate" + placeholder="dd/MM/yyyy" + ng-model="searchOptions.submissionBeforeDate" + uib-datepicker-popup="dd/MM/yyyy" is-open="submitBeforeDateOpened" + ng-click="submitBeforeDateOpened = true"/> + <span class="input-group-addon"><span class="fa fa-calendar" aria-hidden="true" ng-click="openDatePicker(submitBeforeDate)"></span></span> + </div> + + </div> + + <div class="col-md-2"/> + + </div> + + <div class="form-group row"> + + <label class="col-md-2 control-label" for="deadlineAfterDate">{{ 'question.metadata.deadlineAfter' | translate }}</label> + <div class="col-md-3"> + <div class="input-group"> + <input type="text" class="form-control" id="deadlineAfterDate" + placeholder="dd/MM/yyyy" + ng-model="searchOptions.deadlineAfterDate" + uib-datepicker-popup="dd/MM/yyyy" is-open="deadlineAfterDateOpened" + ng-click="deadlineAfterDateOpened = true"/> + <span class="input-group-addon"><span class="fa fa-calendar" aria-hidden="true" ng-click="openDatePicker(deadlineAfterDateOpened)"></span></span> + </div> + </div> + + <label class="col-md-2 control-label" for="deadlineBeforeDate">{{ 'question.metadata.deadlineBefore' | translate }}</label> + <div class="col-md-3"> + <div class="input-group"> + <input type="text" class="form-control" id="deadlineBeforeDate" + placeholder="dd/MM/yyyy" + ng-model="searchOptions.deadlineBeforeDate" + uib-datepicker-popup="dd/MM/yyyy" is-open="deadlineBeforeDateOpened" + ng-click="deadlineBeforeDateOpened = true"/> + <span class="input-group-addon"><span class="fa fa-calendar" aria-hidden="true" ng-click="openDatePicker(deadlineBeforeDateOpened)"></span></span> + </div> + + </div> + <div class="col-md-2 text-right"> + <button type="submit" class="btn btn-primary fa fa-search" ng-click="advancedSearchQuestions()"><span class="paddingLeft10">{{ 'common.button.search' | translate }}</span></button> + </div> + + </div> + </form> +</div> \ No newline at end of file -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@codelutin.com>.