diff --git a/kura/org.eclipse.kura.web2/src/main/java/org/eclipse/kura/web/client/ui/settings/PartialSnapshotCheckboxStatus.java b/kura/org.eclipse.kura.web2/src/main/java/org/eclipse/kura/web/client/ui/settings/PartialSnapshotCheckboxStatus.java new file mode 100644 index 0000000000..443654a139 --- /dev/null +++ b/kura/org.eclipse.kura.web2/src/main/java/org/eclipse/kura/web/client/ui/settings/PartialSnapshotCheckboxStatus.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2025 Eurotech and/or its affiliates and others + * + * 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 + * + * Contributors: + * Eurotech + *******************************************************************************/ + +package org.eclipse.kura.web.client.ui.settings; + +public enum PartialSnapshotCheckboxStatus { + + ALL_VISIBLE_ALL_SELECTED, + ALL_VISIBLE_PARTIAL_SELECTED, + PARTIAL_VISIBLE_ALL_SELECTED, + PARTIAL_VISIBLE_PARTIAL_SELECTED; + + public static PartialSnapshotCheckboxStatus fromVisibleAndSelectedStatus(boolean allVisible, boolean allSelected) { + if (allVisible) { + if (allSelected) { + return PartialSnapshotCheckboxStatus.ALL_VISIBLE_ALL_SELECTED; + } else { + return PartialSnapshotCheckboxStatus.ALL_VISIBLE_PARTIAL_SELECTED; + } + } else { + if (allSelected) { + return PartialSnapshotCheckboxStatus.PARTIAL_VISIBLE_ALL_SELECTED; + } else { + return PartialSnapshotCheckboxStatus.PARTIAL_VISIBLE_PARTIAL_SELECTED; + } + } + } + +} diff --git a/kura/org.eclipse.kura.web2/src/main/java/org/eclipse/kura/web/client/ui/settings/SnapshotDownloadModal.java b/kura/org.eclipse.kura.web2/src/main/java/org/eclipse/kura/web/client/ui/settings/SnapshotDownloadModal.java index 8f9dbd013a..aeb743f2ae 100644 --- a/kura/org.eclipse.kura.web2/src/main/java/org/eclipse/kura/web/client/ui/settings/SnapshotDownloadModal.java +++ b/kura/org.eclipse.kura.web2/src/main/java/org/eclipse/kura/web/client/ui/settings/SnapshotDownloadModal.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2024 Eurotech and/or its affiliates and others + * Copyright (c) 2024, 2025 Eurotech and/or its affiliates and others * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 @@ -26,14 +26,17 @@ import org.gwtbootstrap3.client.ui.CheckBox; import org.gwtbootstrap3.client.ui.FormLabel; import org.gwtbootstrap3.client.ui.Modal; +import org.gwtbootstrap3.client.ui.TextBox; import org.gwtbootstrap3.client.ui.html.Paragraph; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.ScrollPanel; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; @@ -51,6 +54,12 @@ interface SnapshotDownloadModalUiBinder extends UiBinder consumer) { public void show(Consumer consumer, List availablePids) { this.snapshotDownloadConsumer = consumer; this.noPidSelectedError.setVisible(false); + this.searchBoxSeparatorSmall.setVisible(true); + this.searchBoxSeparatorBig.setVisible(true); this.modal.setTitle(MSGS.deviceSnapshotDownloadModalTitle()); this.downloadModalDescription.setText(MSGS.deviceSnapshotDownloadModalHint()); + initPidSearch(); initSnapshotPidList(availablePids); initSnapshotSelectAllAnchor(); initSnapshotScrollPanel(); initSnapshotDownloadButtons(); + initSelectedPidCounter(); this.modal.show(); } @@ -108,6 +126,12 @@ public void show(Consumer consumer, List availa * Snapshot Download Inits */ + private void initPidSearch() { + this.pidSearch.clear(); + this.pidSearch.setVisible(true); + this.pidSearch.addKeyUpHandler(this::onSearchBoxEvent); + } + private void initSnapshotPidList(List snapshotConfigs) { this.pidPanel.clear(); @@ -125,9 +149,8 @@ private void initSnapshotSelectAllAnchor() { if (this.anchorClickHandler != null) { this.anchorClickHandler.removeHandler(); } - this.areAllPidsSelected = true; this.selectOrRemoveAllAnchor.setText(MSGS.removeAllAnchorText()); - this.anchorClickHandler = this.selectOrRemoveAllAnchor.addClickHandler(this::selectOrRemoveAllSelection); + this.anchorClickHandler = this.selectOrRemoveAllAnchor.addClickHandler(this::onSelectOrRemoveAllSelection); this.selectOrRemoveAllAnchor.setVisible(true); } @@ -162,6 +185,11 @@ private void initSnapshotDownloadButtons() { }); } + private void initSelectedPidCounter() { + updateSelectedPidsCounter(); + this.selectedPidCounter.setVisible(true); + } + /* * Wiregraph Snapshot Download Inits */ @@ -180,16 +208,34 @@ private void initWiregraphDownloadButtons() { } /* - * Utils + * OnEvents Methods */ + private void onSearchBoxEvent(KeyUpEvent event) { + TextBox searchBox = (TextBox) event.getSource(); + String searchedPid = searchBox.getValue(); + + if (searchedPid == null || searchedPid.isEmpty() || searchedPid.equals("")) { + this.pidPanel.iterator().forEachRemaining(widget -> widget.setVisible(true)); + } else { + this.pidPanel.iterator() + .forEachRemaining(widget -> widget.setVisible(isMatchingSearch(widget, searchedPid))); + } + + if (this.noPidSelectedError.isVisible()) { + this.noPidSelectedError.setVisible(false); + } + + updateSelectOrRemoveAllText(checkPidsCheckboxStates()); + } + private void onCheckboxClick(ClickEvent handler) { if (noPidSelectedError.isVisible()) { noPidSelectedError.setVisible(false); } - checkAllPidsSelected(); - updateSelectOrRemoveAllText(); + updateSelectOrRemoveAllText(checkPidsCheckboxStates()); + updateSelectedPidsCounter(); } @@ -199,6 +245,41 @@ private void onCancelClick(ClickEvent handler) { this.noPidSelectedError.setVisible(false); } + private void onSelectOrRemoveAllSelection(ClickEvent handler) { + PartialSnapshotCheckboxStatus state = checkPidsCheckboxStates(); + switch (state) { + case ALL_VISIBLE_ALL_SELECTED: + case PARTIAL_VISIBLE_ALL_SELECTED: { + pidPanel.iterator().forEachRemaining(widget -> { + if (widget.isVisible()) { + ((CheckBox) widget).setValue(false); + } + }); + break; + } + + case ALL_VISIBLE_PARTIAL_SELECTED: + case PARTIAL_VISIBLE_PARTIAL_SELECTED: + pidPanel.iterator().forEachRemaining(widget -> { + if (widget.isVisible()) { + ((CheckBox) widget).setValue(true); + } + }); + break; + } + + updateSelectOrRemoveAllText(checkPidsCheckboxStates()); + updateSelectedPidsCounter(); + + if (this.noPidSelectedError.isVisible()) { + this.noPidSelectedError.setVisible(false); + } + } + + /* + * Utils + */ + private Optional> getSelectedPids() { List selectedPids = new ArrayList<>(); this.pidPanel.iterator().forEachRemaining(pid -> { @@ -212,12 +293,6 @@ private Optional> getSelectedPids() { return selectedPids.isEmpty() ? Optional.empty() : Optional.of(selectedPids); } - private void selectOrRemoveAllSelection(ClickEvent handler) { - pidPanel.iterator().forEachRemaining(widget -> ((CheckBox) widget).setValue(!this.areAllPidsSelected)); - this.areAllPidsSelected = !this.areAllPidsSelected; - updateSelectOrRemoveAllText(); - } - private boolean isOnePidSelected() { boolean result = false; Iterator pidPanelIterator = this.pidPanel.iterator(); @@ -232,23 +307,45 @@ private boolean isOnePidSelected() { return result; } - private void checkAllPidsSelected() { + private PartialSnapshotCheckboxStatus checkPidsCheckboxStates() { + boolean areAllVisible = true; boolean areAllSelected = true; - Iterator pidPanelIterator = this.pidPanel.iterator(); - while (pidPanelIterator.hasNext()) { - if (!((CheckBox) pidPanelIterator.next()).getValue().booleanValue()) { + + for (Widget widget : pidPanel) { + if (!widget.isVisible()) { + areAllVisible = false; + break; + } + } + + for (Widget widget : pidPanel) { + if (widget.isVisible() && !((CheckBox) widget).getValue().booleanValue()) { areAllSelected = false; break; } } - this.areAllPidsSelected = areAllSelected; + + return PartialSnapshotCheckboxStatus.fromVisibleAndSelectedStatus(areAllVisible, areAllSelected); } - private void updateSelectOrRemoveAllText() { - if (this.areAllPidsSelected) { + private void updateSelectOrRemoveAllText(PartialSnapshotCheckboxStatus state) { + + switch (state) { + case ALL_VISIBLE_ALL_SELECTED: this.selectOrRemoveAllAnchor.setText(MSGS.removeAllAnchorText()); - } else { + break; + + case ALL_VISIBLE_PARTIAL_SELECTED: this.selectOrRemoveAllAnchor.setText(MSGS.selectAllAnchorText()); + break; + + case PARTIAL_VISIBLE_ALL_SELECTED: + this.selectOrRemoveAllAnchor.setText(MSGS.removeAllVisibleAnchorText()); + break; + + case PARTIAL_VISIBLE_PARTIAL_SELECTED: + this.selectOrRemoveAllAnchor.setText(MSGS.selectAllVisibleAnchorText()); + break; } } @@ -258,4 +355,24 @@ private void resetScrollPanel() { this.noPidSelectedError.setVisible(false); } + private void updateSelectedPidsCounter() { + + int selectedPids = 0; + + Iterator pidPanelIterator = this.pidPanel.iterator(); + while (pidPanelIterator.hasNext()) { + if (((CheckBox) pidPanelIterator.next()).getValue().booleanValue()) { + selectedPids++; + } + } + + StringBuilder counterTextBuilder = new StringBuilder("PIDs Selected ").append(selectedPids).append("/") + .append(this.pidPanel.getWidgetCount()); + + this.selectedPidCounter.setText(counterTextBuilder.toString()); + } + + private boolean isMatchingSearch(Widget widget, String searchedPid) { + return ((CheckBox) widget).getText().toLowerCase().contains(searchedPid.toLowerCase()); + } } diff --git a/kura/org.eclipse.kura.web2/src/main/java/org/eclipse/kura/web/client/ui/settings/SnapshotDownloadModal.ui.xml b/kura/org.eclipse.kura.web2/src/main/java/org/eclipse/kura/web/client/ui/settings/SnapshotDownloadModal.ui.xml index 32fbabf909..9e042ad8bb 100644 --- a/kura/org.eclipse.kura.web2/src/main/java/org/eclipse/kura/web/client/ui/settings/SnapshotDownloadModal.ui.xml +++ b/kura/org.eclipse.kura.web2/src/main/java/org/eclipse/kura/web/client/ui/settings/SnapshotDownloadModal.ui.xml @@ -2,7 +2,7 @@