# Output and Presentation
When the workflow is defined, we want to interact with it in different ways.
## Presentation
### Command Line Interface
<pre class="terminal">
<span class='shell'>> </span><span class='cmd'>./envman</span> <span class='arg'>deploy</span>
Using profile <span style='color:#ffafff'><b>⦗demo⦘</b></span> -- type <span style='color:#5fafff'>`development`</span>
✅ <span style='color:#fff'>1.</span> <span style='color:#5fafff'>app_download</span> <span style='color:#00af5f00; background-color:#00af5f' class="shell_progress_bar">▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰</span> done!
⏳ <span style='color:#fff'>2.</span> <span style='color:#5fafff'>s3_bucket</span> <span style='color:#0087d700; background-color:#0087d7' class="shell_progress_bar">▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▰▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱</span> 0/1 creating bucket <span style='color:#af00d7'>(el: 6s, eta: 0s)</span>
⏳ <span style='color:#fff'>3.</span> <span style='color:#5fafff'>s3_object</span> <span style='color:#555'>▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱</span> <span style='color:#af00d7'>(el: 0s, eta: 0s)</span>
</pre>
### Continuous Integration
```text
2023-05-07T01:30:32.687Z | s3_bucket | bucket created
```
### Web API
```json
// GET /api/v1/demo/env_deploy/progress
{
"item_id": "s3_bucket",
"progress_update": { "Delta": "Tick" },
"msg_update": { "Set": "creating bucket" }
// ..
}
```
### Web page
<div class="column_half">
```dot process
digraph {
graph [
margin = 0.0
penwidth = 0
nodesep = 0.0
ranksep = 0.02
bgcolor = "transparent"
fontname = "helvetica"
fontcolor = "#7f7f7f"
rankdir = TB
splines = line
]
node [
fontcolor = "#111111"
fontname = "monospace"
fontsize = 12
shape = "circle"
style = "filled"
width = 0.3
height = 0.3
margin = 0.04
color = "#9999aa"
fillcolor = "#ddddf5"
penwidth = 2
]
edge [
arrowsize = 0.7
color = "#7f7f7f"
fontcolor = "#7f7f7f"
penwidth = 2
]
subgraph cluster_a {
node [color="#449966" fillcolor="#99dd99"]
a [label = <<b>a</b>>]
a_text [shape="plain" style="" fontcolor="#7f7f7f" label = <<table border="0" cellborder="0" cellpadding="0"><tr>
<td><font point-size="15">📥</font></td>
<td balign="left">file<br/>download</td>
</tr></table>>]
a -> a_text [style = invis]
}
subgraph cluster_b {
node [color="#446699" fillcolor="#99aaee"]
b [label = <<b>b</b>> class="item_b_in_progress" style="dashed,filled"]
b_text [shape="plain" style="" fontcolor="#7f7f7f" label = <<table border="0" cellborder="0" cellpadding="0"><tr>
<td><font point-size="15">🪣</font></td>
<td balign="left">s3<br/>bucket</td>
</tr></table>>]
b -> b_text [style = invis]
}
subgraph cluster_c {
c [label = <<b>c</b>>]
c_text [shape="plain" style="" fontcolor="#7f7f7f" label = <<table border="0" cellborder="0" cellpadding="0"><tr>
<td><font point-size="15">📤</font></td>
<td balign="left">s3<br/>object</td>
</tr></table>>]
c -> c_text [style = invis]
}
a_text -> c [minlen = 9, color="#66aa66"]
b_text -> c [minlen = 9, color="#6688bb"]
}
```
</div><div class="column_half">
<div class="peace_button_container">
<div class="peace_button">
<div class="peace_button_label">Current<br/>State</div>
</div>
<div class="peace_button peace_button_left peace_button_running">
<div class="peace_button_label">Deploy<br/>(preview)</div>
</div>
<div class="peace_button peace_button_right peace_button_running">
<div class="peace_button_label"><div class="peace_button_spinner"></div></div>
</div>
<div class="peace_button peace_button_left">
<div class="peace_button_label">Clean<br/>(preview)</div>
</div>
<div class="peace_button peace_button_right">
<div class="peace_button_label">▶</div>
</div>
</div>
</div>
```rust ,ignore
// outputs to CLI
let mut output = CliOutput::new();
// === Used in tests === //
// discards all output
let mut output = NoOpOutput;
// records which output functions were called
// and what parameters they were called with
let mut output = FnTrackerOutput::new();
// === Write your own === //
// writes JSON to HTTP response
let mut output = JsonResponseOutput::new();
```
<style type="text/css">
.peace_button_container {
display: flex;
flex-direction: row;
}
.peace_button {
background: linear-gradient(0deg, #ddddee, #eeeeff);
border: 1px solid #9999aa;
border-radius: 3px;
padding: 0.3em 0.7em;
font-size: 0.8em;
font-weight: 550;
text-align: center;
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
}
.peace_button:hover {
background: linear-gradient(0deg, #eeeeff, #fafaff);
border: 1px solid #bbbbcc;
}
.peace_button:active {
background: linear-gradient(0deg, #d0d0e0, #e0e0f0);
border: 1px solid #9090a0;
}
.peace_button_running,
.peace_button_running:hover,
.peace_button_running:active {
background-color: #aabbf0;
background-image: none;
color: #0022558f;
border: 1px solid #7070c0;
}
.peace_button_label {
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
}
.peace_button_left,
.peace_button_left:hover,
.peace_button_left:active {
border-bottom-right-radius: 0px;
border-top-right-radius: 0px;
}
.peace_button_right,
.peace_button_right:hover,
.peace_button_right:active {
border-left: 0px;
border-bottom-left-radius: 0px;
border-top-left-radius: 0px;
}
.peace_button_spinner {
display: inline-block;
vertical-align: text-bottom;
border: 2px solid transparent;
background-clip: border-box, content-box;
background-image: conic-gradient(#0022551f, #002255ff), conic-gradient(#aabbf0ff, #aabbf0ff);
background-size: 100%;
background-origin: border-box, content-box;
background-blend-mode: screen;
border-radius: 50%;
width: 1em;
height: 1em;
animation: 3.0s linear forwards 0.0s infinite peace_button_spinner;
}
@keyframes peace_button_spinner {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.item_b_in_progress ellipse {
animation: 10.0s linear forwards 0.0s infinite item_b_in_progress;
}
@keyframes item_b_in_progress {
0% {
transform-origin: 131px -204.31px;
transform: rotate(0deg);
}
100% {
transform-origin: 131px -204.31px;
transform: rotate(360deg);
}
}
.shell_progress_bar {
background-repeat: no-repeat;
background-blend-mode: lighten;
background-clip: text;
background-size: 50px;
text-fill-color: transparent;
animation: 2.5s linear forwards 1.0s infinite shell_progress_bar;
}
@keyframes shell_progress_bar {
0% {
background-position-x: left;
background-image: linear-gradient(90deg, #000000 0%, #ffffffff 90%, #000000 100%);
}
30% {
background-position-x: right;
background-image: linear-gradient(90deg, #000000 0%, #ffffffff 90%, #000000 100%);
}
31% {
background-position-x: right;
background-image: linear-gradient(90deg, #000000 0%, #000000 100%);
}
}
</style>