diff --git a/Kitodo-DataManagement/src/main/java/org/kitodo/data/database/beans/DataEditorSetting.java b/Kitodo-DataManagement/src/main/java/org/kitodo/data/database/beans/DataEditorSetting.java index 93d18fd5428..f1332c30079 100644 --- a/Kitodo-DataManagement/src/main/java/org/kitodo/data/database/beans/DataEditorSetting.java +++ b/Kitodo-DataManagement/src/main/java/org/kitodo/data/database/beans/DataEditorSetting.java @@ -22,8 +22,8 @@ public class DataEditorSetting extends BaseBean { @Column(name = "user_id") private int userId; - @Column(name = "task_id") - private int taskId; + @Column(name = "task_id", nullable = true) + private Integer taskId; @Column(name = "structure_width") private float structureWidth; @@ -40,6 +40,19 @@ public class DataEditorSetting extends BaseBean { public DataEditorSetting() { } + /** + * Copy constructor (without id). + * + * @param setting the data editor settings that are copied + */ + public DataEditorSetting(DataEditorSetting setting) { + setUserId(setting.getUserId()); + setTaskId(setting.getTaskId()); + setStructureWidth(setting.getStructureWidth()); + setMetadataWidth(setting.getMetadataWidth()); + setGalleryWidth(setting.getGalleryWidth()); + } + /** * Get userId. * @@ -59,20 +72,20 @@ public void setUserId(int userId) { } /** - * Get taskId. + * Get taskId. Either the id of the task or null, for a task-independent default layout. * * @return value of taskId */ - public int getTaskId() { + public Integer getTaskId() { return taskId; } /** - * Set taskId. + * Set taskId. Either the id of the task or null, for a task-independent default layout. * * @param taskId as int */ - public void setTaskId(int taskId) { + public void setTaskId(Integer taskId) { this.taskId = taskId; } diff --git a/Kitodo-DataManagement/src/main/resources/db/migration/V2_134__Allow_null_for_taskid_in_dataeditorsetting.sql b/Kitodo-DataManagement/src/main/resources/db/migration/V2_134__Allow_null_for_taskid_in_dataeditorsetting.sql new file mode 100644 index 00000000000..64496cd7986 --- /dev/null +++ b/Kitodo-DataManagement/src/main/resources/db/migration/V2_134__Allow_null_for_taskid_in_dataeditorsetting.sql @@ -0,0 +1,17 @@ +-- +-- (c) Kitodo. Key to digital objects e. V. +-- +-- This file is part of the Kitodo project. +-- +-- It is licensed under GNU General Public License version 3 or later. +-- +-- For the full copyright and license information, please read the +-- GPL3-License.txt file that was distributed with this source code. +-- + +SET SQL_SAFE_UPDATES = 0; + +-- allow null in column task_id of table dataeditor_setting to store task-independent layout +ALTER TABLE dataeditor_setting MODIFY COLUMN task_id INT(11) NULL; + +SET SQL_SAFE_UPDATES = 1; \ No newline at end of file diff --git a/Kitodo/src/main/java/org/kitodo/production/forms/dataeditor/DataEditorForm.java b/Kitodo/src/main/java/org/kitodo/production/forms/dataeditor/DataEditorForm.java index 66e27669f08..03792b11c04 100644 --- a/Kitodo/src/main/java/org/kitodo/production/forms/dataeditor/DataEditorForm.java +++ b/Kitodo/src/main/java/org/kitodo/production/forms/dataeditor/DataEditorForm.java @@ -55,6 +55,7 @@ import org.kitodo.data.database.beans.DataEditorSetting; import org.kitodo.data.database.beans.Process; import org.kitodo.data.database.beans.Project; +import org.kitodo.data.database.beans.Task; import org.kitodo.data.database.beans.User; import org.kitodo.data.database.exceptions.DAOException; import org.kitodo.exceptions.InvalidImagesException; @@ -184,12 +185,12 @@ public class DataEditorForm implements MetadataTreeTableInterface, RulesetSetupI private List> selectedMedia; /** - * The id of the template's task corresponding to the current task that is under edit. + * The template task corresponding to the current task that is under edit. * This is used for saving and loading the metadata editor settings. * The current task, the corresponding template task id and the settings are only available * if the user opened the editor from a task. */ - private int templateTaskId; + private Task templateTask; private DataEditorSetting dataEditorSetting; @@ -271,9 +272,7 @@ public void open(String processID, String referringView, String taskId) { this.currentChildren.addAll(process.getChildren()); this.user = ServiceManager.getUserService().getCurrentUser(); this.checkProjectFolderConfiguration(); - if (StringUtils.isNotBlank(taskId) && StringUtils.isNumeric(taskId)) { - this.templateTaskId = Integer.parseInt(taskId); - } + this.loadTemplateTask(taskId); this.loadDataEditorSettings(); errorMessage = ""; @@ -313,10 +312,15 @@ public void open(String processID, String referringView, String taskId) { } private void showDataEditorSettingsLoadedMessage() throws DAOException { - String task = ServiceManager.getTaskService().getById(templateTaskId).getTitle(); Locale locale = LocaleHelper.getCurrentLocale(); String title = Helper.getString(locale, "dataEditor.layoutLoadedSuccessfullyTitle"); - String text = MessageFormat.format(Helper.getString(locale, "dataEditor.layoutLoadedSuccessfullyText"), task); + String text = Helper.getString(locale, "dataEditor.layoutLoadedSuccessfullyDefaultText"); + if (Objects.nonNull(this.templateTask) && Objects.nonNull(dataEditorSetting) + && templateTask.getId().equals(dataEditorSetting.getTaskId())) { + text = MessageFormat.format( + Helper.getString(locale, "dataEditor.layoutLoadedSuccessfullyForTaskText"), this.templateTask.getTitle() + ); + } String script = GROWL_MESSAGE.replace("SUMMARY", title).replace("DETAIL", text) .replace("SEVERITY", "info"); PrimeFaces.current().executeScript("PF('notifications').removeAll();"); @@ -337,17 +341,47 @@ private void checkProjectFolderConfiguration() { } } - private void loadDataEditorSettings() { - if (templateTaskId > 0) { - dataEditorSetting = ServiceManager.getDataEditorSettingService().loadDataEditorSetting(user.getId(), - templateTaskId); - if (Objects.isNull(dataEditorSetting)) { - dataEditorSetting = new DataEditorSetting(); - dataEditorSetting.setUserId(user.getId()); - dataEditorSetting.setTaskId(templateTaskId); + /** + * Load template task from database. + * + * @param taskId the id of the template task + * @throws DAOException if loading fails + */ + private void loadTemplateTask(String taskId) throws DAOException { + if (StringUtils.isNotBlank(taskId) && StringUtils.isNumeric(taskId)) { + try { + int templateTaskId = Integer.parseInt(taskId); + if (templateTaskId > 0) { + this.templateTask = ServiceManager.getTaskService().getById(templateTaskId); + } + } catch (NumberFormatException e) { + logger.warn("view parameter 'templateTaskId' is not a valid integer"); } - } else { - dataEditorSetting = null; + } + } + + /** + * Load data editor settings (width of metadata editor columns) from database. Either load task-specific + * configuration (if it exists) or default configuration (if it exists) or initialize new empty data editor setting. + */ + private void loadDataEditorSettings() { + // use template task id if it exists, otherwise use null for task-independent layout + Integer taskId = Objects.nonNull(this.templateTask) ? this.templateTask.getId() : null; + int userId = user.getId(); + + // try to load data editor setting from database + dataEditorSetting = ServiceManager.getDataEditorSettingService().loadDataEditorSetting(userId, taskId); + + // try to load task-independent data editor setting from database + if (Objects.isNull(dataEditorSetting)) { + dataEditorSetting = ServiceManager.getDataEditorSettingService().loadDataEditorSetting(userId, null); + } + + // initialize empty data editor setting if none were previously saved by the user + if (Objects.isNull(dataEditorSetting)) { + dataEditorSetting = new DataEditorSetting(); + dataEditorSetting.setUserId(userId); + dataEditorSetting.setTaskId(taskId); } } @@ -1025,8 +1059,8 @@ public String getShortcuts() { * * @return value of templateTaskId */ - public int getTemplateTaskId() { - return templateTaskId; + public Task getTemplateTask() { + return templateTask; } /** @@ -1066,19 +1100,43 @@ public void updateNumberOfScans() { /** - * Save current metadata editor layout. + * Save current metadata editor layout. Either save it as task-specific layout (if editor was opened from a task) + * or as task-independent layout (otherwise). */ public void saveDataEditorSetting() { - if (Objects.nonNull(dataEditorSetting) && dataEditorSetting.getTaskId() > 0) { + if (Objects.nonNull(dataEditorSetting)) { + if (Objects.nonNull(templateTask) && !templateTask.getId().equals(dataEditorSetting.getTaskId())) { + // create a copy of the task-independent configuration + // in case the user wants to save it as task-specific config + dataEditorSetting = new DataEditorSetting(dataEditorSetting); + dataEditorSetting.setTaskId(templateTask.getId()); + } try { ServiceManager.getDataEditorSettingService().saveToDatabase(dataEditorSetting); PrimeFaces.current().executeScript("PF('dataEditorSavingResultDialog').show();"); } catch (DAOException e) { - Helper.setErrorMessage("errorSaving", new Object[] {ObjectType.USER.getTranslationSingular() }, logger, e); + Helper.setErrorMessage("errorSaving", new Object[] {ObjectType.DATAEDITORSETTING.getTranslationSingular() }, logger, e); } } else { - logger.error("Could not save DataEditorSettings with userId {} and templateTaskId {}", user.getId(), - templateTaskId); + // should never happen any more, since layout settings are always created (even outside of task context) + int taskId = Objects.nonNull(this.templateTask) ? this.templateTask.getId() : 0; + int userId = user.getId(); + logger.error("Could not save DataEditorSettings with userId {} and templateTaskId {}", userId, taskId); + } + } + + /** + * Delete current metadata editor layout. + */ + public void deleteDataEditorSetting() { + if (Objects.nonNull(dataEditorSetting)) { + try { + ServiceManager.getDataEditorSettingService().removeFromDatabase(dataEditorSetting); + this.loadDataEditorSettings(); + PrimeFaces.current().executeScript("PF('dataEditorDeletedResultDialog').show();"); + } catch (DAOException e) { + Helper.setErrorMessage("errorDeleting", new Object[] { ObjectType.DATAEDITORSETTING.getTranslationSingular() }, logger, e); + } } } diff --git a/Kitodo/src/main/java/org/kitodo/production/services/data/DataEditorSettingService.java b/Kitodo/src/main/java/org/kitodo/production/services/data/DataEditorSettingService.java index 706a1134e31..926aeef477f 100644 --- a/Kitodo/src/main/java/org/kitodo/production/services/data/DataEditorSettingService.java +++ b/Kitodo/src/main/java/org/kitodo/production/services/data/DataEditorSettingService.java @@ -89,11 +89,11 @@ public boolean areDataEditorSettingsDefinedForWorkflow(Workflow workflow) { /** * Delete data editor settings identified by task id. - * @param taskId ID of the associated task + * @param taskId ID of the associated task (or null for task-independent default layout) * @throws DAOException if data editor setting could not be deleted from database * */ - public void removeFromDatabaseByTaskId(int taskId) throws DAOException { + public void removeFromDatabaseByTaskId(Integer taskId) throws DAOException { List dataEditorSettings = getByTaskId(taskId); for (DataEditorSetting dataEditorSetting: dataEditorSettings) { dao.remove(dataEditorSetting.getId()); @@ -102,30 +102,41 @@ public void removeFromDatabaseByTaskId(int taskId) throws DAOException { /** * Retrieve data editor settings by task id. - * @param taskId ID of the task + * @param taskId ID of the task (or null for task-independent default layout) * * @return List of DataEditorSetting objects */ - public List getByTaskId(int taskId) { + public List getByTaskId(Integer taskId) { Map parameterMap = new HashMap<>(); - parameterMap.put("taskId", taskId); - return getByQuery("FROM DataEditorSetting WHERE task_id = :taskId ORDER BY id ASC", parameterMap); + if (Objects.nonNull(taskId)) { + parameterMap.put("taskId", taskId); + return getByQuery("FROM DataEditorSetting WHERE task_id = :taskId ORDER BY id ASC", parameterMap); + } + return getByQuery("FROM DataEditorSetting WHERE task_id is NULL ORDER BY id ASC", parameterMap); } - private List getByUserAndTask(int userId, int taskId) { + private List getByUserAndTask(int userId, Integer taskId) { Map parameterMap = new HashMap<>(); parameterMap.put("userId", userId); - parameterMap.put("taskId", taskId); - return getByQuery("FROM DataEditorSetting WHERE user_id = :userId AND task_id = :taskId ORDER BY id ASC", parameterMap); + if (Objects.nonNull(taskId)) { + parameterMap.put("taskId", taskId); + return getByQuery( + "FROM DataEditorSetting WHERE user_id = :userId AND task_id = :taskId ORDER BY id ASC", parameterMap + ); + } + return getByQuery( + "FROM DataEditorSetting WHERE user_id = :userId AND task_id IS NULL ORDER BY id ASC", parameterMap + ); } /** * Load DataEditorSetting from database or return null if no entry matches the specified ids. * @param userId id of the user - * @param taskId id of the corresponding template task for the task that is currently edited + * @param taskId id of the corresponding template task for the task that is currently edited + * (or null for task-independent default layout) * @return settings for the data editor */ - public DataEditorSetting loadDataEditorSetting(int userId, int taskId) { + public DataEditorSetting loadDataEditorSetting(int userId, Integer taskId) { List results = getByUserAndTask(userId, taskId); if (Objects.nonNull(results) && !results.isEmpty()) { return results.get(0); diff --git a/Kitodo/src/main/resources/messages/messages_de.properties b/Kitodo/src/main/resources/messages/messages_de.properties index 1dd2fbc31c8..1a63cf0897f 100644 --- a/Kitodo/src/main/resources/messages/messages_de.properties +++ b/Kitodo/src/main/resources/messages/messages_de.properties @@ -281,7 +281,6 @@ dataEditor.addMetadata.newMetadata=Neue Metadaten hinzuf\u00FCgen dataEditor.addMetadata.noMetadataAddable=Zu dem ausgew\u00E4hlten Strukturelement k\u00F6nnen keine weiteren Metadaten hinzugef\u00FCgt werden! dataEditor.addMetadata.noMetadataAddableToGroup=Zu dieser Gruppe k\u00F6nnen keine weiteren Metadaten hinzugef\u00FCgt werden! dataEditor.addMetadata.toGroup=Metadaten zu Gruppe hinzuf\u00FCgen -dataEditor.cannotSaveLayout=Layout kann nur gespeichert werden, wenn der Editor \u00FCber eine Aufgabe ge\u00F6ffnet wird. dataEditor.childNotContainedError=Elternelement von Struktur {0} enth\u00E4lt die Struktur nicht! dataEditor.comment.correctionWorkflowAlreadyActive=Dieser Vorgang befindet sich bereits in einem Korrektur-Workflow dataEditor.comment.firstTaskInWorkflow=Sie k\u00F6nnen f\u00FCr diesen Vorgang derzeit keinen Korrekturkommentar verfassen, da noch keine seiner Aufgaben abgeschlossen sind. @@ -309,7 +308,6 @@ dataEditor.galleryStructuredView=Strukturierte Ansicht dataEditor.galleryDetailView=Detailansicht dataEditor.invalidMetadataValue=\u201E{0}\u201C kann nicht gespeichert werden: Der Wert ist ung\u00FCltig. Wert: {1} dataEditor.invalidStructureField=\u201E{0}\u201C kann nicht gespeichert werden: Es gibt kein solches Feld ({1}). -dataEditor.saveLayout=Aktuelle Spaltenaufteilung als Standard f\u00FCr diese Aufgabe speichern dataEditor.mediaNotFound=Es wurden keine Medien gefunden, aber mindestens eine Dateireferenz ist vorhanden. Die automatische Entfernung der fehlenden Medien aus dem Werkst\u00FCck wurde \u00FCbersprungen. dataEditor.multipleMetadataTasksText=Sie haben mehrere Aufgaben zum Editieren von Metadaten in Bearbeitung. Bitte w\u00E4hlen Sie eine dieser Aufgaben aus! dataEditor.noParentsError=Elternelement von {0} konnte nicht gefunden werden! @@ -322,10 +320,19 @@ dataEditor.position.beforeCurrentElement=Vor dem aktuellen Element dataEditor.position.currentPosition=Aktuelle Position dataEditor.removeElement.noConsecutivePagesSelected=Strukturelemente k\u00F6nnen nur aus fortlaufenden Medien erstellt werden! dataEditor.selectMetadataTask=Aufgabe w\u00E4hlen +dataEditor.layoutDeletedSuccessfullyTitle=Metadaten-Editor-Layout gelöscht +dataEditor.layoutDeletedSuccessfullyText=Die Standard-Spalteneinstellungen wurden erfolgreich gelöscht dataEditor.layoutLoadedSuccessfullyTitle=Metadaten-Editor-Layout geladen -dataEditor.layoutLoadedSuccessfullyText=Spalteneinstellungen f\u00FCr Aufgabe "{0}" erfolgreich geladen +dataEditor.layoutLoadedSuccessfullyDefaultText=Standard-Spalteneinstellungen erfolgreich geladen +dataEditor.layoutLoadedSuccessfullyForTaskText=Standard-Spalteneinstellungen f\u00FCr Aufgabe "{0}" erfolgreich geladen +dataEditor.layoutMenuActiveText=aktiv +dataEditor.layoutMenuButtonTitle=Menu zum Speichern des Layout (Spaltenaufteilung) öffnen +dataEditor.layoutMenuDeleteTitle=Gespeicherte Spaltenaufteilung löschen +dataEditor.layoutMenuSaveDefaultText=Spaltenaufteilung als Standard speichern +dataEditor.layoutMenuSaveForTaskText=Spaltenaufteilung für Aufgabentyp speichern dataEditor.layoutSavedSuccessfullyTitle=Aktuelle Spaltenaufteilung erfolgreich gespeichert -dataEditor.layoutSavedSuccessfullyText=Ihre aktuellen Metadaten-Editor-Einstellungen wurden erfolgreich gespeichert! Sie werden f\u00FCr alle zuk\u00FCnftigen Aufgaben dieses Typs wiederverwendet. +dataEditor.layoutSavedSuccessfullyDefaultText=Ihre Einstellungen wurden erfolgreich als Standard-Einstellungen gespeichert! Beim n\u00E4chsten \u00D6ffnen des Matadaten-Editors wird die Breite der drei Spalten (Strukturdaten, Metadaten und Galerie) entsprechend ihrer aktuellen Einstellung geladen. +dataEditor.layoutSavedSuccessfullyForTaskText=Ihre Einstellungen wurden erfolgreich f\u00FCr alle zuk\u00FCnftigen Aufgaben des Typs "{0}" gespeichert! Beim n\u00E4chsten \u00D6ffnen des Matadaten-Editors f\u00FCr eine Aufgabe des gleichen Typs wird die Breite der drei Spalten (Strukturdaten, Metadaten und Galerie) entsprechend ihrer aktuellen Einstellung geladen. dataEditor.renamingMediaComplete=Das Umbenennen der Medien ist abgeschlossen dataEditor.renamingMediaError=Beim Umbenennen der Medien ist ein Fehler aufgetreten dataEditor.renamingMediaText={0} Mediendateien in {1} Ordnern wurden umbenannt. Bitte Speichern Sie den Vorgang. Andernfalls werden die Dateiumbennungen beim Schlie\u00DFen des Metadateneditors verworfen. diff --git a/Kitodo/src/main/resources/messages/messages_en.properties b/Kitodo/src/main/resources/messages/messages_en.properties index ffaabc80ab9..bce67df6b2e 100644 --- a/Kitodo/src/main/resources/messages/messages_en.properties +++ b/Kitodo/src/main/resources/messages/messages_en.properties @@ -281,7 +281,6 @@ dataEditor.addMetadata.newMetadata=Add new metadata dataEditor.addMetadata.noMetadataAddable=No additional metadata can be added to this structure! dataEditor.addMetadata.noMetadataAddableToGroup=No further metadata can be added to this group dataEditor.addMetadata.toGroup=Add metadata to group -dataEditor.cannotSaveLayout=Layout can only be saved, when the editor is accessed from a task. dataEditor.childNotContainedError=Parents of structure {0} do not contain structure! dataEditor.comment.correctionWorkflowAlreadyActive=This process is already in a correction workflow state dataEditor.comment.firstTaskInWorkflow=Correction comments cannot be created for the first task in a workflow. @@ -309,7 +308,6 @@ dataEditor.galleryStructuredView=Structured view dataEditor.galleryDetailView=Detail view dataEditor.invalidMetadataValue=Cannot store "{0}": The value is invalid. Value: {1} dataEditor.invalidStructureField=Cannot save "{0}": There is no such field ({1}). -dataEditor.saveLayout=Save current layout as preset for this task dataEditor.mediaNotFound=No media found, but at least one file reference is present. The automatic removal of missing media from the workpiece was skipped. dataEditor.multipleMetadataTasksText=There are multiple metadata editing tasks assigned to you for the current process. Please select the task you want to work on! dataEditor.noParentsError=No parents of structure {0} found! @@ -322,10 +320,19 @@ dataEditor.position.beforeCurrentElement=Before current element dataEditor.position.currentPosition=Current position dataEditor.removeElement.noConsecutivePagesSelected=Select consecutive pages to create structure elements! dataEditor.selectMetadataTask=Select task +dataEditor.layoutDeletedSuccessfullyTitle=Custom layout deleted +dataEditor.layoutDeletedSuccessfullyText=Default column configuration deleted successfully dataEditor.layoutLoadedSuccessfullyTitle=Custom layout loaded -dataEditor.layoutLoadedSuccessfullyText=Custom column settings for task "{0}" loaded successfully +dataEditor.layoutLoadedSuccessfullyDefaultText=Default column configuration loaded successfully +dataEditor.layoutLoadedSuccessfullyForTaskText=Default column configuration for task "{0}" loaded successfully +dataEditor.layoutMenuActiveText=active +dataEditor.layoutMenuButtonTitle=Open menu to save default layout (column configuration) +dataEditor.layoutMenuDeleteTitle=Delete default layout +dataEditor.layoutMenuSaveDefaultText=Save default layout +dataEditor.layoutMenuSaveForTaskText=Save task-specific layout dataEditor.layoutSavedSuccessfullyTitle=Current layout successfully saved -dataEditor.layoutSavedSuccessfullyText=Your current editor settings have been saved successfully and will be applied to all future tasks of the same type. +dataEditor.layoutSavedSuccessfullyDefaultText=Your current editor column configuration has been successfully saved as default configuration. The next time you open the editor, the width of all three columns (structure data, metadata, gallery) will be loaded according to your current configuration. +dataEditor.layoutSavedSuccessfullyForTaskText=Your current editor column configuration has been successfully saved as default configuration for the task type "{0}". The next time you open the editor for the same task type, the width of all three columns (structure data, metadata, gallery) will be loaded according to your current configuration. dataEditor.renamingMediaComplete=Finished renaming media dataEditor.renamingMediaError=An error occurred while renaming media files dataEditor.renamingMediaText={0} media files in {1} folders have been renamed. Please click the 'Save' button to persist changes to the filenames. Otherwise the renaming will be reverted upon closing the editor. diff --git a/Kitodo/src/main/resources/messages/messages_es.properties b/Kitodo/src/main/resources/messages/messages_es.properties index 32deac1a1b6..ee94e3f97fb 100644 --- a/Kitodo/src/main/resources/messages/messages_es.properties +++ b/Kitodo/src/main/resources/messages/messages_es.properties @@ -281,7 +281,6 @@ dataEditor.addMetadata.newMetadata=Añadir nuevos metadatos dataEditor.addMetadata.noMetadataAddable=No se pueden añadir más metadatos al elemento de estructura seleccionado. dataEditor.addMetadata.noMetadataAddableToGroup=No se pueden añadir más metadatos a este grupo. dataEditor.addMetadata.toGroup=Añadir metadatos al grupo -dataEditor.cannotSaveLayout=El diseño sólo se puede guardar si el editor se abre a través de una tarea. dataEditor.childNotContainedError=El elemento padre de la estructura {0} no contiene la estructura. dataEditor.comment.correctionWorkflowAlreadyActive=Esta tarea ya se encuentra en un flujo de trabajo de corrección. dataEditor.comment.firstTaskInWorkflow=No puede escribir un comentario de corrección para esta tarea en este momento porque ninguna de sus tareas se ha completado todavía. @@ -309,7 +308,6 @@ dataEditor.galleryStructuredView=Vista estructurada dataEditor.galleryDetailView=Vista detallada dataEditor.invalidMetadataValue=„{0}“ no se puede guardar: El valor no es válido. Valor: {1} dataEditor.invalidStructureField=„{0}“ no se puede guardar: No existe tal campo ({1}). -dataEditor.saveLayout=Guarda el diseño de columna actual como el predeterminado para esta tarea. dataEditor.mediaNotFound=No se encontraron los medios, pero al menos un archivo de referencia está presente. La eleminación de los medios faltantes de la pieza de trabajo fue omitida. dataEditor.multipleMetadataTasksText=Tiene varias tareas de edición de metadatos en curso. Por favor, seleccione una de estas tareas. dataEditor.noParentsError=No se ha encontrado el elemento padre de {0}. @@ -322,10 +320,29 @@ dataEditor.position.beforeCurrentElement=Antes del elemento actual dataEditor.position.currentPosition=Posición actual dataEditor.removeElement.noConsecutivePagesSelected=Los elementos estructurales sólo pueden crearse a partir de medios continuos. dataEditor.selectMetadataTask=Seleccionar la tarea +# please check google translation below and remove comment if translation is acceptable +dataEditor.layoutDeletedSuccessfullyTitle=Diseño personalizado eliminado +# please check google translation below and remove comment if translation is acceptable +dataEditor.layoutDeletedSuccessfullyText=La configuración de columna predeterminada se eliminó correctamente dataEditor.layoutLoadedSuccessfullyTitle=¡La plantilla personificada está cargada! -dataEditor.layoutLoadedSuccessfullyText=La configuración de la columna personalizada para la tarea "{0}" se ha cargado correctamente. +# please check google translation below and remove comment if translation is acceptable +dataEditor.layoutLoadedSuccessfullyDefaultText=La configuración de columna personalizada se cargó correctamente +dataEditor.layoutLoadedSuccessfullyForTaskText=La configuración de la columna personalizada para la tarea "{0}" se ha cargado correctamente. +# please check google translation below and remove comment if translation is acceptable +dataEditor.layoutMenuActiveText=activa +# please check google translation below and remove comment if translation is acceptable +dataEditor.layoutMenuButtonTitle=Abrir menú para guardar el diseño predeterminado (configuración de columna) +# please check google translation below and remove comment if translation is acceptable +dataEditor.layoutMenuDeleteTitle=Eliminar diseño predeterminado +# please check google translation below and remove comment if translation is acceptable +dataEditor.layoutMenuSaveDefaultText=Guardar diseño predeterminado +# please check google translation below and remove comment if translation is acceptable +dataEditor.layoutMenuSaveForTaskText=Guardar diseño específico de la tarea dataEditor.layoutSavedSuccessfullyTitle=La plantilla actual se guardó correctamente -dataEditor.layoutSavedSuccessfullyText=Su configuración actual del editor ha sido guardada con éxito y será aplicadad a todas las tareas futuras del mismo tipo. +# please check google translation below and remove comment if translation is acceptable +dataEditor.layoutSavedSuccessfullyDefaultText=La configuración actual de la columna del editor se ha guardado correctamente como predeterminada. La próxima vez que abra el editor, el ancho de las tres columnas (datos de estructura, metadatos, galería) se cargará de acuerdo con su configuración actual. +# please check google translation below and remove comment if translation is acceptable +dataEditor.layoutSavedSuccessfullyForTaskText=La configuración actual de la columna del editor se ha guardado correctamente como predeterminada para el tipo de tarea "{0}". La próxima vez que abra el editor para el mismo tipo de tarea, el ancho de las tres columnas (datos de estructura, metadatos, galería) se cargará de acuerdo con su configuración actual. dataEditor.renamingMediaComplete=El cambio de nombre de los medios ha finalizado dataEditor.renamingMediaError=Se produjo un error al cambiar el nombre de los archivos multimedia dataEditor.renamingMediaText=Se ha cambiado el nombre de {0} archivos de medios en {1} carpeta. Por favor, haga clic en el botón 'Guardar' para mantener los cambios en los nombres de archivo. De lo contrario, el cambio de nombre se revertirá al cerrar el editor. diff --git a/Kitodo/src/main/webapp/WEB-INF/resources/css/kitodo.css b/Kitodo/src/main/webapp/WEB-INF/resources/css/kitodo.css index 0af10140564..d03b1e14ae7 100644 --- a/Kitodo/src/main/webapp/WEB-INF/resources/css/kitodo.css +++ b/Kitodo/src/main/webapp/WEB-INF/resources/css/kitodo.css @@ -2194,10 +2194,6 @@ Metadata Editor pointer-events: all; } -#metadataEditorLayoutForm { - margin: 0; -} - #metadataEditorHeader .ui-panel, #metadataEditorHeader .ui-panel-content { padding: 0; @@ -2798,6 +2794,30 @@ Column content padding: 0.5em 0.25em; } +#metadataEditorLayoutForm ul { + list-style: none; + margin: 0.25em 0; +} + +#metadataEditorLayoutForm ul li { + padding: 0.25em; + display: flex; + justify-content: space-between; + align-items: center; +} + +#metadataEditorLayoutForm i.fa { + margin-right: 0.5em; +} + +#metadataEditorLayoutForm .ui-commandlink { + margin-right: 1em; +} + +#metadataEditorLayoutForm a, #metadataEditorLayoutForm a:hover { + text-decoration: none; +} + #commentsPanel { margin-top: 5px; height: 100%; diff --git a/Kitodo/src/main/webapp/WEB-INF/templates/includes/metadataEditor/dialogs/dataEditorSettingDeletedResult.xhtml b/Kitodo/src/main/webapp/WEB-INF/templates/includes/metadataEditor/dialogs/dataEditorSettingDeletedResult.xhtml new file mode 100644 index 00000000000..1715d244115 --- /dev/null +++ b/Kitodo/src/main/webapp/WEB-INF/templates/includes/metadataEditor/dialogs/dataEditorSettingDeletedResult.xhtml @@ -0,0 +1,52 @@ + + + + + + + +

#{msgs['dataEditor.layoutDeletedSuccessfullyTitle']}

+ +
+ +
+
+ + + + +
+
+
+
+
diff --git a/Kitodo/src/main/webapp/WEB-INF/templates/includes/metadataEditor/dialogs/dataEditorSettingMenu.xhtml b/Kitodo/src/main/webapp/WEB-INF/templates/includes/metadataEditor/dialogs/dataEditorSettingMenu.xhtml new file mode 100644 index 00000000000..7c6d818f266 --- /dev/null +++ b/Kitodo/src/main/webapp/WEB-INF/templates/includes/metadataEditor/dialogs/dataEditorSettingMenu.xhtml @@ -0,0 +1,83 @@ + + + + + + +
    +
  • + + + + + + +
  • +
  • + + + + + + +
  • +
+ + + +
+
+
+ + + + diff --git a/Kitodo/src/main/webapp/WEB-INF/templates/includes/metadataEditor/dialogs/dataEditorSettingSavingResult.xhtml b/Kitodo/src/main/webapp/WEB-INF/templates/includes/metadataEditor/dialogs/dataEditorSettingSavingResult.xhtml index 1207d5c27ff..303ce9f24d8 100644 --- a/Kitodo/src/main/webapp/WEB-INF/templates/includes/metadataEditor/dialogs/dataEditorSettingSavingResult.xhtml +++ b/Kitodo/src/main/webapp/WEB-INF/templates/includes/metadataEditor/dialogs/dataEditorSettingSavingResult.xhtml @@ -13,6 +13,7 @@ @@ -30,7 +31,14 @@
- + + + + + + + +
diff --git a/Kitodo/src/main/webapp/WEB-INF/templates/includes/metadataEditor/header.xhtml b/Kitodo/src/main/webapp/WEB-INF/templates/includes/metadataEditor/header.xhtml index 6c2afa2a238..1ff9a1c19dc 100644 --- a/Kitodo/src/main/webapp/WEB-INF/templates/includes/metadataEditor/header.xhtml +++ b/Kitodo/src/main/webapp/WEB-INF/templates/includes/metadataEditor/header.xhtml @@ -34,20 +34,14 @@ value="(#{DataEditorForm.numberOfScans} #{DataEditorForm.numberOfScans eq 1 ? msgs.medium : msgs.media})"/> - - - - - + + + + + + diff --git a/Kitodo/src/test/java/org/kitodo/selenium/MetadataST.java b/Kitodo/src/test/java/org/kitodo/selenium/MetadataST.java index 031fc461cb4..ec9496214fd 100644 --- a/Kitodo/src/test/java/org/kitodo/selenium/MetadataST.java +++ b/Kitodo/src/test/java/org/kitodo/selenium/MetadataST.java @@ -14,6 +14,7 @@ import static org.awaitility.Awaitility.await; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; @@ -23,6 +24,7 @@ import java.util.LinkedList; import java.util.List; import java.util.concurrent.TimeUnit; +import java.util.function.Function; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; @@ -330,6 +332,54 @@ public void createStructureElementTest() throws Exception { assertEquals(structureType, firstChild.getText(), "Added structure element has wrong type!"); } + /** + * Tests that column layout can be saved to database and is loaded into hidden form inputs. + * Does not test whether column layout is actually applied via Javascript (see resize.js). + */ + @Test + public void saveLayoutTest() throws Exception { + login("kowal"); + + Pages.getProcessesPage().goTo().editMetadata(MockDatabase.MEDIA_RENAMING_TEST_PROCESS_TITLE); + + String structureWithId = "metadataEditorLayoutForm:structureWidth"; + String metadataWidthId = "metadataEditorLayoutForm:metadataWidth"; + String galleryWithId = "metadataEditorLayoutForm:galleryWidth"; + + Function getValue = + (id) -> Browser.getDriver().findElement(By.id(id)).getAttribute("value"); + + // by default, layout settings are all 0 + assertEquals("0.0", getValue.apply(structureWithId)); + assertEquals("0.0", getValue.apply(metadataWidthId)); + assertEquals("0.0", getValue.apply(galleryWithId)); + + // open layout menu + Browser.getDriver().findElement(By.id("metadataEditorLayoutButtonForm:open")).click(); + await().ignoreExceptions().pollDelay(100, TimeUnit.MILLISECONDS).atMost(5, TimeUnit.SECONDS) + .until(Browser.getDriver().findElement(By.id("metadataEditorLayoutForm:saveDefault"))::isDisplayed); + // save layout + Browser.getDriver().findElement(By.id("metadataEditorLayoutForm:saveDefault")).click(); + + // wait until success message is shown + await().ignoreExceptions().pollDelay(100, TimeUnit.MILLISECONDS).atMost(3, TimeUnit.SECONDS) + .until(Browser.getDriver().findElement(By.id("dataEditorSavingResultDialog_content"))::isDisplayed); + + // confirm success message + Browser.getDriver().findElement(By.id("dataEditorSavingResultForm:reload")).click(); + + // close metadata editor, wait until closed, and re-open + Pages.getMetadataEditorPage().closeEditor(); + await().ignoreExceptions().pollDelay(100, TimeUnit.MILLISECONDS).atMost(3, TimeUnit.SECONDS) + .until(() -> Pages.getProcessesPage().isAt()); + Pages.getProcessesPage().goTo().editMetadata(MockDatabase.MEDIA_RENAMING_TEST_PROCESS_TITLE); + + // verify that layout was saved + assertNotEquals("0.0", getValue.apply(structureWithId)); + assertNotEquals("0.0", getValue.apply(metadataWidthId)); + assertNotEquals("0.0", getValue.apply(galleryWithId)); + } + /** * Verifies that turning the "show physical page number below thumbnail switch" on in the user settings * results in thumbnail banner being displayed in the gallery of the metadata editor.