mirror of
https://github.com/sismics/docs.git
synced 2024-11-22 05:57:57 +01:00
Add doc for search syntax (#634)
This commit is contained in:
parent
46f6b9e537
commit
bd23f14792
51
README.md
51
README.md
@ -14,8 +14,7 @@ Teedy is an open source, lightweight document management system for individuals
|
|||||||
|
|
||||||
![New!](https://teedy.io/img/laptop-demo.png?20180301)
|
![New!](https://teedy.io/img/laptop-demo.png?20180301)
|
||||||
|
|
||||||
Demo
|
# Demo
|
||||||
----
|
|
||||||
|
|
||||||
A demo is available at [demo.teedy.io](https://demo.teedy.io)
|
A demo is available at [demo.teedy.io](https://demo.teedy.io)
|
||||||
|
|
||||||
@ -23,8 +22,7 @@ A demo is available at [demo.teedy.io](https://demo.teedy.io)
|
|||||||
- "admin" login with "admin" password
|
- "admin" login with "admin" password
|
||||||
- "demo" login with "password" password
|
- "demo" login with "password" password
|
||||||
|
|
||||||
Features
|
# Features
|
||||||
--------
|
|
||||||
|
|
||||||
- Responsive user interface
|
- Responsive user interface
|
||||||
- Optical character recognition
|
- Optical character recognition
|
||||||
@ -54,8 +52,7 @@ Features
|
|||||||
- [Bulk files importer](https://github.com/sismics/docs/tree/master/docs-importer) (single or scan mode)
|
- [Bulk files importer](https://github.com/sismics/docs/tree/master/docs-importer) (single or scan mode)
|
||||||
- Tested to one million documents
|
- Tested to one million documents
|
||||||
|
|
||||||
Install with Docker
|
# Install with Docker
|
||||||
-------------------
|
|
||||||
|
|
||||||
A preconfigured Docker image is available, including OCR and media conversion tools, listening on port 8080. The database is an embedded H2 database but PostgreSQL is also supported for more performance.
|
A preconfigured Docker image is available, including OCR and media conversion tools, listening on port 8080. The database is an embedded H2 database but PostgreSQL is also supported for more performance.
|
||||||
|
|
||||||
@ -68,7 +65,7 @@ The data directory is `/data`. Don't forget to mount a volume on it.
|
|||||||
|
|
||||||
To build external URL, the server is expecting a `DOCS_BASE_URL` environment variable (for example https://teedy.mycompany.com)
|
To build external URL, the server is expecting a `DOCS_BASE_URL` environment variable (for example https://teedy.mycompany.com)
|
||||||
|
|
||||||
### Available environment variables
|
## Available environment variables
|
||||||
|
|
||||||
- General
|
- General
|
||||||
- `DOCS_BASE_URL`: The base url used by the application. Generated url's will be using this as base.
|
- `DOCS_BASE_URL`: The base url used by the application. Generated url's will be using this as base.
|
||||||
@ -94,11 +91,11 @@ To build external URL, the server is expecting a `DOCS_BASE_URL` environment var
|
|||||||
- `DOCS_SMTP_USERNAME`: The username to be used.
|
- `DOCS_SMTP_USERNAME`: The username to be used.
|
||||||
- `DOCS_SMTP_PASSWORD`: The password to be used.
|
- `DOCS_SMTP_PASSWORD`: The password to be used.
|
||||||
|
|
||||||
### Examples
|
## Examples
|
||||||
|
|
||||||
In the following examples some passwords are exposed in cleartext. This was done in order to keep the examples simple. We strongly encourage you to use variables with an `.env` file or other means to securely store your passwords.
|
In the following examples some passwords are exposed in cleartext. This was done in order to keep the examples simple. We strongly encourage you to use variables with an `.env` file or other means to securely store your passwords.
|
||||||
|
|
||||||
#### Using the internal database
|
### Using the internal database
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
version: '3'
|
version: '3'
|
||||||
@ -121,7 +118,7 @@ services:
|
|||||||
- ./docs/data:/data
|
- ./docs/data:/data
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Using PostgreSQL
|
### Using PostgreSQL
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
version: '3'
|
version: '3'
|
||||||
@ -179,10 +176,9 @@ networks:
|
|||||||
driver: bridge
|
driver: bridge
|
||||||
```
|
```
|
||||||
|
|
||||||
Manual installation
|
# Manual installation
|
||||||
-------------------
|
|
||||||
|
|
||||||
#### Requirements
|
## Requirements
|
||||||
|
|
||||||
- Java 11
|
- Java 11
|
||||||
- Tesseract 4 for OCR
|
- Tesseract 4 for OCR
|
||||||
@ -190,13 +186,12 @@ Manual installation
|
|||||||
- mediainfo for video metadata extraction
|
- mediainfo for video metadata extraction
|
||||||
- A webapp server like [Jetty](http://eclipse.org/jetty/) or [Tomcat](http://tomcat.apache.org/)
|
- A webapp server like [Jetty](http://eclipse.org/jetty/) or [Tomcat](http://tomcat.apache.org/)
|
||||||
|
|
||||||
#### Download
|
## Download
|
||||||
|
|
||||||
The latest release is downloadable here: <https://github.com/sismics/docs/releases> in WAR format.
|
The latest release is downloadable here: <https://github.com/sismics/docs/releases> in WAR format.
|
||||||
**The default admin password is "admin". Don't forget to change it before going to production.**
|
**The default admin password is "admin". Don't forget to change it before going to production.**
|
||||||
|
|
||||||
How to build Teedy from the sources
|
## How to build Teedy from the sources
|
||||||
----------------------------------
|
|
||||||
|
|
||||||
Prerequisites: JDK 11, Maven 3, NPM, Grunt, Tesseract 4
|
Prerequisites: JDK 11, Maven 3, NPM, Grunt, Tesseract 4
|
||||||
|
|
||||||
@ -209,35 +204,39 @@ Teedy is organized in several Maven modules:
|
|||||||
First off, clone the repository: `git clone git://github.com/sismics/docs.git`
|
First off, clone the repository: `git clone git://github.com/sismics/docs.git`
|
||||||
or download the sources from GitHub.
|
or download the sources from GitHub.
|
||||||
|
|
||||||
#### Launch the build
|
### Launch the build
|
||||||
|
|
||||||
From the root directory:
|
From the root directory:
|
||||||
|
|
||||||
mvn clean -DskipTests install
|
```console
|
||||||
|
mvn clean -DskipTests install
|
||||||
|
```
|
||||||
|
|
||||||
#### Run a stand-alone version
|
### Run a stand-alone version
|
||||||
|
|
||||||
From the `docs-web` directory:
|
From the `docs-web` directory:
|
||||||
|
|
||||||
mvn jetty:run
|
```console
|
||||||
|
mvn jetty:run
|
||||||
|
```
|
||||||
|
|
||||||
#### Build a .war to deploy to your servlet container
|
### Build a .war to deploy to your servlet container
|
||||||
|
|
||||||
From the `docs-web` directory:
|
From the `docs-web` directory:
|
||||||
|
|
||||||
mvn -Pprod -DskipTests clean install
|
```console
|
||||||
|
mvn -Pprod -DskipTests clean install
|
||||||
|
```
|
||||||
|
|
||||||
You will get your deployable WAR in the `docs-web/target` directory.
|
You will get your deployable WAR in the `docs-web/target` directory.
|
||||||
|
|
||||||
Contributing
|
# Contributing
|
||||||
------------
|
|
||||||
|
|
||||||
All contributions are more than welcomed. Contributions may close an issue, fix a bug (reported or not reported), improve the existing code, add new feature, and so on.
|
All contributions are more than welcomed. Contributions may close an issue, fix a bug (reported or not reported), improve the existing code, add new feature, and so on.
|
||||||
|
|
||||||
The `master` branch is the default and base branch for the project. It is used for development and all Pull Requests should go there.
|
The `master` branch is the default and base branch for the project. It is used for development and all Pull Requests should go there.
|
||||||
|
|
||||||
License
|
# License
|
||||||
-------
|
|
||||||
|
|
||||||
Teedy is released under the terms of the GPL license. See `COPYING` for more
|
Teedy is released under the terms of the GPL license. See `COPYING` for more
|
||||||
information or see <http://opensource.org/licenses/GPL-2.0>.
|
information or see <http://opensource.org/licenses/GPL-2.0>.
|
||||||
|
@ -183,12 +183,10 @@ public class GroupDao {
|
|||||||
}
|
}
|
||||||
|
|
||||||
criteriaList.add("g.GRP_DELETEDATE_D is null");
|
criteriaList.add("g.GRP_DELETEDATE_D is null");
|
||||||
|
|
||||||
if (!criteriaList.isEmpty()) {
|
sb.append(" where ");
|
||||||
sb.append(" where ");
|
sb.append(Joiner.on(" and ").join(criteriaList));
|
||||||
sb.append(Joiner.on(" and ").join(criteriaList));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform the search
|
// Perform the search
|
||||||
QueryParam queryParam = QueryUtil.getSortedQueryParam(new QueryParam(sb.toString(), parameterMap), sortCriteria);
|
QueryParam queryParam = QueryUtil.getSortedQueryParam(new QueryParam(sb.toString(), parameterMap), sortCriteria);
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@ -123,10 +123,8 @@ public class MetadataDao {
|
|||||||
|
|
||||||
criteriaList.add("m.MET_DELETEDATE_D is null");
|
criteriaList.add("m.MET_DELETEDATE_D is null");
|
||||||
|
|
||||||
if (!criteriaList.isEmpty()) {
|
sb.append(" where ");
|
||||||
sb.append(" where ");
|
sb.append(Joiner.on(" and ").join(criteriaList));
|
||||||
sb.append(Joiner.on(" and ").join(criteriaList));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform the search
|
// Perform the search
|
||||||
QueryParam queryParam = QueryUtil.getSortedQueryParam(new QueryParam(sb.toString(), parameterMap), sortCriteria);
|
QueryParam queryParam = QueryUtil.getSortedQueryParam(new QueryParam(sb.toString(), parameterMap), sortCriteria);
|
||||||
|
@ -64,10 +64,8 @@ public class RouteDao {
|
|||||||
}
|
}
|
||||||
criteriaList.add("r.RTE_DELETEDATE_D is null");
|
criteriaList.add("r.RTE_DELETEDATE_D is null");
|
||||||
|
|
||||||
if (!criteriaList.isEmpty()) {
|
sb.append(" where ");
|
||||||
sb.append(" where ");
|
sb.append(Joiner.on(" and ").join(criteriaList));
|
||||||
sb.append(Joiner.on(" and ").join(criteriaList));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform the search
|
// Perform the search
|
||||||
QueryParam queryParam = QueryUtil.getSortedQueryParam(new QueryParam(sb.toString(), parameterMap), sortCriteria);
|
QueryParam queryParam = QueryUtil.getSortedQueryParam(new QueryParam(sb.toString(), parameterMap), sortCriteria);
|
||||||
|
@ -145,10 +145,8 @@ public class RouteModelDao {
|
|||||||
|
|
||||||
criteriaList.add("rm.RTM_DELETEDATE_D is null");
|
criteriaList.add("rm.RTM_DELETEDATE_D is null");
|
||||||
|
|
||||||
if (!criteriaList.isEmpty()) {
|
sb.append(" where ");
|
||||||
sb.append(" where ");
|
sb.append(Joiner.on(" and ").join(criteriaList));
|
||||||
sb.append(Joiner.on(" and ").join(criteriaList));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform the search
|
// Perform the search
|
||||||
QueryParam queryParam = QueryUtil.getSortedQueryParam(new QueryParam(sb.toString(), parameterMap), sortCriteria);
|
QueryParam queryParam = QueryUtil.getSortedQueryParam(new QueryParam(sb.toString(), parameterMap), sortCriteria);
|
||||||
|
@ -90,10 +90,8 @@ public class RouteStepDao {
|
|||||||
}
|
}
|
||||||
criteriaList.add("rs.RTP_DELETEDATE_D is null");
|
criteriaList.add("rs.RTP_DELETEDATE_D is null");
|
||||||
|
|
||||||
if (!criteriaList.isEmpty()) {
|
sb.append(" where ");
|
||||||
sb.append(" where ");
|
sb.append(Joiner.on(" and ").join(criteriaList));
|
||||||
sb.append(Joiner.on(" and ").join(criteriaList));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform the search
|
// Perform the search
|
||||||
QueryParam queryParam = QueryUtil.getSortedQueryParam(new QueryParam(sb.toString(), parameterMap), sortCriteria);
|
QueryParam queryParam = QueryUtil.getSortedQueryParam(new QueryParam(sb.toString(), parameterMap), sortCriteria);
|
||||||
|
@ -19,7 +19,6 @@ public class ShareDao {
|
|||||||
*
|
*
|
||||||
* @param share Share
|
* @param share Share
|
||||||
* @return New ID
|
* @return New ID
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
public String create(Share share) {
|
public String create(Share share) {
|
||||||
// Create the UUID
|
// Create the UUID
|
||||||
|
@ -199,10 +199,8 @@ public class TagDao {
|
|||||||
|
|
||||||
criteriaList.add("t.TAG_DELETEDATE_D is null");
|
criteriaList.add("t.TAG_DELETEDATE_D is null");
|
||||||
|
|
||||||
if (!criteriaList.isEmpty()) {
|
sb.append(" where ");
|
||||||
sb.append(" where ");
|
sb.append(Joiner.on(" and ").join(criteriaList));
|
||||||
sb.append(Joiner.on(" and ").join(criteriaList));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform the search
|
// Perform the search
|
||||||
QueryParam queryParam = QueryUtil.getSortedQueryParam(new QueryParam(sb.toString(), parameterMap), sortCriteria);
|
QueryParam queryParam = QueryUtil.getSortedQueryParam(new QueryParam(sb.toString(), parameterMap), sortCriteria);
|
||||||
|
@ -20,7 +20,6 @@ public class VocabularyDao {
|
|||||||
*
|
*
|
||||||
* @param vocabulary Vocabulary
|
* @param vocabulary Vocabulary
|
||||||
* @return New ID
|
* @return New ID
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
public String create(Vocabulary vocabulary) {
|
public String create(Vocabulary vocabulary) {
|
||||||
// Create the UUID
|
// Create the UUID
|
||||||
|
@ -42,11 +42,9 @@ public class WebhookDao {
|
|||||||
}
|
}
|
||||||
criteriaList.add("w.WHK_DELETEDATE_D is null");
|
criteriaList.add("w.WHK_DELETEDATE_D is null");
|
||||||
|
|
||||||
if (!criteriaList.isEmpty()) {
|
sb.append(" where ");
|
||||||
sb.append(" where ");
|
sb.append(Joiner.on(" and ").join(criteriaList));
|
||||||
sb.append(Joiner.on(" and ").join(criteriaList));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform the search
|
// Perform the search
|
||||||
QueryParam queryParam = QueryUtil.getSortedQueryParam(new QueryParam(sb.toString(), parameterMap), sortCriteria);
|
QueryParam queryParam = QueryUtil.getSortedQueryParam(new QueryParam(sb.toString(), parameterMap), sortCriteria);
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.sismics.docs.core.dao.criteria;
|
package com.sismics.docs.core.dao.criteria;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -49,13 +50,13 @@ public class DocumentCriteria {
|
|||||||
* Tag IDs.
|
* Tag IDs.
|
||||||
* The first level list will be AND'ed and the second level list will be OR'ed.
|
* The first level list will be AND'ed and the second level list will be OR'ed.
|
||||||
*/
|
*/
|
||||||
private List<List<String>> tagIdList;
|
private List<List<String>> tagIdList = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tag IDs to exclude.
|
* Tag IDs to exclude.
|
||||||
* The first and second level list will be excluded.
|
* The first and second level list will be excluded.
|
||||||
*/
|
*/
|
||||||
private List<List<String>> excludedTagIdList;
|
private List<List<String>> excludedTagIdList = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shared status.
|
* Shared status.
|
||||||
@ -131,19 +132,10 @@ public class DocumentCriteria {
|
|||||||
return tagIdList;
|
return tagIdList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTagIdList(List<List<String>> tagIdList) {
|
|
||||||
this.tagIdList = tagIdList;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<List<String>> getExcludedTagIdList() {
|
public List<List<String>> getExcludedTagIdList() {
|
||||||
return excludedTagIdList;
|
return excludedTagIdList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DocumentCriteria setExcludedTagIdList(List<List<String>> excludedTagIdList) {
|
|
||||||
this.excludedTagIdList = excludedTagIdList;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean getShared() {
|
public Boolean getShared() {
|
||||||
return shared;
|
return shared;
|
||||||
}
|
}
|
||||||
@ -167,11 +159,7 @@ public class DocumentCriteria {
|
|||||||
public void setCreatorId(String creatorId) {
|
public void setCreatorId(String creatorId) {
|
||||||
this.creatorId = creatorId;
|
this.creatorId = creatorId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean getActiveRoute() {
|
|
||||||
return activeRoute;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getUpdateDateMin() {
|
public Date getUpdateDateMin() {
|
||||||
return updateDateMin;
|
return updateDateMin;
|
||||||
}
|
}
|
||||||
@ -188,6 +176,10 @@ public class DocumentCriteria {
|
|||||||
this.updateDateMax = updateDateMax;
|
this.updateDateMax = updateDateMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean getActiveRoute() {
|
||||||
|
return activeRoute;
|
||||||
|
}
|
||||||
|
|
||||||
public void setActiveRoute(Boolean activeRoute) {
|
public void setActiveRoute(Boolean activeRoute) {
|
||||||
this.activeRoute = activeRoute;
|
this.activeRoute = activeRoute;
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package com.sismics.docs.core.util;
|
package com.sismics.docs.core.util;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.sismics.docs.core.dao.dto.TagDto;
|
import com.sismics.docs.core.dao.dto.TagDto;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -12,14 +12,14 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class TagUtil {
|
public class TagUtil {
|
||||||
/**
|
/**
|
||||||
* Recursively find children of a tags.
|
* Recursively find children of a tag.
|
||||||
*
|
*
|
||||||
* @param parentTagDto Parent tag
|
* @param parentTagDto Parent tag
|
||||||
* @param allTagDtoList List of all tags
|
* @param allTagDtoList List of all tags
|
||||||
* @return Children tags
|
* @return Children tags
|
||||||
*/
|
*/
|
||||||
public static List<TagDto> findChildren(TagDto parentTagDto, List<TagDto> allTagDtoList) {
|
public static List<TagDto> findChildren(TagDto parentTagDto, List<TagDto> allTagDtoList) {
|
||||||
List<TagDto> childrenTagDtoList = Lists.newArrayList();
|
List<TagDto> childrenTagDtoList = new ArrayList<>();
|
||||||
|
|
||||||
for (TagDto tagDto : allTagDtoList) {
|
for (TagDto tagDto : allTagDtoList) {
|
||||||
if (parentTagDto.getId().equals(tagDto.getParentId())) {
|
if (parentTagDto.getId().equals(tagDto.getParentId())) {
|
||||||
@ -32,15 +32,15 @@ public class TagUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find tags by name (start with).
|
* Find tags by name (start with, ignore case).
|
||||||
*
|
*
|
||||||
* @param name Name
|
* @param name Name
|
||||||
* @param allTagDtoList List of all tags
|
* @param allTagDtoList List of all tags
|
||||||
* @return List of filtered tags
|
* @return List of filtered tags
|
||||||
*/
|
*/
|
||||||
public static List<TagDto> findByName(String name, List<TagDto> allTagDtoList) {
|
public static List<TagDto> findByName(String name, List<TagDto> allTagDtoList) {
|
||||||
List<TagDto> tagDtoList = Lists.newArrayList();
|
List<TagDto> tagDtoList = new ArrayList<>();
|
||||||
if (name == null || name.isEmpty()) {
|
if (name.isEmpty()) {
|
||||||
return tagDtoList;
|
return tagDtoList;
|
||||||
}
|
}
|
||||||
name = name.toLowerCase();
|
name = name.toLowerCase();
|
||||||
|
@ -299,7 +299,7 @@ public class LuceneIndexingHandler implements IndexingHandler {
|
|||||||
criteriaList.add("d.DOC_TITLE_C = :title");
|
criteriaList.add("d.DOC_TITLE_C = :title");
|
||||||
parameterMap.put("title", criteria.getTitle());
|
parameterMap.put("title", criteria.getTitle());
|
||||||
}
|
}
|
||||||
if (criteria.getTagIdList() != null && !criteria.getTagIdList().isEmpty()) {
|
if (!criteria.getTagIdList().isEmpty()) {
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (List<String> tagIdList : criteria.getTagIdList()) {
|
for (List<String> tagIdList : criteria.getTagIdList()) {
|
||||||
List<String> tagCriteriaList = Lists.newArrayList();
|
List<String> tagCriteriaList = Lists.newArrayList();
|
||||||
|
@ -67,6 +67,21 @@ import java.util.*;
|
|||||||
*/
|
*/
|
||||||
@Path("/document")
|
@Path("/document")
|
||||||
public class DocumentResource extends BaseResource {
|
public class DocumentResource extends BaseResource {
|
||||||
|
|
||||||
|
protected static final DateTimeParser YEAR_PARSER = DateTimeFormat.forPattern("yyyy").getParser();
|
||||||
|
protected static final DateTimeParser MONTH_PARSER = DateTimeFormat.forPattern("yyyy-MM").getParser();
|
||||||
|
protected static final DateTimeParser DAY_PARSER = DateTimeFormat.forPattern("yyyy-MM-dd").getParser();
|
||||||
|
|
||||||
|
private static final DateTimeFormatter DAY_FORMATTER = new DateTimeFormatter(null, DAY_PARSER);
|
||||||
|
private static final DateTimeFormatter MONTH_FORMATTER = new DateTimeFormatter(null, MONTH_PARSER);
|
||||||
|
private static final DateTimeFormatter YEAR_FORMATTER = new DateTimeFormatter(null, YEAR_PARSER);
|
||||||
|
|
||||||
|
private static final DateTimeParser[] DATE_PARSERS = new DateTimeParser[]{
|
||||||
|
YEAR_PARSER,
|
||||||
|
MONTH_PARSER,
|
||||||
|
DAY_PARSER};
|
||||||
|
private static final DateTimeFormatter DATE_FORMATTER = new DateTimeFormatterBuilder().append( null, DATE_PARSERS).toFormatter();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a document.
|
* Returns a document.
|
||||||
*
|
*
|
||||||
@ -349,7 +364,7 @@ public class DocumentResource extends BaseResource {
|
|||||||
* @apiParam {String} offset Start at this index
|
* @apiParam {String} offset Start at this index
|
||||||
* @apiParam {Number} sort_column Column index to sort on
|
* @apiParam {Number} sort_column Column index to sort on
|
||||||
* @apiParam {Boolean} asc If true, sort in ascending order
|
* @apiParam {Boolean} asc If true, sort in ascending order
|
||||||
* @apiParam {String} search Search query
|
* @apiParam {String} search Search query (see "Document search syntax" on the top of the page for explanations)
|
||||||
* @apiParam {Booleans} files If true includes files information
|
* @apiParam {Booleans} files If true includes files information
|
||||||
* @apiSuccess {Number} total Total number of documents
|
* @apiSuccess {Number} total Total number of documents
|
||||||
* @apiSuccess {Object[]} documents List of documents
|
* @apiSuccess {Object[]} documents List of documents
|
||||||
@ -492,16 +507,8 @@ public class DocumentResource extends BaseResource {
|
|||||||
TagDao tagDao = new TagDao();
|
TagDao tagDao = new TagDao();
|
||||||
List<TagDto> allTagDtoList = tagDao.findByCriteria(new TagCriteria().setTargetIdList(getTargetIdList(null)), null);
|
List<TagDto> allTagDtoList = tagDao.findByCriteria(new TagCriteria().setTargetIdList(getTargetIdList(null)), null);
|
||||||
UserDao userDao = new UserDao();
|
UserDao userDao = new UserDao();
|
||||||
DateTimeParser[] parsers = {
|
|
||||||
DateTimeFormat.forPattern("yyyy").getParser(),
|
|
||||||
DateTimeFormat.forPattern("yyyy-MM").getParser(),
|
|
||||||
DateTimeFormat.forPattern("yyyy-MM-dd").getParser() };
|
|
||||||
DateTimeFormatter yearFormatter = new DateTimeFormatter(null, parsers[0]);
|
|
||||||
DateTimeFormatter monthFormatter = new DateTimeFormatter(null, parsers[1]);
|
|
||||||
DateTimeFormatter dayFormatter = new DateTimeFormatter(null, parsers[2]);
|
|
||||||
DateTimeFormatter formatter = new DateTimeFormatterBuilder().append( null, parsers ).toFormatter();
|
|
||||||
|
|
||||||
String[] criteriaList = search.split(" *");
|
String[] criteriaList = search.split(" +");
|
||||||
List<String> query = new ArrayList<>();
|
List<String> query = new ArrayList<>();
|
||||||
List<String> fullQuery = new ArrayList<>();
|
List<String> fullQuery = new ArrayList<>();
|
||||||
for (String criteria : criteriaList) {
|
for (String criteria : criteriaList) {
|
||||||
@ -511,20 +518,16 @@ public class DocumentResource extends BaseResource {
|
|||||||
fullQuery.add(criteria);
|
fullQuery.add(criteria);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
String paramName = params[0];
|
||||||
|
String paramValue = params[1];
|
||||||
|
|
||||||
switch (params[0]) {
|
switch (paramName) {
|
||||||
case "tag":
|
case "tag":
|
||||||
case "!tag":
|
case "!tag":
|
||||||
// New tag criteria
|
// New tag criteria
|
||||||
List<TagDto> tagDtoList = TagUtil.findByName(params[1], allTagDtoList);
|
List<TagDto> tagDtoList = TagUtil.findByName(paramValue, allTagDtoList);
|
||||||
if (documentCriteria.getTagIdList() == null) {
|
|
||||||
documentCriteria.setTagIdList(new ArrayList<>());
|
|
||||||
}
|
|
||||||
if (documentCriteria.getExcludedTagIdList() == null) {
|
|
||||||
documentCriteria.setExcludedTagIdList(new ArrayList<>());
|
|
||||||
}
|
|
||||||
if (tagDtoList.isEmpty()) {
|
if (tagDtoList.isEmpty()) {
|
||||||
// No tag found, the request must returns nothing
|
// No tag found, the request must return nothing
|
||||||
documentCriteria.getTagIdList().add(Lists.newArrayList(UUID.randomUUID().toString()));
|
documentCriteria.getTagIdList().add(Lists.newArrayList(UUID.randomUUID().toString()));
|
||||||
} else {
|
} else {
|
||||||
List<String> tagIdList = Lists.newArrayList();
|
List<String> tagIdList = Lists.newArrayList();
|
||||||
@ -535,7 +538,7 @@ public class DocumentResource extends BaseResource {
|
|||||||
tagIdList.add(childrenTagDto.getId());
|
tagIdList.add(childrenTagDto.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (params[0].startsWith("!")) {
|
if (paramName.startsWith("!")) {
|
||||||
documentCriteria.getExcludedTagIdList().add(tagIdList);
|
documentCriteria.getExcludedTagIdList().add(tagIdList);
|
||||||
} else {
|
} else {
|
||||||
documentCriteria.getTagIdList().add(tagIdList);
|
documentCriteria.getTagIdList().add(tagIdList);
|
||||||
@ -548,9 +551,9 @@ public class DocumentResource extends BaseResource {
|
|||||||
case "ubefore":
|
case "ubefore":
|
||||||
// New date span criteria
|
// New date span criteria
|
||||||
try {
|
try {
|
||||||
boolean isUpdated = params[0].startsWith("u");
|
boolean isUpdated = paramName.startsWith("u");
|
||||||
DateTime date = formatter.parseDateTime(params[1]);
|
DateTime date = DATE_FORMATTER.parseDateTime(paramValue);
|
||||||
if (params[0].endsWith("before")) {
|
if (paramName.endsWith("before")) {
|
||||||
if (isUpdated) documentCriteria.setUpdateDateMax(date.toDate());
|
if (isUpdated) documentCriteria.setUpdateDateMax(date.toDate());
|
||||||
else documentCriteria.setCreateDateMax(date.toDate());
|
else documentCriteria.setCreateDateMax(date.toDate());
|
||||||
} else {
|
} else {
|
||||||
@ -566,11 +569,11 @@ public class DocumentResource extends BaseResource {
|
|||||||
case "uat":
|
case "uat":
|
||||||
case "at":
|
case "at":
|
||||||
// New specific date criteria
|
// New specific date criteria
|
||||||
|
boolean isUpdated = params[0].startsWith("u");
|
||||||
try {
|
try {
|
||||||
boolean isUpdated = params[0].startsWith("u");
|
switch (paramValue.length()) {
|
||||||
switch (params[1].length()) {
|
|
||||||
case 10: {
|
case 10: {
|
||||||
DateTime date = dayFormatter.parseDateTime(params[1]);
|
DateTime date = DATE_FORMATTER.parseDateTime(params[1]);
|
||||||
if (isUpdated) {
|
if (isUpdated) {
|
||||||
documentCriteria.setUpdateDateMin(date.toDate());
|
documentCriteria.setUpdateDateMin(date.toDate());
|
||||||
documentCriteria.setUpdateDateMax(date.plusDays(1).minusSeconds(1).toDate());
|
documentCriteria.setUpdateDateMax(date.plusDays(1).minusSeconds(1).toDate());
|
||||||
@ -581,7 +584,7 @@ public class DocumentResource extends BaseResource {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 7: {
|
case 7: {
|
||||||
DateTime date = monthFormatter.parseDateTime(params[1]);
|
DateTime date = MONTH_FORMATTER.parseDateTime(params[1]);
|
||||||
if (isUpdated) {
|
if (isUpdated) {
|
||||||
documentCriteria.setUpdateDateMin(date.toDate());
|
documentCriteria.setUpdateDateMin(date.toDate());
|
||||||
documentCriteria.setUpdateDateMax(date.plusMonths(1).minusSeconds(1).toDate());
|
documentCriteria.setUpdateDateMax(date.plusMonths(1).minusSeconds(1).toDate());
|
||||||
@ -592,7 +595,7 @@ public class DocumentResource extends BaseResource {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 4: {
|
case 4: {
|
||||||
DateTime date = yearFormatter.parseDateTime(params[1]);
|
DateTime date = YEAR_FORMATTER.parseDateTime(params[1]);
|
||||||
if (isUpdated) {
|
if (isUpdated) {
|
||||||
documentCriteria.setUpdateDateMin(date.toDate());
|
documentCriteria.setUpdateDateMin(date.toDate());
|
||||||
documentCriteria.setUpdateDateMax(date.plusYears(1).minusSeconds(1).toDate());
|
documentCriteria.setUpdateDateMax(date.plusYears(1).minusSeconds(1).toDate());
|
||||||
@ -601,6 +604,10 @@ public class DocumentResource extends BaseResource {
|
|||||||
documentCriteria.setCreateDateMax(date.plusYears(1).minusSeconds(1).toDate());
|
documentCriteria.setCreateDateMax(date.plusYears(1).minusSeconds(1).toDate());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
} default: {
|
||||||
|
// Invalid format, returns no documents
|
||||||
|
documentCriteria.setCreateDateMin(new Date(0));
|
||||||
|
documentCriteria.setCreateDateMax(new Date(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
@ -611,25 +618,26 @@ public class DocumentResource extends BaseResource {
|
|||||||
break;
|
break;
|
||||||
case "shared":
|
case "shared":
|
||||||
// New shared state criteria
|
// New shared state criteria
|
||||||
documentCriteria.setShared(params[1].equals("yes"));
|
documentCriteria.setShared(paramValue.equals("yes"));
|
||||||
break;
|
break;
|
||||||
case "lang":
|
case "lang":
|
||||||
// New language criteria
|
// New language criteria
|
||||||
if (Constants.SUPPORTED_LANGUAGES.contains(params[1])) {
|
if (Constants.SUPPORTED_LANGUAGES.contains(paramValue)) {
|
||||||
documentCriteria.setLanguage(params[1]);
|
documentCriteria.setLanguage(paramValue);
|
||||||
} else {
|
} else {
|
||||||
|
// Unsupported language, returns no documents
|
||||||
documentCriteria.setLanguage(UUID.randomUUID().toString());
|
documentCriteria.setLanguage(UUID.randomUUID().toString());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "mime":
|
case "mime":
|
||||||
// New mime type criteria
|
// New mime type criteria
|
||||||
documentCriteria.setMimeType(params[1]);
|
documentCriteria.setMimeType(paramValue);
|
||||||
break;
|
break;
|
||||||
case "by":
|
case "by":
|
||||||
// New creator criteria
|
// New creator criteria
|
||||||
User user = userDao.getActiveByUsername(params[1]);
|
User user = userDao.getActiveByUsername(paramValue);
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
// This user doesn't exists, return nothing
|
// This user doesn't exist, return nothing
|
||||||
documentCriteria.setCreatorId(UUID.randomUUID().toString());
|
documentCriteria.setCreatorId(UUID.randomUUID().toString());
|
||||||
} else {
|
} else {
|
||||||
// This user exists, search its documents
|
// This user exists, search its documents
|
||||||
@ -638,19 +646,19 @@ public class DocumentResource extends BaseResource {
|
|||||||
break;
|
break;
|
||||||
case "workflow":
|
case "workflow":
|
||||||
// New shared state criteria
|
// New shared state criteria
|
||||||
documentCriteria.setActiveRoute(params[1].equals("me"));
|
documentCriteria.setActiveRoute(paramValue.equals("me"));
|
||||||
break;
|
break;
|
||||||
case "simple":
|
case "simple":
|
||||||
// New simple search criteria
|
// New simple search criteria
|
||||||
query.add(params[1]);
|
query.add(paramValue);
|
||||||
break;
|
break;
|
||||||
case "full":
|
case "full":
|
||||||
// New fulltext search criteria
|
// New fulltext search criteria
|
||||||
fullQuery.add(params[1]);
|
fullQuery.add(paramValue);
|
||||||
break;
|
break;
|
||||||
case "title":
|
case "title":
|
||||||
// New title criteria
|
// New title criteria
|
||||||
documentCriteria.setTitle(params[1]);
|
documentCriteria.setTitle(paramValue);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fullQuery.add(criteria);
|
fullQuery.add(criteria);
|
||||||
|
@ -10,7 +10,7 @@ The base URL depends on your server. If your instance of Teedy is accessible thr
|
|||||||
`https://teedy.mycompany.com`, then the base API URL is `https://teedy.mycompany.com/api`.
|
`https://teedy.mycompany.com`, then the base API URL is `https://teedy.mycompany.com/api`.
|
||||||
|
|
||||||
## Verbs and status codes
|
## Verbs and status codes
|
||||||
The API uses restful verbs.
|
The API uses RESTful verbs.
|
||||||
|
|
||||||
| Verb | Description |
|
| Verb | Description |
|
||||||
|---|---|
|
|---|---|
|
||||||
@ -46,4 +46,43 @@ curl -i -X GET -H "Cookie: auth_token=64085630-2ae6-415c-9a92-4b22c107eaa4" http
|
|||||||
A call to this API with a given `auth_token` cookie will make it unusable for other calls.
|
A call to this API with a given `auth_token` cookie will make it unusable for other calls.
|
||||||
```
|
```
|
||||||
curl -i -X POST -H "Cookie: auth_token=64085630-2ae6-415c-9a92-4b22c107eaa4" https://docs.mycompany.com/api/user/logout
|
curl -i -X POST -H "Cookie: auth_token=64085630-2ae6-415c-9a92-4b22c107eaa4" https://docs.mycompany.com/api/user/logout
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Document search syntax
|
||||||
|
|
||||||
|
The `/api/document/list` endpoint use a String `search` parameter.
|
||||||
|
|
||||||
|
This parameter is split in segments using the space character (the other whitespace characters are not considered).
|
||||||
|
|
||||||
|
If a segment contains exactly one colon (`:`), it will used as a field criteria (see bellow).
|
||||||
|
In other cases (zero or more than one colon), the segment will be used as a search criteria for all fields including the document's files content.
|
||||||
|
|
||||||
|
### Search fields
|
||||||
|
|
||||||
|
If a search `VALUE` is considered invalid, the search result will be empty.
|
||||||
|
|
||||||
|
* Content
|
||||||
|
* `full:VALUE`: `VALUE` is used as search criteria for all fields, including the document's files content
|
||||||
|
* `simple:VALUE`: `VALUE` is used as a search criteria for all fields except the document's files content
|
||||||
|
* Date
|
||||||
|
* `after:VALUE`: the document must have been created after or at the `VALUE` moment, accepted format are `yyyy`, `yyyy-MM` and `yyyy-MM-dd`
|
||||||
|
* `at:VALUE`: the document must have been created at the `VALUE` moment, accepted format are `yyyy`, `yyyy-MM` and `yyyy-MM-dd` (for `yyyy` it must be the same year, for `yyyy-MM` the same month, for `yyyy-MM-dd` the same day)
|
||||||
|
* `before:VALUE`: the document must have been created before or at the `VALUE` moment, accepted format are `yyyy`, `yyyy-MM` and `yyyy-MM-dd`
|
||||||
|
* `uafter:VALUE`: the document must have been last updated after or at the `VALUE` moment, accepted format are `yyyy`, `yyyy-MM` and `yyyy-MM-dd`
|
||||||
|
* `at:VALUE`: the document must have been updated at the `VALUE` moment, accepted format are `yyyy`, `yyyy-MM` and `yyyy-MM-dd` (for `yyyy` it must be the same year, for `yyyy-MM` the same month, for `yyyy-MM-dd` the same day)
|
||||||
|
* `ubefore:VALUE`: the document must have been updated before or at the `VALUE` moment, accepted format are `yyyy`, `yyyy-MM` and `yyyy-MM-dd`
|
||||||
|
* Language
|
||||||
|
* `lang:VALUE`: the document must be of the specified language (example: `en`)
|
||||||
|
* Mime
|
||||||
|
* `mime:VALUE`: the document must be of the specified mime type (example: `image/png`)
|
||||||
|
* Shared
|
||||||
|
* `shared:VALUE`: if `VALUE` is `yes`the document must be shared, for other `VALUE`s the criteria is ignored
|
||||||
|
* Tags
|
||||||
|
* `tag:VALUE`: the document must contain a tag or a child of a tag that starts with `VALUE`, case is ignored
|
||||||
|
* `!tag:VALUE`: the document must not contain a tag or a child of a tag that starts with `VALUE`, case is ignored
|
||||||
|
* Title
|
||||||
|
* `title:VALUE`: the title of the document must be `VALUE`
|
||||||
|
* User
|
||||||
|
* `by:VALUE`: the document creator's username must be `VALUE` with an exact match, the user must not be deleted
|
||||||
|
* Workflow
|
||||||
|
* `workflow:VALUE`: if `VALUE` is `me` the document must have an active route, for other `VALUE`s the criteria is ignored
|
||||||
|
Loading…
Reference in New Issue
Block a user