diff --git a/docs-core/src/main/java/com/sismics/docs/core/dao/lucene/LuceneDao.java b/docs-core/src/main/java/com/sismics/docs/core/dao/lucene/LuceneDao.java
index 67d733e0..27d7e5c1 100644
--- a/docs-core/src/main/java/com/sismics/docs/core/dao/lucene/LuceneDao.java
+++ b/docs-core/src/main/java/com/sismics/docs/core/dao/lucene/LuceneDao.java
@@ -77,8 +77,20 @@ public class LuceneDao {
}
/**
- * Update document index.
+ * Update file index.
*
+ * @param file Updated file
+ */
+ public void updateFile(final File file) {
+ LuceneUtil.handle(indexWriter -> {
+ org.apache.lucene.document.Document luceneDocument = getDocumentFromFile(file);
+ indexWriter.updateDocument(new Term("id", file.getId()), luceneDocument);
+ });
+ }
+
+ /**
+ * Update document index.
+ *
* @param document Updated document
*/
public void updateDocument(final Document document) {
@@ -87,7 +99,7 @@ public class LuceneDao {
indexWriter.updateDocument(new Term("id", document.getId()), luceneDocument);
});
}
-
+
/**
* Delete document from the index.
*
@@ -112,7 +124,7 @@ public class LuceneDao {
// Build search query
StandardQueryParser qpHelper = new StandardQueryParser(new StandardAnalyzer());
- qpHelper.setPhraseSlop(100000); // PhraseQuery add terms
+ qpHelper.setPhraseSlop(100); // PhraseQuery add terms
// Search on documents and files
BooleanQuery query = new BooleanQuery.Builder()
@@ -126,6 +138,7 @@ public class LuceneDao {
.add(qpHelper.parse(searchQuery, "type"), Occur.SHOULD)
.add(qpHelper.parse(searchQuery, "coverage"), Occur.SHOULD)
.add(qpHelper.parse(searchQuery, "rights"), Occur.SHOULD)
+ .add(qpHelper.parse(searchQuery, "filename"), Occur.SHOULD)
.add(qpHelper.parse(fullSearchQuery, "content"), Occur.SHOULD)
.build();
@@ -150,7 +163,9 @@ public class LuceneDao {
} else if (type.equals("file")) {
documentId = document.get("document_id");
}
- documentIdList.add(documentId);
+ if (documentId != null) {
+ documentIdList.add(documentId);
+ }
}
return documentIdList;
@@ -208,7 +223,12 @@ public class LuceneDao {
org.apache.lucene.document.Document luceneDocument = new org.apache.lucene.document.Document();
luceneDocument.add(new StringField("id", file.getId(), Field.Store.YES));
luceneDocument.add(new StringField("doctype", "file", Field.Store.YES));
- luceneDocument.add(new StringField("document_id", file.getDocumentId(), Field.Store.YES));
+ if (file.getName() != null) {
+ luceneDocument.add(new TextField("filename", file.getName(), Field.Store.NO));
+ }
+ if (file.getDocumentId() != null) {
+ luceneDocument.add(new StringField("document_id", file.getDocumentId(), Field.Store.YES));
+ }
if (file.getContent() != null) {
luceneDocument.add(new TextField("content", file.getContent(), Field.Store.NO));
}
diff --git a/docs-core/src/main/java/com/sismics/docs/core/event/FileCreatedAsyncEvent.java b/docs-core/src/main/java/com/sismics/docs/core/event/FileCreatedAsyncEvent.java
index d83b5de1..5273994d 100644
--- a/docs-core/src/main/java/com/sismics/docs/core/event/FileCreatedAsyncEvent.java
+++ b/docs-core/src/main/java/com/sismics/docs/core/event/FileCreatedAsyncEvent.java
@@ -1,61 +1,9 @@
package com.sismics.docs.core.event;
-import com.google.common.base.MoreObjects;
-import com.sismics.docs.core.model.jpa.File;
-
-import java.nio.file.Path;
-
/**
* New file created event.
*
* @author bgamard
*/
-public class FileCreatedAsyncEvent extends UserEvent {
- /**
- * Created file.
- */
- private File file;
-
- /**
- * Language of the file.
- */
- private String language;
-
- /**
- * Unencrypted original file.
- */
- private Path unencryptedFile;
-
- public File getFile() {
- return file;
- }
-
- public void setFile(File file) {
- this.file = file;
- }
-
- public String getLanguage() {
- return language;
- }
-
- public void setLanguage(String language) {
- this.language = language;
- }
-
- public Path getUnencryptedFile() {
- return unencryptedFile;
- }
-
- public FileCreatedAsyncEvent setUnencryptedFile(Path unencryptedFile) {
- this.unencryptedFile = unencryptedFile;
- return this;
- }
-
- @Override
- public String toString() {
- return MoreObjects.toStringHelper(this)
- .add("file", file)
- .add("language", language)
- .toString();
- }
+public class FileCreatedAsyncEvent extends FileEvent {
}
\ No newline at end of file
diff --git a/docs-core/src/main/java/com/sismics/docs/core/event/FileEvent.java b/docs-core/src/main/java/com/sismics/docs/core/event/FileEvent.java
new file mode 100644
index 00000000..9337e84b
--- /dev/null
+++ b/docs-core/src/main/java/com/sismics/docs/core/event/FileEvent.java
@@ -0,0 +1,61 @@
+package com.sismics.docs.core.event;
+
+import com.google.common.base.MoreObjects;
+import com.sismics.docs.core.model.jpa.File;
+
+import java.nio.file.Path;
+
+/**
+ * New file event.
+ *
+ * @author bgamard
+ */
+public abstract class FileEvent extends UserEvent {
+ /**
+ * Created file.
+ */
+ private File file;
+
+ /**
+ * Language of the file.
+ */
+ private String language;
+
+ /**
+ * Unencrypted original file.
+ */
+ private Path unencryptedFile;
+
+ public File getFile() {
+ return file;
+ }
+
+ public void setFile(File file) {
+ this.file = file;
+ }
+
+ public String getLanguage() {
+ return language;
+ }
+
+ public void setLanguage(String language) {
+ this.language = language;
+ }
+
+ public Path getUnencryptedFile() {
+ return unencryptedFile;
+ }
+
+ public FileEvent setUnencryptedFile(Path unencryptedFile) {
+ this.unencryptedFile = unencryptedFile;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("file", file)
+ .add("language", language)
+ .toString();
+ }
+}
\ No newline at end of file
diff --git a/docs-core/src/main/java/com/sismics/docs/core/event/FileUpdatedAsyncEvent.java b/docs-core/src/main/java/com/sismics/docs/core/event/FileUpdatedAsyncEvent.java
new file mode 100644
index 00000000..622dea6e
--- /dev/null
+++ b/docs-core/src/main/java/com/sismics/docs/core/event/FileUpdatedAsyncEvent.java
@@ -0,0 +1,9 @@
+package com.sismics.docs.core.event;
+
+/**
+ * New file created event.
+ *
+ * @author bgamard
+ */
+public class FileUpdatedAsyncEvent extends FileEvent {
+}
\ No newline at end of file
diff --git a/docs-core/src/main/java/com/sismics/docs/core/listener/async/FileCreatedAsyncListener.java b/docs-core/src/main/java/com/sismics/docs/core/listener/async/FileProcessingAsyncListener.java
similarity index 81%
rename from docs-core/src/main/java/com/sismics/docs/core/listener/async/FileCreatedAsyncListener.java
rename to docs-core/src/main/java/com/sismics/docs/core/listener/async/FileProcessingAsyncListener.java
index b8948753..9ab45855 100644
--- a/docs-core/src/main/java/com/sismics/docs/core/listener/async/FileCreatedAsyncListener.java
+++ b/docs-core/src/main/java/com/sismics/docs/core/listener/async/FileProcessingAsyncListener.java
@@ -5,6 +5,8 @@ import com.sismics.docs.core.dao.jpa.FileDao;
import com.sismics.docs.core.dao.jpa.UserDao;
import com.sismics.docs.core.dao.lucene.LuceneDao;
import com.sismics.docs.core.event.FileCreatedAsyncEvent;
+import com.sismics.docs.core.event.FileEvent;
+import com.sismics.docs.core.event.FileUpdatedAsyncEvent;
import com.sismics.docs.core.model.jpa.File;
import com.sismics.docs.core.model.jpa.User;
import com.sismics.docs.core.util.DirectoryUtil;
@@ -28,19 +30,19 @@ import java.text.MessageFormat;
import java.util.concurrent.atomic.AtomicReference;
/**
- * Listener on file created.
+ * Listener on file processing.
*
* @author bgamard
*/
-public class FileCreatedAsyncListener {
+public class FileProcessingAsyncListener {
/**
* Logger.
*/
- private static final Logger log = LoggerFactory.getLogger(FileCreatedAsyncListener.class);
+ private static final Logger log = LoggerFactory.getLogger(FileProcessingAsyncListener.class);
/**
* File created.
- *
+ *
* @param event File created event
*/
@Subscribe
@@ -49,6 +51,41 @@ public class FileCreatedAsyncListener {
log.info("File created event: " + event.toString());
}
+ processFile(event);
+
+ // Update Lucene index
+ LuceneDao luceneDao = new LuceneDao();
+ luceneDao.createFile(event.getFile());
+
+ FileUtil.endProcessingFile(event.getFile().getId());
+ }
+
+ /**
+ * File updated.
+ *
+ * @param event File updated event
+ */
+ @Subscribe
+ public void on(final FileUpdatedAsyncEvent event) {
+ if (log.isInfoEnabled()) {
+ log.info("File updated event: " + event.toString());
+ }
+
+ processFile(event);
+
+ // Update Lucene index
+ LuceneDao luceneDao = new LuceneDao();
+ luceneDao.updateFile(event.getFile());
+
+ FileUtil.endProcessingFile(event.getFile().getId());
+ }
+
+ /**
+ * Process the file (create/update).
+ *
+ * @param event File event
+ */
+ private void processFile(FileEvent event) {
// Find a format handler
final File file = event.getFile();
FormatHandler formatHandler = FormatHandlerUtil.find(file.getMimeType());
@@ -102,7 +139,7 @@ public class FileCreatedAsyncListener {
try {
content.set(formatHandler.extractContent(event.getLanguage(), event.getUnencryptedFile()));
} catch (Exception e) {
- log.error("Error extracting content from: " + event.getFile());
+ log.error("Error extracting content from: " + event.getFile(), e);
}
log.info(MessageFormat.format("File content extracted in {0}ms", System.currentTimeMillis() - startTime));
@@ -117,13 +154,5 @@ public class FileCreatedAsyncListener {
file.setContent(content.get());
fileDao.update(file);
});
-
- if (file.getDocumentId() != null) {
- // Update Lucene index
- LuceneDao luceneDao = new LuceneDao();
- luceneDao.createFile(event.getFile());
- }
-
- FileUtil.endProcessingFile(file.getId());
}
}
diff --git a/docs-core/src/main/java/com/sismics/docs/core/listener/async/TemporaryFileCleanupAsyncListener.java b/docs-core/src/main/java/com/sismics/docs/core/listener/async/TemporaryFileCleanupAsyncListener.java
index 9bb6bfd3..fe59739c 100644
--- a/docs-core/src/main/java/com/sismics/docs/core/listener/async/TemporaryFileCleanupAsyncListener.java
+++ b/docs-core/src/main/java/com/sismics/docs/core/listener/async/TemporaryFileCleanupAsyncListener.java
@@ -17,7 +17,7 @@ public class TemporaryFileCleanupAsyncListener {
/**
* Logger.
*/
- private static final Logger log = LoggerFactory.getLogger(FileCreatedAsyncListener.class);
+ private static final Logger log = LoggerFactory.getLogger(TemporaryFileCleanupAsyncListener.class);
/**
* Cleanup temporary files.
diff --git a/docs-core/src/main/java/com/sismics/docs/core/model/context/AppContext.java b/docs-core/src/main/java/com/sismics/docs/core/model/context/AppContext.java
index 3d8ea0c9..f8618d9f 100644
--- a/docs-core/src/main/java/com/sismics/docs/core/model/context/AppContext.java
+++ b/docs-core/src/main/java/com/sismics/docs/core/model/context/AppContext.java
@@ -117,7 +117,7 @@ public class AppContext {
asyncExecutorList = new ArrayList<>();
asyncEventBus = newAsyncEventBus();
- asyncEventBus.register(new FileCreatedAsyncListener());
+ asyncEventBus.register(new FileProcessingAsyncListener());
asyncEventBus.register(new FileDeletedAsyncListener());
asyncEventBus.register(new DocumentCreatedAsyncListener());
asyncEventBus.register(new DocumentUpdatedAsyncListener());
diff --git a/docs-core/src/main/java/com/sismics/docs/core/service/InboxService.java b/docs-core/src/main/java/com/sismics/docs/core/service/InboxService.java
index 5dbda09a..6817a06a 100644
--- a/docs-core/src/main/java/com/sismics/docs/core/service/InboxService.java
+++ b/docs-core/src/main/java/com/sismics/docs/core/service/InboxService.java
@@ -232,7 +232,8 @@ public class InboxService extends AbstractScheduledService {
// Add files to the document
for (EmailUtil.FileContent fileContent : mailContent.getFileContentList()) {
- FileUtil.createFile(fileContent.getName(), fileContent.getFile(), fileContent.getSize(), "eng", "admin", document.getId());
+ FileUtil.createFile(fileContent.getName(), fileContent.getFile(), fileContent.getSize(),
+ document.getLanguage(), "admin", document.getId());
}
}
diff --git a/docs-core/src/main/java/com/sismics/docs/core/util/EncryptionUtil.java b/docs-core/src/main/java/com/sismics/docs/core/util/EncryptionUtil.java
index 0713280f..dd7ecf94 100644
--- a/docs-core/src/main/java/com/sismics/docs/core/util/EncryptionUtil.java
+++ b/docs-core/src/main/java/com/sismics/docs/core/util/EncryptionUtil.java
@@ -54,7 +54,7 @@ public class EncryptionUtil {
* @param is InputStream to encrypt
* @param privateKey Private key
* @return Encrypted stream
- * @throws Exception
+ * @throws Exception e
*/
public static InputStream decryptInputStream(InputStream is, String privateKey) throws Exception {
return new CipherInputStream(is, getCipher(privateKey, Cipher.DECRYPT_MODE));
@@ -66,7 +66,7 @@ public class EncryptionUtil {
* @param file Encrypted file
* @param privateKey Private key
* @return Decrypted temporary file
- * @throws Exception
+ * @throws Exception e
*/
public static Path decryptFile(Path file, String privateKey) throws Exception {
if (privateKey == null) {
@@ -86,7 +86,7 @@ public class EncryptionUtil {
*
* @param privateKey Private key
* @return Encryption cipher
- * @throws Exception
+ * @throws Exception e
*/
public static Cipher getEncryptionCipher(String privateKey) throws Exception {
if (Strings.isNullOrEmpty(privateKey)) {
@@ -101,7 +101,7 @@ public class EncryptionUtil {
* @param privateKey Private key
* @param mode Mode (encrypt or decrypt)
* @return Cipher
- * @throws Exception
+ * @throws Exception e
*/
private static Cipher getCipher(String privateKey, int mode) throws Exception {
PBEKeySpec keySpec = new PBEKeySpec(privateKey.toCharArray(), SALT.getBytes(), 2000, 256);
diff --git a/docs-core/src/main/java/com/sismics/docs/core/util/format/ImageFormatHandler.java b/docs-core/src/main/java/com/sismics/docs/core/util/format/ImageFormatHandler.java
index c0de99b9..5d3a2459 100644
--- a/docs-core/src/main/java/com/sismics/docs/core/util/format/ImageFormatHandler.java
+++ b/docs-core/src/main/java/com/sismics/docs/core/util/format/ImageFormatHandler.java
@@ -45,6 +45,10 @@ public class ImageFormatHandler implements FormatHandler {
@Override
public String extractContent(String language, Path file) throws Exception {
+ if (language == null) {
+ return null;
+ }
+
try (InputStream inputStream = Files.newInputStream(file)) {
return FileUtil.ocrFile(language, ImageIO.read(inputStream));
}
diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/DocumentResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/DocumentResource.java
index dc086fa4..60b0fae7 100644
--- a/docs-web/src/main/java/com/sismics/docs/rest/resource/DocumentResource.java
+++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/DocumentResource.java
@@ -894,7 +894,8 @@ public class DocumentResource extends BaseResource {
// Add files to the document
try {
for (EmailUtil.FileContent fileContent : mailContent.getFileContentList()) {
- FileUtil.createFile(fileContent.getName(), fileContent.getFile(), fileContent.getSize(), "eng", principal.getId(), document.getId());
+ FileUtil.createFile(fileContent.getName(), fileContent.getFile(), fileContent.getSize(),
+ document.getLanguage(), principal.getId(), document.getId());
}
} catch (IOException e) {
throw new ClientException(e.getMessage(), e.getMessage(), e);
diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java
index a60a5d14..4a00cdee 100644
--- a/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java
+++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java
@@ -10,8 +10,8 @@ import com.sismics.docs.core.dao.jpa.FileDao;
import com.sismics.docs.core.dao.jpa.UserDao;
import com.sismics.docs.core.dao.jpa.dto.DocumentDto;
import com.sismics.docs.core.event.DocumentUpdatedAsyncEvent;
-import com.sismics.docs.core.event.FileCreatedAsyncEvent;
import com.sismics.docs.core.event.FileDeletedAsyncEvent;
+import com.sismics.docs.core.event.FileUpdatedAsyncEvent;
import com.sismics.docs.core.model.jpa.File;
import com.sismics.docs.core.model.jpa.User;
import com.sismics.docs.core.util.DirectoryUtil;
@@ -166,7 +166,7 @@ public class FileResource extends BaseResource {
}
// Validate input data
- ValidationUtil.validateRequired(documentId, "id");
+ ValidationUtil.validateRequired(documentId, "documentId");
// Get the current user
UserDao userDao = new UserDao();
@@ -191,17 +191,17 @@ public class FileResource extends BaseResource {
file.setOrder(fileDao.getByDocumentId(principal.getId(), documentId).size());
fileDao.update(file);
- // Raise a new file created event and document updated event (it wasn't sent during file creation)
+ // Raise a new file updated event and document updated event (it wasn't sent during file creation)
try {
java.nio.file.Path storedFile = DirectoryUtil.getStorageDirectory().resolve(id);
java.nio.file.Path unencryptedFile = EncryptionUtil.decryptFile(storedFile, user.getPrivateKey());
FileUtil.startProcessingFile(id);
- FileCreatedAsyncEvent fileCreatedAsyncEvent = new FileCreatedAsyncEvent();
- fileCreatedAsyncEvent.setUserId(principal.getId());
- fileCreatedAsyncEvent.setLanguage(documentDto.getLanguage());
- fileCreatedAsyncEvent.setFile(file);
- fileCreatedAsyncEvent.setUnencryptedFile(unencryptedFile);
- ThreadLocalContext.get().addAsyncEvent(fileCreatedAsyncEvent);
+ FileUpdatedAsyncEvent fileUpdatedAsyncEvent = new FileUpdatedAsyncEvent();
+ fileUpdatedAsyncEvent.setUserId(principal.getId());
+ fileUpdatedAsyncEvent.setLanguage(documentDto.getLanguage());
+ fileUpdatedAsyncEvent.setFile(file);
+ fileUpdatedAsyncEvent.setUnencryptedFile(unencryptedFile);
+ ThreadLocalContext.get().addAsyncEvent(fileUpdatedAsyncEvent);
DocumentUpdatedAsyncEvent documentUpdatedAsyncEvent = new DocumentUpdatedAsyncEvent();
documentUpdatedAsyncEvent.setUserId(principal.getId());
@@ -210,7 +210,7 @@ public class FileResource extends BaseResource {
} catch (Exception e) {
throw new ServerException("AttachError", "Error attaching file to document", e);
}
-
+
// Always return OK
JsonObjectBuilder response = Json.createObjectBuilder()
.add("status", "ok");
@@ -258,6 +258,67 @@ public class FileResource extends BaseResource {
.add("status", "ok");
return Response.ok().entity(response.build()).build();
}
+
+ /**
+ * Process a file manually.
+ *
+ * @api {post} /file/:id/process Process a file manually
+ * @apiName PostFileProcess
+ * @apiGroup File
+ * @apiParam {String} id File ID
+ * @apiSuccess {String} status Status OK
+ * @apiError (client) ForbiddenError Access denied
+ * @apiError (client) ValidationError Validation error
+ * @apiError (server) ProcessingError Processing error
+ * @apiPermission user
+ * @apiVersion 1.6.0
+ *
+ * @param id File ID
+ * @return Response
+ */
+ @POST
+ @Path("{id: [a-z0-9\\-]+}/process")
+ public Response process(@PathParam("id") String id) {
+ if (!authenticate()) {
+ throw new ForbiddenClientException();
+ }
+
+ // Get the current user
+ UserDao userDao = new UserDao();
+ User user = userDao.getById(principal.getId());
+
+ // Get the document and the file
+ DocumentDao documentDao = new DocumentDao();
+ FileDao fileDao = new FileDao();
+ File file = fileDao.getFile(id);
+ if (file == null) {
+ throw new NotFoundException();
+ }
+ DocumentDto documentDto = documentDao.getDocument(file.getDocumentId(), PermType.WRITE, getTargetIdList(null));
+ if (documentDto == null) {
+ throw new NotFoundException();
+ }
+
+ // Start the processing asynchronously
+ try {
+ java.nio.file.Path storedFile = DirectoryUtil.getStorageDirectory().resolve(id);
+ java.nio.file.Path unencryptedFile = EncryptionUtil.decryptFile(storedFile, user.getPrivateKey());
+ FileUtil.startProcessingFile(id);
+ FileUpdatedAsyncEvent fileUpdatedAsyncEvent = new FileUpdatedAsyncEvent();
+ fileUpdatedAsyncEvent.setUserId(principal.getId());
+ fileUpdatedAsyncEvent.setLanguage(documentDto.getLanguage());
+ fileUpdatedAsyncEvent.setFile(file);
+ fileUpdatedAsyncEvent.setUnencryptedFile(unencryptedFile);
+ ThreadLocalContext.get().addAsyncEvent(fileUpdatedAsyncEvent);
+ } catch (Exception e) {
+ throw new ServerException("ProcessingError", "Error processing this file", e);
+ }
+
+ // Always return OK
+ JsonObjectBuilder response = Json.createObjectBuilder()
+ .add("status", "ok");
+ return Response.ok().entity(response.build()).build();
+ }
/**
* Reorder files.
diff --git a/docs-web/src/main/webapp/src/app/docs/controller/document/DocumentViewContent.js b/docs-web/src/main/webapp/src/app/docs/controller/document/DocumentViewContent.js
index f5631693..f8f021fe 100644
--- a/docs-web/src/main/webapp/src/app/docs/controller/document/DocumentViewContent.js
+++ b/docs-web/src/main/webapp/src/app/docs/controller/document/DocumentViewContent.js
@@ -157,4 +157,13 @@ angular.module('docs').controller('DocumentViewContent', function ($scope, $root
})
});
};
+
+ /**
+ * Process a file.
+ */
+ $scope.processFile = function (file) {
+ Restangular.one('file/' + file.id).post('process').then(function () {
+ file.processing = true;
+ });
+ };
});
\ No newline at end of file
diff --git a/docs-web/src/main/webapp/src/locale/en.json b/docs-web/src/main/webapp/src/locale/en.json
index c77223a7..27579683 100644
--- a/docs-web/src/main/webapp/src/locale/en.json
+++ b/docs-web/src/main/webapp/src/locale/en.json
@@ -115,7 +115,8 @@
"upload_error_quota": "Quota reached",
"drop_zone": "Drag & drop files here to upload",
"add_files": "Add files",
- "file_processing_indicator": "This file is being processed. Searching will not be available before it is complete."
+ "file_processing_indicator": "This file is being processed. Searching will not be available before it is complete.",
+ "reprocess_file": "Reprocess this file"
},
"workflow": {
"workflow": "Workflow",
diff --git a/docs-web/src/main/webapp/src/partial/docs/document.view.content.html b/docs-web/src/main/webapp/src/partial/docs/document.view.content.html
index f4c37fa6..974e9286 100644
--- a/docs-web/src/main/webapp/src/partial/docs/document.view.content.html
+++ b/docs-web/src/main/webapp/src/partial/docs/document.view.content.html
@@ -72,6 +72,10 @@
{{ 'rename' | translate }}
+
+
+ {{ 'document.view.content.reprocess_file' | translate }}
+
{{ 'delete' | translate }}
diff --git a/docs-web/src/test/java/com/sismics/docs/rest/TestFileResource.java b/docs-web/src/test/java/com/sismics/docs/rest/TestFileResource.java
index f0a9c6cd..053b72e6 100644
--- a/docs-web/src/test/java/com/sismics/docs/rest/TestFileResource.java
+++ b/docs-web/src/test/java/com/sismics/docs/rest/TestFileResource.java
@@ -220,6 +220,11 @@ public class TestFileResource extends BaseJerseyTest {
.get(JsonObject.class);
files = json.getJsonArray("files");
Assert.assertEquals(1, files.size());
+
+ // Process a file
+ target().path("/file/" + file2Id + "/process").request()
+ .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file1Token)
+ .post(Entity.form(new Form()), JsonObject.class);
}
/**