Integrated Maintenance Window fields in Management API and UI (#677)

* Added Maintenance Window properties to API and UI

* extended Management API with Maintenance Window schedule, duration, timezone and nextAt properties
* extended integration tests for the above properties
* extended Management UI with Maintenance Window column in Action History grid, added tooltip for next execution
* general refactoring

Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch-si.com>

* fixed Sonar issues

Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch-si.com>

* changed the documentation help link for maintenance window

Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch-si.com>

* added licence header, first refactoring after partial PR review

Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch-si.com>

* changes related to PR review findings

Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch-si.com>

* last PR review findings

Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch-si.com>
This commit is contained in:
Bondar Bogdan
2018-05-15 11:12:33 +02:00
committed by Dominic Schabel
parent 1deb47a4db
commit b5114081be
22 changed files with 474 additions and 210 deletions

View File

@@ -8,12 +8,16 @@
*/
package org.eclipse.hawkbit.ui.common.grid;
import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.Locale;
import java.util.Objects;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.components.RefreshableContainer;
import org.eclipse.hawkbit.ui.management.actionhistory.ProxyAction;
import org.eclipse.hawkbit.ui.management.actionhistory.ProxyActionStatus;
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
@@ -284,8 +288,8 @@ public abstract class AbstractGrid<T extends Indexed> extends Grid implements Re
/**
* Template method invoked by {@link this#addNewContainerDS()} for adding
* properties to the container (usually by invoing
* {@link Container#addContainerProperty(Object, Class, Object))})
* properties to the container (usually by invoking { @link
* Container#addContainerProperty(Object, Class, Object))})
*/
protected abstract void addContainerProperties();
@@ -581,7 +585,7 @@ public abstract class AbstractGrid<T extends Indexed> extends Grid implements Re
* CellStyleGenerator that concerns about alignment in the grid cells.
*/
protected static class AlignCellStyleGenerator implements CellStyleGenerator {
private static final long serialVersionUID = 5573570647129792429L;
private static final long serialVersionUID = 1L;
private final String[] left;
private final String[] center;
@@ -621,29 +625,40 @@ public abstract class AbstractGrid<T extends Indexed> extends Grid implements Re
}
/**
* Adds a tooltip to the 'Date and time' column in detailed format.
* Adds a tooltip to the 'Date and time' and 'Maintenance Window' columns in
* detailed format.
*/
public static class ModifiedTimeTooltipGenerator implements CellDescriptionGenerator {
private static final long serialVersionUID = -6617911967167729195L;
protected static class TooltipGenerator implements CellDescriptionGenerator {
private static final long serialVersionUID = 1L;
private final String datePropertyId;
private final VaadinMessageSource i18n;
/**
* Constructor.
*
* @param datePropertyId
*/
public ModifiedTimeTooltipGenerator(final String datePropertyId) {
this.datePropertyId = datePropertyId;
public TooltipGenerator(final VaadinMessageSource i18n) {
this.i18n = i18n;
}
@Override
public String getDescription(final CellReference cell) {
if (!datePropertyId.equals(cell.getPropertyId())) {
final String propertyId = (String) cell.getPropertyId();
switch (propertyId) {
case ProxyAction.PXY_ACTION_LAST_MODIFIED_AT:
case ProxyActionStatus.PXY_AS_CREATED_AT:
final Long timestamp = (Long) cell.getItem().getItemProperty(propertyId).getValue();
return SPDateTimeUtil.getFormattedDate(timestamp);
case ProxyAction.PXY_ACTION_MAINTENANCE_WINDOW:
final Action action = (Action) cell.getItem().getItemProperty(ProxyAction.PXY_ACTION).getValue();
return action.getMaintenanceWindowStartTime().map(this::getFormattedNextMaintenanceWindow).orElse(null);
default:
return null;
}
final Long timestamp = (Long) cell.getItem().getItemProperty(datePropertyId).getValue();
return SPDateTimeUtil.getFormattedDate(timestamp);
}
private String getFormattedNextMaintenanceWindow(final ZonedDateTime nextAt) {
final long nextAtMilli = nextAt.toInstant().toEpochMilli();
return i18n.getMessage("tooltip.next.maintenancewindow",
SPDateTimeUtil.getFormattedDate(nextAtMilli, SPUIDefinitions.LAST_QUERY_DATE_FORMAT_SHORT));
}
}

View File

@@ -115,12 +115,19 @@ public class ActionBeanQuery extends AbstractBeanQuery<ProxyAction> {
proxyAction.setLastModifiedAt(action.getLastModifiedAt());
proxyAction.setRolloutName(action.getRollout() != null ? action.getRollout().getName() : "");
proxyAction.setStatus(action.getStatus());
proxyAction.setMaintenanceWindow(
action.hasMaintenanceSchedule() ? buildMaintenanceWindowDisplayText(action) : "");
proxyActions.add(proxyAction);
}
return proxyActions;
}
private static String buildMaintenanceWindowDisplayText(final Action action) {
return action.getMaintenanceWindowSchedule() + "/" + action.getMaintenanceWindowDuration() + "/"
+ action.getMaintenanceWindowTimeZone();
}
/**
* Generates a virtual IsActiveDecoration for the presentation layer that is
* calculated from {@link Action#isActive()} and

View File

@@ -78,13 +78,14 @@ public class ActionHistoryGrid extends AbstractGrid<LazyQueryContainer> {
private static final Object[] maxColumnOrder = new Object[] { ProxyAction.PXY_ACTION_IS_ACTIVE_DECO,
ProxyAction.PXY_ACTION_ID, ProxyAction.PXY_ACTION_DS_NAME_VERSION, ProxyAction.PXY_ACTION_LAST_MODIFIED_AT,
ProxyAction.PXY_ACTION_STATUS, ProxyAction.PXY_ACTION_ROLLOUT_NAME, VIRT_PROP_FORCED, VIRT_PROP_TIMEFORCED,
VIRT_PROP_ACTION_CANCEL, VIRT_PROP_ACTION_FORCE, VIRT_PROP_ACTION_FORCE_QUIT };
ProxyAction.PXY_ACTION_STATUS, ProxyAction.PXY_ACTION_MAINTENANCE_WINDOW,
ProxyAction.PXY_ACTION_ROLLOUT_NAME, VIRT_PROP_FORCED, VIRT_PROP_TIMEFORCED, VIRT_PROP_ACTION_CANCEL,
VIRT_PROP_ACTION_FORCE, VIRT_PROP_ACTION_FORCE_QUIT };
private static final Object[] minColumnOrder = new Object[] { ProxyAction.PXY_ACTION_IS_ACTIVE_DECO,
ProxyAction.PXY_ACTION_DS_NAME_VERSION, ProxyAction.PXY_ACTION_LAST_MODIFIED_AT,
ProxyAction.PXY_ACTION_STATUS, VIRT_PROP_FORCED, VIRT_PROP_TIMEFORCED, VIRT_PROP_ACTION_CANCEL,
VIRT_PROP_ACTION_FORCE, VIRT_PROP_ACTION_FORCE_QUIT };
ProxyAction.PXY_ACTION_STATUS, ProxyAction.PXY_ACTION_MAINTENANCE_WINDOW, VIRT_PROP_FORCED,
VIRT_PROP_TIMEFORCED, VIRT_PROP_ACTION_CANCEL, VIRT_PROP_ACTION_FORCE, VIRT_PROP_ACTION_FORCE_QUIT };
private static final String[] leftAlignedColumns = new String[] { VIRT_PROP_TIMEFORCED };
@@ -99,7 +100,7 @@ public class ActionHistoryGrid extends AbstractGrid<LazyQueryContainer> {
private Target selectedTarget;
private final AlignCellStyleGenerator alignGenerator;
private final ModifiedTimeTooltipGenerator modTimetooltipGenerator;
private final TooltipGenerator tooltipGenerator;
private final Map<Action.Status, StatusFontIcon> states;
private final Map<IsActiveDecoration, StatusFontIcon> activeStates;
@@ -139,7 +140,7 @@ public class ActionHistoryGrid extends AbstractGrid<LazyQueryContainer> {
activeStates = conf
.createActiveStatusLabelConfig(UIComponentIdProvider.ACTION_HISTORY_TABLE_ACTIVESTATE_LABEL_ID);
alignGenerator = new AlignCellStyleGenerator(leftAlignedColumns, centerAlignedColumns, rightAlignedColumns);
modTimetooltipGenerator = new ModifiedTimeTooltipGenerator(ProxyAction.PXY_ACTION_LAST_MODIFIED_AT);
tooltipGenerator = new TooltipGenerator(i18n);
init();
}
@@ -208,6 +209,7 @@ public class ActionHistoryGrid extends AbstractGrid<LazyQueryContainer> {
rawCont.addContainerProperty(ProxyAction.PXY_ACTION_ID, String.class, null, true, true);
rawCont.addContainerProperty(ProxyAction.PXY_ACTION_ROLLOUT_NAME, String.class, null, true, true);
rawCont.addContainerProperty(ProxyAction.PXY_ACTION_MAINTENANCE_WINDOW, String.class, null, true, false);
}
@Override
@@ -436,11 +438,14 @@ public class ActionHistoryGrid extends AbstractGrid<LazyQueryContainer> {
getColumn(VIRT_PROP_ACTION_CANCEL).setHidable(false);
getColumn(VIRT_PROP_ACTION_FORCE).setHidable(false);
getColumn(VIRT_PROP_ACTION_FORCE_QUIT).setHidable(false);
getColumn(ProxyAction.PXY_ACTION_MAINTENANCE_WINDOW).setHidden(true);
getColumn(ProxyAction.PXY_ACTION_MAINTENANCE_WINDOW).setHidable(true);
}
@Override
protected CellDescriptionGenerator getDescriptionGenerator() {
return modTimetooltipGenerator;
return tooltipGenerator;
}
@Override
@@ -451,6 +456,8 @@ public class ActionHistoryGrid extends AbstractGrid<LazyQueryContainer> {
getColumn(ProxyAction.PXY_ACTION_DS_NAME_VERSION).setHeaderCaption(SPUIDefinitions.ACTION_HIS_TBL_DIST);
getColumn(ProxyAction.PXY_ACTION_LAST_MODIFIED_AT).setHeaderCaption(SPUIDefinitions.ACTION_HIS_TBL_DATETIME);
getColumn(ProxyAction.PXY_ACTION_STATUS).setHeaderCaption(SPUIDefinitions.ACTION_HIS_TBL_STATUS);
getColumn(ProxyAction.PXY_ACTION_MAINTENANCE_WINDOW)
.setHeaderCaption(SPUIDefinitions.ACTION_HIS_TBL_MAINTENANCE_WINDOW);
getColumn(VIRT_PROP_FORCED).setHeaderCaption(String.valueOf(forceClientRefreshToggle));
forceClientRefreshToggle = !forceClientRefreshToggle;
@@ -463,8 +470,9 @@ public class ActionHistoryGrid extends AbstractGrid<LazyQueryContainer> {
protected void setColumnExpandRatio() {
setColumnsSize(50.0, 50.0, ProxyAction.PXY_ACTION_IS_ACTIVE_DECO);
setColumnsSize(107.0, 500.0, ProxyAction.PXY_ACTION_DS_NAME_VERSION);
setColumnsSize(100.0, 120.0, ProxyAction.PXY_ACTION_LAST_MODIFIED_AT);
setColumnsSize(100.0, 130.0, ProxyAction.PXY_ACTION_LAST_MODIFIED_AT);
setColumnsSize(53.0, 55.0, ProxyAction.PXY_ACTION_STATUS);
setColumnsSize(150.0, 200.0, ProxyAction.PXY_ACTION_MAINTENANCE_WINDOW);
setColumnsSize(FIXED_PIX_MIN, FIXED_PIX_MIN, VIRT_PROP_FORCED, VIRT_PROP_TIMEFORCED, VIRT_PROP_ACTION_CANCEL,
VIRT_PROP_ACTION_FORCE, VIRT_PROP_ACTION_FORCE_QUIT);
}

View File

@@ -36,7 +36,7 @@ public class ActionStatusGrid extends AbstractGrid<LazyQueryContainer> {
private static final String[] centerAlignedColumns = new String[] { ProxyActionStatus.PXY_AS_STATUS };
private final AlignCellStyleGenerator alignGenerator;
private final ModifiedTimeTooltipGenerator modTimetooltipGenerator;
private final TooltipGenerator tooltipGenerator;
private final Map<Action.Status, StatusFontIcon> states;
@@ -58,7 +58,7 @@ public class ActionStatusGrid extends AbstractGrid<LazyQueryContainer> {
final LabelConfig conf = new ActionHistoryGrid.LabelConfig();
states = conf.createStatusLabelConfig(i18n, UIComponentIdProvider.ACTION_STATUS_GRID_STATUS_LABEL_ID);
alignGenerator = new AlignCellStyleGenerator(leftAlignedColumns, centerAlignedColumns, null);
modTimetooltipGenerator = new ModifiedTimeTooltipGenerator(ProxyActionStatus.PXY_AS_CREATED_AT);
tooltipGenerator = new TooltipGenerator(i18n);
init();
}
@@ -153,7 +153,7 @@ public class ActionStatusGrid extends AbstractGrid<LazyQueryContainer> {
@Override
protected CellDescriptionGenerator getDescriptionGenerator() {
return modTimetooltipGenerator;
return tooltipGenerator;
}
}

View File

@@ -26,6 +26,7 @@ public class ProxyAction implements Serializable {
public static final String PXY_ACTION = "action";
public static final String PXY_ACTION_LAST_MODIFIED_AT = "lastModifiedAt";
public static final String PXY_ACTION_ROLLOUT_NAME = "rolloutName";
public static final String PXY_ACTION_MAINTENANCE_WINDOW = "maintenanceWindow";
private Action.Status status;
private boolean isActive;
@@ -35,6 +36,15 @@ public class ProxyAction implements Serializable {
private Action action;
private Long lastModifiedAt;
private String rolloutName;
private String maintenanceWindow;
public String getMaintenanceWindow() {
return maintenanceWindow;
}
public void setMaintenanceWindow(final String maintenanceWindow) {
this.maintenanceWindow = maintenanceWindow;
}
/**
* Get id for the entry.
@@ -51,7 +61,7 @@ public class ProxyAction implements Serializable {
* @param id
* of the action entry.
*/
public void setId(Long id) {
public void setId(final Long id) {
this.id = id;
}
@@ -70,7 +80,7 @@ public class ProxyAction implements Serializable {
* @param status
* literal
*/
public void setStatus(Action.Status status) {
public void setStatus(final Action.Status status) {
this.status = status;
}
@@ -91,7 +101,7 @@ public class ProxyAction implements Serializable {
* <code>true</code> if the action is active, otherwise
* <code>false</code>
*/
public void setActive(boolean isActive) {
public void setActive(final boolean isActive) {
this.isActive = isActive;
}
@@ -113,7 +123,7 @@ public class ProxyAction implements Serializable {
* @param isActiveDecoration
* pre-calculated literal
*/
public void setIsActiveDecoration(IsActiveDecoration isActiveDecoration) {
public void setIsActiveDecoration(final IsActiveDecoration isActiveDecoration) {
this.isActiveDecoration = isActiveDecoration;
}
@@ -133,7 +143,7 @@ public class ProxyAction implements Serializable {
* @param dsNameVersion
* combined value
*/
public void setDsNameVersion(String dsNameVersion) {
public void setDsNameVersion(final String dsNameVersion) {
this.dsNameVersion = dsNameVersion;
}
@@ -151,7 +161,7 @@ public class ProxyAction implements Serializable {
*
* @param action
*/
public void setAction(Action action) {
public void setAction(final Action action) {
this.action = action;
}
@@ -170,7 +180,7 @@ public class ProxyAction implements Serializable {
* @param lastModifiedAt
* raw long-value for lastModifiedAt-date
*/
public void setLastModifiedAt(Long lastModifiedAt) {
public void setLastModifiedAt(final Long lastModifiedAt) {
this.lastModifiedAt = lastModifiedAt;
}
@@ -188,7 +198,7 @@ public class ProxyAction implements Serializable {
*
* @param rolloutName
*/
public void setRolloutName(String rolloutName) {
public void setRolloutName(final String rolloutName) {
this.rolloutName = rolloutName;
}

View File

@@ -84,7 +84,7 @@ public class MaintenanceWindowLayout extends VerticalLayout {
* Text field to specify the schedule.
*/
private void createMaintenanceScheduleControl() {
schedule = new TextFieldBuilder(Action.MAINTENANCE_SCHEDULE_CRON_LENGTH)
schedule = new TextFieldBuilder(Action.MAINTENANCE_WINDOW_SCHEDULE_LENGTH)
.id(UIComponentIdProvider.MAINTENANCE_WINDOW_SCHEDULE_ID)
.caption(i18n.getMessage("caption.maintenancewindow.schedule")).validator(new CronValidator())
.prompt("0 0 3 ? * 6").required(true, i18n).buildTextComponent();
@@ -259,6 +259,7 @@ public class MaintenanceWindowLayout extends VerticalLayout {
schedule.setValue("");
duration.setValue("");
timeZone.setValue(getClientTimeZone());
scheduleTranslator.setValue(i18n.getMessage(CRON_VALIDATION_ERROR));
}
/**

View File

@@ -561,6 +561,8 @@ public final class SPUIDefinitions {
*/
public static final String SP_BUTTON_STATUS_STYLE = "targetStatusBtn";
public static final String ACTION_HIS_TBL_MAINTENANCE_WINDOW = "Maintenance Window";
/**
* /** Constructor.
*/

View File

@@ -251,6 +251,7 @@ tooltip.check.for.mandatory=Check to make Mandatory
tooltip.artifact.icon=Show Artifact Details
tooltip.click.to.edit = Click to edit
tooltip.metadata.icon = Manage Metadata
tooltip.next.maintenancewindow = next on {0}
#rollout action
tooltip.rollout.run = Run
tooltip.rollout.pause = Pause