From 8477a5ac4cd40b76d9c273c6153cc758cacf488f Mon Sep 17 00:00:00 2001 From: Janne Valkealahti Date: Wed, 11 May 2022 15:36:10 +0100 Subject: [PATCH] Update docs - Add docs for component flow - Relates #383 --- spring-shell-docs/readme.txt | 8 ++ .../component-flow-conditional-1.cast | 43 +++++++++ .../asciinema/component-flow-showcase-1.cast | 42 +++++++++ .../images/component-flow-conditional-1.svg | 1 + .../images/component-flow-showcase-1.svg | 1 + .../asciidoc/using-shell-components-flow.adoc | 33 +++++++ .../asciidoc/using-shell-components-ui.adoc | 2 +- .../main/asciidoc/using-shell-components.adoc | 1 + .../shell/docs/FlowComponentSnippets.java | 89 +++++++++++++++++++ 9 files changed, 219 insertions(+), 1 deletion(-) create mode 100644 spring-shell-docs/src/main/asciidoc/asciinema/component-flow-conditional-1.cast create mode 100644 spring-shell-docs/src/main/asciidoc/asciinema/component-flow-showcase-1.cast create mode 100644 spring-shell-docs/src/main/asciidoc/images/component-flow-conditional-1.svg create mode 100644 spring-shell-docs/src/main/asciidoc/images/component-flow-showcase-1.svg create mode 100644 spring-shell-docs/src/main/asciidoc/using-shell-components-flow.adoc create mode 100644 spring-shell-docs/src/test/java/org/springframework/shell/docs/FlowComponentSnippets.java diff --git a/spring-shell-docs/readme.txt b/spring-shell-docs/readme.txt index c62f65a1..34e9a673 100644 --- a/spring-shell-docs/readme.txt +++ b/spring-shell-docs/readme.txt @@ -5,6 +5,8 @@ asciinema rec spring-shell-docs/src/main/asciidoc/asciinema/component-path-input asciinema rec spring-shell-docs/src/main/asciidoc/asciinema/component-confirmation-1.cast asciinema rec spring-shell-docs/src/main/asciidoc/asciinema/component-single-select-1.cast asciinema rec spring-shell-docs/src/main/asciidoc/asciinema/component-multi-select-1.cast +asciinema rec spring-shell-docs/src/main/asciidoc/asciinema/component-flow-showcase-1.cast +asciinema rec spring-shell-docs/src/main/asciidoc/asciinema/component-flow-conditional-1.cast svg-term \ --in spring-shell-docs/src/main/asciidoc/asciinema/component-text-input-1.cast \ @@ -21,3 +23,9 @@ svg-term \ svg-term \ --in spring-shell-docs/src/main/asciidoc/asciinema/component-multi-select-1.cast \ --out spring-shell-docs/src/main/asciidoc/images/component-multi-select-1.svg +svg-term \ + --in spring-shell-docs/src/main/asciidoc/asciinema/component-flow-showcase-1.cast \ + --out spring-shell-docs/src/main/asciidoc/images/component-flow-showcase-1.svg +svg-term \ + --in spring-shell-docs/src/main/asciidoc/asciinema/component-flow-conditional-1.cast \ + --out spring-shell-docs/src/main/asciidoc/images/component-flow-conditional-1.svg diff --git a/spring-shell-docs/src/main/asciidoc/asciinema/component-flow-conditional-1.cast b/spring-shell-docs/src/main/asciidoc/asciinema/component-flow-conditional-1.cast new file mode 100644 index 00000000..584a4ea1 --- /dev/null +++ b/spring-shell-docs/src/main/asciidoc/asciinema/component-flow-conditional-1.cast @@ -0,0 +1,43 @@ +{"version": 2, "width": 85, "height": 11, "timestamp": 1645645867, "env": {"SHELL": "/bin/bash", "TERM": "xterm-256color"}} +[1.590847, "o", "java -jar spring-shell-samples/target/spring-shell-samples-2.1.0-SNAPSHOT.jar"] +[5.030349, "o", "\r\n"] +[7.108752, "o", "\u001b[?1h\u001b=\u001b[?2004h\u001b[33mmy-shell:>\u001b[0m"] +[7.604731, "o", "\u001b[31mf\u001b[0m"] +[7.754184, "o", "\u001b[31ml\u001b[0m"] +[7.98951, "o", "\u001b[31mo\u001b[0m"] +[8.405578, "o", "\u001b[31mw\u001b[0m"] +[8.763007, "o", "\u001b[31m \u001b[0m"] +[8.963478, "o", "\u001b[31mc\u001b[0m"] +[9.036017, "o", "\u001b[31mo\u001b[0m"] +[9.353476, "o", "\u001b[31mn\u001b[0m"] +[9.517639, "o", "\u001b[8D\u001b[1mflow conditional\u001b[0m \u001b[K"] +[10.036978, "o", "\r\r\n\u001b[?1l\u001b>\u001b[?1000l\u001b[?2004l"] +[10.115908, "o", "\u001b[?1h\u001b=\u001b[?25l"] +[10.176519, "o", "\u001b[32;1m?\u001b[0m \u001b[97;1mSingle1\u001b[0m [Use arrows to move], type to filter\u001b[97C \u001b[96;1m>\u001b[0m\u001b[96;1m Field1\u001b[0m\u001b[135C Field2\u001b[2A\r"] +[11.824714, "o", "\u001b[?1l\u001b>\u001b[?12;25h\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\u001b[2A"] +[11.835781, "o", "\u001b[32;1m?\u001b[0m \u001b[97;1mSingle1\u001b[0m \u001b[34mfield1\u001b[0m\r\n"] +[11.838786, "o", "\u001b[?1h\u001b=\u001b[?25l"] +[11.844824, "o", "\u001b[32;1m?\u001b[0m \u001b[97;1mField1\u001b[0m \u001b[34m[Default defaultField1Value]\u001b[0m\r"] +[12.734384, "o", "\u001b[?1l\u001b>\u001b[?12;25h\u001b[K"] +[12.740754, "o", "\u001b[32;1m?\u001b[0m \u001b[97;1mField1\u001b[0m \u001b[34mdefaultField1Value\u001b[0m\r\n"] +[12.74362, "o", "\u001b[?1h\u001b=\u001b[?25l"] +[12.750944, "o", "\u001b[32;1m?\u001b[0m \u001b[97;1mField2\u001b[0m \u001b[34m[Default defaultField2Value]\u001b[0m\r"] +[13.542429, "o", "\u001b[?1l\u001b>\u001b[?12;25h\u001b[K"] +[13.545672, "o", "\u001b[32;1m?\u001b[0m \u001b[97;1mField2\u001b[0m \u001b[34mdefaultField2Value\u001b[0m\r\n"] +[13.547149, "o", "\u001b[?1h\u001b=\u001b[?2004h\u001b[33mmy-shell:>\u001b[0m"] +[14.091367, "o", "\u001b[1mflow conditional\u001b[0m"] +[14.419251, "o", "\r\r\n\u001b[?1l\u001b>\u001b[?1000l\u001b[?2004l"] +[14.424986, "o", "\u001b[?1h\u001b=\u001b[?25l"] +[14.432116, "o", "\u001b[32;1m?\u001b[0m \u001b[97;1mSingle1\u001b[0m [Use arrows to move], type to filter\u001b[97C \u001b[96;1m>\u001b[0m\u001b[96;1m Field1\u001b[0m\u001b[135C Field2\u001b[2A\r"] +[14.995304, "o", "\r\r\n Field1\r\r\n\u001b[96;1m> Field2\u001b[0m\u001b[2A\r"] +[15.409104, "o", "\u001b[?1l\u001b>\u001b[?12;25h\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\u001b[2A"] +[15.416729, "o", "\u001b[32;1m?\u001b[0m \u001b[97;1mSingle1\u001b[0m \u001b[34mfield2\u001b[0m\r\n"] +[15.41833, "o", "\u001b[?1h\u001b=\u001b[?25l"] +[15.424318, "o", "\u001b[32;1m?\u001b[0m \u001b[97;1mField2\u001b[0m \u001b[34m[Default defaultField2Value]\u001b[0m\r"] +[16.002129, "o", "\u001b[?1l\u001b>\u001b[?12;25h\u001b[K"] +[16.007474, "o", "\u001b[32;1m?\u001b[0m \u001b[97;1mField2\u001b[0m \u001b[34mdefaultField2Value\u001b[0m\r\n"] +[16.010197, "o", "\u001b[?1h\u001b=\u001b[?2004h\u001b[33mmy-shell:>\u001b[0m"] +[19.865275, "o", "\r\r\n\u001b[?1l\u001b>\u001b[?1000l"] +[19.865497, "o", "\u001b[?2004l"] +[19.868634, "o", "\u001b[31morg.jline.reader.EndOfFileException\u001b[0m\r\n\u001b[31mDetails of the error have been omitted. You can use the \u001b[1mstacktrace\u001b[22m command to print the full stacktrace.\u001b[0m\r\n"] +[19.870354, "o", "\u001b[?1h\u001b=\u001b[?2004h\u001b[33mmy-shell:>\u001b[0m"] diff --git a/spring-shell-docs/src/main/asciidoc/asciinema/component-flow-showcase-1.cast b/spring-shell-docs/src/main/asciidoc/asciinema/component-flow-showcase-1.cast new file mode 100644 index 00000000..354bd5c8 --- /dev/null +++ b/spring-shell-docs/src/main/asciidoc/asciinema/component-flow-showcase-1.cast @@ -0,0 +1,42 @@ +{"version": 2, "width": 85, "height": 15, "timestamp": 1645645867, "env": {"SHELL": "/bin/bash", "TERM": "xterm-256color"}} +[1.590847, "o", "java -jar spring-shell-samples/target/spring-shell-samples-2.1.0-SNAPSHOT.jar"] +[5.968022, "o", "\r\n"] +[8.099727, "o", "\u001b[?1h\u001b=\u001b[?2004h\u001b[33mmy-shell:>\u001b[0m"] +[11.261894, "o", "\u001b[1mflow showcase\u001b[0m"] +[12.6451, "o", "\r\r\n\u001b[?1l\u001b>\u001b[?1000l\u001b[?2004l"] +[12.721206, "o", "\u001b[?1h\u001b=\u001b[?25l"] +[12.780227, "o", "\u001b[32;1m?\u001b[0m \u001b[97;1mField1\u001b[0m \u001b[34m[Default defaultField1Value]\u001b[0m\r"] +[14.703281, "o", "\u001b[?1l\u001b>\u001b[?12;25h\u001b[K"] +[14.711232, "o", "\u001b[32;1m?\u001b[0m \u001b[97;1mField1\u001b[0m \u001b[34mdefaultField1Value\u001b[0m\r\n"] +[14.713588, "o", "\u001b[?1h\u001b=\u001b[?25l"] +[14.720745, "o", "\u001b[32;1m?\u001b[0m \u001b[97;1mField2\u001b[0m \r"] +[16.084492, "o", "\u001b[9Ch\r"] +[16.176942, "o", "\u001b[10Ci\r"] +[16.620009, "o", "\u001b[?1l\u001b>\u001b[?12;25h\u001b[K"] +[16.625711, "o", "\u001b[32;1m?\u001b[0m \u001b[97;1mField2\u001b[0m \u001b[34mhi\u001b[0m\r\n"] +[16.628041, "o", "\u001b[?1h\u001b=\u001b[?25l"] +[16.633919, "o", "\u001b[32;1m?\u001b[0m \u001b[97;1mConfirmation1\u001b[0m \u001b[2m(Y/n)\u001b[0m\r"] +[20.090558, "o", "\u001b[?1l\u001b>\u001b[?12;25h\u001b[K"] +[20.098654, "o", "\u001b[32;1m?\u001b[0m \u001b[97;1mConfirmation1\u001b[0m \u001b[34mtrue\u001b[0m\r\n"] +[20.101548, "o", "\u001b[?1h\u001b=\u001b[?25l"] +[20.105099, "o", "\u001b[32;1m?\u001b[0m \u001b[97;1mPath1\u001b[0m \r"] +[21.53213, "o", "\u001b[8Cp\u001b[134C \u001b[32m>\u001b[0m \u001b[32mPath ok\u001b[0m\u001b[A\r"] +[21.626297, "o", "\u001b[9Ca\r"] +[21.896442, "o", "\u001b[10Ct\r"] +[21.941151, "o", "\u001b[11Ch\r"] +[23.041717, "o", "\u001b[?1l\u001b>\u001b[?12;25h\u001b[K\r\r\n\u001b[K\u001b[A"] +[23.044506, "o", "\u001b[32;1m?\u001b[0m \u001b[97;1mPath1\u001b[0m \u001b[34mpath\u001b[0m\r\n"] +[23.049225, "o", "\u001b[?1h\u001b=\u001b[?25l"] +[23.05459, "o", "\u001b[32;1m?\u001b[0m \u001b[97;1mSingle1\u001b[0m [Use arrows to move], type to filter\u001b[97C \u001b[96;1m>\u001b[0m\u001b[96;1m key1\u001b[0m\u001b[137C key2\u001b[2A\r"] +[24.520415, "o", "\r\r\n key1\r\r\n\u001b[96;1m> key2\u001b[0m\u001b[2A\r"] +[25.431855, "o", "\u001b[?1l\u001b>\u001b[?12;25h\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\u001b[2A"] +[25.438619, "o", "\u001b[32;1m?\u001b[0m \u001b[97;1mSingle1\u001b[0m \u001b[34mvalue2\u001b[0m\r\n"] +[25.441975, "o", "\u001b[?1h\u001b=\u001b[?25l"] +[25.446547, "o", "\u001b[32;1m?\u001b[0m \u001b[97;1mMulti1\u001b[0m [Use arrows to move], type to filter\u001b[98C \u001b[96;1m>\u001b[0m\u001b[96;1m \u001b[39m[ ]\u001b[0m key1\u001b[133C \u001b[1m[ ]\u001b[0m key2\u001b[133C \u001b[1m[ ]\u001b[0m key3\u001b[3A\r"] +[26.698294, "o", "\r\r\n\u001b[2C\u001b[32m[x]\u001b[0m\u001b[A\r"] +[28.022787, "o", "\r\r\n \r\r\n\u001b[96;1m> \u001b[0m\u001b[2A\r"] +[28.110824, "o", "\r\r\n\r\n\u001b[2C\u001b[32m[x]\u001b[0m\u001b[2A\r"] +[29.250629, "o", "\r\r\n\r\n\u001b[2C\u001b[1m[ ]\u001b[0m\u001b[2A\r"] +[30.360368, "o", "\u001b[?1l\u001b>\u001b[?12;25h\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\r\r\n\u001b[K\u001b[3A"] +[30.368273, "o", "\u001b[32;1m?\u001b[0m \u001b[97;1mMulti1\u001b[0m \u001b[34mvalue1\u001b[0m\r\n"] +[30.370638, "o", "\u001b[?1h\u001b=\u001b[?2004h\u001b[33mmy-shell:>\u001b[0m"] diff --git a/spring-shell-docs/src/main/asciidoc/images/component-flow-conditional-1.svg b/spring-shell-docs/src/main/asciidoc/images/component-flow-conditional-1.svg new file mode 100644 index 00000000..a325b472 --- /dev/null +++ b/spring-shell-docs/src/main/asciidoc/images/component-flow-conditional-1.svg @@ -0,0 +1 @@ +java-jarspring-shell-samples/target/spring-shell-samples-2.1.0-SNAPSHOT.jarmy-shell:>my-shell:>flowmy-shell:>flowconditional?Single1[Usearrowstomove],typetofilter>Field1Field2?Single1field1?Field1defaultField1Value?Field2[DefaultdefaultField2Value]?Field2defaultField2Value?Single1field2org.jline.reader.EndOfFileExceptionDetailsoftheerrorhavebeenomitted.Youcanusethestacktracecommandtoprintthefullstacktrace.my-shell:>fmy-shell:>flmy-shell:>flomy-shell:>flowcmy-shell:>flowcomy-shell:>flowcon?Field1[DefaultdefaultField1Value]Field1>Field2 \ No newline at end of file diff --git a/spring-shell-docs/src/main/asciidoc/images/component-flow-showcase-1.svg b/spring-shell-docs/src/main/asciidoc/images/component-flow-showcase-1.svg new file mode 100644 index 00000000..23363bb4 --- /dev/null +++ b/spring-shell-docs/src/main/asciidoc/images/component-flow-showcase-1.svg @@ -0,0 +1 @@ +java-jarspring-shell-samples/target/spring-shell-samples-2.1.0-SNAPSHOT.jarmy-shell:>my-shell:>flowshowcase?Field1defaultField1Value?Field2hi?Confirmation1true>Pathok?Path1path?Single1[Usearrowstomove],typetofilter?Single1value2?Multi1[Usearrowstomove],typetofilter[]key2[]key3[x]key1>[]key2?Multi1value1?Field1[DefaultdefaultField1Value]?Field2?Field2h?Field2hi?Confirmation1(Y/n)?Path1?Path1p?Path1pa?Path1pat?Path1path>key1key2key1>key2>[]key1>[x]key1>[x]key2 \ No newline at end of file diff --git a/spring-shell-docs/src/main/asciidoc/using-shell-components-flow.adoc b/spring-shell-docs/src/main/asciidoc/using-shell-components-flow.adoc new file mode 100644 index 00000000..5cd5f806 --- /dev/null +++ b/spring-shell-docs/src/main/asciidoc/using-shell-components-flow.adoc @@ -0,0 +1,33 @@ +[[using-shell-components-flow]] +==== Flow +ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs] + +When using <> to build something which involves +use of a multiple components your implemention may become a bit cluttered. +Nothing wrong with that but to ease these use cases we've build a +`ComponentFlow` which is able to hook multiple component executions together +as a _flow_. + +Here is some examples of a flows and what it looks like in a shell: + +==== +[source, java, indent=0] +---- +include::{snippets}/FlowComponentSnippets.java[tag=snippet1] +---- +==== + +image::images/component-flow-showcase-1.svg[text input] + + +==== +[source, java, indent=0] +---- +include::{snippets}/FlowComponentSnippets.java[tag=snippet2] +---- +==== + +image::images/component-flow-conditional-1.svg[text input] + +Results from running a flow returns `ComponentFlowResult` which you can +use to do furher actions. diff --git a/spring-shell-docs/src/main/asciidoc/using-shell-components-ui.adoc b/spring-shell-docs/src/main/asciidoc/using-shell-components-ui.adoc index 5317a5c5..46182258 100644 --- a/spring-shell-docs/src/main/asciidoc/using-shell-components-ui.adoc +++ b/spring-shell-docs/src/main/asciidoc/using-shell-components-ui.adoc @@ -1,4 +1,4 @@ -[[uicomponents]] +[[using-shell-components-ui]] ==== UI Components ifndef::snippets[:snippets: ../../test/java/org/springframework/shell/docs] diff --git a/spring-shell-docs/src/main/asciidoc/using-shell-components.adoc b/spring-shell-docs/src/main/asciidoc/using-shell-components.adoc index b524cca8..e408b03c 100644 --- a/spring-shell-docs/src/main/asciidoc/using-shell-components.adoc +++ b/spring-shell-docs/src/main/asciidoc/using-shell-components.adoc @@ -5,3 +5,4 @@ include::using-shell-components-ui.adoc[] include::using-shell-components-builtin.adoc[] +include::using-shell-components-flow.adoc[] diff --git a/spring-shell-docs/src/test/java/org/springframework/shell/docs/FlowComponentSnippets.java b/spring-shell-docs/src/test/java/org/springframework/shell/docs/FlowComponentSnippets.java new file mode 100644 index 00000000..7f59b64e --- /dev/null +++ b/spring-shell-docs/src/test/java/org/springframework/shell/docs/FlowComponentSnippets.java @@ -0,0 +1,89 @@ +package org.springframework.shell.docs; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.shell.component.flow.ComponentFlow; +import org.springframework.shell.component.flow.SelectItem; + +public class FlowComponentSnippets { + + // tag::snippet1[] + static class FlowSampleComplex { + + @Autowired + private ComponentFlow.Builder componentFlowBuilder; + + public void runFlow() { + Map single1SelectItems = new HashMap<>(); + single1SelectItems.put("key1", "value1"); + single1SelectItems.put("key2", "value2"); + List multi1SelectItems = Arrays.asList(SelectItem.of("key1", "value1"), + SelectItem.of("key2", "value2"), SelectItem.of("key3", "value3")); + ComponentFlow flow = componentFlowBuilder.clone().reset() + .withStringInput("field1") + .name("Field1") + .defaultValue("defaultField1Value") + .and() + .withStringInput("field2") + .name("Field2") + .and() + .withConfirmationInput("confirmation1") + .name("Confirmation1") + .and() + .withPathInput("path1") + .name("Path1") + .and() + .withSingleItemSelector("single1") + .name("Single1") + .selectItems(single1SelectItems) + .and() + .withMultiItemSelector("multi1") + .name("Multi1") + .selectItems(multi1SelectItems) + .and() + .build(); + flow.run(); + } + + } + // end::snippet1[] + + + // tag::snippet2[] + static class FlowSampleConditional { + + @Autowired + private ComponentFlow.Builder componentFlowBuilder; + + public void runFlow() { + Map single1SelectItems = new HashMap<>(); + single1SelectItems.put("Field1", "field1"); + single1SelectItems.put("Field2", "field2"); + ComponentFlow flow = componentFlowBuilder.clone().reset() + .withSingleItemSelector("single1") + .name("Single1") + .selectItems(single1SelectItems) + .next(ctx -> ctx.getResultItem().get().getItem()) + .and() + .withStringInput("field1") + .name("Field1") + .defaultValue("defaultField1Value") + .next(ctx -> null) + .and() + .withStringInput("field2") + .name("Field2") + .defaultValue("defaultField2Value") + .next(ctx -> null) + .and() + .build(); + flow.run(); + } + + } + // end::snippet2[] + +}