diff --git a/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/MainLayout.java b/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/MainLayout.java index 787a9e395..424c48d3f 100644 --- a/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/MainLayout.java +++ b/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/MainLayout.java @@ -47,7 +47,7 @@ public class MainLayout extends AppLayout { private H2 viewTitle; - private final AuthenticatedUser authenticatedUser; + private final transient AuthenticatedUser authenticatedUser; private final AccessAnnotationChecker accessChecker; public MainLayout(final AuthenticatedUser authenticatedUser, final AccessAnnotationChecker accessChecker) { diff --git a/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/SimpleUIApp.java b/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/SimpleUIApp.java index 3ca8d66f6..a4a6d0341 100644 --- a/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/SimpleUIApp.java +++ b/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/SimpleUIApp.java @@ -83,7 +83,11 @@ public class SimpleUIApp implements AppShellConfigurator { return new UsernamePasswordAuthenticationToken( username, password, roles.stream().map(role -> new SimpleGrantedAuthority("ROLE_" + role)).toList()) { - public void eraseCredentials() {} + @Override + public void eraseCredentials() { + // don't erase credentials because they will be used + // to authenticate to the hawkBit update server / mgmt server + } }; }; } diff --git a/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/Constants.java b/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/Constants.java new file mode 100644 index 000000000..37c79d9c4 --- /dev/null +++ b/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/Constants.java @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2023 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package com.eclipse.hawkbit.ui.view; + +public interface Constants { + + // properties + String ID = "Id"; + String NAME = "Name"; + String DESCRIPTION = "Description"; + String VERSION = "Version"; + String VENDOR = "Vendor"; + String TYPE = "Type"; + String CREATED_BY = "Created by"; + String CREATED_AT = "Created at"; + String LAST_MODIFIED_BY = "Last modified by"; + String LAST_MODIFIED_AT = "Last modified at"; + + // rollout + String GROUP_COUNT = "Group Count"; + String TARGET_COUNT = "Target Count"; + String STATS = "Stats"; + String STATUS = "Status"; + String ACTIONS = "Actions"; + + // create rollout + String TARGET_FILTER = "Target Filter"; + String DISTRIBUTION_SET = "Distribution Set"; + String ACTION_TYPE = "Action Type"; + String START_AT = "Start At"; + String SOFT = "Soft"; + String FORCED = "Forced"; + String DOWNLOAD_ONLY = "Download Only"; + String START_TYPE = "Start Type"; + String MANUAL = "Manual"; + String AUTO = "Auto"; + + String NAME_ASC = "name:asc"; +} diff --git a/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/DistributionSetView.java b/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/DistributionSetView.java index 321f40fe2..81978cf1c 100644 --- a/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/DistributionSetView.java +++ b/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/DistributionSetView.java @@ -65,10 +65,10 @@ public class DistributionSetView extends TableView { @Override protected void addColumns(Grid grid) { - grid.addColumn(MgmtDistributionSet::getDsId).setHeader("Id").setAutoWidth(true); - grid.addColumn(MgmtDistributionSet::getName).setHeader("Name").setAutoWidth(true); - grid.addColumn(MgmtDistributionSet::getVersion).setHeader("Version").setAutoWidth(true); - grid.addColumn(MgmtDistributionSet::getTypeName).setHeader("Type").setAutoWidth(true); + grid.addColumn(MgmtDistributionSet::getDsId).setHeader(ID).setAutoWidth(true); + grid.addColumn(MgmtDistributionSet::getName).setHeader(NAME).setAutoWidth(true); + grid.addColumn(MgmtDistributionSet::getVersion).setHeader(VERSION).setAutoWidth(true); + grid.addColumn(MgmtDistributionSet::getTypeName).setHeader(TYPE).setAutoWidth(true); grid.setItemDetailsRenderer(new ComponentRenderer<>( () -> details, DistributionSetDetails::setItem)); @@ -76,7 +76,7 @@ public class DistributionSetView extends TableView { }, (query, rsqlFilter) -> hawkbitClient.getDistributionSetRestApi() .getDistributionSets( - query.getOffset(), query.getPageSize(), "name:asc", rsqlFilter) + query.getOffset(), query.getPageSize(), NAME_ASC, rsqlFilter) .getBody() .getContent() .stream(), @@ -95,10 +95,11 @@ public class DistributionSetView extends TableView { MgmtSoftwareModule.class, MgmtSoftwareModule::getModuleId) { @Override protected void addColumns(Grid grid) { - grid.addColumn(MgmtSoftwareModule::getModuleId).setHeader("Id").setAutoWidth(true); - grid.addColumn(MgmtSoftwareModule::getVersion).setHeader("Version").setAutoWidth(true); - grid.addColumn(MgmtSoftwareModule::getTypeName).setHeader("Name").setAutoWidth(true); - grid.addColumn(MgmtSoftwareModule::getVendor).setHeader("Vendor").setAutoWidth(true); + grid.addColumn(MgmtSoftwareModule::getModuleId).setHeader(ID).setAutoWidth(true); + grid.addColumn(MgmtSoftwareModule::getName).setHeader(NAME).setAutoWidth(true); + grid.addColumn(MgmtSoftwareModule::getVersion).setHeader(VERSION).setAutoWidth(true); + grid.addColumn(MgmtSoftwareModule::getTypeName).setHeader(TYPE).setAutoWidth(true); + grid.addColumn(MgmtSoftwareModule::getVendor).setHeader(VENDOR).setAutoWidth(true); } }); } @@ -114,13 +115,13 @@ public class DistributionSetView extends TableView { type.setItemLabelGenerator(MgmtDistributionSetType::getName); type.setItems( hawkbitClient.getDistributionSetTypeRestApi() - .getDistributionSetTypes(0, 20, "name:asc", null) + .getDistributionSetTypes(0, 20, NAME_ASC, null) .getBody() .getContent()); tag.setItemLabelGenerator(MgmtTag::getName); tag.setItems( hawkbitClient.getDistributionSetTagRestApi() - .getDistributionSetTags(0, 20, "name:asc", null) + .getDistributionSetTags(0, 20, NAME_ASC, null) .getBody() .getContent()); } @@ -143,7 +144,7 @@ public class DistributionSetView extends TableView { private static class DistributionSetDetails extends FormLayout { - private final HawkbitClient hawkbitClient; + private final transient HawkbitClient hawkbitClient; private final TextArea description = new TextArea("Description"); private final TextField createdBy = Utils.textField("Created by"); @@ -182,7 +183,7 @@ public class DistributionSetView extends TableView { hawkbitClient.getDistributionSetRestApi() .getAssignedSoftwareModules( distributionSet.getDsId(), - query.getOffset(), query.getLimit(), "name:asc") + query.getOffset(), query.getLimit(), NAME_ASC) .getBody() .getContent() .stream()); @@ -192,7 +193,7 @@ public class DistributionSetView extends TableView { private static class CreateDialog extends Utils.BaseDialog { - private final HawkbitClient hawkbitClient; + private final transient HawkbitClient hawkbitClient; private final Select type; private final TextField name; @@ -209,7 +210,7 @@ public class DistributionSetView extends TableView { "Type", this::readyToCreate, hawkbitClient.getDistributionSetTypeRestApi() - .getDistributionSetTypes(0, 30, "name:asc", null) + .getDistributionSetTypes(0, 30, NAME_ASC, null) .getBody() .getContent() .toArray(new MgmtDistributionSetType[0])); @@ -217,13 +218,13 @@ public class DistributionSetView extends TableView { type.setWidthFull(); type.setRequiredIndicatorVisible(true); type.setItemLabelGenerator(MgmtDistributionSetType::getName); - name = Utils.textField("Name", this::readyToCreate); - version = Utils.textField("Version", this::readyToCreate); - final TextField vendor = Utils.textField("Vendor"); - description = new TextArea("Description"); + name = Utils.textField(NAME, this::readyToCreate); + version = Utils.textField(VERSION, this::readyToCreate); + final TextField vendor = Utils.textField(VENDOR); + description = new TextArea(DESCRIPTION); description.setWidthFull(); description.setMinLength(2); - requiredMigrationStep = new Checkbox("Reguired Migration Step"); + requiredMigrationStep = new Checkbox("Required Migration Step"); create = Utils.tooltip(new Button("Create"), "Create (Enter)"); create.setEnabled(false); @@ -275,7 +276,7 @@ public class DistributionSetView extends TableView { private static class AddSoftwareModulesDialog extends Utils.BaseDialog { - private final Set softwareModules = Collections.synchronizedSet(new HashSet<>()); + private final transient Set softwareModules = Collections.synchronizedSet(new HashSet<>()); private AddSoftwareModulesDialog(final long distributionSetId, final HawkbitClient hawkbitClient) { super("Add Software Modules"); @@ -304,7 +305,7 @@ public class DistributionSetView extends TableView { softwareModulesGrid.refreshGrid(false); return CompletableFuture.completedFuture(null); }, - softwareModulesGrid, true).get(); + softwareModulesGrid, true); final Button finishBtn = Utils.tooltip(new Button("Finish"), "Finish (Esc)"); finishBtn.addClickListener(e -> { hawkbitClient.getDistributionSetRestApi().assignSoftwareModules( diff --git a/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/LoginView.java b/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/LoginView.java index d261d0bb1..acb551c1b 100644 --- a/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/LoginView.java +++ b/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/LoginView.java @@ -25,7 +25,7 @@ import com.vaadin.flow.server.auth.AnonymousAllowed; @Route(value = "login") public class LoginView extends LoginOverlay implements BeforeEnterObserver { - private final AuthenticatedUser authenticatedUser; + private final transient AuthenticatedUser authenticatedUser; public LoginView(final AuthenticatedUser authenticatedUser) { this.authenticatedUser = authenticatedUser; diff --git a/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/RolloutView.java b/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/RolloutView.java index f5a941ab5..9c8faff17 100644 --- a/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/RolloutView.java +++ b/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/RolloutView.java @@ -62,21 +62,21 @@ public class RolloutView extends TableView { public RolloutView(final HawkbitClient hawkbitClient) { super( - new RolloutFilter(hawkbitClient), + new RolloutFilter(), new SelectionGrid.EntityRepresentation<>( MgmtRolloutResponseBody.class, MgmtRolloutResponseBody::getRolloutId) { private final RolloutDetails details = new RolloutDetails(hawkbitClient); @Override protected void addColumns(final Grid grid) { - grid.addColumn(MgmtRolloutResponseBody::getRolloutId).setHeader("Id").setAutoWidth(true); - grid.addColumn(MgmtRolloutResponseBody::getName).setHeader("Name").setAutoWidth(true); - grid.addColumn(MgmtRolloutResponseBody::getTotalGroups).setHeader("Group Count").setAutoWidth(true); - grid.addColumn(MgmtRolloutResponseBody::getTotalTargets).setHeader("Target Count").setAutoWidth(true); - grid.addColumn(MgmtRolloutResponseBody::getTotalTargetsPerStatus).setHeader("Stats").setAutoWidth(true); - grid.addColumn(MgmtRolloutResponseBody::getStatus).setHeader("Status").setAutoWidth(true); + grid.addColumn(MgmtRolloutResponseBody::getRolloutId).setHeader(ID).setAutoWidth(true); + grid.addColumn(MgmtRolloutResponseBody::getName).setHeader(NAME).setAutoWidth(true); + grid.addColumn(MgmtRolloutResponseBody::getTotalGroups).setHeader(GROUP_COUNT).setAutoWidth(true); + grid.addColumn(MgmtRolloutResponseBody::getTotalTargets).setHeader(TARGET_COUNT).setAutoWidth(true); + grid.addColumn(MgmtRolloutResponseBody::getTotalTargetsPerStatus).setHeader(STATS).setAutoWidth(true); + grid.addColumn(MgmtRolloutResponseBody::getStatus).setHeader(STATUS).setAutoWidth(true); - grid.addComponentColumn(rollout -> new Actions(rollout, grid, hawkbitClient)).setHeader("Actions").setAutoWidth(true); + grid.addComponentColumn(rollout -> new Actions(rollout, grid, hawkbitClient)).setHeader(ACTIONS).setAutoWidth(true); grid.setItemDetailsRenderer(new ComponentRenderer<>( () -> details, RolloutDetails::setItem)); @@ -84,7 +84,7 @@ public class RolloutView extends TableView { }, (query, rsqlFilter) -> hawkbitClient.getRolloutRestApi() .getRollouts( - query.getOffset(), query.getPageSize(), "name:asc", rsqlFilter, null) + query.getOffset(), query.getPageSize(), NAME_ASC, rsqlFilter, null) .getBody() .getContent() .stream(), @@ -102,11 +102,11 @@ public class RolloutView extends TableView { new SelectionGrid.EntityRepresentation<>(MgmtRolloutGroupResponseBody.class, MgmtRolloutGroupResponseBody::getRolloutGroupId) { @Override protected void addColumns(final Grid grid) { - grid.addColumn(MgmtRolloutGroupResponseBody::getRolloutGroupId).setHeader("Id").setAutoWidth(true); - grid.addColumn(MgmtRolloutGroupResponseBody::getName).setHeader("Name").setAutoWidth(true); - grid.addColumn(MgmtRolloutGroupResponseBody::getTotalTargets).setHeader("Target Count").setAutoWidth(true); - grid.addColumn(MgmtRolloutGroupResponseBody::getTotalTargetsPerStatus).setHeader("Stats").setAutoWidth(true); - grid.addColumn(MgmtRolloutGroupResponseBody::getStatus).setHeader("Status").setAutoWidth(true); + grid.addColumn(MgmtRolloutGroupResponseBody::getRolloutGroupId).setHeader(ID).setAutoWidth(true); + grid.addColumn(MgmtRolloutGroupResponseBody::getName).setHeader(NAME).setAutoWidth(true); + grid.addColumn(MgmtRolloutGroupResponseBody::getTotalTargets).setHeader(TARGET_COUNT).setAutoWidth(true); + grid.addColumn(MgmtRolloutGroupResponseBody::getTotalTargetsPerStatus).setHeader(STATS).setAutoWidth(true); + grid.addColumn(MgmtRolloutGroupResponseBody::getStatus).setHeader(STATUS).setAutoWidth(true); } }); } @@ -115,7 +115,7 @@ public class RolloutView extends TableView { private final long rolloutId; private final Grid grid; - private final HawkbitClient hawkbitClient; + private final transient HawkbitClient hawkbitClient; private Actions(final MgmtRolloutResponseBody rollout, final Grid grid, final HawkbitClient hawkbitClient) { this.rolloutId = rollout.getRolloutId(); @@ -163,9 +163,9 @@ public class RolloutView extends TableView { private static class RolloutFilter implements Filter.Rsql { - private final TextField name = Utils.textField("Name"); + private final TextField name = Utils.textField(NAME); - private RolloutFilter(final HawkbitClient hawkbitClient) { + private RolloutFilter() { name.setPlaceholder(""); } @@ -182,17 +182,17 @@ public class RolloutView extends TableView { private static class RolloutDetails extends FormLayout { - private final HawkbitClient hawkbitClient; + private final transient HawkbitClient hawkbitClient; - private final TextArea description = new TextArea("Description"); - private final TextField createdBy = Utils.textField("Created by"); - private final TextField createdAt = Utils.textField("Created at"); - private final TextField lastModifiedBy = Utils.textField("Last modified by"); - private final TextField lastModifiedAt = Utils.textField("Last modified at"); - private final TextField targetFilter = Utils.textField("Target Filter"); - private final TextField distributionSet = Utils.textField("Distribution Set"); - private final TextField actonType = Utils.textField("Action Type"); - private final TextField startAt = Utils.textField("Start At"); + private final TextArea description = new TextArea(DESCRIPTION); + private final TextField createdBy = Utils.textField(CREATED_BY); + private final TextField createdAt = Utils.textField(CREATED_AT); + private final TextField lastModifiedBy = Utils.textField(LAST_MODIFIED_BY); + private final TextField lastModifiedAt = Utils.textField(LAST_MODIFIED_AT); + private final TextField targetFilter = Utils.textField(TARGET_FILTER); + private final TextField distributionSet = Utils.textField(DISTRIBUTION_SET); + private final TextField actonType = Utils.textField(ACTION_TYPE); + private final TextField startAt = Utils.textField(START_AT); private final SelectionGrid groupGrid; private RolloutDetails(final HawkbitClient hawkbitClient) { @@ -228,9 +228,9 @@ public class RolloutView extends TableView { .getDistributionSet(rollout.getDistributionSetId()).getBody(); distributionSet.setValue(distributionSetMgmt.getName() + ":" + distributionSetMgmt.getVersion()); actonType.setValue(switch (rollout.getType()) { - case SOFT -> "Soft"; - case FORCED -> "Forced"; - case DOWNLOAD_ONLY -> "Download Only"; + case SOFT -> SOFT; + case FORCED -> FORCED; + case DOWNLOAD_ONLY -> DOWNLOAD_ONLY; case TIMEFORCED -> "Scheduled at " + new Date(rollout.getForcetime()); }); startAt.setValue(ObjectUtils.isEmpty(rollout.getStartAt()) ? "" : new Date(rollout.getStartAt()).toString()); @@ -261,7 +261,7 @@ public class RolloutView extends TableView { private final Select actionType; private final DateTimePicker forceTime = new DateTimePicker("Force Time"); private final Select startType; - private final DateTimePicker startAt = new DateTimePicker("Start At"); + private final DateTimePicker startAt = new DateTimePicker(START_AT); private final NumberField groupNumber; private final NumberField triggerThreshold; private final NumberField errorThreshold; @@ -277,66 +277,66 @@ public class RolloutView extends TableView { "Distribution Set", this::readyToCreate, hawkbitClient.getDistributionSetRestApi() - .getDistributionSets(0, 30, "name:asc", null) + .getDistributionSets(0, 30, NAME_ASC, null) .getBody() .getContent() .toArray(new MgmtDistributionSet[0])); distributionSet.setRequiredIndicatorVisible(true); - distributionSet.setItemLabelGenerator(distributionSet -> - distributionSet.getName() + ":" + distributionSet.getVersion()); + distributionSet.setItemLabelGenerator(distributionSetO -> + distributionSetO.getName() + ":" + distributionSetO.getVersion()); distributionSet.setWidthFull(); targetFilter = new Select<>( "Target Filter", this::readyToCreate, hawkbitClient.getTargetFilterQueryRestApi() - .getFilters(0, 30, "name:asc", null, null) + .getFilters(0, 30, NAME_ASC, null, null) .getBody() .getContent() .toArray(new MgmtTargetFilterQuery[0])); targetFilter.setRequiredIndicatorVisible(true); targetFilter.setItemLabelGenerator(MgmtTargetFilterQuery::getName); targetFilter.setWidthFull(); - description = new TextArea("Description"); + description = new TextArea(DESCRIPTION); description.setMinLength(2); description.setWidthFull(); actionType = new Select<>(); - actionType.setLabel("Action Type"); + actionType.setLabel(ACTION_TYPE); actionType.setItems(MgmtActionType.values()); actionType.setValue(MgmtActionType.FORCED); - final ComponentRenderer actionTypeRenderer = new ComponentRenderer<>(actionType -> - switch (actionType) { - case SOFT -> new Text("Soft"); - case FORCED -> new Text("Forced"); - case DOWNLOAD_ONLY -> new Text("Download Only"); + final ComponentRenderer actionTypeRenderer = new ComponentRenderer<>(actionTypeO -> + switch (actionTypeO) { + case SOFT -> new Text(SOFT); + case FORCED -> new Text(FORCED); + case DOWNLOAD_ONLY -> new Text(DOWNLOAD_ONLY); case TIMEFORCED -> forceTime; }); actionType.addValueChangeListener(e -> actionType.setRenderer(actionTypeRenderer)); - actionType.setItemLabelGenerator(startType -> - switch (startType) { - case SOFT -> "Soft"; - case FORCED -> "Forced"; - case DOWNLOAD_ONLY -> "Download Only"; + actionType.setItemLabelGenerator(startTypeO -> + switch (startTypeO) { + case SOFT -> SOFT; + case FORCED -> FORCED; + case DOWNLOAD_ONLY -> DOWNLOAD_ONLY; case TIMEFORCED -> "Time Forced at " + (forceTime.isEmpty() ? "" : " " + forceTime.getValue()); }); actionType.setWidthFull(); startType = new Select<>(); startType.setValue(StartType.MANUAL); - startType.setLabel("Start Type"); + startType.setLabel(START_TYPE); startType.setItems(StartType.values()); startType.setValue(StartType.MANUAL); - final ComponentRenderer startTypeRenderer = new ComponentRenderer<>(startType -> - switch (startType) { - case MANUAL -> new Text("Manual"); - case AUTO -> new Text("Auto"); + final ComponentRenderer startTypeRenderer = new ComponentRenderer<>(startTypeO -> + switch (startTypeO) { + case MANUAL -> new Text(MANUAL); + case AUTO -> new Text(AUTO); case SCHEDULED -> startAt; }); startType.setRenderer(startTypeRenderer); startType.addValueChangeListener(e -> startType.setRenderer(startTypeRenderer)); startType.setItemLabelGenerator(startType -> switch (startType) { - case MANUAL -> "Manual"; - case AUTO -> "Auto"; + case MANUAL -> MANUAL; + case AUTO -> AUTO; case SCHEDULED -> "Scheduled" + (startAt.isEmpty() ? "" : " at " + startAt.getValue()); }); startType.setWidthFull(); @@ -396,17 +396,26 @@ public class RolloutView extends TableView { final MgmtRolloutRestRequestBody request = new MgmtRolloutRestRequestBody(); request.setName(name.getValue()); request.setDistributionSetId(distributionSet.getValue().getDsId()); - request.setTargetFilterQuery(targetFilter.getValue().getName()); + request.setTargetFilterQuery(targetFilter.getValue().getQuery()); request.setDescription(description.getValue()); request.setType(actionType.getValue()); - if (actionType.getValue() == MgmtActionType.FORCED) { - request.setForcetime(forceTime.getValue().toEpochSecond(ZoneOffset.UTC) * 1000); + if (actionType.getValue() == MgmtActionType.TIMEFORCED) { + request.setForcetime( + forceTime.isEmpty() ? + System.currentTimeMillis() : + forceTime.getValue().toEpochSecond(ZoneOffset.UTC) * 1000); } switch (startType.getValue()) { case AUTO -> request.setStartAt(System.currentTimeMillis()); - case SCHEDULED -> request.setStartAt(startAt.getValue().toEpochSecond(ZoneOffset.UTC) * 1000); - } // else - manual, do not start + case SCHEDULED -> request.setStartAt( + startAt.isEmpty() ? + System.currentTimeMillis() : + startAt.getValue().toEpochSecond(ZoneOffset.UTC) * 1000); + case MANUAL -> { + // do nothing, will be started manually + } + } request.setAmountGroups(groupNumber.getValue().intValue()); request.setSuccessCondition( diff --git a/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/SoftwareModuleView.java b/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/SoftwareModuleView.java index a4fce787d..b87dde657 100644 --- a/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/SoftwareModuleView.java +++ b/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/SoftwareModuleView.java @@ -60,7 +60,7 @@ import java.util.stream.Stream; @Route(value = "software_modules", layout = MainLayout.class) @RolesAllowed({"SOFTWARE_MODULE_READ"}) @Uses(Icon.class) -public class SoftwareModuleView extends TableView { +public class SoftwareModuleView extends TableView{ @Autowired public SoftwareModuleView(final HawkbitClient hawkbitClient) { @@ -75,11 +75,11 @@ public class SoftwareModuleView extends TableView { private final SoftwareModuleDetails details = new SoftwareModuleDetails(hawkbitClient); @Override protected void addColumns(final Grid grid) { - grid.addColumn(MgmtSoftwareModule::getModuleId).setHeader("Id").setAutoWidth(true); - grid.addColumn(MgmtSoftwareModule::getName).setHeader("Name").setAutoWidth(true); - grid.addColumn(MgmtSoftwareModule::getVersion).setHeader("Version").setAutoWidth(true); - grid.addColumn(MgmtSoftwareModule::getTypeName).setHeader("Type").setAutoWidth(true); - grid.addColumn(MgmtSoftwareModule::getVendor).setHeader("Vendor").setAutoWidth(true); + grid.addColumn(MgmtSoftwareModule::getModuleId).setHeader(ID).setAutoWidth(true); + grid.addColumn(MgmtSoftwareModule::getName).setHeader(NAME).setAutoWidth(true); + grid.addColumn(MgmtSoftwareModule::getVersion).setHeader(VERSION).setAutoWidth(true); + grid.addColumn(MgmtSoftwareModule::getTypeName).setHeader(TYPE).setAutoWidth(true); + grid.addColumn(MgmtSoftwareModule::getVendor).setHeader(VENDOR).setAutoWidth(true); grid.setItemDetailsRenderer(new ComponentRenderer<>( () -> details, SoftwareModuleDetails::setItem)); @@ -88,7 +88,7 @@ public class SoftwareModuleView extends TableView { }, (query, rsqlFilter) -> hawkbitClient.getSoftwareModuleRestApi() .getSoftwareModules( - query.getOffset(), query.getPageSize(), "name:asc", rsqlFilter) + query.getOffset(), query.getPageSize(), NAME_ASC, rsqlFilter) .getBody() .getContent() .stream(), @@ -110,25 +110,24 @@ public class SoftwareModuleView extends TableView { new SelectionGrid.EntityRepresentation<>(MgmtArtifact.class, MgmtArtifact::getArtifactId) { @Override protected void addColumns(final Grid grid) { - grid.addColumn(MgmtArtifact::getArtifactId).setHeader("Id").setAutoWidth(true); - grid.addColumn(MgmtArtifact::getProvidedFilename).setHeader("Name").setAutoWidth(true); + grid.addColumn(MgmtArtifact::getArtifactId).setHeader(ID).setAutoWidth(true); + grid.addColumn(MgmtArtifact::getProvidedFilename).setHeader(NAME).setAutoWidth(true); grid.addColumn(MgmtArtifact::getSize).setHeader("Size").setAutoWidth(true); - grid.addColumn(MgmtArtifact::getHashes).setHeader("Hashes").setAutoWidth(true); } }); } private static class SoftwareModuleFilter implements Filter.Rsql { - private final TextField name = Utils.textField("Name"); - private final CheckboxGroup type = new CheckboxGroup<>("Type"); + private final TextField name = Utils.textField(NAME); + private final CheckboxGroup type = new CheckboxGroup<>(TYPE); private SoftwareModuleFilter(final HawkbitClient hawkbitClient) { name.setPlaceholder(""); type.setItemLabelGenerator(MgmtSoftwareModuleType::getName); type.setItems( hawkbitClient.getSoftwareModuleTypeRestApi() - .getTypes(0, 20, "name:asc", null) + .getTypes(0, 20, NAME_ASC, null) .getBody() .getContent()); } @@ -151,13 +150,13 @@ public class SoftwareModuleView extends TableView { private static class SoftwareModuleDetails extends FormLayout { - private final HawkbitClient hawkbitClient; + private final transient HawkbitClient hawkbitClient; - private final TextArea description = new TextArea("Description"); - private final TextField createdBy = Utils.textField("Created by"); - private final TextField createdAt = Utils.textField("Created at"); - private final TextField lastModifiedBy = Utils.textField("Last modified by"); - private final TextField lastModifiedAt = Utils.textField("Last modified at"); + private final TextArea description = new TextArea(DESCRIPTION); + private final TextField createdBy = Utils.textField(CREATED_BY); + private final TextField createdAt = Utils.textField(CREATED_AT); + private final TextField lastModifiedBy = Utils.textField(LAST_MODIFIED_BY); + private final TextField lastModifiedAt = Utils.textField(LAST_MODIFIED_AT); private final SelectionGrid artifactGrid; private SoftwareModuleDetails(final HawkbitClient hawkbitClient) { @@ -212,10 +211,10 @@ public class SoftwareModuleView extends TableView { super("Create Software Module"); type = new Select<>( - "Type", + TYPE, this::readyToCreate, hawkbitClient.getSoftwareModuleTypeRestApi() - .getTypes(0, 30, "name:asc", null) + .getTypes(0, 30, NAME_ASC, null) .getBody() .getContent() .toArray(new MgmtSoftwareModuleType[0])); @@ -223,10 +222,10 @@ public class SoftwareModuleView extends TableView { type.setRequiredIndicatorVisible(true); type.setItemLabelGenerator(MgmtSoftwareModuleType::getName); type.focus(); - name = Utils.textField("Name", this::readyToCreate); - version = Utils.textField("Version", this::readyToCreate); - vendor = Utils.textField("Vendor"); - description = new TextArea("Description"); + name = Utils.textField(NAME, this::readyToCreate); + version = Utils.textField(VERSION, this::readyToCreate); + vendor = Utils.textField(VENDOR); + description = new TextArea(DESCRIPTION); description.setWidthFull(); description.setMinLength(2); enableArtifactEncryption = new Checkbox("Enable artifact encryption"); @@ -280,7 +279,7 @@ public class SoftwareModuleView extends TableView { private static class AddArtifactsDialog extends Utils.BaseDialog { - private final Set artifacts = Collections.synchronizedSet(new HashSet<>()); + private final transient Set artifacts = Collections.synchronizedSet(new HashSet<>()); private AddArtifactsDialog( final long softwareModuleId, diff --git a/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/TargetView.java b/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/TargetView.java index 6e86c044c..370dff2a8 100644 --- a/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/TargetView.java +++ b/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/TargetView.java @@ -40,10 +40,6 @@ import org.eclipse.hawkbit.mgmt.json.model.target.MgmtTargetRequestBody; import org.eclipse.hawkbit.mgmt.json.model.targetfilter.MgmtTargetFilterQuery; import org.eclipse.hawkbit.mgmt.json.model.targetfilter.MgmtTargetFilterQueryRequestBody; import org.eclipse.hawkbit.mgmt.json.model.targettype.MgmtTargetType; -import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetFilterQueryRestApi; -import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetRestApi; -import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetTagRestApi; -import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetTypeRestApi; import org.springframework.util.ObjectUtils; import java.util.Collections; @@ -61,12 +57,8 @@ import java.util.stream.Stream; @Uses(Icon.class) public class TargetView extends TableView { - private final HawkbitClient hawkbitClient; - - private final MgmtTargetRestApi targetRestApi; - private final MgmtTargetTypeRestApi targetTypeRestApi; - private final MgmtTargetTagRestApi targetTagRestApi; - private final MgmtTargetFilterQueryRestApi targetFilterQueryRestApi; + public static final String CONTROLLER_ID = "Controller Id"; + public static final String TAG = "Tag"; public TargetView(final HawkbitClient hawkbitClient) { super( @@ -75,9 +67,9 @@ public class TargetView extends TableView { @Override protected void addColumns(final Grid grid) { - grid.addColumn(MgmtTarget::getControllerId).setHeader("Controller Id").setAutoWidth(true); - grid.addColumn(MgmtTarget::getName).setHeader("Name").setAutoWidth(true); - grid.addColumn(MgmtTarget::getTargetTypeName).setHeader("Type").setAutoWidth(true); + grid.addColumn(MgmtTarget::getControllerId).setHeader(CONTROLLER_ID).setAutoWidth(true); + grid.addColumn(MgmtTarget::getName).setHeader(NAME).setAutoWidth(true); + grid.addColumn(MgmtTarget::getTargetTypeName).setHeader(TYPE).setAutoWidth(true); grid.setItemDetailsRenderer(new ComponentRenderer<>( TargetDetails::new, TargetDetails::setItem)); @@ -85,7 +77,7 @@ public class TargetView extends TableView { }, (query, filter) -> hawkbitClient.getTargetRestApi() .getTargets( - query.getOffset(), query.getPageSize(), "name:asc", + query.getOffset(), query.getPageSize(), NAME_ASC, filter) .getBody() .getContent() @@ -96,11 +88,6 @@ public class TargetView extends TableView { hawkbitClient.getTargetRestApi().deleteTarget(toDelete.getControllerId())); return CompletableFuture.completedFuture(null); }); - this.hawkbitClient = hawkbitClient; - this.targetRestApi = hawkbitClient.getTargetRestApi(); - this.targetTypeRestApi = hawkbitClient.getTargetTypeRestApi(); - this.targetTagRestApi = hawkbitClient.getTargetTagRestApi(); - this.targetFilterQueryRestApi = hawkbitClient.getTargetFilterQueryRestApi(); } private static class SimpleFilter implements Filter.Rsql { @@ -114,11 +101,11 @@ public class TargetView extends TableView { private SimpleFilter(final HawkbitClient hawkbitClient) { this.hawkbitClient = hawkbitClient; - controllerId = Utils.textField("Controller Id"); + controllerId = Utils.textField(CONTROLLER_ID); controllerId.setPlaceholder(""); - type = new CheckboxGroup<>("Type"); + type = new CheckboxGroup<>(TYPE); type.setItemLabelGenerator(MgmtTargetType::getName); - tag = new CheckboxGroup<>("Tag"); + tag = new CheckboxGroup<>(TAG); tag.setItemLabelGenerator(MgmtTag::getName); } @@ -126,11 +113,11 @@ public class TargetView extends TableView { public List components() { final List components = new LinkedList<>(); components.add(controllerId); - type.setItems(hawkbitClient.getTargetTypeRestApi().getTargetTypes(0, 20, "name:asc", null).getBody().getContent()); + type.setItems(hawkbitClient.getTargetTypeRestApi().getTargetTypes(0, 20, NAME_ASC, null).getBody().getContent()); if (!type.getValue().isEmpty()) { components.add(type); } - tag.setItems(hawkbitClient.getTargetTagRestApi().getTargetTags(0, 20, "name:asc", null).getBody().getContent()); + tag.setItems(hawkbitClient.getTargetTagRestApi().getTargetTags(0, 20, NAME_ASC, null).getBody().getContent()); if (!tag.isEmpty()) { components.add(tag); } @@ -150,14 +137,10 @@ public class TargetView extends TableView { private static class RawFilter implements Filter.Rsql { - private final HawkbitClient hawkbitClient; - private final TextField textFilter = new TextField("Raw Filter"); private final VerticalLayout layout = new VerticalLayout(); private RawFilter(final HawkbitClient hawkbitClient) { - this.hawkbitClient = hawkbitClient; - textFilter.setPlaceholder(""); final Select savedFilters = new Select<>( "Saved Filters", @@ -178,12 +161,12 @@ public class TargetView extends TableView { textFilter.setWidthFull(); final Button saveBtn = Utils.tooltip(new Button(VaadinIcon.ARCHIVE.create()), "Save (Enter)"); - saveBtn.addClickListener(e -> { - new Utils.BaseDialog("Save Filter") {{ + saveBtn.addClickListener(e -> + new Utils.BaseDialog("Save Filter") {{ setHeight("40%"); final Button finishBtn = Utils.tooltip(new Button("Save"), "Save (Enter)"); final TextField name = Utils.textField( - "Name", + NAME, e -> finishBtn.setEnabled(!e.getHasValue().isEmpty())); name.focus(); finishBtn.addClickShortcut(Key.ENTER); @@ -200,8 +183,7 @@ public class TargetView extends TableView { }); add(name, finishBtn); open(); - }}; - }); + }}); saveBtn.addClickShortcut(Key.ENTER); layout.setSpacing(false); @@ -224,11 +206,11 @@ public class TargetView extends TableView { private static class TargetDetails extends FormLayout { - private final TextArea description = new TextArea("Description"); - private final TextField createdBy = Utils.textField("Created by"); - private final TextField createdAt = Utils.textField("Created at"); - private final TextField lastModifiedBy = Utils.textField("Last modified by"); - private final TextField lastModifiedAt = Utils.textField("Last modified at"); + private final TextArea description = new TextArea(DESCRIPTION); + private final TextField createdBy = Utils.textField(CREATED_BY); + private final TextField createdAt = Utils.textField(CREATED_AT); + private final TextField lastModifiedBy = Utils.textField(LAST_MODIFIED_BY); + private final TextField lastModifiedAt = Utils.textField(LAST_MODIFIED_AT); private TargetDetails() { description.setMinLength(2); @@ -254,7 +236,7 @@ public class TargetView extends TableView { } } - private static class RegisterDialog extends Utils.BaseDialog { + private static class RegisterDialog extends Utils.BaseDialog { private final Select type; private final TextField controllerId; @@ -269,20 +251,19 @@ public class TargetView extends TableView { "Type", e -> {}, hawkbitClient.getTargetTypeRestApi() - .getTargetTypes(0, 30, "name:asc", null) + .getTargetTypes(0, 30, NAME_ASC, null) .getBody() .getContent() .toArray(new MgmtTargetType[0])); type.setWidthFull(); type.setEmptySelectionAllowed(true); type.setItemLabelGenerator(item -> item == null ? "" : item.getName()); - controllerId = Utils.textField( - "Controller Id", + controllerId = Utils.textField(CONTROLLER_ID, e -> register.setEnabled(!e.getHasValue().isEmpty())); controllerId.focus(); - name = Utils.textField("Name"); + name = Utils.textField(NAME); name.setWidthFull(); - description = new TextArea("Description"); + description = new TextArea(DESCRIPTION); description.setMinLength(2); description.setWidthFull(); diff --git a/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/util/Filter.java b/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/util/Filter.java index ba3982559..95650182c 100644 --- a/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/util/Filter.java +++ b/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/util/Filter.java @@ -30,7 +30,7 @@ import java.util.stream.Stream; public class Filter extends Div { - private Rsql rsql; + private transient Rsql rsql; public Filter(final Consumer changeListener, final Rsql primaryRsql, final Rsql secondaryOptionalRsql) { rsql = primaryRsql; @@ -89,7 +89,7 @@ public class Filter extends Div { .entrySet() .stream() .filter(e -> { - if (e.getValue() instanceof Optional opt) { + if (e.getValue() instanceof Optional opt) { return opt.isPresent(); } else { return e.getValue() != null; @@ -100,13 +100,14 @@ public class Filter extends Div { if (normalized.isEmpty()) { return null; } else if (normalized.size() == 1) { - return normalized.entrySet().stream().findFirst().map(e -> filter(e.getKey(), e.getValue())).get(); + return normalized.entrySet().stream() + .findFirst().map(e -> filter(e.getKey(), e.getValue())).orElse(null); // never return null! } else { final StringBuilder sb = new StringBuilder(); normalized.forEach((k, v) -> { if (v instanceof Collection) { sb.append('(').append(filter(k, v)).append(')'); - } else if (v instanceof Optional opt) { + } else if (v instanceof Optional opt) { sb.append(filter(k, opt.get())); } else { sb.append(filter(k, v)); @@ -118,16 +119,20 @@ public class Filter extends Div { } private static String filter(final String key, final Object value) { - if (value == null || (value instanceof Collection coll && coll.isEmpty())) { + if (value == null || (value instanceof Collection coll && coll.isEmpty())) { return null; } - if (value instanceof Collection coll) { + if (value instanceof Collection coll) { final StringBuilder sb = new StringBuilder(); coll.stream().forEach(next -> sb.append(key).append("==").append(next).append(',')); return sb.substring(0, sb.length() - 1); - } else if (value instanceof Optional opt) { - return key + "==" + opt.get(); + } else if (value instanceof Optional opt) { + if (opt.isEmpty()) { + return null; + } else { + return key + "==" + opt.get(); + } } else { return key + "==" + value; } diff --git a/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/util/SelectionGrid.java b/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/util/SelectionGrid.java index 212b4eeb7..d727bfcef 100644 --- a/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/util/SelectionGrid.java +++ b/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/util/SelectionGrid.java @@ -51,7 +51,10 @@ public class SelectionGrid extends Grid { return fetch; } else { final Set selectedIds = new HashSet<>(); - selected.stream().forEach(next -> selectedIds.add(entityRepresentation.idFn.apply(next))); + selected.forEach(next -> selectedIds.add(entityRepresentation.idFn.apply(next))); + // if matching keeps old entries instead of new the new ones in order to + // select them in case refresh is made with keepSelection + // this however means that if they are changed the old state will be shown!!! return Streams.concat(selected.stream(), fetch.filter(next -> !selectedIds.contains(entityRepresentation.idFn.apply(next)))); } @@ -70,7 +73,7 @@ public class SelectionGrid extends Grid { if (keepSelection) { final Set selected = getSelectedItems(); getDataProvider().refreshAll(); - if (selected == null || selected.isEmpty()) { + if (selected != null && !selected.isEmpty()) { selected.forEach(this::select); } } else { diff --git a/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/util/TableView.java b/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/util/TableView.java index bba73e80a..aca4ea957 100644 --- a/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/util/TableView.java +++ b/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/util/TableView.java @@ -9,6 +9,7 @@ */ package com.eclipse.hawkbit.ui.view.util; +import com.eclipse.hawkbit.ui.view.Constants; import com.vaadin.flow.component.html.Div; import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.data.provider.Query; @@ -18,7 +19,7 @@ import java.util.function.BiFunction; import java.util.function.Function; import java.util.stream.Stream; -public class TableView extends Div { +public class TableView extends Div implements Constants { protected SelectionGrid selectionGrid; private final Filter filter; @@ -58,7 +59,9 @@ public class TableView extends Div { layout.setSizeFull(); layout.setPadding(false); layout.setSpacing(false); - Utils.addRemoveControls(addHandler, removeHandler, selectionGrid, false).ifPresent(layout::add); + if (addHandler != null || removeHandler != null) { + layout.add(Utils.addRemoveControls(addHandler, removeHandler, selectionGrid, false)); + } add(layout); } } diff --git a/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/util/Utils.java b/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/util/Utils.java index 3a26e58b1..4609dd4c9 100644 --- a/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/util/Utils.java +++ b/hawkbit-runtime/hawkbit-simple-ui/src/main/java/com/eclipse/hawkbit/ui/view/util/Utils.java @@ -39,6 +39,10 @@ import java.util.function.Function; public class Utils { + private Utils() { + // prevent initialization + } + public static TextField textField(final String label) { return textField(label, null); } @@ -69,12 +73,12 @@ public class Utils { return numberField; } - public static Optional addRemoveControls( + public static HorizontalLayout addRemoveControls( final Function, CompletionStage> addHandler, final Function, CompletionStage> removeHandler, final SelectionGrid selectionGrid, final boolean noPadding) { if (addHandler == null && removeHandler == null) { - return Optional.empty(); + throw new IllegalArgumentException("At least one of add or remove handlers must not be null!"); } final HorizontalLayout layout = new HorizontalLayout(); @@ -100,7 +104,7 @@ public class Utils { .thenAccept(v -> selectionGrid.refreshGrid(false))); layout.add(removeBtn); } - return Optional.of(layout); + return layout; } public static void remove(final Collection remove, final Set from, final Function idFn) { @@ -144,7 +148,7 @@ public class Utils { public static class BaseDialog extends Dialog { - protected final CompletableFuture result = new CompletableFuture<>(); + protected final transient CompletableFuture result = new CompletableFuture<>(); protected BaseDialog(final String headerTitle) { setHeaderTitle(headerTitle);