Search on creation date (server), edit creation date (client)

This commit is contained in:
jendib 2013-07-31 00:07:30 +02:00
parent a8b9148359
commit 871e531c4b
15 changed files with 711 additions and 351 deletions

View File

@ -41,7 +41,6 @@ public class DocumentDao {
// Create the document
EntityManager em = ThreadLocalContext.get().getEntityManager();
document.setCreateDate(new Date());
em.persist(document);
return document.getId();
@ -121,11 +120,18 @@ public class DocumentDao {
criteriaList.add("d.DOC_IDUSER_C = :userId");
parameterMap.put("userId", criteria.getUserId());
}
if (criteria.getSearch() != null) {
criteriaList.add("(d.DOC_TITLE_C LIKE :search OR d.DOC_DESCRIPTION_C LIKE :search)");
parameterMap.put("search", "%" + criteria.getSearch() + "%");
}
if (criteria.getCreateDateMin() != null) {
criteriaList.add("d.DOC_CREATEDATE_D >= :createDateMin");
parameterMap.put("createDateMin", criteria.getCreateDateMin());
}
if (criteria.getCreateDateMax() != null) {
criteriaList.add("d.DOC_CREATEDATE_D <= :createDateMax");
parameterMap.put("createDateMax", criteria.getCreateDateMax());
}
criteriaList.add("d.DOC_DELETEDATE_D is null");

View File

@ -1,5 +1,7 @@
package com.sismics.docs.core.dao.jpa.criteria;
import java.util.Date;
/**
* Document criteria.
@ -17,6 +19,16 @@ public class DocumentCriteria {
*/
private String search;
/**
* Minimum creation date.
*/
private Date createDateMin;
/**
* Maximum creation date.
*/
private Date createDateMax;
/**
* Getter of userId.
*
@ -52,4 +64,40 @@ public class DocumentCriteria {
public void setSearch(String search) {
this.search = search;
}
/**
* Getter of createDateMin.
*
* @return the createDateMin
*/
public Date getCreateDateMin() {
return createDateMin;
}
/**
* Setter of createDateMin.
*
* @param createDateMin createDateMin
*/
public void setCreateDateMin(Date createDateMin) {
this.createDateMin = createDateMin;
}
/**
* Getter of createDateMax.
*
* @return the createDateMax
*/
public Date getCreateDateMax() {
return createDateMax;
}
/**
* Setter of createDateMax.
*
* @param createDateMax createDateMax
*/
public void setCreateDateMax(Date createDateMax) {
this.createDateMax = createDateMax;
}
}

View File

@ -1,5 +1,4 @@
- Client/server side edition of created date
- Client/server side search on tags
- Client/server side search on creation date
- Client side search on creation date
- Client/server side edition of existing tag names
- Server side reordering files

View File

