Skip to content

Commit

Permalink
Add the ability to load 'examples' and create examples by saving hist…
Browse files Browse the repository at this point in the history
…ory (#167)

Co-authored-by: Cosmin Mogos <contact@mogos.ro>
  • Loading branch information
jhump and cosmin-mogos committed Feb 14, 2022
1 parent d70ce5c commit e458831
Show file tree
Hide file tree
Showing 9 changed files with 540 additions and 59 deletions.
35 changes: 35 additions & 0 deletions cmd/grpcui/grpcui.go
Expand Up @@ -137,6 +137,13 @@ var (
This defaults to true when grpcui is used in an interactive mode; e.g.
when the tool detects that stdin is a terminal/tty. Otherwise, this
defaults to false.`))
examplesFile = flags.String("examples", "", prettify(`
Load examples from the given JSON file. The examples are shown in the UI
which lets users pick pre-defined RPC and request data, like a recipe.
This can be templates for common requests or could even represent a test
suite as a sequence of RPCs. This is similar to the "collections" feature
in postman. The format of this file is the same as used when saving
history from the gRPC UI "History" tab.`))
reflection = optionalBoolFlag{val: true}

port = flags.Int("port", 0, prettify(`
Expand Down Expand Up @@ -437,6 +444,31 @@ func main() {
grpclog.SetLoggerV2(grpclog.NewLoggerV2WithVerbosity(os.Stdout, ioutil.Discard, ioutil.Discard, grpcVerbosity))
}

var examplesOpt standalone.HandlerOption
if *examplesFile != "" {
func() {
f, err := os.Open(*examplesFile)
if err != nil {
if os.IsNotExist(err) {
fail(nil, "File %q does not exist", *examplesFile)
} else {
fail(err, "Failed to open %q", *examplesFile)
}
}
defer func() {
_ = f.Close()
}()
data, err := ioutil.ReadAll(f)
if err != nil {
fail(err, "Failed to read contents of %q", *examplesFile)
}
examplesOpt, err = standalone.WithExampleData(data)
if err != nil {
fail(err, "Failed to process contents of %q", *examplesFile)
}
}()
}

ctx := context.Background()
dialTime := 10 * time.Second
if *connectTimeout > 0 {
Expand Down Expand Up @@ -591,6 +623,9 @@ func main() {
if debug.set {
handlerOpts = append(handlerOpts, standalone.WithClientDebug(debug.val))
}
if examplesOpt != nil {
handlerOpts = append(handlerOpts, examplesOpt)
}
handlerOpts = append(handlerOpts, configureJSandCSS(extraJS, standalone.AddJSFile)...)
handlerOpts = append(handlerOpts, configureJSandCSS(extraCSS, standalone.AddCSSFile)...)
handlerOpts = append(handlerOpts, configureAssets(otherAssets)...)
Expand Down
6 changes: 3 additions & 3 deletions internal/resources/webform/bindata.go

Large diffs are not rendered by default.

53 changes: 51 additions & 2 deletions internal/resources/webform/webform-sample.css
Expand Up @@ -65,10 +65,34 @@
padding-bottom:14px;
}

#grpc-container {
display: flex;
}

#grpc-request-examples-container {
flex: 1;
max-width: 200px;
margin-right: 10px;
margin-top: 25px;
border: 1px solid #ccc;
border-radius: 5px;
padding: 10px;
}

#grpc-request-examples-container h3 {
margin: 0;
padding-top: 1px;
padding-bottom: 9px;
border-bottom: 1px solid #d8d8d8;
text-align: center;
font-size: 18px;
}

#grpc-request-response {
margin-top: 24px;
border: none;
padding: 0;
flex: 1;
}

#grpc-request-response ul.ui-tabs-nav {
Expand Down Expand Up @@ -125,6 +149,29 @@
font-size: 18px;
}

#grpc-request-examples {
list-style-type: none;
margin: 0;
padding: 0;
}

ol#grpc-request-examples {
margin-top: 16px;
}

#grpc-request-examples li {
padding: 10px;
}

#grpc-request-examples li:hover {
background-color: #f4f4f4;
}

#grpc-request-examples .ui-selected {
background: #f0f0f0;
font-weight: 500;
}

#grpc-form button {
border-radius: 3px;
background: #f0f0f0;
Expand Down Expand Up @@ -556,8 +603,10 @@ textarea.grpc-response-textarea {
color: #c00;
}

#grpc-history-clear {
margin-bottom: 20px;
button#grpc-history-clear, button#grpc-history-save {
margin-bottom: 16px;
font-size: 96%;
padding: 8px 15px;
}

#grpc-history-list button.delete {
Expand Down
103 changes: 55 additions & 48 deletions internal/resources/webform/webform-template.html
Expand Up @@ -38,60 +38,67 @@
</tr>
</table>

