diff --git a/Kitodo-DataManagement/src/main/resources/db/migration/V2_125__Add_authority_to_broadcast_messages.sql b/Kitodo-DataManagement/src/main/resources/db/migration/V2_125__Add_authority_to_broadcast_messages.sql new file mode 100644 index 00000000000..bedb3be9e38 --- /dev/null +++ b/Kitodo-DataManagement/src/main/resources/db/migration/V2_125__Add_authority_to_broadcast_messages.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. +-- + +-- Insert authority to broadcast messages + +INSERT IGNORE INTO authority (title) VALUES ('broadcastMessage_globalAssignable'); + +INSERT IGNORE INTO role_x_authority (role_id, authority_id) +SELECT (SELECT id FROM role WHERE title = 'Administration'), id FROM authority WHERE title = 'broadcastMessage_globalAssignable'; diff --git a/Kitodo/src/main/java/org/kitodo/production/channel/SystemMessageChannel.java b/Kitodo/src/main/java/org/kitodo/production/channel/SystemMessageChannel.java new file mode 100644 index 00000000000..eff669ab637 --- /dev/null +++ b/Kitodo/src/main/java/org/kitodo/production/channel/SystemMessageChannel.java @@ -0,0 +1,185 @@ +/* + * (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. + */ + +package org.kitodo.production.channel; + +import java.util.HashMap; +import java.util.Set; + +import javax.enterprise.context.ApplicationScoped; +import javax.faces.push.Push; +import javax.faces.push.PushContext; +import javax.inject.Inject; +import javax.inject.Named; + +import org.kitodo.data.database.beans.User; +import org.kitodo.production.security.SecuritySession; +import org.kitodo.production.services.ServiceManager; + +@Named("SystemMessageChannel") +@ApplicationScoped +public class SystemMessageChannel { + + @Inject + @Push + PushContext messageChannel; + + private static final String SHOW_MESSAGE = "showMessage"; + private static final String UPDATE_USER_TABLE = "updateUserTable"; + + private String userName = ""; + private String message = ""; + private HashMap currentUsers; + + private String staticSystemMessage = ""; + private Boolean showSystemMessage = false; + + /** + * Inform connected websocket clients to show message. + */ + public void showMessage() { + messageChannel.send(SHOW_MESSAGE); + } + + /** + * Inform connected websocket clients to update user table. + */ + public void updateUserTable() { + messageChannel.send(UPDATE_USER_TABLE); + } + + /** + * Set message String. + * + * @param messageText message String + */ + public void setMessage(String messageText) { + this.message = messageText; + } + + /** + * Get message String. + * + * @return message String + */ + public String getMessage() { + return this.message; + } + + /** + * Acknowledge system message. + * + * @param user User that acknowledges system message + */ + public void acknowledge(User user) { + this.currentUsers.put(user.getLogin(), true); + this.updateUserTable(); + } + + /** + * Load list of current users. + */ + public void loadCurrentUsers() { + this.currentUsers = new HashMap<>(); + for (SecuritySession session : ServiceManager.getSessionService().getActiveSessions()) { + this.currentUsers.put(session.getUserName(), null); + } + } + + /** + * Reset status of current users. + */ + public void resetCurrentUsersStatus() { + this.currentUsers.replaceAll((n, v) -> false); + } + + /** + * Get list of current users. + * + * @return list of current users + */ + public Set getCurrentUsers() { + return this.currentUsers.keySet(); + } + + /** + * Return whether User with user name 'userName' acknowledged system message or not. + * + * @param userName user name of user to check + * @return whether user acknowledged system message or not + */ + public Boolean acknowledged(String userName) { + return this.currentUsers.get(userName); + } + + /** + * Get user name of broadcaster. + * + * @return user name + */ + public String getUserName() { + return this.userName; + } + + /** + * Set user name of broadcaster. + * + * @param name user name + */ + public void setUserName(String name) { + this.userName = name; + } + + /** + * Send message String to connected clients. + */ + public void sendMessage() { + this.resetCurrentUsersStatus(); + this.showMessage(); + } + + /** + * Get staticSystemMessage. + * + * @return value of staticSystemMessage + */ + public String getStaticSystemMessage() { + return staticSystemMessage; + } + + /** + * Set staticSystemMessage. + * + * @param staticSystemMessage as java.lang.String + */ + public void setStaticSystemMessage(String staticSystemMessage) { + this.staticSystemMessage = staticSystemMessage; + } + + /** + * Get showSystemMessage. + * + * @return value of showSystemMessage + */ + public boolean isShowSystemMessage() { + return showSystemMessage; + } + + /** + * Set showSystemMessage. + * + * @param showSystemMessage as boolean + */ + public void setShowSystemMessage(boolean showSystemMessage) { + this.showSystemMessage = showSystemMessage; + } + +} diff --git a/Kitodo/src/main/java/org/kitodo/production/controller/SecurityAccessController.java b/Kitodo/src/main/java/org/kitodo/production/controller/SecurityAccessController.java index 032f46ef4ba..bf53d87838e 100644 --- a/Kitodo/src/main/java/org/kitodo/production/controller/SecurityAccessController.java +++ b/Kitodo/src/main/java/org/kitodo/production/controller/SecurityAccessController.java @@ -714,7 +714,8 @@ public boolean hasAuthorityToViewSystemPage() { return securityAccessService.hasAuthorityToViewIndexPage() || securityAccessService.hasAuthorityToViewTaskManagerPage() || securityAccessService.hasAuthorityToViewTermsPage() - || securityAccessService.hasAuthorityToViewMigrationPage(); + || securityAccessService.hasAuthorityToViewMigrationPage() + || securityAccessService.hasAuthorityToViewMessagePage(); } /** @@ -753,6 +754,15 @@ public boolean hasAuthorityToViewMigrationPage() { return securityAccessService.hasAuthorityToViewMigrationPage(); } + /** + * Check if current user has authority to view message tab of system page. + * + * @return true if user has authority to view message tab of system page + */ + public boolean hasAuthorityToViewMessagePage() { + return securityAccessService.hasAuthorityToViewMessagePage(); + } + /** * Check if current user has authority to view task page. It returns true if * user has "viewAllTasks" authority for client. diff --git a/Kitodo/src/main/java/org/kitodo/production/forms/createprocess/SelectProjectDialogView.java b/Kitodo/src/main/java/org/kitodo/production/forms/createprocess/SelectProjectDialogView.java index 5f0e37652e3..97f59cf7800 100644 --- a/Kitodo/src/main/java/org/kitodo/production/forms/createprocess/SelectProjectDialogView.java +++ b/Kitodo/src/main/java/org/kitodo/production/forms/createprocess/SelectProjectDialogView.java @@ -14,7 +14,9 @@ import java.io.IOException; import java.io.Serializable; import java.util.Collections; +import java.util.Comparator; import java.util.List; +import java.util.stream.Collectors; import javax.faces.context.FacesContext; import javax.faces.view.ViewScoped; @@ -85,7 +87,8 @@ public void setSelectedProjectId(int projectId) { public List getTemplateProjects() { try { Template template = ServiceManager.getTemplateService().getById(this.templateDTO.getId()); - return template.getProjects(); + return template.getProjects().stream().sorted(Comparator.comparing(Project::getTitle)) + .collect(Collectors.toList()); } catch (DAOException e) { Helper.setErrorMessage(ERROR_LOADING_ONE, new Object[] {ObjectType.TEMPLATE.getTranslationSingular(), this.templateDTO.getId()}, logger, e); diff --git a/Kitodo/src/main/java/org/kitodo/production/services/data/ProjectService.java b/Kitodo/src/main/java/org/kitodo/production/services/data/ProjectService.java index b64135c8fbe..207c3210bb8 100644 --- a/Kitodo/src/main/java/org/kitodo/production/services/data/ProjectService.java +++ b/Kitodo/src/main/java/org/kitodo/production/services/data/ProjectService.java @@ -152,8 +152,9 @@ public List getAllNotIndexed() { @Override public List getAllForSelectedClient() { - return dao.getByQuery("SELECT p FROM Project AS p INNER JOIN p.client AS c WITH c.id = :clientId", - Collections.singletonMap("clientId", ServiceManager.getUserService().getSessionClientId())); + return dao.getByQuery( + "SELECT p FROM Project AS p INNER JOIN p.client AS c WITH c.id = :clientId ORDER BY title", + Collections.singletonMap("clientId", ServiceManager.getUserService().getSessionClientId())); } @Override diff --git a/Kitodo/src/main/java/org/kitodo/production/services/data/TemplateService.java b/Kitodo/src/main/java/org/kitodo/production/services/data/TemplateService.java index b196f66d095..cdb2be13383 100644 --- a/Kitodo/src/main/java/org/kitodo/production/services/data/TemplateService.java +++ b/Kitodo/src/main/java/org/kitodo/production/services/data/TemplateService.java @@ -17,11 +17,13 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.stream.Collectors; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -41,6 +43,7 @@ import org.kitodo.data.elasticsearch.search.Searcher; import org.kitodo.data.exceptions.DataException; import org.kitodo.exceptions.ProcessGenerationException; +import org.kitodo.production.dto.ProjectDTO; import org.kitodo.production.dto.TaskDTO; import org.kitodo.production.dto.TemplateDTO; import org.kitodo.production.dto.WorkflowDTO; @@ -204,7 +207,8 @@ public TemplateDTO convertJSONObjectToDTO(Map jsonObject, boolea private void convertRelatedJSONObjects(Map jsonObject, TemplateDTO templateDTO) throws DataException { templateDTO.setProjects(convertRelatedJSONObjectToDTO(jsonObject, TemplateTypeField.PROJECTS.getKey(), - ServiceManager.getProjectService())); + ServiceManager.getProjectService()).stream().sorted(Comparator.comparing(ProjectDTO::getTitle)) + .collect(Collectors.toList())); } /** diff --git a/Kitodo/src/main/java/org/kitodo/production/services/security/SecurityAccessService.java b/Kitodo/src/main/java/org/kitodo/production/services/security/SecurityAccessService.java index 963344c9b9d..06856d7af52 100644 --- a/Kitodo/src/main/java/org/kitodo/production/services/security/SecurityAccessService.java +++ b/Kitodo/src/main/java/org/kitodo/production/services/security/SecurityAccessService.java @@ -1034,6 +1034,15 @@ public boolean hasAuthorityToViewMigrationPage() { return hasAnyAuthorityGlobal("viewMigration"); } + /** + * Check if the current user has the authority to view the message tab of the system page. + * + * @return true if the current user has the authority to view the message tab of the system page + */ + public boolean hasAuthorityToViewMessagePage() { + return hasAnyAuthorityGlobal("broadcastMessage"); + } + private boolean hasAuthorityForTask(int taskId) throws DataException { Integer processId = ServiceManager.getTaskService().findById(taskId).getProcess().getId(); diff --git a/Kitodo/src/main/resources/messages/messages_de.properties b/Kitodo/src/main/resources/messages/messages_de.properties index 629c97d3ab1..6a0b57d398e 100644 --- a/Kitodo/src/main/resources/messages/messages_de.properties +++ b/Kitodo/src/main/resources/messages/messages_de.properties @@ -17,6 +17,7 @@ emptyTask=Beispiel f\u00FCr eine lang laufende Aufgabe mapping=ElasticSearch Mapping NOT=Enth\u00E4lt nicht NoCataloguePluginForCatalogue=Keines der verf\u00fcgbaren OPAC-Plugins unterst\u00fctzt diesen Katalog. +acknowledged=Best\u00E4tigt active=Aktiv ACTIVE=Aktiv activeUsers=Aktive Benutzer @@ -681,6 +682,7 @@ locked=Gesperrt location=Standort loggedIn=Angemeldet logical=Logische +loggedInUsers=Angemeldete Benutzer login=Login loginNoteText=Kitodo.Production ist das Workflowmanagementmodul der Kitodo-Suite. Es unterst\u00FCtzt den Digitalisierungsprozess verschiedener Materialarten wie z.B. Drucken, Periodika, Handschriften, Noten und Musikalien, Einblattmedien und Dokumentennachl\u00E4ssen. logout=Logout @@ -996,6 +998,7 @@ selectProject=Bitte Projekt ausw\u00E4hlen selectTemplate=Bitte Produktionsvorlage ausw\u00E4hlen selectWorkflow=Bitte Workflow ausw\u00E4hlen selfAssignTask=Die Bearbeitung dieser Aufgabe \u00FCbernehmen +send=Absenden sendSolutionMessageNextTask=Meldung \u00FCber Probleml\u00F6sung an nachfolgende Station senden sendSolutionMessage=Meldung \u00FCber Probleml\u00F6sung senden sendSolutionMessageForAll=Meldung \u00FCber Probleml\u00F6sung f\u00FCr alle Schritte senden @@ -1073,6 +1076,9 @@ systemErrorInformAdminMessage=Bitte informieren Sie einen Administrator! systemErrorMessage=Es ist ein Fehler im System aufgetreten. systemMaintenanceHeader=Systemwartung systemMaintenanceMessage=Das System wird derzeit gewartet. +systemMessage=Systemnachricht +systemMessage.broadcast=Broadcast +systemMessage.static=Statische Systemnachricht table=Tabelle tableSize=Tabellengr\u00F6\u00DFe task=Aufgabe diff --git a/Kitodo/src/main/resources/messages/messages_en.properties b/Kitodo/src/main/resources/messages/messages_en.properties index a982066c38f..bbf0e341fb0 100644 --- a/Kitodo/src/main/resources/messages/messages_en.properties +++ b/Kitodo/src/main/resources/messages/messages_en.properties @@ -17,6 +17,7 @@ emptyTask=Example of a long-running task mapping=ElasticSearch mapping NOT=does not contain NoCataloguePluginForCatalogue=None of the OPAC plugins available is capable of reading this catalogue. +acknowledged=Acknowledged active=Active ACTIVE=Active activeUsers=Current users @@ -682,6 +683,7 @@ locked=Locked location=Location loggedIn=Logged in logical=Logical +loggedInUsers=Logged in users login=Login loginNoteText=Kitodo.Production is the workflow management module in the Kitodo suite. It supports the process of digitising a range of material types, such as books, periodicals, manuscripts, printed music, single-sheet media, and document collections. logout=Log out @@ -997,6 +999,7 @@ selectProject=Please select a project selectTemplate=Please select a template selectWorkflow=Please select a workflow selfAssignTask=Accept editing of this task +send=Send sendSolutionMessageNextTask=Send message about problem solution to following task sendSolutionMessage=Send message about problem solution sendSolutionMessageForAll=send troubleshooting message to all steps @@ -1074,6 +1077,9 @@ systemErrorInformAdminMessage=Please inform an administrator! systemErrorMessage=A system error occurred. systemMaintenanceHeader=System maintenance systemMaintenanceMessage=The system is currently under maintenance. +systemMessage=System message +systemMessage.broadcast=Broadcast +systemMessage.static=Static system message table=Table tableSize=Table size task=Task 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 a44a54fbf43..aea396e9eb2 100644 --- a/Kitodo/src/main/webapp/WEB-INF/resources/css/kitodo.css +++ b/Kitodo/src/main/webapp/WEB-INF/resources/css/kitodo.css @@ -3489,6 +3489,59 @@ kbd { padding: 0 var(--default-half-size); } +/*---------------------------------------------------------------------- +System page +----------------------------------------------------------------------*/ + +#systemTabView .messageWrapper { + border: 1px solid var(--carbon-blue); + border-radius: var(--default-border-radius); + margin: auto; + padding: var(--default-double-size); + width: 50%; +} + +#systemTabView\:systemWarningForm\:warningText { + height: 100px; +} + +#systemTabView\:systemWarningForm\:sendWarningButton { + margin-top: var(--default-half-size); +} + +#acknowledgeSystemWarningForm\:okButton { + margin-right: var(--default-double-size); +} + +#acknowledgeSystemWarningForm\:systemMessageLabel { + font-style: italic; + font-weight: bold; +} + +#acknowledgeSystemWarningForm\:messageWrapper { + padding: 0 var(--default-double-size); +} + +#systemMessagePanel { + background-color: white; + border: 3px solid red; + color: red; + height: 70px; + left: calc(50% - 320px); + opacity: 80%; + padding: var(--default-full-size); + pointer-events: none; + position: absolute; + text-align: center; + top: 10px; + width: 640px; + z-index: 9999; +} + +#systemTabView\:messagePanel.ui-accordion .ui-accordion-content { + padding: 0; +} + /*---------------------------------------------------------------------- Workflow Editor ----------------------------------------------------------------------*/ diff --git a/Kitodo/src/main/webapp/WEB-INF/resources/css/pattern-library.css b/Kitodo/src/main/webapp/WEB-INF/resources/css/pattern-library.css index 6a2b2796cfd..434aedb9d39 100644 --- a/Kitodo/src/main/webapp/WEB-INF/resources/css/pattern-library.css +++ b/Kitodo/src/main/webapp/WEB-INF/resources/css/pattern-library.css @@ -1718,6 +1718,15 @@ Popup dialogs padding: 0; } +/* Helper classes for colors */ +.red { + color: var(--focused-orange); +} + +.green { + color: var(--focused-green); +} + /* Messages */ .ui-messages-error.ui-corner-all, .ui-messages-warn.ui-corner-all, diff --git a/Kitodo/src/main/webapp/WEB-INF/resources/js/defaultScript.js b/Kitodo/src/main/webapp/WEB-INF/resources/js/defaultScript.js index 42a5680572f..55fa76d1494 100644 --- a/Kitodo/src/main/webapp/WEB-INF/resources/js/defaultScript.js +++ b/Kitodo/src/main/webapp/WEB-INF/resources/js/defaultScript.js @@ -12,3 +12,4 @@ $(document).ready(function() { $('#loadingScreen').hide(); }); + diff --git a/Kitodo/src/main/webapp/WEB-INF/resources/js/systemMessage.js b/Kitodo/src/main/webapp/WEB-INF/resources/js/systemMessage.js new file mode 100644 index 00000000000..f8c60ee2300 --- /dev/null +++ b/Kitodo/src/main/webapp/WEB-INF/resources/js/systemMessage.js @@ -0,0 +1,23 @@ +/** + * (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. + */ +/* globals updateSystemMessageDialog, updateUserTable */ + +function onMessage(message) { + if (message === "showMessage") { + updateSystemMessageDialog(); + } else if (message === "updateUserTable" && typeof updateUserTable === "function") { + updateUserTable(); + } +} + +function onChannelClose(code, channel) { + channel = null; +} diff --git a/Kitodo/src/main/webapp/WEB-INF/templates/base.xhtml b/Kitodo/src/main/webapp/WEB-INF/templates/base.xhtml index d7fc149ddb7..e9cad872930 100644 --- a/Kitodo/src/main/webapp/WEB-INF/templates/base.xhtml +++ b/Kitodo/src/main/webapp/WEB-INF/templates/base.xhtml @@ -26,15 +26,23 @@ + + + +

#{SystemMessageChannel.message}

+
+ + + +
+
- - - - - +
@@ -42,6 +50,13 @@
Loading...
+ + + + + + +