Skip to content

Commit f6cf2bf

Browse files
feat: add download provider, upload components, measurement presenter, QC dialogs, and haproxy config
1 parent 8262497 commit f6cf2bf

11 files changed

Lines changed: 1633 additions & 0 deletions

File tree

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package life.qbic.datamanager.download;
2+
3+
import com.vaadin.flow.component.UI;
4+
import com.vaadin.flow.component.html.Anchor;
5+
import com.vaadin.flow.server.StreamResource;
6+
import java.io.ByteArrayInputStream;
7+
import life.qbic.application.commons.ApplicationException;
8+
9+
/**
10+
* The DownloadProvider class extends the Anchor class and provides functionality for triggering
11+
* any kind of download based on a provided DownloadContentProvider
12+
*/
13+
public class DownloadProvider extends Anchor {
14+
15+
private final transient DownloadContentProvider downloadContentProvider;
16+
17+
public DownloadProvider(DownloadContentProvider downloadContentProvider) {
18+
super("_blank", "Download");
19+
this.downloadContentProvider = downloadContentProvider;
20+
/*
21+
* Using setVisisble(false), vaadin prevents any client side actions.
22+
* This prevents us from using JavaScript to click the link, which is the only option
23+
* for using anchors now.
24+
* Thus, we prevent the display of the link with `display: none`.
25+
* The link is still on the page but invisible.
26+
*/
27+
getStyle().set("display", "none");
28+
29+
setTarget("_blank");
30+
getElement().setAttribute("download", true);
31+
}
32+
33+
public void trigger() {
34+
byte[] content = downloadContentProvider.getContent();
35+
if(content.length > 0) {
36+
UI ui = getUI().orElseThrow(() -> new ApplicationException(
37+
"Download component triggered but not attached to any UI."));
38+
StreamResource resource = new StreamResource(downloadContentProvider.getFileName(),
39+
() -> new ByteArrayInputStream(content));
40+
this.setHref(resource);
41+
ui.getPage().executeJs("$0.click()", this.getElement());
42+
}
43+
}
44+
45+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package life.qbic.datamanager.views.general.upload;
2+
3+
import com.vaadin.flow.component.upload.MultiFileReceiver;
4+
import com.vaadin.flow.component.upload.receivers.FileData;
5+
import java.io.ByteArrayInputStream;
6+
import java.io.ByteArrayOutputStream;
7+
import java.io.InputStream;
8+
import java.io.OutputStream;
9+
import java.io.Serial;
10+
import java.util.HashMap;
11+
import java.util.Map;
12+
import java.util.Optional;
13+
import java.util.stream.Stream;
14+
15+
/**
16+
* <b>Editable multi-file memory buffer</b>
17+
* <p>
18+
* An improved {@link MultiFileReceiver} enables removing cached file content, which Vaadin's
19+
* {@link com.vaadin.flow.component.upload.receivers.MultiFileMemoryBuffer} does not provide.
20+
*
21+
* @since 1.0.0
22+
*/
23+
public class EditableMultiFileMemoryBuffer implements MultiFileReceiver {
24+
25+
@Serial
26+
private static final long serialVersionUID = 2041166242210420469L;
27+
private final Map<String, FileData> files = new HashMap<>();
28+
29+
@Override
30+
public OutputStream receiveUpload(String fileName, String mimeType) {
31+
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
32+
this.files.put(fileName, new FileData(fileName, mimeType, byteArrayOutputStream));
33+
return byteArrayOutputStream;
34+
}
35+
36+
public Optional<OutputStream> outputStream(String fileName) {
37+
return Optional.ofNullable(files.getOrDefault(fileName, null)).map(FileData::getOutputBuffer);
38+
}
39+
40+
public Optional<InputStream> inputStream(String fileName) {
41+
return Optional.ofNullable(files.getOrDefault(fileName, null))
42+
.map(fileData -> (ByteArrayOutputStream) fileData.getOutputBuffer())
43+
.map(outputStream -> new ByteArrayInputStream(outputStream.toByteArray()));
44+
}
45+
46+
public void remove(String fileName) {
47+
files.remove(fileName);
48+
}
49+
50+
/**
51+
* Clears the complete buffer and removes any content cashed in the buffer.
52+
* <p>
53+
* All cached files and their content are removed from the buffer.
54+
*
55+
* @since 1.0.0
56+
*/
57+
public void clear() {
58+
files.clear();
59+
}
60+
61+
public Stream<String> fileNames() {
62+
return this.files.keySet().stream();
63+
}
64+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package life.qbic.datamanager.views.general.upload;
2+
3+
import static java.util.Objects.nonNull;
4+
5+
import com.vaadin.flow.component.upload.Receiver;
6+
import com.vaadin.flow.component.upload.receivers.FileData;
7+
import java.io.ByteArrayInputStream;
8+
import java.io.ByteArrayOutputStream;
9+
import java.io.InputStream;
10+
import java.io.OutputStream;
11+
import java.util.Optional;
12+
13+
/**
14+
* Simple in-memory buffer for receiving uploaded content in the application.
15+
*/
16+
public class FileMemoryBuffer implements Receiver {
17+
18+
private FileData fileData;
19+
20+
@Override
21+
public OutputStream receiveUpload(String fileName, String mimeType) {
22+
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
23+
this.fileData = new FileData(fileName, mimeType, byteArrayOutputStream);
24+
return byteArrayOutputStream;
25+
}
26+
27+
public boolean hasUploadedData() {
28+
return nonNull(fileData);
29+
}
30+
31+
public Optional<InputStream> getInputStream() {
32+
return Optional.ofNullable(fileData)
33+
.map(FileData::getOutputBuffer)
34+
.filter(ByteArrayOutputStream.class::isInstance)
35+
.map(ByteArrayOutputStream.class::cast)
36+
.map(ByteArrayOutputStream::toByteArray)
37+
.map(ByteArrayInputStream::new);
38+
}
39+
40+
public Optional<String> getFileName() {
41+
return Optional.ofNullable(fileData.getFileName());
42+
}
43+
44+
public Optional<String> getMimeType() {
45+
return Optional.ofNullable(fileData.getMimeType());
46+
}
47+
48+
public void clear() {
49+
fileData = null;
50+
}
51+
52+
}

0 commit comments

Comments
 (0)