<div id="grpc-request-response">
<ul>
<li id="#grpc-request-tab-button"><a href="#grpc-request-tab">Request Form</a></li>
<li id="#grpc-request-raw-tab-button"><a href="#grpc-request-raw-tab">Raw Request (JSON)</a></li>
<li id="#grpc-response-tab-button"><a href="#grpc-response-tab">Response</a></li>
<li id="#grpc-history-tab-button"><a href="#grpc-history-tab">History</a></li>
</ul>
<div class="grpc-tabcontent" id="grpc-request-tab">
<h3>Request Metadata</h3>
<div id="grpc-request-metadata">
<table class="grpc-request-table" id="grpc-request-metadata-form">
<tr><th></th><th class="name">Name</th><th class="value">Value</th></tr>
<tr><td><button id="grpc-request-metadata-add-row" class="add">+</button></td><td colspan="2"><span class="add-row-label">Add item</span></td></tr>
</table>
</div>

<h3>Request Data</h3>
<div id="grpc-request-form"></div>
<div id="grpc-container">
<div id="grpc-request-examples-container" style="display: none">
<h3>Examples</h3>
<ol id="grpc-request-examples"/>
</div>
<div id="grpc-request-response">
<ul>
<li id="#grpc-request-tab-button"><a href="#grpc-request-tab">Request Form</a></li>
<li id="#grpc-request-raw-tab-button"><a href="#grpc-request-raw-tab">Raw Request (JSON)</a></li>
<li id="#grpc-response-tab-button"><a href="#grpc-response-tab">Response</a></li>
<li id="#grpc-history-tab-button"><a href="#grpc-history-tab">History</a></li>
</ul>
<div class="grpc-tabcontent" id="grpc-request-tab">
<h3>Request Metadata</h3>
<div id="grpc-request-metadata">
<table class="grpc-request-table" id="grpc-request-metadata-form">
<tr><th></th><th class="name">Name</th><th class="value">Value</th></tr>
<tr><td><button id="grpc-request-metadata-add-row" class="add">+</button></td><td colspan="2"><span class="add-row-label">Add item</span></td></tr>
</table>
</div>

<h3>Request Timeout</h3>
<div id="grpc-request-timeout">
<input/> seconds
</div>
<h3>Request Data</h3>
<div id="grpc-request-form"></div>

<button class="grpc-invoke" disabled>Invoke</button>
</div>
<div class="grpc-tabcontent" id="grpc-request-raw-tab">
<textarea id="grpc-request-raw-text"></textarea><br/>
<button class="grpc-invoke" disabled>Invoke</button>
</div>
<div class="grpc-tabcontent" id="grpc-response-tab">
<h3>Response Headers</h3>
<table class="grpc-metadata-table" id="grpc-response-headers"></table>
<h3>Response Data</h3>
<div id="grpc-response-req-stats"></div>
<div class="grpc-response-messages" id="grpc-response-data"></div>
<div id="grpc-response-error">
<div id="grpc-response-error-summary">
<span id="grpc-response-error-desc"></span> <span id="grpc-response-error-num"></span>
<h3>Request Timeout</h3>
<div id="grpc-request-timeout">
<input/> seconds
</div>
<div id = "response-error-extra">
<span id="grpc-response-error-msg"></span>
<div id="grpc-response-error-details-container">
<h4>Error Details:</h4>
<div class="grpc-response-messages" id="grpc-response-error-details"></div>

<button class="grpc-invoke" disabled>Invoke</button>
</div>
<div class="grpc-tabcontent" id="grpc-request-raw-tab">
<textarea id="grpc-request-raw-text"></textarea><br/>
<button class="grpc-invoke" disabled>Invoke</button>
</div>
<div class="grpc-tabcontent" id="grpc-response-tab">
<h3>Response Headers</h3>
<table class="grpc-metadata-table" id="grpc-response-headers"></table>
<h3>Response Data</h3>
<div id="grpc-response-req-stats"></div>
<div class="grpc-response-messages" id="grpc-response-data"></div>
<div id="grpc-response-error">
<div id="grpc-response-error-summary">
<span id="grpc-response-error-desc"></span> <span id="grpc-response-error-num"></span>
</div>
<div id = "response-error-extra">
<span id="grpc-response-error-msg"></span>
<div id="grpc-response-error-details-container">
<h4>Error Details:</h4>
<div class="grpc-response-messages" id="grpc-response-error-details"></div>
</div>
</div>
</div>
<h3>Response Trailers</h3>
<table class="grpc-metadata-table" id="grpc-response-trailers"></table>
</div>
<h3>Response Trailers</h3>
<table class="grpc-metadata-table" id="grpc-response-trailers"></table>
</div>
<div class="grpc-tabcontent" id="grpc-history-tab">
<button class="grpc-history-clear" id="grpc-history-clear">Clear History</button>
<div class="grpc-history-list" id="grpc-history-list">
<div class="grpc-tabcontent" id="grpc-history-tab">
<button class="grpc-history-clear" id="grpc-history-clear">Clear History</button>
<button class="grpc-history-save" id="grpc-history-save">Save History</button>
<div class="grpc-history-list" id="grpc-history-list">
</div>
</div>
</div>
</div>
Expand Down

0 comments on commit e458831

Please sign in to comment.