diff --git a/forms/src/main/java/org/devgateway/toolkit/forms/wicket/page/Header.html b/forms/src/main/java/org/devgateway/toolkit/forms/wicket/page/Header.html index cd8a4972..2754c11c 100644 --- a/forms/src/main/java/org/devgateway/toolkit/forms/wicket/page/Header.html +++ b/forms/src/main/java/org/devgateway/toolkit/forms/wicket/page/Header.html @@ -9,6 +9,7 @@
+
diff --git a/forms/src/main/java/org/devgateway/toolkit/forms/wicket/page/Header.java b/forms/src/main/java/org/devgateway/toolkit/forms/wicket/page/Header.java index 82824b87..13870ee4 100644 --- a/forms/src/main/java/org/devgateway/toolkit/forms/wicket/page/Header.java +++ b/forms/src/main/java/org/devgateway/toolkit/forms/wicket/page/Header.java @@ -11,8 +11,24 @@ *******************************************************************************/ package org.devgateway.toolkit.forms.wicket.page; +import org.apache.commons.lang3.time.DurationFormatUtils; +import org.apache.wicket.Component; +import org.apache.wicket.ajax.AbstractAjaxTimerBehavior; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.StringResourceModel; import org.apache.wicket.request.mapper.parameter.PageParameters; +import org.apache.wicket.spring.injection.annot.SpringBean; +import org.devgateway.toolkit.forms.security.SecurityConstants; +import org.devgateway.toolkit.persistence.dao.AdminSettings; +import org.devgateway.toolkit.persistence.service.AdminSettingsService; + +import java.time.Duration; +import java.time.LocalDateTime; /** * @author idobre @@ -22,11 +38,74 @@ public class Header extends Panel { private static final long serialVersionUID = 1L; + private static final Duration ONE_MIN = Duration.ofMinutes(1); + private static final long ALERT_UPDATE_INTERVAL_SECONDS = 15; + + @SpringBean + private AdminSettingsService adminSettingsService; + + private LocalDateTime rebootSince; + public Header(final String markupId) { this(markupId, null); } public Header(final String markupId, final PageParameters parameters) { super(markupId); + + addRebootAlert(); + } + + private void addRebootAlert() { + AdminSettings as = adminSettingsService.get(); + if (as == null) { + add(new WebMarkupContainer("rebootAlert")); + return; + } + rebootSince = as.isRebootServer() ? as.getRebootAlertSince() : null; + + IModel rebootDurationModel = new IModel() { + private static final long serialVersionUID = -8601598474017148336L; + + @Override + public String getObject() { + if (rebootSince == null) { + return ""; + } else { + Duration remaining = AdminSettings.REBOOT_ALERT_DURATION + .minus(Duration.between(rebootSince, LocalDateTime.now())) + // round up + .plusSeconds(30); + if (remaining.minus(ONE_MIN).isNegative()) { + remaining = ONE_MIN; + } + return DurationFormatUtils.formatDuration(remaining.toMillis(), "m"); + } + } + }; + + Label rebootAlert = new Label("rebootAlert", new StringResourceModel("rebootAlert", rebootDurationModel)) { + private static final long serialVersionUID = -3562806753180165059L; + + @Override + protected void onConfigure() { + super.onConfigure(); + setVisible(rebootSince != null); + } + }; + rebootAlert.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true); + add(rebootAlert); + MetaDataRoleAuthorizationStrategy.authorize(rebootAlert, Component.RENDER, SecurityConstants.Roles.ROLE_USER); + + add(new AbstractAjaxTimerBehavior(org.apache.wicket.util.time.Duration.seconds(ALERT_UPDATE_INTERVAL_SECONDS)) { + private static final long serialVersionUID = -1168209018766325709L; + + @Override + protected void onTimer(final AjaxRequestTarget target) { + AdminSettings as = adminSettingsService.get(); + rebootSince = as.isRebootServer() ? as.getRebootAlertSince() : null; + target.add(rebootAlert); + } + }); } } diff --git a/forms/src/main/java/org/devgateway/toolkit/forms/wicket/page/Header.properties b/forms/src/main/java/org/devgateway/toolkit/forms/wicket/page/Header.properties new file mode 100644 index 00000000..6e9b11c1 --- /dev/null +++ b/forms/src/main/java/org/devgateway/toolkit/forms/wicket/page/Header.properties @@ -0,0 +1 @@ +rebootAlert=Server will be rebooted within next ${} minute(s). Please save your data and logout. The system will be back online in a few minutes. diff --git a/forms/src/main/java/org/devgateway/toolkit/forms/wicket/styles/BaseStyles.css b/forms/src/main/java/org/devgateway/toolkit/forms/wicket/styles/BaseStyles.css index 8a2bca13..7fb763a1 100644 --- a/forms/src/main/java/org/devgateway/toolkit/forms/wicket/styles/BaseStyles.css +++ b/forms/src/main/java/org/devgateway/toolkit/forms/wicket/styles/BaseStyles.css @@ -39,7 +39,18 @@ body { * @see: bootstrap::navbar.less */ min-height: 50px; - margin-bottom: 20px; + margin-bottom: 32px; +} + +.rebootAlert { + position: fixed; + top: 50px; + padding: 6px; + text-align: center; + width: 100%; + border-width: 1px; + border-style: solid; + z-index: 1029; } .mainContainer { diff --git a/persistence/src/main/java/org/devgateway/toolkit/persistence/dao/AdminSettings.java b/persistence/src/main/java/org/devgateway/toolkit/persistence/dao/AdminSettings.java index 919bd13b..8caae641 100644 --- a/persistence/src/main/java/org/devgateway/toolkit/persistence/dao/AdminSettings.java +++ b/persistence/src/main/java/org/devgateway/toolkit/persistence/dao/AdminSettings.java @@ -5,7 +5,8 @@ import org.hibernate.envers.Audited; import javax.persistence.Entity; -import java.io.Serializable; +import java.time.Duration; +import java.time.LocalDateTime; /** * @author idobre @@ -15,10 +16,14 @@ @Audited @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) public class AdminSettings extends AbstractAuditableEntity { - private static final long serialVersionUID = -1051140524022133178L; + + public static final Duration REBOOT_ALERT_DURATION = Duration.ofMinutes(10L); + private Boolean rebootServer = false; + private LocalDateTime rebootAlertSince; + @Override public AbstractAuditableEntity getParent() { return null; @@ -31,4 +36,16 @@ public Boolean getRebootServer() { public void setRebootServer(final Boolean rebootServer) { this.rebootServer = rebootServer; } + + public boolean isRebootServer() { + return Boolean.TRUE.equals(getRebootServer()); + } + + public LocalDateTime getRebootAlertSince() { + return rebootAlertSince; + } + + public void setRebootAlertSince(final LocalDateTime rebootAlertSince) { + this.rebootAlertSince = rebootAlertSince; + } } diff --git a/persistence/src/main/java/org/devgateway/toolkit/persistence/service/AdminSettingsService.java b/persistence/src/main/java/org/devgateway/toolkit/persistence/service/AdminSettingsService.java index 021e599f..61e14626 100644 --- a/persistence/src/main/java/org/devgateway/toolkit/persistence/service/AdminSettingsService.java +++ b/persistence/src/main/java/org/devgateway/toolkit/persistence/service/AdminSettingsService.java @@ -4,4 +4,5 @@ public interface AdminSettingsService extends BaseJpaService { + AdminSettings get(); } diff --git a/persistence/src/main/java/org/devgateway/toolkit/persistence/service/AdminSettingsServiceImpl.java b/persistence/src/main/java/org/devgateway/toolkit/persistence/service/AdminSettingsServiceImpl.java index 20ecf170..a3177998 100644 --- a/persistence/src/main/java/org/devgateway/toolkit/persistence/service/AdminSettingsServiceImpl.java +++ b/persistence/src/main/java/org/devgateway/toolkit/persistence/service/AdminSettingsServiceImpl.java @@ -4,10 +4,12 @@ import org.devgateway.toolkit.persistence.repository.AdminSettingsRepository; import org.devgateway.toolkit.persistence.repository.norepository.BaseJpaRepository; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.annotation.CacheConfig; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDateTime; +import java.util.List; + /** * @author idobre * @since 2019-03-04 @@ -28,4 +30,32 @@ public AdminSettings newInstance() { return new AdminSettings(); } + @Override + @Transactional + public S save(final S entity) { + preProcessRebootAlert(entity); + return repository().save(entity); + } + + @Override + @Transactional + public S saveAndFlush(final S entity) { + preProcessRebootAlert(entity); + return repository().saveAndFlush(entity); + } + + private void preProcessRebootAlert(final S as) { + if (!as.isRebootServer()) { + as.setRebootAlertSince(null); + } else if (as.getRebootAlertSince() == null) { + as.setRebootAlertSince(LocalDateTime.now()); + } + } + + @Override + public AdminSettings get() { + List entries = repository().findAll(); + return entries.isEmpty() ? null : entries.get(0); + } + }