diff --git a/.travis.yml b/.travis.yml index 30fe4095..6a1c0e61 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,17 +4,20 @@ language: java before_install: - sudo add-apt-repository -y ppa:mc3man/trusty-media - sudo apt-get -qq update - - sudo apt-get -y -q install ffmpeg mediainfo tesseract-ocr tesseract-ocr-fra tesseract-ocr-ita tesseract-ocr-kor tesseract-ocr-rus tesseract-ocr-ukr tesseract-ocr-spa tesseract-ocr-ara tesseract-ocr-hin tesseract-ocr-deu tesseract-ocr-pol tesseract-ocr-jpn tesseract-ocr-por tesseract-ocr-tha tesseract-ocr-jpn tesseract-ocr-chi-sim tesseract-ocr-chi-tra + - sudo apt-get -y -q install ffmpeg mediainfo tesseract-ocr tesseract-ocr-fra tesseract-ocr-ita tesseract-ocr-kor tesseract-ocr-rus tesseract-ocr-ukr tesseract-ocr-spa tesseract-ocr-ara tesseract-ocr-hin tesseract-ocr-deu tesseract-ocr-pol tesseract-ocr-jpn tesseract-ocr-por tesseract-ocr-tha tesseract-ocr-jpn tesseract-ocr-chi-sim tesseract-ocr-chi-tra tesseract-ocr-nld - sudo apt-get -y -q install haveged && sudo service haveged start after_success: - - mvn -Pprod -DskipTests clean install - - docker login -u $DOCKER_USER -p $DOCKER_PASS - - export REPO=sismics/docs - - export TAG=`if [ "$TRAVIS_BRANCH" == "master" ]; then echo "latest"; else echo $TRAVIS_BRANCH ; fi` - - docker build -f Dockerfile -t $REPO:$COMMIT . - - docker tag $REPO:$COMMIT $REPO:$TAG - - docker tag $REPO:$COMMIT $REPO:travis-$TRAVIS_BUILD_NUMBER - - docker push $REPO + - | + if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then + mvn -Pprod -DskipTests clean install + docker login -u $DOCKER_USER -p $DOCKER_PASS + export REPO=sismics/docs + export TAG=`if [ "$TRAVIS_BRANCH" == "master" ]; then echo "latest"; else echo $TRAVIS_BRANCH ; fi` + docker build -f Dockerfile -t $REPO:$COMMIT . + docker tag $REPO:$COMMIT $REPO:$TAG + docker tag $REPO:$COMMIT $REPO:travis-$TRAVIS_BUILD_NUMBER + docker push $REPO + fi env: global: - secure: LRGpjWORb0qy6VuypZjTAfA8uRHlFUMTwb77cenS9PPRBxuSnctC531asS9Xg3DqC5nsRxBBprgfCKotn5S8nBSD1ceHh84NASyzLSBft3xSMbg7f/2i7MQ+pGVwLncusBU6E/drnMFwZBleo+9M8Tf96axY5zuUp90MUTpSgt0= diff --git a/Dockerfile b/Dockerfile index 74764c72..ddb5eb09 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ FROM sismics/ubuntu-jetty:9.4.12 MAINTAINER b.gamard@sismics.com -RUN apt-get update && apt-get -y -q install ffmpeg mediainfo tesseract-ocr tesseract-ocr-fra tesseract-ocr-ita tesseract-ocr-kor tesseract-ocr-rus tesseract-ocr-ukr tesseract-ocr-spa tesseract-ocr-ara tesseract-ocr-hin tesseract-ocr-deu tesseract-ocr-pol tesseract-ocr-jpn tesseract-ocr-por tesseract-ocr-tha tesseract-ocr-jpn tesseract-ocr-chi-sim tesseract-ocr-chi-tra && \ +RUN apt-get update && apt-get -y -q install ffmpeg mediainfo tesseract-ocr tesseract-ocr-fra tesseract-ocr-ita tesseract-ocr-kor tesseract-ocr-rus tesseract-ocr-ukr tesseract-ocr-spa tesseract-ocr-ara tesseract-ocr-hin tesseract-ocr-deu tesseract-ocr-pol tesseract-ocr-jpn tesseract-ocr-por tesseract-ocr-tha tesseract-ocr-jpn tesseract-ocr-chi-sim tesseract-ocr-chi-tra tesseract-ocr-nld && \ apt-get clean && rm -rf /var/lib/apt/lists/* # Remove the embedded javax.mail jar from Jetty diff --git a/docs-android/app/src/main/AndroidManifest.xml b/docs-android/app/src/main/AndroidManifest.xml index 66708a1d..7cb9edaf 100644 --- a/docs-android/app/src/main/AndroidManifest.xml +++ b/docs-android/app/src/main/AndroidManifest.xml @@ -8,6 +8,7 @@ + + + + + Ungültige E-Mail + Zu kurz (min. %d) + Zu lang (max. %d) + Erforderlich + Nur Buchstaben und Zahlen + + + Sismics Docs + Navigationsleiste öffnen + Navigationsleiste schließen + github.com/sismics/docs, sowie die Login-Daten unten eingeben]]> + Server + Username + Password + Login + OK + Abbrechen + Login gescheitert + Benutzername oder Passwort falsch + Netzwerkfehler + Netzwerkfehler, überprüfen Sie die Internetverbindung und die Server-URL + Ungültige URL + Bitte überprüfen Sie die Server-URL und versuchen Sie es erneut + Ein Absturz ist aufgetreten, ein Bericht wurde gesendet, um dieses Problem zu beheben + Erstellungsdatum + Aktuelle Datei herunterladen + Herunterladen + Dokumente durchsuchen + Alle Dokumente + Geteilte Dokumente + Alle Tags + Keine Tags + Fehler beim Laden von Tags + Keine Dokumente + Fehler beim Laden von Dokumenten + Keine Dateien + Fehler beim Laden von Dateien + Neues Dokument + Teilen + Schließen + Hinzufügen + Freigabename (optional) + Dieses Dokument wird derzeit nicht freigegeben + Diese Freigabe löschen + Send this share link + Fehler beim Laden von Freigaben + Fehler beim Hinzufügen der Freigabe + Freigabe Link + Fehler beim Löschen der Freigabe + Freigabe senden an + Datei hinzufügen + Datei hochladen von + Einstellungen + Ausloggen + Version + Build + Erweiterte Einstellungen + Über + GitHub + Fehler berichten + Cache leeren + Zwischengespeicherte Dateien löschen + Cache wurde geleert + Suchhistorie löschen + Leert die aktuellen Suchvorschläge + Suchvorschläge wurden gelöscht + Cache Größe + Français + English + Deutsch + Speichern + Bearbeiten + Netzwerkfehler, bitte versuchen Sie es erneut + Bitte warten + Daten werden gesendet + Löschen + Dokument löschen + Dieses Dokument und alle zugehörigen Dateien wirklich löschen? + Netzwerkfehler beim Löschen des Dokuments + Lösche Dokument + Datei löschen + Die aktuelle Datei wirklich löschen? + Netzwerkfehler beim Löschen der Datei + Lösche Datei + Fehler beim Lesen der Datei + Sismics Docs + Neue Datei in das Dokument hochladen + Fehler beim Hochladen der neuen Datei + Aktuelle Datei löschen + Erweiterte Suche + Suche + Tags hinzufügen + Erstellungsdatum + Beschreibung + Titel + Einfache Suche + Volltextsuche + Ersteller + Nach Datum + Vor Datum + Tags durchsuchen + Alle Sprachen + Informationen anzeigen + Wer kann darauf zugreifen? + Kommentare + Keine Kommentare + Fehler beim Laden von Kommentaren + Senden + Kommentar hinzufügen + Fehler beim Hinzufügen des Kommentars + Füge Kommentar hinzu + Kommentar löschen + Lösche Kommentar + Fehler beim Löschen des Kommentars + PDF + Download + Rand + Bild an Seite anpassen + Kommentare exportieren + Metadaten exportieren + mm + Sismics Docs Datei Export + Sismics Docs Dokumentenexport + Sismics Docs PDF Export + Letzte Aktivität + Aktivitäten + E-Mail + Speicherbegrenzung + %1$d/%2$d MB + Validierungscode + Geteilt + Sprache + Geltungsbereich + Typ + Quelle + Format + Verleger + Identifikator + Thema + Rechte + Mitwirkende + Beziehungen + + diff --git a/docs-android/app/src/main/res/values/strings.xml b/docs-android/app/src/main/res/values/strings.xml index 5d453293..e5ca3d48 100644 --- a/docs-android/app/src/main/res/values/strings.xml +++ b/docs-android/app/src/main/res/values/strings.xml @@ -71,6 +71,7 @@ Cache size Français English + Deutsch Save Edit Network error, please try again diff --git a/docs-core/src/main/java/com/sismics/docs/core/constant/Constants.java b/docs-core/src/main/java/com/sismics/docs/core/constant/Constants.java index 78aebf50..70037313 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/constant/Constants.java +++ b/docs-core/src/main/java/com/sismics/docs/core/constant/Constants.java @@ -38,7 +38,7 @@ public class Constants { /** * Supported document languages. */ - public static final List SUPPORTED_LANGUAGES = Lists.newArrayList("eng", "fra", "ita", "deu", "spa", "por", "pol", "rus", "ukr", "ara", "hin", "chi_sim", "chi_tra", "jpn", "tha", "kor"); + public static final List SUPPORTED_LANGUAGES = Lists.newArrayList("eng", "fra", "ita", "deu", "spa", "por", "pol", "rus", "ukr", "ara", "hin", "chi_sim", "chi_tra", "jpn", "tha", "kor", "nld"); /** * Base URL environment variable. diff --git a/docs-core/src/main/java/com/sismics/docs/core/dao/FileDao.java b/docs-core/src/main/java/com/sismics/docs/core/dao/FileDao.java index 4610621e..a35a03e4 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/dao/FileDao.java +++ b/docs-core/src/main/java/com/sismics/docs/core/dao/FileDao.java @@ -148,7 +148,9 @@ public class FileDao { fileDb.setContent(file.getContent()); fileDb.setOrder(file.getOrder()); fileDb.setMimeType(file.getMimeType()); - + fileDb.setVersionId(file.getVersionId()); + fileDb.setLatestVersion(file.isLatestVersion()); + return file; } @@ -180,11 +182,11 @@ public class FileDao { public List getByDocumentId(String userId, String documentId) { EntityManager em = ThreadLocalContext.get().getEntityManager(); if (documentId == null) { - Query q = em.createQuery("select f from File f where f.documentId is null and f.deleteDate is null and f.userId = :userId order by f.createDate asc"); + Query q = em.createQuery("select f from File f where f.documentId is null and f.deleteDate is null and f.latestVersion = true and f.userId = :userId order by f.createDate asc"); q.setParameter("userId", userId); return q.getResultList(); } - Query q = em.createQuery("select f from File f where f.documentId = :documentId and f.deleteDate is null order by f.order asc"); + Query q = em.createQuery("select f from File f where f.documentId = :documentId and f.latestVersion = true and f.deleteDate is null order by f.order asc"); q.setParameter("documentId", documentId); return q.getResultList(); } diff --git a/docs-core/src/main/java/com/sismics/docs/core/model/jpa/File.java b/docs-core/src/main/java/com/sismics/docs/core/model/jpa/File.java index 3db2ab7b..c3e7064a 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/model/jpa/File.java +++ b/docs-core/src/main/java/com/sismics/docs/core/model/jpa/File.java @@ -71,6 +71,24 @@ public class File implements Loggable { @Column(name = "FIL_ORDER_N") private Integer order; + /** + * Version ID. + */ + @Column(name = "FIL_IDVERSION_C") + private String versionId; + + /** + * Version number (starting at 0). + */ + @Column(name = "FIL_VERSION_N", nullable = false) + private Integer version; + + /** + * True if it's the latest version of the file. + */ + @Column(name = "FIL_LATESTVERSION_B", nullable = false) + private boolean latestVersion; + /** * Private key to decrypt the file. * Not saved to database, of course. @@ -160,6 +178,33 @@ public class File implements Loggable { this.privateKey = privateKey; } + public String getVersionId() { + return versionId; + } + + public File setVersionId(String versionId) { + this.versionId = versionId; + return this; + } + + public Integer getVersion() { + return version; + } + + public File setVersion(Integer version) { + this.version = version; + return this; + } + + public boolean isLatestVersion() { + return latestVersion; + } + + public File setLatestVersion(boolean latestVersion) { + this.latestVersion = latestVersion; + return this; + } + @Override public String toString() { return MoreObjects.toStringHelper(this) 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 a349d329..ae0b7500 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 @@ -212,7 +212,7 @@ public class InboxService extends AbstractScheduledService { } // Save the document, create the base ACLs - document = DocumentUtil.createDocument(document, "admin"); + DocumentUtil.createDocument(document, "admin"); // Add the tag String tagId = ConfigUtil.getConfigStringValue(ConfigType.INBOX_TAG); @@ -232,7 +232,7 @@ public class InboxService extends AbstractScheduledService { // Add files to the document for (EmailUtil.FileContent fileContent : mailContent.getFileContentList()) { - FileUtil.createFile(fileContent.getName(), fileContent.getFile(), fileContent.getSize(), + FileUtil.createFile(fileContent.getName(), null, fileContent.getFile(), fileContent.getSize(), document.getLanguage(), "admin", document.getId()); } } diff --git a/docs-core/src/main/java/com/sismics/docs/core/util/FileUtil.java b/docs-core/src/main/java/com/sismics/docs/core/util/FileUtil.java index a4604038..98dbeca0 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/util/FileUtil.java +++ b/docs-core/src/main/java/com/sismics/docs/core/util/FileUtil.java @@ -98,6 +98,7 @@ public class FileUtil { * Create a new file. * * @param name File name, can be null + * @param previousFileId ID of the previous version of the file, if the new file is a new version * @param unencryptedFile Path to the unencrypted file * @param fileSize File size * @param language File language, can be null if associated to no document @@ -106,7 +107,7 @@ public class FileUtil { * @return File ID * @throws Exception e */ - public static String createFile(String name, Path unencryptedFile, long fileSize, String language, String userId, String documentId) throws Exception { + public static String createFile(String name, String previousFileId, Path unencryptedFile, long fileSize, String language, String userId, String documentId) throws Exception { // Validate mime type String mimeType; try { @@ -132,22 +133,42 @@ public class FileUtil { } } - // Get files of this document - FileDao fileDao = new FileDao(); - int order = 0; - if (documentId != null) { - for (File file : fileDao.getByDocumentId(userId, documentId)) { - file.setOrder(order++); - } - } - - // Create the file + // Prepare the file File file = new File(); - file.setOrder(order); + file.setOrder(0); + file.setVersion(0); + file.setLatestVersion(true); file.setDocumentId(documentId); file.setName(StringUtils.abbreviate(name, 200)); file.setMimeType(mimeType); file.setUserId(userId); + + // Get files of this document + FileDao fileDao = new FileDao(); + if (documentId != null) { + if (previousFileId == null) { + // It's not a new version, so put it in last order + file.setOrder(fileDao.getByDocumentId(userId, documentId).size()); + } else { + // It's a new version, update the previous version + File previousFile = fileDao.getActiveById(previousFileId); + if (previousFile == null || !previousFile.getDocumentId().equals(documentId)) { + throw new IOException("Previous version mismatch"); + } + + if (previousFile.getVersionId() == null) { + previousFile.setVersionId(UUID.randomUUID().toString()); + } + + previousFile.setLatestVersion(false); + file.setVersionId(previousFile.getVersionId()); + file.setVersion(previousFile.getVersion() + 1); + + fileDao.update(previousFile); + } + } + + // Create the file String fileId = fileDao.create(file, userId); // Save the file diff --git a/docs-core/src/main/java/com/sismics/docs/core/util/indexing/LuceneIndexingHandler.java b/docs-core/src/main/java/com/sismics/docs/core/util/indexing/LuceneIndexingHandler.java index 40f17127..948e18fb 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/util/indexing/LuceneIndexingHandler.java +++ b/docs-core/src/main/java/com/sismics/docs/core/util/indexing/LuceneIndexingHandler.java @@ -25,8 +25,7 @@ import org.apache.lucene.document.Field; import org.apache.lucene.document.StringField; import org.apache.lucene.document.TextField; import org.apache.lucene.index.*; -import org.apache.lucene.queryparser.flexible.standard.QueryParserUtil; -import org.apache.lucene.queryparser.flexible.standard.StandardQueryParser; +import org.apache.lucene.queryparser.simple.SimpleQueryParser; import org.apache.lucene.search.*; import org.apache.lucene.search.highlight.Highlighter; import org.apache.lucene.search.highlight.QueryScorer; @@ -371,29 +370,26 @@ public class LuceneIndexingHandler implements IndexingHandler { * @throws Exception e */ private Map search(String searchQuery, String fullSearchQuery) throws Exception { - // Escape query and add quotes so QueryParser generate a PhraseQuery - String escapedSearchQuery = "\"" + QueryParserUtil.escape(searchQuery + " " + fullSearchQuery) + "\""; - String escapedFullSearchQuery = "\"" + QueryParserUtil.escape(fullSearchQuery) + "\""; + // The fulltext query searches in all fields + searchQuery = searchQuery + " " + fullSearchQuery; // Build search query Analyzer analyzer = new StandardAnalyzer(); - StandardQueryParser qpHelper = new StandardQueryParser(analyzer); - qpHelper.setPhraseSlop(100); // PhraseQuery add terms // Search on documents and files BooleanQuery query = new BooleanQuery.Builder() - .add(qpHelper.parse(escapedSearchQuery, "title"), BooleanClause.Occur.SHOULD) - .add(qpHelper.parse(escapedSearchQuery, "description"), BooleanClause.Occur.SHOULD) - .add(qpHelper.parse(escapedSearchQuery, "subject"), BooleanClause.Occur.SHOULD) - .add(qpHelper.parse(escapedSearchQuery, "identifier"), BooleanClause.Occur.SHOULD) - .add(qpHelper.parse(escapedSearchQuery, "publisher"), BooleanClause.Occur.SHOULD) - .add(qpHelper.parse(escapedSearchQuery, "format"), BooleanClause.Occur.SHOULD) - .add(qpHelper.parse(escapedSearchQuery, "source"), BooleanClause.Occur.SHOULD) - .add(qpHelper.parse(escapedSearchQuery, "type"), BooleanClause.Occur.SHOULD) - .add(qpHelper.parse(escapedSearchQuery, "coverage"), BooleanClause.Occur.SHOULD) - .add(qpHelper.parse(escapedSearchQuery, "rights"), BooleanClause.Occur.SHOULD) - .add(qpHelper.parse(escapedSearchQuery, "filename"), BooleanClause.Occur.SHOULD) - .add(qpHelper.parse(escapedFullSearchQuery, "content"), BooleanClause.Occur.SHOULD) + .add(buildQueryParser(analyzer, "title").parse(searchQuery), BooleanClause.Occur.SHOULD) + .add(buildQueryParser(analyzer, "description").parse(searchQuery), BooleanClause.Occur.SHOULD) + .add(buildQueryParser(analyzer, "subject").parse(searchQuery), BooleanClause.Occur.SHOULD) + .add(buildQueryParser(analyzer, "identifier").parse(searchQuery), BooleanClause.Occur.SHOULD) + .add(buildQueryParser(analyzer, "publisher").parse(searchQuery), BooleanClause.Occur.SHOULD) + .add(buildQueryParser(analyzer, "format").parse(searchQuery), BooleanClause.Occur.SHOULD) + .add(buildQueryParser(analyzer, "source").parse(searchQuery), BooleanClause.Occur.SHOULD) + .add(buildQueryParser(analyzer, "type").parse(searchQuery), BooleanClause.Occur.SHOULD) + .add(buildQueryParser(analyzer, "coverage").parse(searchQuery), BooleanClause.Occur.SHOULD) + .add(buildQueryParser(analyzer, "rights").parse(searchQuery), BooleanClause.Occur.SHOULD) + .add(buildQueryParser(analyzer, "filename").parse(searchQuery), BooleanClause.Occur.SHOULD) + .add(buildQueryParser(analyzer, "content").parse(fullSearchQuery), BooleanClause.Occur.SHOULD) .build(); // Search @@ -435,6 +431,19 @@ public class LuceneIndexingHandler implements IndexingHandler { return documentMap; } + /** + * Build a query parser for searching. + * + * @param analyzer Analyzer + * @param field Field + * @return Query parser + */ + private SimpleQueryParser buildQueryParser(Analyzer analyzer, String field) { + SimpleQueryParser simpleQueryParser = new SimpleQueryParser(analyzer, field); + simpleQueryParser.setDefaultOperator(BooleanClause.Occur.MUST); // AND all the terms + return simpleQueryParser; + } + /** * Build Lucene document from database document. * diff --git a/docs-core/src/main/resources/config.properties b/docs-core/src/main/resources/config.properties index eb3e256a..5d8d3532 100644 --- a/docs-core/src/main/resources/config.properties +++ b/docs-core/src/main/resources/config.properties @@ -1 +1 @@ -db.version=21 \ No newline at end of file +db.version=22 \ No newline at end of file diff --git a/docs-core/src/main/resources/db/update/dbupdate-022-0.sql b/docs-core/src/main/resources/db/update/dbupdate-022-0.sql new file mode 100644 index 00000000..c8333f93 --- /dev/null +++ b/docs-core/src/main/resources/db/update/dbupdate-022-0.sql @@ -0,0 +1,5 @@ +alter table T_FILE add column FIL_VERSION_N int not null default 0; +alter table T_FILE add column FIL_LATESTVERSION_B bit not null default 1; +alter table T_FILE add column FIL_IDVERSION_C varchar(36); + +update T_CONFIG set CFG_VALUE_C = '22' where CFG_ID_C = 'DB_VERSION'; diff --git a/docs-core/src/main/resources/messages.properties.de b/docs-core/src/main/resources/messages.properties.de new file mode 100644 index 00000000..bfdd17d9 --- /dev/null +++ b/docs-core/src/main/resources/messages.properties.de @@ -0,0 +1,10 @@ +email.template.password_recovery.subject=Bitte setzen Sie ihr Passwort zur\u00FCck +email.template.password_recovery.hello=Hallo {0}. +email.template.password_recovery.instruction1=Wir haben eine Anfrage zum Zur\u00FCcksetzen Ihres Passworts erhalten.
Wenn Sie keine Hilfe angefordert haben, können Sie diese E-Mail einfach ignorieren. +email.template.password_recovery.instruction2=Um Ihr Passwort zur\u00FCckzusetzen, besuchen Sie bitte den folgenden Link: +email.template.password_recovery.click_here=Klicken Sie hier, um Ihr Passwort zur\u00FCckzusetzen +email.template.route_step_validate.subject=Ein Dokument braucht Ihre Aufmerksamkeit +email.template.route_step_validate.hello=Hallo {0}. +email.template.route_step_validate.instruction1=Ihnen wurde ein Workflow-Schritt zugewiesen, der Ihre Aufmerksamkeit erfordert. +email.template.route_step_validate.instruction2=Um das Dokument anzuzeigen und den Workflow zu \u00FCberpr\u00FCfen, besuchen Sie bitte den folgenden Link: +email.no_html.error=Ihr E-Mail-Client unterst\u00FCtzt keine HTML-Nachrichten \ No newline at end of file diff --git a/docs-core/src/main/resources/messages_de.properties b/docs-core/src/main/resources/messages_de.properties new file mode 100644 index 00000000..bfdd17d9 --- /dev/null +++ b/docs-core/src/main/resources/messages_de.properties @@ -0,0 +1,10 @@ +email.template.password_recovery.subject=Bitte setzen Sie ihr Passwort zur\u00FCck +email.template.password_recovery.hello=Hallo {0}. +email.template.password_recovery.instruction1=Wir haben eine Anfrage zum Zur\u00FCcksetzen Ihres Passworts erhalten.
Wenn Sie keine Hilfe angefordert haben, können Sie diese E-Mail einfach ignorieren. +email.template.password_recovery.instruction2=Um Ihr Passwort zur\u00FCckzusetzen, besuchen Sie bitte den folgenden Link: +email.template.password_recovery.click_here=Klicken Sie hier, um Ihr Passwort zur\u00FCckzusetzen +email.template.route_step_validate.subject=Ein Dokument braucht Ihre Aufmerksamkeit +email.template.route_step_validate.hello=Hallo {0}. +email.template.route_step_validate.instruction1=Ihnen wurde ein Workflow-Schritt zugewiesen, der Ihre Aufmerksamkeit erfordert. +email.template.route_step_validate.instruction2=Um das Dokument anzuzeigen und den Workflow zu \u00FCberpr\u00FCfen, besuchen Sie bitte den folgenden Link: +email.no_html.error=Ihr E-Mail-Client unterst\u00FCtzt keine HTML-Nachrichten \ No newline at end of file diff --git a/docs-importer/SismicsDocs.ico b/docs-importer/SismicsDocs.ico new file mode 100644 index 00000000..4042f802 Binary files /dev/null and b/docs-importer/SismicsDocs.ico differ diff --git a/docs-web/pom.xml b/docs-web/pom.xml index b5eb7f28..32aa4aa7 100644 --- a/docs-web/pom.xml +++ b/docs-web/pom.xml @@ -26,6 +26,25 @@ docs-web-common + + + javax.xml.bind + jaxb-api + 2.3.0 + + + + com.sun.xml.bind + jaxb-core + 2.3.0 + + + + com.sun.xml.bind + jaxb-impl + 2.3.0 + + org.glassfish.jersey.containers diff --git a/docs-web/src/dev/resources/config.properties b/docs-web/src/dev/resources/config.properties index e55e3dbc..7ab7347c 100644 --- a/docs-web/src/dev/resources/config.properties +++ b/docs-web/src/dev/resources/config.properties @@ -1,3 +1,3 @@ api.current_version=${project.version} api.min_version=1.0 -db.version=21 \ No newline at end of file +db.version=22 \ No newline at end of file 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 2c7380b7..7de9134f 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 @@ -900,7 +900,7 @@ public class DocumentResource extends BaseResource { } // Save the document, create the base ACLs - document = DocumentUtil.createDocument(document, principal.getId()); + DocumentUtil.createDocument(document, principal.getId()); // Raise a document created event DocumentCreatedAsyncEvent documentCreatedAsyncEvent = new DocumentCreatedAsyncEvent(); @@ -911,7 +911,7 @@ 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(), + FileUtil.createFile(fileContent.getName(), null, fileContent.getFile(), fileContent.getSize(), document.getLanguage(), principal.getId(), document.getId()); } } catch (IOException 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 ea6dbfcb..02195329 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 @@ -66,6 +66,7 @@ public class FileResource extends BaseResource { * @apiName PutFile * @apiGroup File * @apiParam {String} id Document ID + * @apiParam {String} previousFileId ID of the file to replace by this new version * @apiParam {String} file File data * @apiSuccess {String} status Status OK * @apiSuccess {String} id File ID @@ -88,6 +89,7 @@ public class FileResource extends BaseResource { @Consumes("multipart/form-data") public Response add( @FormDataParam("id") String documentId, + @FormDataParam("previousFileId") String previousFileId, @FormDataParam("file") FormDataBodyPart fileBodyPart) { if (!authenticate()) { throw new ForbiddenClientException(); @@ -122,7 +124,7 @@ public class FileResource extends BaseResource { try { String name = fileBodyPart.getContentDisposition() != null ? URLDecoder.decode(fileBodyPart.getContentDisposition().getFileName(), "UTF-8") : null; - String fileId = FileUtil.createFile(name, unencryptedFile, fileSize, documentDto == null ? + String fileId = FileUtil.createFile(name, previousFileId, unencryptedFile, fileSize, documentDto == null ? null : documentDto.getLanguage(), principal.getId(), documentId); // Always return OK @@ -392,6 +394,7 @@ public class FileResource extends BaseResource { * @apiSuccess {String} files.id ID * @apiSuccess {String} files.mimetype MIME type * @apiSuccess {String} files.name File name + * @apiSuccess {String} files.version Zero-based version number * @apiSuccess {String} files.processing True if the file is currently processing * @apiSuccess {String} files.document_id Document ID * @apiSuccess {String} files.create_date Create date (timestamp) @@ -433,6 +436,7 @@ public class FileResource extends BaseResource { .add("id", fileDb.getId()) .add("processing", FileUtil.isProcessingFile(fileDb.getId())) .add("name", JsonUtil.nullable(fileDb.getName())) + .add("version", fileDb.getVersion()) .add("mimetype", fileDb.getMimeType()) .add("document_id", JsonUtil.nullable(fileDb.getDocumentId())) .add("create_date", fileDb.getCreateDate().getTime()) diff --git a/docs-web/src/main/webapp/src/app/docs/app.js b/docs-web/src/main/webapp/src/app/docs/app.js index 7b9e26da..c6e1c90a 100644 --- a/docs-web/src/main/webapp/src/app/docs/app.js +++ b/docs-web/src/main/webapp/src/app/docs/app.js @@ -507,7 +507,8 @@ angular.module('docs', { key: 'chi_tra', label: '繁体中文' }, { key: 'jpn', label: '日本語' }, { key: 'tha', label: 'ภาษาไทย' }, - { key: 'kor', label: '한국어' } + { key: 'kor', label: '한국어' }, + { key: 'nld', label: 'Nederlands' } ]; }) /** @@ -530,4 +531,4 @@ angular.module('docs', if (location.search.indexOf("protractor") > -1) { window.name = 'NG_DEFER_BOOTSTRAP!'; -} \ No newline at end of file +} diff --git a/docs-web/src/main/webapp/src/locale/de.json b/docs-web/src/main/webapp/src/locale/de.json index 476d0dcc..7fdf845f 100644 --- a/docs-web/src/main/webapp/src/locale/de.json +++ b/docs-web/src/main/webapp/src/locale/de.json @@ -24,8 +24,8 @@ "passwordreset": { "message": "Bitte geben Sie ein neues Passwort ein.", "submit": "Mein Passwort ändern", - "error_title": "Fehler beim ändern des Passworts.", - "error_message": "Ihre Anfrage zur Passwort-Wiederherstellung ist abgelaufen, bitte wiederholen Sie die die Anfrage." + "error_title": "Fehler beim Ändern des Passworts.", + "error_message": "Ihre Anfrage zur Passwort-Wiederherstellung ist abgelaufen, bitte wiederholen Sie die Anfrage." }, "index": { "toggle_navigation": "Navigation ein-/ausblenden", @@ -36,11 +36,13 @@ "logged_as": "Eingeloggt als {{ username }}", "nav_settings": "Einstellungen", "logout": "Logout", - "global_quota_warning": "Warnung! Der frei zur Verfügung stehende maximale Speicherplatz ist fast erreicht bei {{ current | number: 0 }}MB ({{ percent | number: 1 }}%) verwendet {{ total | number: 0 }}MB" + "global_quota_warning": "Warnung! Der frei zur Verfügung stehende, maximale Speicherplatz ist fast erreicht bei {{ current | number: 0 }}MB ({{ percent | number: 1 }}%) verwendet {{ total | number: 0 }}MB" }, "document": { "navigation_up": "Eine Stufe höher", "toggle_navigation": "Navigation ein-/ausblenden", + "display_mode_list": "Dokumente in Liste anzeigen", + "display_mode_grid": "Dokumente im Raster anzeigen", "search_simple": "Einfache Suche", "search_fulltext": "Volltext Suche", "search_creator": "Urheber", @@ -76,8 +78,8 @@ "type": "Typ", "coverage": "Geltungsbereich", "rights": "Rechte", - "relations": "Beziehung", - "page_size": "Seiten Größe", + "relations": "Beziehungen", + "page_size": "Seitengröße", "page_size_10": "10 pro Seite", "page_size_20": "20 pro Seite", "page_size_30": "30 pro Seite", @@ -94,12 +96,12 @@ "shared_document_message": "Sie können dieses Dokument mit diesem Link freigeben. Beachten Sie, dass jeder, der diesen Link hat, das Dokument sehen kann.
", "not_found": "Dokument nicht gefunden", "forbidden": "Zugriff verweigert", - "download_files": "Download Datei", + "download_files": "Datei herunterladen", "export_pdf": "in PDF exportieren", "by_creator": "von", "comments": "Kommentar", "no_comments": "Noch keine Kommentare zu diesem Dokument vorhanden", - "add_comment": "Fügen sie einen Komentar hinzu", + "add_comment": "Fügen sie einen Kommentar hinzu", "error_loading_comments": "Fehler beim Laden eines Kommentars", "workflow_current": "Aktueller Workflow-Status", "workflow_comment": "Fügen Sie einen Workflow Kommentar hinzu", @@ -111,27 +113,28 @@ "delete_file_message": "Wollen Sie diese Datei wirklich löschen?", "upload_pending": "Ausstehend...", "upload_progress": "Hochladen...", - "upload_error": "Fehler beim hochladen", + "upload_error": "Fehler beim Hochladen", "upload_error_quota": "Maximaler Speicherplatz erreicht", - "drop_zone": "Drag & Drop Dateien hier her ziehen, um diese hochzuladen", + "drop_zone": "Drag & Drop Dateien hierherziehen, um diese hochzuladen", "add_files": "Dateien hinzufügen", - "file_processing_indicator": "Diese Datei wird gerade bearbeitet. Die Suche wird nicht verfügbar sein, bevor sie abgeschlossen ist.", - "reprocess_file": "Diese Datei erneut bearbeiten" + "file_processing_indicator": "Diese Datei wird gerade bearbeitet. Die Suche wird nicht verfügbar sein, bevor der Vorgang abgeschlossen ist.", + "reprocess_file": "Diese Datei erneut verarbeiten" }, "workflow": { "workflow": "Workflow", - "message": "Verifizieren oder validieren Sie Ihre Dokumente mit Mitarbeitern Ihres Unternehmens mithilfe von Workflows.", + "message": "Verifizieren oder validieren Sie Ihre Dokumente mit Mitarbeitern Ihres Unternehmens mit Hilfe von Workflows.", "workflow_start_label": "Welcher Workflow soll gestartet werden?", "add_more_workflow": "Fügen Sie weitere Workflows hinzu", "start_workflow_submit": "Starten Sie den Workflow", "full_name": "{{ name }} gestartet am {{ create_date | date }}", "cancel_workflow": "Abbrechen des aktuellen Workflows", "cancel_workflow_title": "Abbrechen des Workflows", - "cancel_workflow_message": "Wollen Sie den laufenden Workflow wirklich abbrechen?" + "cancel_workflow_message": "Wollen Sie den laufenden Workflow wirklich abbrechen?", + "no_workflow": "Sie können keinen Workflow für dieses Dokument starten." }, "permissions": { "permissions": "Berechtigungen", - "message": "Die Berechtigungen können direkt auf dieses Dokument angewendet werden, oder sind erhältlich bei tags.", + "message": "Die Berechtigungen können direkt auf dieses Dokument angewendet werden, oder können von tags vorgegeben werden.", "title": "Berechtigungen auf diesem Dokument", "inherited_tags": "Von Tags geerbte Berechtigungen", "acl_source": "Von", @@ -150,7 +153,7 @@ "primary_metadata": "Primäre Metadaten", "title_placeholder": "Titel des Dokuments", "description_placeholder": "Zusammenfassung, Inhaltsverzeichnis oder Freitext", - "new_files": "New files", + "new_files": "neue Dateien", "orphan_files": "+ {{ count }} Datei{{ count > 1 ? 's' : '' }}", "additional_metadata": "Weitere Metadaten", "subject_placeholder": "Schlüsselwörter, abstrakte Sätze oder Klassifizierungscodes", @@ -163,16 +166,16 @@ "default": { "upload_pending": "Ausstehend...", "upload_progress": "Lädt hoch...", - "upload_error": "Fehler beim hochladen", + "upload_error": "Fehler beim Hochladen", "upload_error_quota": "Maximaler Speicherplatz erreicht", - "quick_upload": "Schnelles hochladen", - "drop_zone": "Drag & Drop Dateien hier her ziehen, um diese hochzuladen", + "quick_upload": "Schnelles Hochladen", + "drop_zone": "Drag & Drop Dateien hierherziehen, um diese hochzuladen", "add_files": "Dateien hinzufügen", "add_new_document": "Neues Dokument hinzufügen", "latest_activity": "Letzte Aktivitäten", - "footer_sismics": "Programmiert mit by Sismics", + "footer_sismics": "Programmiert mit von Sismics", "api_documentation": "API Dokumentation", - "feedback": "Geben Sie uns Feedback", + "feedback": "Geben Sie uns Ihr Feedback", "workflow_document_list": "Mir zugeordnete Dokumente", "select_all": "Alle auswählen", "select_none": "Nichts auswählen" @@ -209,7 +212,7 @@ "title": "Tags", "message_1": "Tags sind Kategorien, die den Dokumenten zugeordnet sind.", "message_2": "Ein Dokument kann mit mehreren Tags versehen werden und ein Tag kann auf mehrere Dokumente angewendet werden.", - "message_3": "Verwendung der Schaltfläche können Sie die Berechtigungen für ein Tag bearbeiten.", + "message_3": "Unter Verwendung der Schaltfläche können Sie die Berechtigungen für ein Tag bearbeiten.", "message_4": "Wenn ein Tag von einem anderen Benutzer oder einer anderen Gruppe gelesen werden kann, können die zugehörigen Dokumente auch von diesen Personen gelesen werden.", "message_5": "Kennzeichnen Sie z.B. Ihre Firmendokumente mit einem Tag MyCompany und fügen Sie die Berechtigung Can read zu einer Gruppe hinzu employees" }, @@ -219,7 +222,9 @@ "name": "Name", "color": "Farbe", "parent": "Übergeordnet", - "info": "Berechtigungen für dieses Tag werden auch auf Dokumente angewendet, die mit einem Tag versehen sind {{ name }}" + "info": "Berechtigungen für dieses Tag werden auch auf Dokumente angewendet, die mit einem Tag versehen sind {{ name }}", + "circular_reference_title": "Zirkuläre Referenz", + "circular_reference_message": "Die Hierarchie der übergeordneten Tags bildet eine Schleife. Bitte wählen Sie ein anderes übergeordnetes Tag." } }, "group": { @@ -234,7 +239,7 @@ "profile": { "groups": "Gruppen", "quota_used": "Benutzter Speicherplatz", - "percent_used": "{{ percent | number: 0 }}% Benutzt", + "percent_used": "{{ percent | number: 0 }}% genutzt", "related_links": "Weiterführende Links", "document_created": "Dokumente erstellt von {{ username }}", "edit_user": "Benutzer {{ username }} bearbeiten" @@ -250,18 +255,18 @@ } }, "settings": { - "menu_personal_settings": "Peröhnliche Einstellungen", + "menu_personal_settings": "Persönliche Einstellungen", "menu_user_account": "Benutzerkonto", "menu_two_factor_auth": "Zwei-Faktor-Authentifizierung", - "menu_opened_sessions": "Geöffnete Sitzung", + "menu_opened_sessions": "Geöffnete Sitzungen", "menu_file_importer": "Massen Datei Importer", "menu_general_settings": "Generelle Einstellungen", - "menu_workflow": "Workflow", - "menu_users": "Benutzer", - "menu_groups": "Gruppen", - "menu_vocabularies": "Vokabulare", + "menu_workflow": "Workflows", + "menu_users": "Benutzerverwaltung", + "menu_groups": "Gruppenverwaltung", + "menu_vocabularies": "Vokabulareinträge", "menu_configuration": "Einstellungen", - "menu_inbox": "Inbox scannen", + "menu_inbox": "Posteingang durchsuchen", "menu_monitoring": "Überwachung", "user": { "title": "Benutzerverwaltung", @@ -290,7 +295,7 @@ } }, "workflow": { - "title": "Workflow Konfigurator", + "title": "Workflows", "add_workflow": "Workflow hinzufügen", "name": "Name", "create_date": "Erstellungsdatum", @@ -306,22 +311,23 @@ "type_approve": "Genehmigen", "type_validate": "Bestätigen", "target": "Zugewiesen an", - "target_help": "Zulassen: Überprüfen und fortsetzen des Workflows
Genemigen: Übernehmen oder lehnen Sie die Überprüfung ab", + "target_help": "Zulassen: Überprüfen und fortsetzen des Workflows
Genehmigen: Übernehmen oder lehnen Sie die Überprüfung ab", "add_step": "Workflow Schritt hinzufügen", "actions": "Was passiert danach?", - "remove_action": "Aktion entfernen" + "remove_action": "Aktion entfernen", + "acl_info": "Nur hier definierte Benutzer und Gruppen können diesen Workflow für ein Dokument starten" } }, "security": { "enable_totp": "Zwei-Faktor-Authentifizierung aktivieren", - "enable_totp_message": "Stellen Sie sicher, dass Sie eine TOTP-kompatible Anwendung auf Ihrem Handy haben, die bereit ist, ein neues Konto hinzuzufügen.", + "enable_totp_message": "Stellen Sie sicher, dass Sie eine TOTP-kompatible Anwendung auf Ihrem Telefon haben, die bereit ist, ein neues Konto hinzuzufügen.", "title": "Zwei-Faktor-Authentifizierung", - "message_1": "Die Zwei-Faktor-Authentifizierung ermöglicht Ihnen eine weitere Abischerung Ihres {{ appName }} Benutzerkontos. Bevor Sie diese Funktion aktivieren, stellen Sie sicher, dass Sie eine TOTP-kompatible Anwendung auf Ihrem Telefon haben:", + "message_1": "Die Zwei-Faktor-Authentifizierung ermöglicht Ihnen eine weitere Absicherung Ihres {{ appName }} Benutzerkontos. Bevor Sie diese Funktion aktivieren, stellen Sie sicher, dass Sie eine TOTP-kompatible Anwendung auf Ihrem Telefon haben:", "message_google_authenticator": "Für Android, iOS, und Blackberry: Google Authenticator", "message_duo_mobile": "Für Android und iOS: Duo Mobile", "message_authenticator": "Für Windows Phone: Authenticator", - "message_2": "Diese Anwendungen generieren automatisch einen Validierungscod der sich nach einer gewissen Zeitspanne ändert. Sie müssen diesen Validierungscode jedes Mal eingeben, wenn Sie sich bei {{ appName }} anmelden. .", - "secret_key": "Ihr geheimer Schlüssel ist: {{ secret }}", + "message_2": "Diese Anwendungen generieren automatisch einen Validierungscode, der sich nach einer gewissen Zeitspanne ändert. Sie müssen diesen Validierungscode jedes Mal eingeben, wenn Sie sich bei {{ appName }} anmelden. .", + "secret_key": "Ihr geheimer Schlüssel lautet: {{ secret }}", "secret_key_warning": "Konfigurieren Sie Ihre TOTP-App jetzt mit diesem geheimen Schlüssel auf Ihrem Telefon. Sie können später nicht mehr darauf zugreifen.", "totp_enabled_message": "Die Zwei-Faktor-Authentifizierung ist in Ihrem Konto aktiviert.
Bei jeder Anmeldung auf {{ appName }}, werden Sie in Ihrer konfigurierten Telefon-App nach einem Bestätigungscode gefragt.
Wenn Sie Ihr Telefon verlieren, können Sie sich nicht in Ihrem Konto anmelden, aber aktive Sitzungen ermöglichen es Ihnen, einen geheimen Schlüssel neu zu generieren.", "disable_totp": { @@ -358,7 +364,7 @@ }, "config": { "title_guest_access": "Gastzugang", - "message_guest_access": "Der Gastzugang ist ein Modus in dem jeder Zugriff hat und {{ appName }} ohne Passwort nutzen kann.
Wie ein normaler Benutzer kann der Gastbenutzer nur auf seine Dokumente zugreifen und Berechtigungen zugreifen.
", + "message_guest_access": "Der Gastzugang ist ein Modus, in dem jeder auf {{appName}} ohne Kennwort zugreifen kann.
Wie ein normaler Benutzer kann der Gastbenutzer nur auf seine Dokumente und diejenigen zugreifen, auf die er über Berechtigungen zugreifen kann.
", "enable_guest_access": "Gastzugang aktivieren", "disable_guest_access": "Gastzugang deaktivieren", "title_theme": "Aussehen anpassen", @@ -371,18 +377,24 @@ "logo": "Logo (quadratische Größe)", "background_image": "Hintergrundbild", "uploading_image": "Bild hochladen...", - "title_smtp": "SMTP Email Einstellungen für Passwort wiederherstellungfür das Zürucksetzen des Passworts", "smtp_hostname": "SMTP Server", "smtp_port": "SMTP Port", "smtp_from": "Absender E-Mail", "smtp_username": "SMTP Benutzername", "smtp_password": "SMTP Passwort", - "smtp_updated": "SMTP Konfiguration erfolgreich aktualisiert" + "smtp_updated": "SMTP Konfiguration erfolgreich aktualisiert", + "webhooks": "Webhooks", + "webhooks_explain": "Webhooks werden aufgerufen, wenn das angegebene Ereignis eintritt. Die angegebene URL wird mit einer JSON-Payload gepostet, die den Ereignisnamen und die ID der betreffenden Ressource enthält.", + "webhook_event": "Ereignisse", + "webhook_url": "URL", + "webhook_create_date": "Erstelldatum", + "webhook_add": "Webhook hinzufügen" }, "inbox": { "title": "Posteingang durchsuchen", - "message": "Wenn Sie diese Funktion aktivieren, durchsucht das System den angegebenen Posteingang jede Minute nach ungelesenen E-Mails und importieren diese automatisch.
Nach dem Import einer E-Mail wird diese als gelesen markiert.
Folgen Sie den Links zu Konfigurationseinstellungen für Gmail, Outlook.com, Yahoo.", - "enabled": "Posteingang duchrsuchen aktivieren", + "message": "Wenn Sie diese Funktion aktivieren, durchsucht das System den angegebenen Posteingang jede Minute nach ungelesenen E-Mails und importiert diese automatisch.
Nach dem Import einer E-Mail wird diese als gelesen markiert.
Folgen Sie den Links zu Konfigurationseinstellungen für Gmail, Outlook.com, Yahoo.", + "enabled": "Durchsuchen des Posteingangs aktivieren", "hostname": "IMAP Server", "port": "IMAP Port (143 oder 993)", "username": "IMAP Benutzername", @@ -391,16 +403,21 @@ "test": "Konfiguration testen", "last_sync": "Letzte Synchronisation: {{ data.date | date: 'medium' }}, {{ data.count }} E-Mail(s){{ data.count > 1 ? 's' : '' }} importiert", "test_success": "Die Verbindung zum Posteingang war erfolgreich ({{ count }} unread message{{ count > 1 ? 's' : '' }})", - "test_fail": "Beim Verbinden mit dem Posteingang ist ein Fehler aufgetreten, bitte überprüfen Sie die Einstellungen" + "test_fail": "Beim Verbinden mit dem Posteingang ist ein Fehler aufgetreten, bitte überprüfen Sie die Einstellungen", + "saved": "IMAP Konfiguration erfolgreich gespeichert" }, "monitoring": { "background_tasks": "Hintergrundaufgaben", - "queued_tasks": "Es gibt derzeit {{ count }}} anstehende Tasks.", + "queued_tasks": "Es gibt derzeit {{ count }} anstehende Tasks.", "queued_tasks_explain": "Dateiverarbeitung, Thumbnail-Erstellung, Index-Update, optische Zeichenerkennung sind Hintergrundaufgaben. Eine große Anzahl unbearbeiteter Aufgaben führt zu unvollständigen Suchergebnissen.", - "server_logs": "Server logs", + "server_logs": "Server Logs", "log_date": "Datum", "log_tag": "Tag", - "log_message": "Nachricht" + "log_message": "Nachricht", + "indexing": "Indexierung", + "indexing_info": "Wenn Sie Unstimmigkeiten in den Suchergebnissen feststellen, können Sie versuchen, eine vollständige Neuindizierung durchzuführen. Die Suchergebnisse sind bis zum Abschluss dieser Operation unvollständig.", + "start_reindexing": "Vollständige Neuindizierung starten", + "reindexing_started": "Neuindizierung wurde gestartet, bitte warten Sie, bis es keine Hintergrundaufgaben mehr gibt." }, "session": { "title": "Geöffnete Sitzungen", @@ -413,7 +430,7 @@ "clear": "Alle anderen Sitzungen löschen" }, "vocabulary": { - "title": "Vokabulareinträge", + "title": "Vokabular", "choose_vocabulary": "Wählen Sie ein Vokabular aus, das Sie bearbeiten möchten.", "type": "Typ", "coverage": "Abdeckung", @@ -423,31 +440,31 @@ "new_entry": "Neuer Eintrag" }, "fileimporter": { - "title": "Massen Datei Importeur", + "title": "Massen Datei Importer", "advanced_users": "Für fortgeschrittene Benutzer!", "need_intro": "Wenn Sie:", "need_1": "Ganze Verzeichnisse von Dateien auf einmal importieren möchten", "need_2": "Ein Verzeichnis nach neuen Dateien durchsuchen lassen und gefunden Dateien importieren lassen möchten", "line_1": "Gehen Sie zu sismics/docs/releases und laden Sie das Datei-Importer-Tool für Ihr System herunter.", - "line_2": "Folgen Sie dem Link instructions here um das Import-Toll zu nutzen.", - "line_3": "Ihre Dateien werden in Quick upload importiert, danach können Sie die Dateien weiterbearbeiten und Dokumenten zuordnen oder Dokumente erstellen.", + "line_2": "Folgen Sie den Anweisungen, um das Import-Tool zu nutzen.", + "line_3": "Ihre Dateien werden in Modus 'Schnelles Hochladen' importiert. Danach können Sie die Dateien weiterbearbeiten und Dokumenten zuordnen oder Dokumente erstellen.", "download": "Herunterladen", "instructions": "Anweisungen" } }, "feedback": { "title": "Geben Sie uns Feedback", - "message": "Irgendwelche Vorschläge oder Fragen zu Sismics Docs? Wir hören Ihnen genre zu!", + "message": "Irgendwelche Vorschläge oder Fragen zu Sismics Docs? Wir hören Ihnen gerne zu!", "sent_title": "Feedback gesendet", "sent_message": "Vielen Dank für Ihr Feedback! Es wird uns helfen, Sismics Docs noch besser zu machen." }, "import": { "title": "Wird importiert", - "error_quota": "Speicher Limit erreicht, kontaktieren Sie Ihren Administrator, um den Ihnen zur verfügung gestellten Speicherplatz zu erhöhen.", + "error_quota": "Speicherlimit erreicht. Kontaktieren Sie Ihren Administrator, um den Ihnen zur Verfügung gestellten Speicherplatz zu erhöhen.", "error_general": "Beim Versuch, Ihre Datei zu importieren, ist ein Fehler aufgetreten. Bitte stellen Sie sicher, dass es sich um eine gültige EML-Datei handelt." }, "app_share": { - "main": "Fragen Sie nach einen Link zu einem gemeinsam genutzten Dokument, um darauf zuzugreifen.", + "main": "Fragen Sie nach einem Link zu einem gemeinsam genutzten Dokument, um darauf zuzugreifen.", "403": { "title": "Nicht erlaubt", "message": "Das Dokument, das Sie anzeigen möchten, ist nicht mehr freigegeben." @@ -458,7 +475,7 @@ "acl_target": "Für", "acl_permission": "Zugriffsberechtigung", "add_permission": "Zugriffsberechtigung hinzufügen", - "search_user_group": "Suchen einen Benutzer oder eine Gruppe" + "search_user_group": "Suchen nach einem Benutzer oder einer Gruppe" }, "auditlog": { "log_created": "erstellt", @@ -468,7 +485,7 @@ "Comment": "Kommentar", "Document": "Dokument", "File": "Datei", - "Group": "Guppe", + "Group": "Gruppe", "Tag": "Tag", "User": "Benutzer", "RouteModel": "Workflow-Muster", @@ -515,13 +532,13 @@ "too_long": "Zu lang", "email": "Muss eine gültige E-Mailadresse sein", "password_confirm": "Passwort und Passwortbestätigung müssen übereinstimmen", - "number": "Nummer erfoderlich", + "number": "Nummer erforderlich", "no_space": "Leerzeichen sind nicht erlaubt" }, "action_type": { "ADD_TAG": "Tag hinzufügen", "REMOVE_TAG": "Tag entfernen", - "PROCESS_FILES": "Dateien bearbeiten" + "PROCESS_FILES": "Dateien verarbeiten" }, "pagination": { "previous": "Vorherige", @@ -532,7 +549,7 @@ "ok": "OK", "cancel": "Abbrechen", "share": "Teilen", - "unshare": "Nicht mehr Teilen", + "unshare": "Nicht mehr teilen", "close": "Schliessen", "add": "Hinzufügen", "open": "Öffnen", @@ -543,7 +560,7 @@ "delete": "Löschen", "rename": "Umbenennen", "loading": "Lädt...", - "send": "Gesendet", + "send": "Absenden", "enabled": "Aktiviert", "disabled": "Deaktiviert" } \ No newline at end of file diff --git a/docs-web/src/prod/resources/config.properties b/docs-web/src/prod/resources/config.properties index e55e3dbc..7ab7347c 100644 --- a/docs-web/src/prod/resources/config.properties +++ b/docs-web/src/prod/resources/config.properties @@ -1,3 +1,3 @@ api.current_version=${project.version} api.min_version=1.0 -db.version=21 \ No newline at end of file +db.version=22 \ No newline at end of file diff --git a/docs-web/src/stress/resources/config.properties b/docs-web/src/stress/resources/config.properties index e55e3dbc..7ab7347c 100644 --- a/docs-web/src/stress/resources/config.properties +++ b/docs-web/src/stress/resources/config.properties @@ -1,3 +1,3 @@ api.current_version=${project.version} api.min_version=1.0 -db.version=21 \ No newline at end of file +db.version=22 \ No newline at end of file diff --git a/docs-web/src/test/java/com/sismics/docs/rest/TestDocumentResource.java b/docs-web/src/test/java/com/sismics/docs/rest/TestDocumentResource.java index 964e7e6d..9f0c78d0 100644 --- a/docs-web/src/test/java/com/sismics/docs/rest/TestDocumentResource.java +++ b/docs-web/src/test/java/com/sismics/docs/rest/TestDocumentResource.java @@ -184,6 +184,7 @@ public class TestDocumentResource extends BaseJerseyTest { // Search documents Assert.assertEquals(1, searchDocuments("full:uranium full:einstein", document1Token)); + Assert.assertEquals(2, searchDocuments("tit*", document1Token)); Assert.assertEquals(2, searchDocuments("full:title", document1Token)); Assert.assertEquals(2, searchDocuments("title", document1Token)); Assert.assertEquals(1, searchDocuments("super description", document1Token)); 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 053b72e6..278f1bb6 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 @@ -140,9 +140,11 @@ public class TestFileResource extends BaseJerseyTest { Assert.assertEquals(2, files.size()); Assert.assertEquals(file1Id, files.getJsonObject(0).getString("id")); Assert.assertEquals("PIA00452.jpg", files.getJsonObject(0).getString("name")); + Assert.assertEquals(0, files.getJsonObject(0).getInt("version")); Assert.assertEquals(163510L, files.getJsonObject(0).getJsonNumber("size").longValue()); Assert.assertEquals(file2Id, files.getJsonObject(1).getString("id")); Assert.assertEquals("PIA00452.jpg", files.getJsonObject(1).getString("name")); + Assert.assertEquals(0, files.getJsonObject(1).getInt("version")); // Rename a file target().path("file/" + file1Id) @@ -225,6 +227,38 @@ public class TestFileResource extends BaseJerseyTest { target().path("/file/" + file2Id + "/process").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file1Token) .post(Entity.form(new Form()), JsonObject.class); + + // Add a new version to a file + String file3Id; + try (InputStream is0 = Resources.getResource("file/document.txt").openStream()) { + StreamDataBodyPart streamDataBodyPart = new StreamDataBodyPart("file", is0, "document.txt"); + try (FormDataMultiPart multiPart = new FormDataMultiPart()) { + json = target() + .register(MultiPartFeature.class) + .path("/file").request() + .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file1Token) + .put(Entity.entity( + multiPart + .field("id", document1Id) + .field("previousFileId", file2Id) + .bodyPart(streamDataBodyPart), + MediaType.MULTIPART_FORM_DATA_TYPE), JsonObject.class); + file3Id = json.getString("id"); + Assert.assertNotNull(file2Id); + } + } + + // Check the newly created version + json = target().path("/file/list") + .queryParam("id", document1Id) + .request() + .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file1Token) + .get(JsonObject.class); + files = json.getJsonArray("files"); + Assert.assertEquals(1, files.size()); + Assert.assertEquals(file3Id, files.getJsonObject(0).getString("id")); + Assert.assertEquals("document.txt", files.getJsonObject(0).getString("name")); + Assert.assertEquals(1, files.getJsonObject(0).getInt("version")); } /**