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(UI): File output preview #1770

Merged
merged 6 commits into from
Aug 17, 2023
Merged

feat(UI): File output preview #1770

merged 6 commits into from
Aug 17, 2023

Conversation

Skraye
Copy link
Member

@Skraye Skraye commented Jul 18, 2023

close #1767

@Skraye Skraye self-assigned this Jul 18, 2023
Copy link
Member

@loicmathieu loicmathieu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the behaviour should change: we should only supported a fixed set of extensions and if a file is not of this extension didn't show the button and generates an error in the backend. We can revisit this later but it is preferable for security, performance (some file may not be multi-line) and usability (binary may crash the browser).

Also, I think the preview may be better on a modal on the centre instead of the "coming from right" modal but it can wait for some redesign.

"dependency task": "Task {taskId} is a dependency of another task"
"dependency task": "Task {taskId} is a dependency of another task",
"preview": "Preview",
"open": "Open"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Show is better than Open


String extension = FilenameUtils.getExtension(path.toString());

if (ImageFileExtension.isImageFileExtension(extension)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use a simple List of extensions as you didn't really use the enum

case "png":
case "svg":
return "image";
default:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should not default to text, this should be an extension like the other and default to not preview.
This can be a security risk to allow any extension file.
And this can crash Kestra UI for example if a binary format with non-displayable characters is used.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see how it can be a security risk as I just display character. The only difference is that if I don't know the extension, there will be no syntax highlighting.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well security issues can hide in multiple way.

Anyway, as I commented somewhere else, binary format may crash the browser, and some files may also be one long line that (avro, parquet, ...) so better only display what we are sure can be displayed.

return httpResponse;
}

InputStream fileStream = storageInterface.get(path);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should restrict the loading of files only to supported extensions and throws an error for the other.

ui/src/components/executions/FilePreview.vue Outdated Show resolved Hide resolved
case "svg":
return "data:image/" + this.extension + ";base64," + this.content;
default:
return this.content;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not a good idea as some files may not be displayable.

ui/src/components/executions/FilePreview.vue Outdated Show resolved Hide resolved

StringBuilder contentBuilder = new StringBuilder();

while (line != null && lineCount < 100) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not all files are multi-line, you can have a huge file with a one-in JSON in it.
I'm not sure we can do something better than that anyway

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One solution would be to limit the size of the content return, limit to a size of 2mb for example so even if my file is a heavy one-line, I will return limited content

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree that we need an limit in MB or number of lines, the first that will cut of

@Skraye
Copy link
Member Author

Skraye commented Jul 18, 2023

@loicmathieu
Added size limit so no issue with one line file
I tried with file like binary, it's just not readable but no issue

@Skraye Skraye force-pushed the feat/file-preview branch 2 times, most recently from 7b47dc3 to 5d68498 Compare July 18, 2023 14:29
@brian-mulier-p brian-mulier-p removed their request for review July 20, 2023 15:13
@Skraye Skraye force-pushed the feat/file-preview branch from 5d68498 to 9bb2f3c Compare July 26, 2023 14:27
@Skraye Skraye requested a review from loicmathieu July 26, 2023 14:28
}
}

return HttpResponse.ok(PreviewResponse.builder().extension(extension).content(truncateStringSize(contentBuilder.toString())).build());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Truncating the file after it has been read is not a good idea as the file will still be loaded entirely in memory.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree also


public String truncateStringSize(String content) {
// Equivalent to 2MB
int maxSizeInBytes = 2097152;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use a constant.
A good practice is to declare it something like:

private int TWO_MB = 2 * 1024 * 1024;

ui/src/translations.json Show resolved Hide resolved
Copy link
Member

@tchiotludo tchiotludo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please:

  • move the rendering of the data on the server side
  • fix an issue where multiple drawer will be open if I have multiple output preview on the same execution

@tchiotludo tchiotludo force-pushed the feat/file-preview branch 3 times, most recently from e2261fc to a03c61d Compare August 8, 2023 08:58
@Skraye Skraye force-pushed the feat/file-preview branch 2 times, most recently from d71c407 to ac78a83 Compare August 16, 2023 14:15
@tchiotludo tchiotludo merged commit eab705b into develop Aug 17, 2023
@tchiotludo tchiotludo deleted the feat/file-preview branch August 17, 2023 21:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Display file preview in Outputs
3 participants