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(core): add icon for group and sub-group of plugins #1086

Merged
merged 2 commits into from
Mar 20, 2023
Merged
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
Expand Up @@ -56,18 +56,19 @@ void run() throws IOException, URISyntaxException {
assertThat(directory.listFiles().length, is(3));

var readme = directory.toPath().resolve("README.md");
assertThat(new String(Files.readAllBytes(readme)), is("---\n" +
assertThat(new String(Files.readAllBytes(readme)), containsString("---\n" +
"title: Plugin template test\n" +
"editLink: false\n" +
"editLink: false\n\n" +
"---\n" +
"# Plugin template test\n" +
"\n" +
"Plugin template for Kestra\n" +
"\n" +
"This is a more complex description of the plugin.\n" +
"\n" +
"This is in markdown and will be inline inside the plugin page.\n" +
"## Subgroup title\n" +
"This is in markdown and will be inline inside the plugin page.\n"));
assertThat(new String(Files.readAllBytes(readme)), containsString(
"Subgroup title\n" +
" \n" +
"Subgroup description\n" +
"### Tasks\n" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,18 @@ private static List<Document> index(RegisteredPlugin plugin) throws IOException
builder.put("classPlugins", pluginDocumentation.getClassPlugins());
}

if (pluginDocumentation.getIcon() != null) {
builder.put("icon", pluginDocumentation.getIcon());
}

if(!plugin.getGuides().isEmpty()) {
builder.put("guides", plugin.getGuides());
}

return Collections.singletonList(new Document(
docPath(plugin),
render("index", builder.build()),
null
pluginDocumentation.getIcon()
));
}

Expand Down Expand Up @@ -187,6 +191,18 @@ public static String icon(RegisteredPlugin plugin, Class<?> cls ) {
return null;
}

@SneakyThrows
public static String icon(RegisteredPlugin plugin, String iconName) {
InputStream resourceAsStream = plugin.getClassLoader().getResourceAsStream("icons/" + iconName + ".svg");
if (resourceAsStream != null) {
return Base64.getEncoder().encodeToString(
IOUtils.toString(resourceAsStream, Charsets.UTF_8).getBytes(StandardCharsets.UTF_8)
);
}

return null;
}

private static <T> String docPath(RegisteredPlugin registeredPlugin) {
String pluginName = Slugify.of(registeredPlugin.title());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@
public class PluginDocumentation {
private String title;
private String group;
private String icon;
private Map<SubGroup, Map<String, List<ClassPlugin>>> classPlugins;

private Map<String, String> guides;

private PluginDocumentation(RegisteredPlugin plugin) {
this.title = plugin.title();
this.group = plugin.group();
this.icon = DocumentationGenerator.icon(plugin, "plugin-icon");

this.classPlugins = plugin.allClassGrouped()
.entrySet()
Expand All @@ -46,7 +48,8 @@ private PluginDocumentation(RegisteredPlugin plugin) {
var subGroupDescription = pluginSubGroup != null ? pluginSubGroup.description() : null;
// hack to avoid adding the subgroup in the task URL when it's the group to keep search engine indexes
var subgroupIsGroup = cls.getPackageName().length() <= this.group.length();
var subgroup = new SubGroup(subGroupName, subGroupTitle, subGroupDescription, subgroupIsGroup);
var subGroupIcon = DocumentationGenerator.icon(plugin, cls.getPackageName());
var subgroup = new SubGroup(subGroupName, subGroupTitle, subGroupDescription, subGroupIcon, subgroupIsGroup);
builder.subgroup(subgroup);
} else {
// should never occur
Expand Down Expand Up @@ -89,6 +92,7 @@ public static class SubGroup implements Comparable<SubGroup>{
String name;
String title;
String description;
String icon;

boolean subgroupIsGroup;

Expand Down
7 changes: 4 additions & 3 deletions core/src/main/resources/docs/index.hbs
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
---
title: {{ capitalizeFirst (replace title "-" " ") }}
editLink: false
{{#if icon}}icon: {{ icon }}{{~/if}}
---
# {{ capitalizeFirst (replace title "-" " ") }}
# {{#if icon ~}}<img width="25" src="data:image/svg+xml;base64,{{icon}}" /> {{/if }}{{ capitalizeFirst (replace title "-" " ") }}

{{ description }}

{{ longDescription }}

{{~#each classPlugins }}
{{~#if @key.title}}
## {{ @key.title }}
## {{#if @key.icon ~}}<img width="25" src="data:image/svg+xml;base64,{{@key.icon}}" /> {{/if }}{{ @key.title }}
{{else}}
## {{ @key.name }}
## {{#if @key.icon ~}}<img width="25" src="data:image/svg+xml;base64,{{@key.icon}}" /> {{/if }}{{ @key.name }}
{{/if}}
{{ @key.description }}

Expand Down
10 changes: 10 additions & 0 deletions core/src/main/resources/icons/io.kestra.core.tasks.debugs.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions core/src/main/resources/icons/io.kestra.core.tasks.flows.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions core/src/main/resources/icons/io.kestra.core.tasks.log.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions core/src/main/resources/icons/io.kestra.core.tasks.scripts.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions core/src/main/resources/icons/plugin-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,16 @@
import jakarta.inject.Inject;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.*;

@MicronautTest
class DocumentationGeneratorTest {
@Inject
JsonSchemaGenerator jsonSchemaGenerator;

@Inject
DocumentationGenerator documentationGenerator;

@Test
void tasks() throws URISyntaxException, IOException {
Path plugins = Paths.get(Objects.requireNonNull(ClassPluginDocumentationTest.class.getClassLoader().getResource("plugins")).toURI());
Expand Down Expand Up @@ -106,4 +108,15 @@ void echo() throws IOException {
assertThat(render, containsString("Echo"));
assertThat(render, containsString("- \uD83D\uDD12 Deprecated"));
}

@Test
void pluginDoc() throws IOException, URISyntaxException {
PluginScanner pluginScanner = new PluginScanner(ClassPluginDocumentationTest.class.getClassLoader());
RegisteredPlugin core = pluginScanner.scan();

List<Document> docs = documentationGenerator.generate(core);
Document doc = docs.get(0);
assertThat(doc.getIcon(), is(notNullValue()));
assertThat(doc.getBody(), containsString("## <img width=\"25\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMzIiIGhlaWdodD0iMzIiCiAgICAgcHJlc2VydmVBc3BlY3RSYXRpbz0ieE1pZFlNaWQgbWVldCIgdmlld0JveD0iMCAwIDMyIDMyIgogICAgIHN0eWxlPSItbXMtdHJhbnNmb3JtOiByb3RhdGUoMzYwZGVnKTsgLXdlYmtpdC10cmFuc2Zvcm06IHJvdGF0ZSgzNjBkZWcpOyB0cmFuc2Zvcm06IHJvdGF0ZSgzNjBkZWcpOyI+CiAgICA8ZGVmcy8+CiAgICA8cGF0aCBkPSJNMjAgMjRoLTR2Mmg0djNoOHYtOGgtOHptMi0xaDR2NGgtNHoiIGZpbGw9IiMwRDE1MjMiLz4KICAgIDxwYXRoIGQ9Ik00IDIwdjJoNC41ODZMMiAyOC41ODZMMy40MTQgMzBMMTAgMjMuNDE0VjI4aDJ2LThINHoiIGZpbGw9IiMwRDE1MjMiLz4KICAgIDxwYXRoCiAgICAgICAgZD0iTTI0IDVhMy45OTYgMy45OTYgMCAwIDAtMy44NTggM0gxNHYyaDYuMTQyYTMuOTQgMy45NCAwIDAgMCAuNDI1IDEuMDE5TDE0IDE3LjU4NkwxNS40MTQgMTlsNi41NjctNi41NjdBMy45NTIgMy45NTIgMCAwIDAgMjQgMTNhNCA0IDAgMCAwIDAtOHptMCA2YTIgMiAwIDEgMSAyLTJhMi4wMDIgMi4wMDIgMCAwIDEtMiAyeiIKICAgICAgICBmaWxsPSIjMEQxNTIzIi8+CiAgICA8cGF0aCBkPSJNOS42OTMgMTIuNzVhNSA1IDAgMCAxIDAtNy41bDEuMzI0IDEuNWEzIDMgMCAwIDAgMCA0LjUwMXoiIGZpbGw9IiMwRDE1MjMiLz4KICAgIDxwYXRoIGQ9Ik03LjA0NyAxNS43NTFhOSA5IDAgMCAxIDAtMTMuNTAxbDEuMzI0IDEuNWE3IDcgMCAwIDAgMCAxMC41MDF6IiBmaWxsPSIjMEQxNTIzIi8+Cjwvc3ZnPg==\" /> flows"));
}
}