@ -2,6 +2,7 @@ package com.sismics.docs.rest.resource;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@ -105,11 +106,17 @@ public class DocumentResource extends BaseResource {
@QueryParam("offset") Integer offset,
@QueryParam("sort_column") Integer sortColumn,
@QueryParam("asc") Boolean asc,
@QueryParam("search") String search) throws JSONException {
@QueryParam("search") String search,
@QueryParam("create_date_min") String createDateMinStr,
@QueryParam("create_date_max") String createDateMaxStr) throws JSONException {
if (!authenticate()) {
throw new ForbiddenClientException();
}
// Validate input data
Date createDateMin = ValidationUtil.validateDate(createDateMinStr, "create_date_min", true);
Date createDateMax = ValidationUtil.validateDate(createDateMaxStr, "create_date_max", true);
JSONObject response = new JSONObject();
List<JSONObject> documents = new ArrayList<JSONObject>();
@ -118,6 +125,8 @@ public class DocumentResource extends BaseResource {
SortCriteria sortCriteria = new SortCriteria(sortColumn, asc);
DocumentCriteria documentCriteria = new DocumentCriteria();
documentCriteria.setUserId(principal.getId());
documentCriteria.setCreateDateMin(createDateMin);
documentCriteria.setCreateDateMax(createDateMax);
if (!Strings.isNullOrEmpty(search)) {
documentCriteria.setSearch(search);
}
@ -150,7 +159,8 @@ public class DocumentResource extends BaseResource {
public Response add(
@FormParam("title") String title,
@FormParam("description") String description,
@FormParam("tags[]") List<String> tagList) throws JSONException {
@FormParam("tags[]") List<String> tagList,
@FormParam("create_date") String createDateStr) throws JSONException {
if (!authenticate()) {
throw new ForbiddenClientException();
}
@ -158,6 +168,7 @@ public class DocumentResource extends BaseResource {
// Validate input data
title = ValidationUtil.validateLength(title, "title", 1, 100, false);
description = ValidationUtil.validateLength(description, "description", 0, 4000, true);
Date createDate = ValidationUtil.validateDate(createDateStr, "create_date", true);
// Create the document
DocumentDao documentDao = new DocumentDao();
@ -165,6 +176,11 @@ public class DocumentResource extends BaseResource {
document.setUserId(principal.getId());
document.setTitle(title);
document.setDescription(description);
if (createDate == null) {
document.setCreateDate(new Date());
} else {
document.setCreateDate(createDate);
}
String documentId = documentDao.create(document);
// Update tags
@ -190,7 +206,8 @@ public class DocumentResource extends BaseResource {
@PathParam("id") String id,
@FormParam("title") String title,
@FormParam("description") String description,
@FormParam("tags[]") List<String> tagList) throws JSONException {
@FormParam("tags[]") List<String> tagList,
@FormParam("create_date") String createDateStr) throws JSONException {
if (!authenticate()) {
throw new ForbiddenClientException();
}
@ -198,6 +215,7 @@ public class DocumentResource extends BaseResource {
// Validate input data
title = ValidationUtil.validateLength(title, "title", 1, 100, false);
description = ValidationUtil.validateLength(description, "description", 0, 4000, true);
Date createDate = ValidationUtil.validateDate(createDateStr, "create_date", true);
// Get the document
DocumentDao documentDao = new DocumentDao();
@ -215,6 +233,9 @@ public class DocumentResource extends BaseResource {
if (description != null) {
document.setDescription(description);
}
if (createDate != null) {
document.setCreateDate(createDate);
}
// Update tags
updateTagList(id, tagList);

View File

@ -26,6 +26,9 @@ App.controller('DocumentEdit', function($scope, $q, $http, $state, $stateParams,
$scope.edit = function() {
var promise = null;
var document = angular.copy($scope.document);
if (document.create_date instanceof Date) {
document.create_date = document.create_date.getTime();
}
// Extract ids from tags
document.tags = _.pluck(document.tags, 'id');

View File

@ -3,7 +3,7 @@
/**
* Document view controller.
*/
App.controller('DocumentView', function($rootScope, $scope, $state, $stateParams, $dialog, Restangular) {
App.controller('DocumentView', function($scope, $state, $stateParams, $dialog, Restangular) {
// Load data from server
$scope.document = Restangular.one('document', $stateParams.id).get();
@ -25,7 +25,7 @@ App.controller('DocumentView', function($rootScope, $scope, $state, $stateParams
*/
$scope.loadFiles = function() {
Restangular.one('file').getList('list', { id: $stateParams.id }).then(function(data) {
$rootScope.files = data.files;
$scope.files = data.files;
});
};
$scope.loadFiles();

View File

@ -7,23 +7,28 @@ App.controller('FileView', function($dialog, $state, $stateParams) {
var dialog = $dialog.dialog({
keyboard: true,
templateUrl: 'partial/file.view.html',
controller: function($rootScope, $scope, $state, $stateParams) {
controller: function($scope, $state, $stateParams, Restangular) {
$scope.id = $stateParams.fileId;
// Search current file
_.each($rootScope.files, function(value, key, list) {
if (value.id == $scope.id) {
$scope.file = value;
}
// Load files
Restangular.one('file').getList('list', { id: $stateParams.id }).then(function(data) {
$scope.files = data.files;
// Search current file
_.each($scope.files, function(value, key, list) {
if (value.id == $scope.id) {
$scope.file = value;
}
});
});
/**
* Navigate to the next file.
*/
$scope.nextFile = function() {
_.each($rootScope.files, function(value, key, list) {
_.each($scope.files, function(value, key, list) {
if (value.id == $scope.id) {
var next = $rootScope.files[key + 1];
var next = $scope.files[key + 1];
if (next) {
dialog.close({});
$state.transitionTo('document.view.file', { id: $stateParams.id, fileId: next.id });
@ -36,9 +41,9 @@ App.controller('FileView', function($dialog, $state, $stateParams) {
* Navigate to the previous file.
*/
$scope.previousFile = function() {
_.each($rootScope.files, function(value, key, list) {
_.each($scope.files, function(value, key, list) {
if (value.id == $scope.id) {
var previous = $rootScope.files[key - 1];
var previous = $scope.files[key - 1];
if (previous) {
dialog.close({});
$state.transitionTo('document.view.file', { id: $stateParams.id, fileId: previous.id });

View File

@ -3,9 +3,10 @@
/**
* Login controller.
*/
App.controller('Login', function($scope, $state, $dialog, User) {
App.controller('Login', function($scope, $rootScope, $state, $dialog, User) {
$scope.login = function() {
User.login($scope.user).then(function() {
$rootScope.userInfo = User.userInfo(true);
$state.transitionTo('document.default');
}, function() {
var title = 'Login failed';

View File

@ -3,6 +3,6 @@
/**
* Navigation controller.
*/
App.controller('Navigation', function($scope, User) {
$scope.userInfo = User.userInfo();
App.controller('Navigation', function($scope, $rootScope, User) {
$rootScope.userInfo = User.userInfo();
});

View File

@ -12,17 +12,7 @@ App.factory('Tag', function(Restangular) {
* @param force If true, force reloading data
*/
tags: function(force) {
if (tags == null || force) {
tags = Restangular.one('tag/list').get();
}
return tags;
},
/**
* Login an user.
*/
login: function(user) {
return Restangular.one('user').post('login', user);
return Restangular.one('tag/list').get();
}
}
});

File diff suppressed because it is too large Load Diff

View File

@ -11,6 +11,12 @@
<textarea ng-maxlength="4000" class="input-block-level" rows="5" id="inputDescription" name="description" ng-model="document.description"></textarea>
</div>
</div>
<div class="control-group">
<label class="control-label" for="inputCreateDate">Creation date</label>
<div class="controls">
<input type="text" id="inputCreateDate" datepicker-popup="yyyy-MM-dd" ng-model="document.create_date" starting-day="1" show-weeks="false" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="inputFiles">New files</label>
<div class="controls">

View File

@ -18,7 +18,7 @@
<tbody>
<tr ng-click="viewDocument(document.id)" ng-repeat="document in documents.documents">
<td>{{ document.title }}</td>
<td>{{ document.create_date | date: 'short' }}</td>
<td>{{ document.create_date | date: 'yyyy-MM-dd' }}</td>
</tr>
</tbody>
</table>

View File

@ -6,7 +6,7 @@
</div>
<div class="page-header">
<h1>{{ document.title }} <small>{{ document.create_date | date: 'short' }}</small></h1>
<h1>{{ document.title }} <small>{{ document.create_date | date: 'yyyy-MM-dd' }}</small></h1>
<ul class="inline">
<li ng-repeat="tag in document.tags"><span class="label label-info">{{ tag.name }}</span></li>
</ul>

View File

@ -1,5 +1,8 @@
package com.sismics.docs.rest;
import java.util.Date;
import junit.framework.Assert;
import org.codehaus.jettison.json.JSONArray;
@ -48,6 +51,8 @@ public class TestDocumentResource extends BaseJerseyTest {
postParams.add("title", "My super document 1");
postParams.add("description", "My super description for document 1");
postParams.add("tags[]", tag1Id);
long create1Date = new Date().getTime();
postParams.add("create_date", create1Date);
response = documentResource.put(ClientResponse.class, postParams);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
json = response.getEntity(JSONObject.class);
@ -67,7 +72,7 @@ public class TestDocumentResource extends BaseJerseyTest {
Assert.assertTrue(documents.length() == 1);
Assert.assertEquals(document1Id, documents.getJSONObject(0).getString("id"));
// Search documents
// Search documents by query
documentResource = resource().path("/document/list");
documentResource.addFilter(new CookieAuthenticationFilter(document1Token));
getParams = new MultivaluedMapImpl();
@ -78,6 +83,20 @@ public class TestDocumentResource extends BaseJerseyTest {
documents = json.getJSONArray("documents");
Assert.assertTrue(documents.length() == 1);
Assert.assertEquals(document1Id, documents.getJSONObject(0).getString("id"));
Assert.assertEquals(create1Date, documents.getJSONObject(0).getLong("create_date"));
// Search documents by date
documentResource = resource().path("/document/list");
documentResource.addFilter(new CookieAuthenticationFilter(document1Token));
getParams = new MultivaluedMapImpl();
getParams.putSingle("create_date_min", create1Date - 3600000);
getParams.putSingle("create_date_max", create1Date + 1800000);
response = documentResource.queryParams(getParams).get(ClientResponse.class);
json = response.getEntity(JSONObject.class);
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
documents = json.getJSONArray("documents");
Assert.assertTrue(documents.length() == 1);
Assert.assertEquals(document1Id, documents.getJSONObject(0).getString("id"));
// Search documents (nothing)
documentResource = resource().path("/document/list");