diff --git a/app/src/main/java/org/jboss/hal/client/installer/UpdateManagerHostColumn.java b/app/src/main/java/org/jboss/hal/client/installer/UpdateManagerHostColumn.java index 66e5ea06fb..8eb87c0943 100644 --- a/app/src/main/java/org/jboss/hal/client/installer/UpdateManagerHostColumn.java +++ b/app/src/main/java/org/jboss/hal/client/installer/UpdateManagerHostColumn.java @@ -103,7 +103,7 @@ public UpdateManagerHostColumn(Finder finder, })) .onItemSelect(host -> eventBus.fireEvent(new HostSelectionEvent(host.getName()))) - .onPreview(item -> new HostPreview(hostActions, item, resources)) + .onPreview(item -> new HostPreview(dispatcher, hostActions, item, resources)) .pinnable() .showCount() .useFirstActionAsBreadcrumbHandler() diff --git a/app/src/main/java/org/jboss/hal/client/runtime/host/HostColumn.java b/app/src/main/java/org/jboss/hal/client/runtime/host/HostColumn.java index 45c8c5e9b2..bd5dd76a93 100644 --- a/app/src/main/java/org/jboss/hal/client/runtime/host/HostColumn.java +++ b/app/src/main/java/org/jboss/hal/client/runtime/host/HostColumn.java @@ -122,7 +122,7 @@ public HostColumn(Finder finder, super(new Builder(finder, Ids.HOST, Names.HOST) .onItemSelect(host -> eventBus.fireEvent(new HostSelectionEvent(host.getAddressName()))) - .onPreview(item -> new HostPreview(hostActions, item, resources)) + .onPreview(item -> new HostPreview(dispatcher, hostActions, item, resources)) .pinnable() .showCount() // Unlike other columns the host column does not have a custom breadcrumb item handler. diff --git a/app/src/main/java/org/jboss/hal/client/runtime/host/HostPreview.java b/app/src/main/java/org/jboss/hal/client/runtime/host/HostPreview.java index 41295d58db..035a5e920f 100644 --- a/app/src/main/java/org/jboss/hal/client/runtime/host/HostPreview.java +++ b/app/src/main/java/org/jboss/hal/client/runtime/host/HostPreview.java @@ -15,6 +15,8 @@ */ package org.jboss.hal.client.runtime.host; +import java.util.List; + import org.jboss.elemento.Elements; import org.jboss.hal.ballroom.Format; import org.jboss.hal.ballroom.LabelBuilder; @@ -24,6 +26,10 @@ import org.jboss.hal.core.runtime.host.Host; import org.jboss.hal.core.runtime.host.HostActions; import org.jboss.hal.core.runtime.host.HostPreviewAttributes; +import org.jboss.hal.dmr.ModelDescriptionConstants; +import org.jboss.hal.dmr.ModelNode; +import org.jboss.hal.dmr.Operation; +import org.jboss.hal.dmr.dispatch.Dispatcher; import org.jboss.hal.resources.Names; import org.jboss.hal.resources.Resources; @@ -33,9 +39,14 @@ import static org.jboss.elemento.Elements.a; import static org.jboss.elemento.Elements.div; +import static org.jboss.elemento.Elements.h; +import static org.jboss.elemento.Elements.li; +import static org.jboss.elemento.Elements.setVisible; import static org.jboss.elemento.Elements.span; +import static org.jboss.elemento.Elements.ul; import static org.jboss.elemento.EventType.click; import static org.jboss.hal.client.runtime.host.HostColumn.hostTemplate; +import static org.jboss.hal.dmr.ModelDescriptionConstants.CHANNEL_VERSIONS; import static org.jboss.hal.dmr.ModelDescriptionConstants.DISCONNECTED; import static org.jboss.hal.dmr.ModelDescriptionConstants.HOST_STATE; import static org.jboss.hal.dmr.ModelDescriptionConstants.LAST_CONNECTED; @@ -43,6 +54,7 @@ import static org.jboss.hal.dmr.ModelDescriptionConstants.MANAGEMENT_MICRO_VERSION; import static org.jboss.hal.dmr.ModelDescriptionConstants.MANAGEMENT_MINOR_VERSION; import static org.jboss.hal.dmr.ModelDescriptionConstants.MANAGEMENT_VERSION; +import static org.jboss.hal.dmr.ModelDescriptionConstants.PRODUCT_INFO; import static org.jboss.hal.dmr.ModelDescriptionConstants.PRODUCT_NAME; import static org.jboss.hal.dmr.ModelDescriptionConstants.PRODUCT_VERSION; import static org.jboss.hal.dmr.ModelDescriptionConstants.RELEASE_CODENAME; @@ -50,23 +62,35 @@ import static org.jboss.hal.dmr.ModelDescriptionConstants.RELOAD; import static org.jboss.hal.dmr.ModelDescriptionConstants.RESTART; import static org.jboss.hal.dmr.ModelDescriptionConstants.RUNNING_MODE; +import static org.jboss.hal.dmr.ModelDescriptionConstants.SUMMARY; import static org.jboss.hal.meta.security.Constraint.executable; import static org.jboss.hal.resources.CSS.alertLink; import static org.jboss.hal.resources.CSS.clickable; import static org.jboss.hal.resources.CSS.hidden; +import static org.jboss.hal.resources.CSS.listGroup; +import static org.jboss.hal.resources.CSS.listGroupItem; +import static org.jboss.hal.resources.CSS.value; import static org.jboss.hal.resources.UIConstants.CONSTRAINT; public class HostPreview extends RuntimePreview { + private static final String ID_HEADER_CHANNEL_VERSIONS = "h2-channel-versions"; + private static final String ID_CHANNEL_VERSIONS = "channel-versions"; + + private final Dispatcher dispatcher; private final HTMLElement reloadLink; private final HTMLElement restartLink; private final PreviewAttributes attributes; private final HostActions hostActions; private final Resources resources; private final LabelBuilder labelBuilder; + private final HTMLElement headerChannelVersions = h(2, new LabelBuilder().label(CHANNEL_VERSIONS)).id( + ID_HEADER_CHANNEL_VERSIONS).element(); + private final HTMLElement ulChannelVersions = ul().id(ID_CHANNEL_VERSIONS).css(listGroup).element(); - public HostPreview(HostActions hostActions, Host host, Resources resources) { + public HostPreview(Dispatcher dispatcher, HostActions hostActions, Host host, Resources resources) { super(host.getName(), host.isDomainController() ? Names.DOMAIN_CONTROLLER : Names.HOST_CONTROLLER, resources); + this.dispatcher = dispatcher; this.hostActions = hostActions; this.resources = resources; this.labelBuilder = new LabelBuilder(); @@ -104,6 +128,11 @@ public HostPreview(HostActions hostActions, Host host, Resources resources) { : Names.NOT_AVAILABLE)); previewBuilder().addAll(attributes); + setVisible(headerChannelVersions, false); + setVisible(ulChannelVersions, false); + previewBuilder().add(headerChannelVersions); + previewBuilder().add(ulChannelVersions); + update(host); } @@ -127,11 +156,45 @@ public void update(Host host) { unknown(resources.messages().hostUndefined(host.getName())); } - // Do not simply hide the links, but add the hidden CSS class. + // Do not simply hide the links but add the hidden CSS class. // Important when constraints for the links are processed later. Elements.toggle(reloadLink, hidden, !host.needsReload()); Elements.toggle(restartLink, hidden, !host.needsRestart()); HostPreviewAttributes.refresh(host, attributes, hostActions); + + if (host.isRunning() || host.needsRestart() || host.needsReload()) { + dispatcher.execute(new Operation.Builder(host.getAddress(), PRODUCT_INFO).build()).then(result -> { + boolean showChannelVersions = false; + if (result.isDefined()) { + ModelNode summary = findSummary(result.asList(), host); + if (summary.hasDefined(CHANNEL_VERSIONS)) { + Elements.removeChildrenFrom(ulChannelVersions); + summary.get(CHANNEL_VERSIONS) + .asList() + .forEach(cv -> ulChannelVersions.appendChild(li().css(listGroupItem) + .add(span().css(value).style("margin-left:0") + .textContent(cv.asString()).element()) + .element())); + showChannelVersions = true; + } + } + setVisible(headerChannelVersions, showChannelVersions); + setVisible(ulChannelVersions, showChannelVersions); + return null; + }); + } + } + + private ModelNode findSummary(List summaries, Host host) { + for (ModelNode modelNode : summaries) { + if (modelNode.hasDefined(ModelDescriptionConstants.SUMMARY)) { + ModelNode summary = modelNode.get(SUMMARY); + if (host.getName().equals(summary.get("node-name").asString())) { + return summary; + } + } + } + return new ModelNode(); } } diff --git a/app/src/main/java/org/jboss/hal/client/runtime/server/ServerPreview.java b/app/src/main/java/org/jboss/hal/client/runtime/server/ServerPreview.java index 9796fbd662..8b57ec050c 100644 --- a/app/src/main/java/org/jboss/hal/client/runtime/server/ServerPreview.java +++ b/app/src/main/java/org/jboss/hal/client/runtime/server/ServerPreview.java @@ -60,14 +60,17 @@ import static org.jboss.elemento.Elements.div; import static org.jboss.elemento.Elements.h; import static org.jboss.elemento.Elements.li; +import static org.jboss.elemento.Elements.setVisible; import static org.jboss.elemento.Elements.span; import static org.jboss.elemento.Elements.ul; import static org.jboss.elemento.EventType.click; import static org.jboss.hal.client.runtime.server.ServerColumn.serverConfigTemplate; import static org.jboss.hal.dmr.ModelDescriptionConstants.AUTO_START; +import static org.jboss.hal.dmr.ModelDescriptionConstants.CHANNEL_VERSIONS; import static org.jboss.hal.dmr.ModelDescriptionConstants.CHILD_TYPE; import static org.jboss.hal.dmr.ModelDescriptionConstants.HOST; import static org.jboss.hal.dmr.ModelDescriptionConstants.NAME; +import static org.jboss.hal.dmr.ModelDescriptionConstants.PRODUCT_INFO; import static org.jboss.hal.dmr.ModelDescriptionConstants.PROFILE_NAME; import static org.jboss.hal.dmr.ModelDescriptionConstants.QUERY; import static org.jboss.hal.dmr.ModelDescriptionConstants.READ_CHILDREN_NAMES_OPERATION; @@ -85,6 +88,7 @@ import static org.jboss.hal.dmr.ModelDescriptionConstants.START; import static org.jboss.hal.dmr.ModelDescriptionConstants.STATUS; import static org.jboss.hal.dmr.ModelDescriptionConstants.STOP; +import static org.jboss.hal.dmr.ModelDescriptionConstants.SUMMARY; import static org.jboss.hal.dmr.ModelDescriptionConstants.SUSPEND_STATE; import static org.jboss.hal.dmr.ModelDescriptionConstants.WHERE; import static org.jboss.hal.flow.Flow.sequential; @@ -103,6 +107,8 @@ class ServerPreview extends RuntimePreview { private static final AddressTemplate SELECTED_SERVER = AddressTemplate.of("{selected.host}/{selected.server}"); private static final String ID_OPEN_PORTS = "open-ports"; private static final String ID_HEADER_OPEN_PORTS = "h2-open-ports"; + private static final String ID_HEADER_CHANNEL_VERSIONS = "h2-channel-versions"; + private static final String ID_CHANNEL_VERSIONS = "channel-versions"; private final ServerActions serverActions; private final Dispatcher dispatcher; @@ -119,6 +125,9 @@ class ServerPreview extends RuntimePreview { private final PreviewAttributes attributes; private final HTMLElement ulOpenPorts = ul().id(ID_OPEN_PORTS).css(listGroup).element(); private final HTMLElement headerOpenPorts = h(2, resources.constants().openPorts()).id(ID_HEADER_OPEN_PORTS).element(); + private final HTMLElement headerChannelVersions = h(2, new LabelBuilder().label(CHANNEL_VERSIONS)).id( + ID_HEADER_CHANNEL_VERSIONS).element(); + private final HTMLElement ulChannelVersions = ul().id(ID_CHANNEL_VERSIONS).css(listGroup).element(); ServerPreview(ServerActions serverActions, Server server, @@ -169,7 +178,7 @@ class ServerPreview extends RuntimePreview { .add(bootErrorsLink = a().css(clickable, alertLink) .on(click, event -> { PlaceRequest placeRequest = new PlaceRequest.Builder().nameToken( - NameTokens.SERVER_BOOT_ERRORS) + NameTokens.SERVER_BOOT_ERRORS) .with(HOST, server.getHost()) .with(SERVER, server.getName()) .build(); @@ -178,7 +187,7 @@ class ServerPreview extends RuntimePreview { .textContent(resources.constants().view()).element()) .element()); - links = new HTMLElement[] { startLink, stopLink, reloadLink, restartLink, resumeLink, bootErrorsLink }; + links = new HTMLElement[]{startLink, stopLink, reloadLink, restartLink, resumeLink, bootErrorsLink}; serverUrl = span().textContent(Names.NOT_AVAILABLE).element(); PreviewAttributeFunction previewFunction = model -> new PreviewAttribute(Names.URL, serverUrl); @@ -227,6 +236,10 @@ class ServerPreview extends RuntimePreview { previewBuilder().add(this.headerOpenPorts); previewBuilder().add(this.ulOpenPorts); } + setVisible(headerChannelVersions, false); + setVisible(ulChannelVersions, false); + previewBuilder().add(headerChannelVersions); + previewBuilder().add(ulChannelVersions); } @Override @@ -363,11 +376,38 @@ protected void onUnknown(Server server) { } Elements.setVisible(headerOpenPorts, displayOpenPorts); Elements.setVisible(ulOpenPorts, displayOpenPorts); + + if (displayOpenPorts) { + dispatcher.execute(new Operation.Builder(server.getServerAddress(), PRODUCT_INFO).build()).then(result -> { + boolean showChannelVersions = false; + if (result.isDefined()) { + if (!result.asList().isEmpty()) { + ModelNode payload = result.asList().get(0); + if (payload.hasDefined(SUMMARY)) { + ModelNode summary = payload.get(SUMMARY); + if (summary.hasDefined(CHANNEL_VERSIONS)) { + Elements.removeChildrenFrom(ulChannelVersions); + summary.get(CHANNEL_VERSIONS) + .asList() + .forEach(cv -> ulChannelVersions.appendChild(li().css(listGroupItem) + .add(span().css(value).style("margin-left:0") + .textContent(cv.asString()).element()) + .element())); + showChannelVersions = true; + } + } + } + } + setVisible(headerChannelVersions, showChannelVersions); + setVisible(ulChannelVersions, showChannelVersions); + return null; + }); + } } private void disableAllLinks() { for (HTMLElement l : links) { - // Do not simply hide the links, but add the hidden CSS class. + // Do not simply hide the links but add the hidden CSS class. // Important when constraints for the links are processed later. l.classList.add(hidden); } @@ -378,7 +418,7 @@ private void disableAllLinksBut(HTMLElement link) { if (l == link) { continue; } - // Do not simply hide the links, but add the hidden CSS class. + // Do not simply hide the links but add the hidden CSS class. // Important when constraints for the links are processed later. l.classList.add(hidden); } diff --git a/dmr/src/main/java/org/jboss/hal/dmr/ModelDescriptionConstants.java b/dmr/src/main/java/org/jboss/hal/dmr/ModelDescriptionConstants.java index d6a0d81142..a7b314ade4 100644 --- a/dmr/src/main/java/org/jboss/hal/dmr/ModelDescriptionConstants.java +++ b/dmr/src/main/java/org/jboss/hal/dmr/ModelDescriptionConstants.java @@ -731,6 +731,7 @@ public interface ModelDescriptionConstants { String PROCESS_STATE_LISTENER = "process-state-listener"; String PROCESSING_TIME = "processing-time"; String PRODUCES = "produces"; + String PRODUCT_INFO = "product-info"; String PRODUCT_NAME = "product-name"; String PRODUCT_VERSION = "product-version"; String PROFILE = "profile"; @@ -994,6 +995,7 @@ public interface ModelDescriptionConstants { String SUBSYSTEM = "subsystem"; String SUCCESS = "success"; String SUGGEST_CAPABILITIES = "suggest-capabilities"; + String SUMMARY = "summary"; String SUSPEND = "suspend"; String SUSPEND_SERVERS = "suspend-servers"; String SUSPEND_STATE = "suspend-state";