Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(web2): partial snapshot download #5617

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2021 Eurotech and/or its affiliates and others
* Copyright (c) 2024 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
Expand All @@ -12,50 +12,251 @@
*******************************************************************************/
package org.eclipse.kura.web.client.ui.settings;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import org.eclipse.kura.web.client.messages.Messages;
import org.eclipse.kura.web.client.ui.wires.SnapshotDownloadOptions;
import org.gwtbootstrap3.client.ui.Anchor;
import org.gwtbootstrap3.client.ui.Button;
import org.gwtbootstrap3.client.ui.ListBox;
import org.gwtbootstrap3.client.ui.CheckBox;
import org.gwtbootstrap3.client.ui.FormLabel;
import org.gwtbootstrap3.client.ui.Modal;
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.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.ScrollPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

public class SnapshotDownloadModal extends Composite {

private static SnapshotDownloadModalUiBinder uiBinder = GWT.create(SnapshotDownloadModalUiBinder.class);
private static final Messages MSGS = GWT.create(Messages.class);

private static final String SELECT_ALL_PIDS_SELECTION = "Select All Pids";
private static final String REMOVE_ALL_PIDS_SELECTION = "Remove All Pids";

interface SnapshotDownloadModalUiBinder extends UiBinder<Widget, SnapshotDownloadModal> {
}

@UiField
Paragraph downloadModalDescription;
@UiField
ScrollPanel pidSelectionScrollPanel;
@UiField
Anchor selectOrRemoveAllAnchor;
@UiField
Modal modal;
@UiField
ListBox formatList;
Button downloadXml;
@UiField
Button downloadJson;
@UiField
Button download;
Button cancelButton;
@UiField
FormLabel noPidSelectedError;

boolean areAllPidsSelected = true;
VerticalPanel pidPanel = new VerticalPanel();

private Listener listener = format -> {
};
HandlerRegistration anchorClickHandler;

Consumer<SnapshotDownloadOptions> snapshotDownloadConsumer;

public SnapshotDownloadModal() {

initWidget(uiBinder.createAndBindUi(this));

this.download.addClickHandler(e -> {
this.pidSelectionScrollPanel.setVisible(false);
this.selectOrRemoveAllAnchor.setVisible(false);
this.noPidSelectedError.setVisible(false);
this.noPidSelectedError.setText("Please select at least one pid from the list");

this.cancelButton.addClickHandler(this::onCancelClick);

}

public void show(Consumer<SnapshotDownloadOptions> consumer) {
this.snapshotDownloadConsumer = consumer;
this.modal.setTitle(MSGS.deviceWiregraphDownloadModalTitle());
initWiregraphDownloadButtons();
this.modal.show();
}

public void show(Consumer<SnapshotDownloadOptions> consumer, List<String> availablePids) {
this.snapshotDownloadConsumer = consumer;
this.noPidSelectedError.setVisible(false);
this.modal.setTitle(MSGS.deviceSnapshotDownloadModalTitle());
this.downloadModalDescription.setText(MSGS.deviceSnapshotDownloadModalHint());
initSnapshotPidList(availablePids);
initSnapshotSelectAllAnchor();
initSnapshotScrollPanel();
initSnapshotDownloadButtons();
this.modal.show();
}

/*
* Snapshot Download Inits
*/

private void initSnapshotPidList(List<String> snapshotConfigs) {

this.pidPanel.clear();

List<String> orderedPids = snapshotConfigs.stream().sorted().collect(Collectors.toList());
orderedPids.forEach(pid -> {
CheckBox box = new CheckBox(pid);
box.setValue(true);
box.addClickHandler(this::onCheckboxClick);
this.pidPanel.add(box);
});
}

private void initSnapshotSelectAllAnchor() {
if (this.anchorClickHandler != null) {
this.anchorClickHandler.removeHandler();
}
this.areAllPidsSelected = true;
this.selectOrRemoveAllAnchor.setText(REMOVE_ALL_PIDS_SELECTION);
this.anchorClickHandler = this.selectOrRemoveAllAnchor.addClickHandler(this::selectOrRemoveAllSelection);
this.selectOrRemoveAllAnchor.setVisible(true);
}

private void initSnapshotScrollPanel() {
this.pidSelectionScrollPanel.setAlwaysShowScrollBars(false);
this.pidSelectionScrollPanel.setHeight("350px");
this.pidSelectionScrollPanel.clear();
this.pidSelectionScrollPanel.add(pidPanel);
this.pidSelectionScrollPanel.setVisible(true);
}

private void initSnapshotDownloadButtons() {
this.downloadJson.addClickHandler(e -> {
if (isOnePidSelected()) {
this.modal.hide();
resetScrollPanel();
this.snapshotDownloadConsumer.accept(new SnapshotDownloadOptions("JSON", getSelectedPids()));
} else {
this.noPidSelectedError.setVisible(true);
}

});

this.downloadXml.addClickHandler(e -> {
if (isOnePidSelected()) {
this.modal.hide();
resetScrollPanel();
this.snapshotDownloadConsumer.accept(new SnapshotDownloadOptions("XML", getSelectedPids()));
} else {
this.noPidSelectedError.setVisible(true);
}
});
}

/*
* Wiregraph Snapshot Download Inits
*/

private void initWiregraphDownloadButtons() {

this.downloadJson.addClickHandler(e -> {
this.modal.hide();
this.listener.onDonwload(this.formatList.getSelectedValue());
this.snapshotDownloadConsumer.accept(new SnapshotDownloadOptions("JSON"));
});

this.downloadXml.addClickHandler(e -> {
this.modal.hide();
this.snapshotDownloadConsumer.accept(new SnapshotDownloadOptions("XML"));
});
}

public void show(final Listener listener) {
this.listener = listener;
this.modal.show();
/*
* Utils
*/

private void onCheckboxClick(ClickEvent handler) {
if (noPidSelectedError.isVisible()) {
noPidSelectedError.setVisible(false);
}

checkAllPidsSelected();
updateSelectOrRemoveAllText();

}

public interface Listener {
private void onCancelClick(ClickEvent handler) {
this.modal.hide();
resetScrollPanel();
this.noPidSelectedError.setVisible(false);
}

private Optional<List<String>> getSelectedPids() {
List<String> selectedPids = new ArrayList<>();
this.pidPanel.iterator().forEachRemaining(pid -> {
CheckBox checkBox = (CheckBox) pid;
if (checkBox.getValue().booleanValue() && !checkBox.getText().equals(SELECT_ALL_PIDS_SELECTION)
&& !checkBox.getText().equals(REMOVE_ALL_PIDS_SELECTION)) {
selectedPids.add(checkBox.getText());
}
});

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<Widget> pidPanelIterator = this.pidPanel.iterator();
while (pidPanelIterator.hasNext()) {
CheckBox box = (CheckBox) pidPanelIterator.next();
if (box.getValue().booleanValue()) {
result = true;
break;
}
}

return result;
}

private void checkAllPidsSelected() {
boolean areAllSelected = true;
Iterator<Widget> pidPanelIterator = this.pidPanel.iterator();
while (pidPanelIterator.hasNext()) {
if (!((CheckBox) pidPanelIterator.next()).getValue().booleanValue()) {
areAllSelected = false;
break;
}
}
this.areAllPidsSelected = areAllSelected;
}

private void updateSelectOrRemoveAllText() {
if (this.areAllPidsSelected) {
this.selectOrRemoveAllAnchor.setText(REMOVE_ALL_PIDS_SELECTION);
} else {
this.selectOrRemoveAllAnchor.setText(SELECT_ALL_PIDS_SELECTION);
}
}

public void onDonwload(String format);
private void resetScrollPanel() {
this.pidSelectionScrollPanel.setVerticalScrollPosition(0);
this.pidSelectionScrollPanel.setHorizontalScrollPosition(0);
this.noPidSelectedError.setVisible(false);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<!--

Copyright (c) 2021 Eurotech and/or its affiliates and others
Copyright (c) 2024 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
Expand All @@ -22,24 +22,34 @@

<ui:with field="msgs" type="org.eclipse.kura.web.client.messages.Messages" />

<b:Modal closable="false" fade="true" dataBackdrop="STATIC" ui:field="modal" title="{msgs.deviceSnapshotDownloadModalTitle}">
<ui:style>
.channel-name-validation-label {
padding-top: 10px;
color: red;
font-size: 0.35cm;
font-weight: normal;
}
</ui:style>

<b:Modal closable="false" fade="true" dataBackdrop="STATIC" ui:field="modal">
<b:ModalBody>
<g:FormPanel>
<b:FieldSet>
<b:FormGroup>
<b.html:Paragraph text="{msgs.deviceSnapshotDownloadModalLabel}" />
<b:ListBox b:id="formatList" ui:field="formatList">
<g:item>XML</g:item>
<g:item>JSON</g:item>
</b:ListBox>
<b.html:Paragraph ui:field="downloadModalDescription" />
<g:ScrollPanel ui:field="pidSelectionScrollPanel"></g:ScrollPanel>
<b:FormLabel addStyleNames="{style.channel-name-validation-label}" ui:field="noPidSelectedError" />
</b:FormGroup>
</b:FieldSet>
</g:FormPanel>
<b:Anchor ui:field="selectOrRemoveAllAnchor" />
</b:ModalBody>
<b:ModalFooter>
<b:Button addStyleNames="fa" type="PRIMARY" dataDismiss="MODAL" text="{msgs.cancelButton}" />
<b:Button addStyleNames="fa" type="PRIMARY" ui:field="download" text="{msgs.download}" />
<b.html:Paragraph text="Choose the format in which the file will be downloaded" />
<b:Button addStyleNames="fa" type="PRIMARY" ui:field= "cancelButton" text="{msgs.cancelButton}" />
<b:Button addStyleNames="fa" type="PRIMARY" ui:field="downloadJson" text="{msgs.downloadSnapshotJsonButton}" />
<b:Button addStyleNames="fa" type="PRIMARY" ui:field="downloadXml" text="{msgs.downloadSnapshotXmlButton}" />
</b:ModalFooter>
</b:Modal>

</ui:UiBinder>
</ui:UiBinder>
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2011, 2021 Eurotech and/or its affiliates and others
* Copyright (c) 2011, 2024 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
Expand Down Expand Up @@ -350,16 +350,36 @@ public void onSuccess(Void result) {
}

private void downloadSnapshot(GwtXSRFToken token) {
final StringBuilder sbUrl = new StringBuilder();

Long snapshot = this.selected.getSnapshotId();
this.gwtSnapshotService.getSnapshotConfigurationFromSid(token, snapshot.longValue(),
new AsyncCallback<List<String>>() {

downloadModal.show(format -> {
sbUrl.append("/device_snapshots?snapshotId=").append(snapshot).append("&format=").append(format);
@Override
public void onFailure(Throwable ex) {
FailureHandler.handle(ex);
}

DownloadHelper.instance().startDownload(token, sbUrl.toString());
});
@Override
public void onSuccess(List<String> configs) {
downloadModal.show(snapshotDownloadOptions -> {

final StringBuilder sbUrl = new StringBuilder();

sbUrl.append("/device_snapshots?snapshotId=").append(snapshot).append("&format=")
.append(snapshotDownloadOptions.getFormat());

if (snapshotDownloadOptions.getSelectedPids().isPresent()) {

DownloadHelper.instance().startDownload(token, sbUrl.toString(),
snapshotDownloadOptions.getSelectedPids().get());

} else {
DownloadHelper.instance().startDownload(token, sbUrl.toString());
}
}, configs);
}
});
}

private void uploadAndApply() {
Expand Down
Loading
Loading