From 1ddff7a54af4b2b2759631e8806126a7b188ba3b Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Sat, 5 Dec 2020 19:36:39 +0100 Subject: [PATCH] Aktueller Stand ImExport UI Former-commit-id: 0acc7f17b4b361e1683f901df225a8fe5752fa09 --- .../imexport/AbstractEntityImExporter.java | 1 - .../imexport/EntityImExporterTreeNode.java | 8 +- .../org/libreccm/imexport/ImportExport.java | 8 +- .../org/libreccm/security/RoleImExporter.java | 3 + .../ui/admin/imexport/ImExportController.java | 95 ++++++++++- .../ui/admin/imexport/ImExportTask.java | 139 ++++++++++++++++ .../ui/admin/imexport/ImExportTasks.java | 64 ++++++++ .../imexport/ImportExportTaskManager.java | 152 ++++++++++++++++++ .../components/bootstrap/formCheck.xhtml | 3 +- .../libreccm/ui/admin/imexport/export.xhtml | 20 ++- .../ui/admin/imexport/exporting.xhtml | 36 +++++ .../libreccm/ui/admin/imexport/imexport.xhtml | 96 ++++++++++- .../org/libreccm/ui/AdminBundle.properties | 20 +++ .../org/libreccm/ui/AdminBundle_de.properties | 20 +++ 14 files changed, 644 insertions(+), 21 deletions(-) create mode 100644 ccm-core/src/main/java/org/libreccm/ui/admin/imexport/ImExportTask.java create mode 100644 ccm-core/src/main/java/org/libreccm/ui/admin/imexport/ImExportTasks.java create mode 100644 ccm-core/src/main/java/org/libreccm/ui/admin/imexport/ImportExportTaskManager.java create mode 100644 ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/imexport/exporting.xhtml diff --git a/ccm-core/src/main/java/org/libreccm/imexport/AbstractEntityImExporter.java b/ccm-core/src/main/java/org/libreccm/imexport/AbstractEntityImExporter.java index 249801fca..e4bbeb207 100644 --- a/ccm-core/src/main/java/org/libreccm/imexport/AbstractEntityImExporter.java +++ b/ccm-core/src/main/java/org/libreccm/imexport/AbstractEntityImExporter.java @@ -85,7 +85,6 @@ public abstract class AbstractEntityImExporter { @Transactional(Transactional.TxType.REQUIRED) public String exportEntity(final Exportable entity) throws ExportException { - try { return objectMapper.writeValueAsString(entity); } catch (JsonProcessingException ex) { diff --git a/ccm-core/src/main/java/org/libreccm/imexport/EntityImExporterTreeNode.java b/ccm-core/src/main/java/org/libreccm/imexport/EntityImExporterTreeNode.java index 60ec32f2f..1173dc42f 100644 --- a/ccm-core/src/main/java/org/libreccm/imexport/EntityImExporterTreeNode.java +++ b/ccm-core/src/main/java/org/libreccm/imexport/EntityImExporterTreeNode.java @@ -105,10 +105,10 @@ public final class EntityImExporterTreeNode { @Override public int hashCode() { int hash = 7; - hash = 47 - * hash - + Objects - .hashCode(this.entityImExporter.getClass().getName()); + hash = 47 * hash + + Objects.hashCode( + this.entityImExporter.getClass().getName() + ); return hash; } diff --git a/ccm-core/src/main/java/org/libreccm/imexport/ImportExport.java b/ccm-core/src/main/java/org/libreccm/imexport/ImportExport.java index e896ceb20..1402b6a22 100644 --- a/ccm-core/src/main/java/org/libreccm/imexport/ImportExport.java +++ b/ccm-core/src/main/java/org/libreccm/imexport/ImportExport.java @@ -38,6 +38,7 @@ import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.ArrayList; +import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -59,6 +60,7 @@ import javax.json.JsonObjectBuilder; import javax.json.JsonReader; import javax.json.JsonString; import javax.json.JsonWriter; +import javax.transaction.Transactional; /** * Central service for importing and exporting entities. @@ -106,8 +108,9 @@ public class ImportExport { * * @see CcmFilesConfiguration#dataPath */ + @Transactional(Transactional.TxType.REQUIRED) public void exportEntities( - final List entities, final String exportName + final Collection entities, final String exportName ) { final JsonObjectBuilder manifestBuilder = Json.createObjectBuilder(); manifestBuilder.add("created", @@ -162,7 +165,6 @@ public class ImportExport { for (final Map.Entry> entry : typeEntityMap.entrySet()) { - createExportedEntities(exportName, entry.getKey(), entry.getValue()); @@ -182,8 +184,8 @@ public class ImportExport { * * @see CcmFilesConfiguration#dataPath */ + @Transactional(Transactional.TxType.REQUIRED) public void importEntities(final String importName) { - final String importsPath = String.format("imports/%s", importName); try { diff --git a/ccm-core/src/main/java/org/libreccm/security/RoleImExporter.java b/ccm-core/src/main/java/org/libreccm/security/RoleImExporter.java index f2a4d9bf2..2f2656163 100644 --- a/ccm-core/src/main/java/org/libreccm/security/RoleImExporter.java +++ b/ccm-core/src/main/java/org/libreccm/security/RoleImExporter.java @@ -19,6 +19,7 @@ package org.libreccm.security; import org.libreccm.imexport.AbstractEntityImExporter; +import org.libreccm.imexport.ExportException; import org.libreccm.imexport.Exportable; import org.libreccm.imexport.Processes; @@ -55,4 +56,6 @@ public class RoleImExporter extends AbstractEntityImExporter { return Collections.emptySet(); } + + } diff --git a/ccm-core/src/main/java/org/libreccm/ui/admin/imexport/ImExportController.java b/ccm-core/src/main/java/org/libreccm/ui/admin/imexport/ImExportController.java index ffdde63fa..faecb9f50 100644 --- a/ccm-core/src/main/java/org/libreccm/ui/admin/imexport/ImExportController.java +++ b/ccm-core/src/main/java/org/libreccm/ui/admin/imexport/ImExportController.java @@ -18,23 +18,28 @@ */ package org.libreccm.ui.admin.imexport; -import com.arsdigita.ui.admin.importexport.ImportExportMonitor; - import org.libreccm.core.CoreConstants; import org.libreccm.imexport.AbstractEntityImExporter; import org.libreccm.imexport.EntityImExporterTreeNode; +import org.libreccm.imexport.Exportable; import org.libreccm.imexport.ImportExport; import org.libreccm.security.AuthorizationRequired; import org.libreccm.security.RequiresPrivilege; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.TreeMap; import java.util.stream.Collectors; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.mvc.Controller; import javax.mvc.Models; +import javax.ws.rs.FormParam; import javax.ws.rs.GET; import javax.ws.rs.NotFoundException; +import javax.ws.rs.POST; import javax.ws.rs.Path; /** @@ -50,7 +55,7 @@ public class ImExportController { private ImportExport importExport; @Inject - private ImportExportMonitor importExportMonitor; + private ImportExportTaskManager taskManager; @Inject private Models models; @@ -77,12 +82,65 @@ public class ImExportController { .map(AbstractEntityImExporter::getEntityClass) .map(Class::getName) .sorted() - .collect(Collectors.toList()) + .collect( + Collectors.toMap( + clazz -> clazz, + clazz -> clazz, + this::noDuplicateKeys, + TreeMap::new + ) + ) + //.collect(Collectors.toList()) ); return "org/libreccm/ui/admin/imexport/export.xhtml"; } - + + @POST + @Path("/export") + @AuthorizationRequired + @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) + public String exportEntities( + @FormParam("selectedEntities") final String[] selectedEntitiesParam, + @FormParam("exportName") final String exportName + ) { + final Set selectedEntities = Arrays + .stream(selectedEntitiesParam) + .collect(Collectors.toSet()); + + final Set selectedNodes = importExport + .getExportableEntityTypes() + .stream() + .filter( + node -> selectedEntities.contains( + node.getEntityImExporter().getEntityClass().getName() + ) + ) + .collect(Collectors.toSet()); + + final Set exportNodes = addRequiredEntities( + new HashSet<>(selectedNodes) + ); + + final Set> exportTypes = exportNodes + .stream() + .map(node -> node.getEntityImExporter().getEntityClass()) + .collect(Collectors.toSet()); + + taskManager.exportEntities(exportTypes, exportName); + +// models.put( +// "exportEntities", +// exportNodes +// .stream() +// .map(node -> node.getEntityImExporter().getEntityClass().getName()) +// .sorted() +// .collect(Collectors.joining("\n")) +// ); +// return "org/libreccm/ui/admin/imexport/exporting.xhtml"; + return "redirect:imexport"; + } + @GET @Path("/import") @AuthorizationRequired @@ -91,4 +149,31 @@ public class ImExportController { throw new NotFoundException(); } + private String noDuplicateKeys(final String str1, final String str2) { + throw new RuntimeException("No duplicate keys allowed."); + } + + private Set addRequiredEntities( + final Set selectedNodes + ) { + boolean foundRequiredNodes = false; + final Set exportNodes = new HashSet<>( + selectedNodes + ); + for (final EntityImExporterTreeNode node : selectedNodes) { + if (node.getDependsOn() != null + && !node.getDependsOn().isEmpty() + && !exportNodes.containsAll(node.getDependsOn())) { + exportNodes.addAll(node.getDependsOn()); + foundRequiredNodes = true; + } + } + + if (foundRequiredNodes) { + return addRequiredEntities(exportNodes); + } else { + return exportNodes; + } + } + } diff --git a/ccm-core/src/main/java/org/libreccm/ui/admin/imexport/ImExportTask.java b/ccm-core/src/main/java/org/libreccm/ui/admin/imexport/ImExportTask.java new file mode 100644 index 000000000..da1688804 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/ui/admin/imexport/ImExportTask.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2020 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.libreccm.ui.admin.imexport; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.Comparator; +import java.util.Objects; +import java.util.concurrent.Future; + +/** + * + * @author Jens Pelzetter + */ +public class ImExportTask implements Comparable { + + private String name; + + private LocalDateTime started; + + private Future status; + + public String getName() { + return name; + } + + protected void setName(final String name) { + this.name = name; + } + + public LocalDateTime getStarted() { + return started; + } + + public String getStartedAsIso() { + return DateTimeFormatter.ISO_DATE_TIME.withZone( + ZoneId.systemDefault()).format(started + ); + } + + protected void setStarted(final LocalDateTime started) { + this.started = started; + } + + public Future getStatus() { + return status; + } + + protected void setStatus(final Future status) { + this.status = status; + } + + public boolean isDone() { + return status.isDone(); + } + + protected void cancel() { + status.cancel(true); + } + + @Override + public int hashCode() { + int hash = 7; + hash = 23 * hash + Objects.hashCode(this.name); + hash = 23 * hash + Objects.hashCode(this.started); + return hash; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof ImExportTask)) { + return false; + } + final ImExportTask other = (ImExportTask) obj; + if (!other.canEqual(this)) { + return false; + } + if (!Objects.equals(this.name, other.getName())) { + return false; + } + return Objects.equals(this.started, other.getStarted()); + } + + public boolean canEqual(final Object obj) { + return obj instanceof ImExportTask; + } + + @Override + public int compareTo(final ImExportTask other) { + return Comparator + .nullsFirst(Comparator + .comparing(ImExportTask::getName) + .thenComparing(ImExportTask::getStarted) + ) + .compare(this, other); + } + + @Override + public String toString() { + return String.format( + "%s{ " + + "name = %s, " + + "started = %s, " + + "status = %s" + + " }", + super.toString(), + name, + DateTimeFormatter.ISO_DATE_TIME.withZone( + ZoneId.systemDefault() + ).format(started), + Objects.toString(status) + ); + } + +} diff --git a/ccm-core/src/main/java/org/libreccm/ui/admin/imexport/ImExportTasks.java b/ccm-core/src/main/java/org/libreccm/ui/admin/imexport/ImExportTasks.java new file mode 100644 index 000000000..4e425ac38 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/ui/admin/imexport/ImExportTasks.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2020 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.libreccm.ui.admin.imexport; + +import org.libreccm.imexport.Exportable; +import org.libreccm.imexport.ImportExport; + +import java.util.Collection; +import java.util.concurrent.Future; + +import javax.ejb.AsyncResult; +import javax.ejb.Asynchronous; +import javax.ejb.Stateless; +import javax.ejb.TransactionAttribute; +import javax.ejb.TransactionAttributeType; +import javax.inject.Inject; +import javax.transaction.Transactional; + +/** + * + * @author Jens Pelzetter + */ +@Stateless +public class ImExportTasks { + + @Inject + private ImportExport importExport; + + @Asynchronous + @Transactional(Transactional.TxType.REQUIRES_NEW) + @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) + public Future startExport( + final Collection entities, + final String exportName + ) { + importExport.exportEntities(entities, exportName); + return new AsyncResult<>(null); + } + + @Asynchronous + @Transactional(Transactional.TxType.REQUIRES_NEW) + @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) + public Future startImport(final String importName) { + importExport.importEntities(importName); + return new AsyncResult<>(null); + } + +} diff --git a/ccm-core/src/main/java/org/libreccm/ui/admin/imexport/ImportExportTaskManager.java b/ccm-core/src/main/java/org/libreccm/ui/admin/imexport/ImportExportTaskManager.java new file mode 100644 index 000000000..546ed1c71 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/ui/admin/imexport/ImportExportTaskManager.java @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2020 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.libreccm.ui.admin.imexport; + +import org.libreccm.imexport.Exportable; +import org.libreccm.imexport.ImportExport; + +import java.time.LocalDateTime; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.concurrent.Future; + +import javax.ejb.AsyncResult; +import javax.ejb.Asynchronous; +import javax.ejb.Schedule; +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; +import javax.inject.Named; +import javax.persistence.EntityManager; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; +import javax.transaction.Transactional; + +/** + * + * @author Jens Pelzetter + */ +@ApplicationScoped +@Named("ImportExportTaskManager") +public class ImportExportTaskManager { + + @Inject + private EntityManager entityManager; + + @Inject + private ImExportTasks imExportTasks; + + private SortedSet exportTasks; + + private SortedSet importTasks; + + public ImportExportTaskManager() { + exportTasks = new TreeSet<>( + Comparator.comparing( + ImExportTask::getStarted) + .thenComparing(ImExportTask::getName) + ); + importTasks = new TreeSet<>( + Comparator.comparing( + ImExportTask::getStarted) + .thenComparing(ImExportTask::getName) + ); + } + + public SortedSet getExportTasks() { + return Collections.unmodifiableSortedSet(exportTasks); + } + + public SortedSet getImportTasks() { + return Collections.unmodifiableSortedSet(importTasks); + } + + @Transactional(Transactional.TxType.REQUIRED) + public void exportEntities( + final Set> exportTypes, + final String exportName + ) { + final Set entities = new HashSet<>(); + for (final Class type : exportTypes) { + @SuppressWarnings("unchecked") + final Set entitiesOfType = collectEntities( + (Class) type + ); + entities.addAll(entitiesOfType); + } + + final ImExportTask task = new ImExportTask(); + task.setName(exportName); + task.setStarted(LocalDateTime.now()); + final Future status = imExportTasks.startExport( + entities, exportName + ); + task.setStatus(status); + exportTasks.add(task); + } + +// public void exportEntities( +// final Collection entities, final String exportName +// ) { +// final ImExportTask task = new ImExportTask(); +// task.setName(exportName); +// task.setStarted(LocalDate.now()); +// final Future status = startExport(entities, exportName); +// task.setStatus(status); +// exportTasks.add(task); +// } + public void importEntities(final String importName) { + final ImExportTask task = new ImExportTask(); + task.setName(importName); + task.setStarted(LocalDateTime.now()); + final Future status = imExportTasks.startImport(importName); + task.setStatus(status); + importTasks.add(task); + } + + @Schedule(hour = "*", minute = "*/5", persistent = false) + protected void removeFinishedTasks() { + exportTasks.removeIf(ImExportTask::isDone); + importTasks.removeIf(ImExportTask::isDone); + } + + public void cancelTask(final ImExportTask task) { + task.cancel(); + } + + private Set collectEntities( + final Class ofType + ) { + final CriteriaBuilder builder = entityManager.getCriteriaBuilder(); + final CriteriaQuery query = builder.createQuery(ofType); + final Root from = query.from(ofType); + + return new HashSet<>( + entityManager.createQuery( + query.select(from) + ).getResultList() + ); + } + +} diff --git a/ccm-core/src/main/resources/META-INF/resources/components/bootstrap/formCheck.xhtml b/ccm-core/src/main/resources/META-INF/resources/components/bootstrap/formCheck.xhtml index 7e4dd479e..5c1d349b3 100644 --- a/ccm-core/src/main/resources/META-INF/resources/components/bootstrap/formCheck.xhtml +++ b/ccm-core/src/main/resources/META-INF/resources/components/bootstrap/formCheck.xhtml @@ -36,7 +36,8 @@ class="form-check-input" id="#{cc.attrs.inputId}" name="#{cc.attrs.name}" - type="checkbox" /> + type="checkbox" + value="#{value}" /> diff --git a/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/imexport/export.xhtml b/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/imexport/export.xhtml index 81b18b118..d10a2a48f 100644 --- a/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/imexport/export.xhtml +++ b/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/imexport/export.xhtml @@ -26,23 +26,31 @@

#{AdminMessages['imexport.export.label']}

-
+

#{AdminMessages['imexport.export.help']}

- + + + + name="exportName" + required="treu" /> diff --git a/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/imexport/exporting.xhtml b/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/imexport/exporting.xhtml new file mode 100644 index 000000000..2b5bdc8ee --- /dev/null +++ b/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/imexport/exporting.xhtml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + +
+

#{AdminMessages['imexport.export.label']}

+ +
#{exportEntities}
+
+
+ + + + + diff --git a/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/imexport/imexport.xhtml b/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/imexport/imexport.xhtml index 848ebcebe..9f524b6e9 100644 --- a/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/imexport/imexport.xhtml +++ b/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/imexport/imexport.xhtml @@ -42,7 +42,7 @@
- +
+ +
+

#{AdminMessages['imexport.activeexports.heading']}

+ + + +

+ #{AdminMessages['imexport.activeexports.none']} +

+
+ + + + + + + + + + + + + + + + + + + + +
#{AdminMessages['imexport.activeexports.table.columns.name.heading']}#{AdminMessages['imexport.activeexports.table.columns.started.heading']}#{AdminMessages['imexport.activeexports.table.columns.status.heading']}#{AdminMessages['imexport.activeexports.table.columns.actions.heading']}
#{task.name}#{task.started} + + + #{AdminMessages['imexport.activeexports.table.columns.status.finished']} + + + #{AdminMessages['imexport.activeexports.table.columns.status.running']} + + + + + #{AdminMessages['imexport.activeexports.table.columns.actions.button_label']} + +
+
+
+
+ +
+

#{AdminMessages['imexport.activeimports.heading']}

+ + + +

+ #{AdminMessages['imexport.activeimports.none']} +

+
+ + + + + + + + + + + + + + + + + + + + +
#{AdminMessages['imexport.activeimports.table.columns.name.heading']}#{AdminMessages['imexport.activeimports.table.columns.started.heading']}#{AdminMessages['imexport.activeimports.table.columns.status.heading']}#{AdminMessages['imexport.activeimports.table.columns.actions.heading']}
#{task.name}#{task.started} + + + #{AdminMessages['imexport.activeimports.table.columns.status.finished']} + + + #{AdminMessages['imexport.activeimports.table.columns.status.running']} + + + + + #{AdminMessages['imexport.activeimports.table.columns.actions.button_label']} + +
+
+
+
diff --git a/ccm-core/src/main/resources/org/libreccm/ui/AdminBundle.properties b/ccm-core/src/main/resources/org/libreccm/ui/AdminBundle.properties index cd568dd92..2de1c0183 100644 --- a/ccm-core/src/main/resources/org/libreccm/ui/AdminBundle.properties +++ b/ccm-core/src/main/resources/org/libreccm/ui/AdminBundle.properties @@ -536,3 +536,23 @@ imexport.export.export_name.help=Name of the export archive imexport.export.export_name.label=to imexport.export.submit=Export imexport.export.cancel=Cancel +imexport.export.exportentities.help=Select the entity types to export. Additional required types will be selected automatically +imexport.export.exportentities.label=Export types +imexport.activeexports.heading=Active Exports +imexport.activeexports.table.columns.name.heading=Name +imexport.activeexports.table.columns.started.heading=Started +imexport.activeexports.table.columns.status.heading=Status +imexport.activeexports.table.columns.actions.heading=Actions +imexport.activeexports.table.columns.status.finished=Finished +imexport.activeexports.table.columns.status.running=In progress +imexport.activeexports.table.columns.actions.button_label=Cancel +imexport.activeexports.none=No active exports +imexport.activeimports.heading=Active Imports +imexport.activeimports.none=No active imports +imexport.activeimports.table.columns.name.heading=Name +imexport.activeimports.table.columns.started.heading=Started +imexport.activeimports.table.columns.status.heading=Status +imexport.activeimports.table.columns.actions.heading=Actions +imexport.activeimports.table.columns.status.finished=Finished +imexport.activeimports.table.columns.status.running=In progress +imexport.activeimports.table.columns.actions.button_label=Cancel diff --git a/ccm-core/src/main/resources/org/libreccm/ui/AdminBundle_de.properties b/ccm-core/src/main/resources/org/libreccm/ui/AdminBundle_de.properties index 6b488ba9d..79c56bf03 100644 --- a/ccm-core/src/main/resources/org/libreccm/ui/AdminBundle_de.properties +++ b/ccm-core/src/main/resources/org/libreccm/ui/AdminBundle_de.properties @@ -536,3 +536,23 @@ imexport.export.export_name.help=Name des Export Archives imexport.export.export_name.label=nach imexport.export.submit=Exportieren imexport.export.cancel=Abbrechen +imexport.export.exportentities.help=W\u00e4hlen Sie die zu exportierenden Typen aus. Weitere ben\u00f6tigte Typen werden automatisch ausgew\u00e4hlt. +imexport.export.exportentities.label=Exportiere +imexport.activeexports.heading=Aktive Exporte +imexport.activeexports.table.columns.name.heading=Name +imexport.activeexports.table.columns.started.heading=Gestartet +imexport.activeexports.table.columns.status.heading=Status +imexport.activeexports.table.columns.actions.heading=Aktionen +imexport.activeexports.table.columns.status.finished=Abgeschlossen +imexport.activeexports.table.columns.status.running=In Arbeit +imexport.activeexports.table.columns.actions.button_label=Abbrechen +imexport.activeexports.none=Keine aktiven Exporte +imexport.activeimports.heading=Aktive Importe +imexport.activeimports.none=Keine aktiven Importe +imexport.activeimports.table.columns.name.heading=Name +imexport.activeimports.table.columns.started.heading=Gestartet +imexport.activeimports.table.columns.status.heading=Status +imexport.activeimports.table.columns.actions.heading=Aktionen +imexport.activeimports.table.columns.status.finished=Abgeschlossen +imexport.activeimports.table.columns.status.running=In Arbeit +imexport.activeimports.table.columns.actions.button_label=Abbrechen