rapidoc
Version:
RapiDoc - Open API spec viewer with built in console
224 lines (218 loc) • 8.46 kB
JavaScript
/**
* Renders the interactive API response panel (status, headers, body, blob actions),
* live cURL preview/copy, and the execute/Try action controls for <api-request>.
*/
import { html } from "lit";
import { ifDefined } from "lit/directives/if-defined.js";
import { copyToClipboard, downloadResource, viewResource } from "~/utils/common-utils";
export function curlSyntaxTemplate(display = "flex") {
return html`
<div class="col m-markdown" style="flex:1; display:${display}; position:relative; max-width: 100%;">
<button
class="btn btn-sm btn-outline toolbar-btn"
style="position:absolute; top:12px; right:8px"
@click="${(e) => {
copyToClipboard(this.curlSyntax.trim().replace(/\\$/, ""), e);
}}"
part="btn btn-outline btn-copy"
>
Copy
</button>
<pre style="white-space:pre"><code class="language-shell">${this.curlSyntax.trim().replace(/\\$/, "")}</code></pre>
</div>
`;
}
export function apiResponseTabTemplate() {
let responseFormat = "";
let responseContent = "";
if (!this.responseIsBlob) {
if (
this.responseHeaders.includes("application/x-ndjson") ||
this.responseHeaders.includes("json")
) {
responseFormat = "json";
} else if (this.responseHeaders.includes("html") || this.responseHeaders.includes("xml")) {
responseFormat = "html";
} else {
responseFormat = "text";
}
responseContent = html`<code class="language-${responseFormat}">${this.responseText}</code>`;
}
return html` <div class="row" style="font-size:var(--font-size-small); margin:5px 0; justify-content:space-between; align-items:center;">
<div class="response-message ${this.responseStatus}">Response Status: ${this.responseMessage}</div>
<button class="btn btn-outline" part="btn btn-outline btn-clear-response" @click="${this.clearResponseData}">CLEAR RESPONSE</button>
</div>
<div part="tab-panel" class="tab-panel col">
<div
id="tab_buttons"
part="tab-btn-row"
class="tab-buttons row"
@click="${(e) => {
if (
e.target.classList.contains("tab-btn") === false &&
e.target.classList.contains("tab") === false
) {
return;
}
this.activeResponseTab = e.target.dataset.tab;
}}"
>
<button part="tab-btn" class="tab-btn ${this.activeResponseTab === "response" ? "active" : ""}" data-tab="response">
RESPONSE
</button>
<button part="tab-btn" class="tab-btn ${this.activeResponseTab === "headers" ? "active" : ""}" data-tab="headers">
RESPONSE HEADERS
</button>
${
this.showCurlBeforeTry === "true"
? ""
: html`<button part="tab-btn" class="tab-btn ${this.activeResponseTab === "curl" ? "active" : ""}" data-tab="curl">
CURL
</button>`
}
</div>
${
this.responseIsBlob
? html`<div
part="tab-content"
class="tab-content col"
style="flex:1; display:${this.activeResponseTab === "response" ? "flex" : "none"};"
>
${
this.responseBlobType === "image"
? html`<img style="max-height:var(--resp-area-height); object-fit:contain;" class="mar-top-8" src="${ifDefined(this.responseBlobUrl)}"></img>`
: ""
}
<button
class="btn btn-outline mar-top-8"
style="width:135px"
@click="${() => {
downloadResource(this.responseBlobUrl, this.respContentDisposition);
}}"
part="btn btn-outline"
>
DOWNLOAD
</button>
${
this.responseBlobType === "view" || this.responseBlobType === "image"
? html`<button
class="btn btn-outline mar-top-8"
style="width:135px"
@click="${() => {
viewResource(this.responseBlobUrl);
}}"
part="btn btn-outline"
>
VIEW (NEW TAB)
</button>`
: ""
}
</div>`
: html`<div
part="tab-content"
class="tab-content col m-markdown"
style="flex:1; display:${this.activeResponseTab === "response" ? "flex" : "none"};"
>
<button
class="btn btn-sm btn-outline toolbar-btn"
@click="${(e) => {
copyToClipboard(this.responseText, e);
}}"
part="btn btn-outline btn-copy"
>
Copy
</button>
<pre style="white-space:pre; min-height:50px; height:var(--resp-area-height); resize:vertical; overflow:auto">
${responseContent}</pre>
</div>`
}
<div
part="tab-content"
class="tab-content col m-markdown"
style="flex:1; display:${this.activeResponseTab === "headers" ? "flex" : "none"};"
>
<button
class="btn btn-sm btn-outline toolbar-btn"
@click="${(e) => {
copyToClipboard(this.responseHeaders, e);
}}"
part="btn btn-outline btn-copy"
>
Copy
</button>
<pre style="white-space:pre"><code class="language-css">${this.responseHeaders}</code></pre>
</div>
${this.showCurlBeforeTry === "true" ? "" : curlSyntaxTemplate.call(this, this.activeResponseTab === "curl" ? "flex" : "none")}
</div>`;
}
export function apiCallTemplate() {
let authHtml;
if (this.security?.length > 0 && !this.security.every((s) => !s || Object.keys(s).length === 0)) {
if (this.api_keys.length > 0) {
authHtml = html`<span class="blue-text">
${this.api_keys.length === 1 ? `${this.api_keys[0]?.typeDisplay} in ${this.api_keys[0].in}` : `${this.api_keys.length} API keys applied`}
</span>`;
} else if (this.security.some((s) => !s || Object.keys(s).length === 0)) {
authHtml = html`Optional (None Applied)`;
} else {
authHtml = html`Required <span class="red-text">(None Applied)</span>`;
}
} else {
authHtml = html`Not Required`;
}
return html`<div class="try-bar" part="wrap-request-btn">
<div class="try-layout">
<dl class="try-info">
${
this.serverUrl
? html`<dt>API Server</dt>
<dd class="try-server-url">${this.serverUrl}</dd>`
: ""
}
<dt>Authentication</dt>
<dd>${authHtml}</dd>
</dl>
<div class="try-actions">
${
this.parameters.length > 0 || this.request_body
? html`${
this.hasExampleToFill
? html`<button
class="btn btn-outline"
part="btn btn-outline btn-fill btn-fill-example"
?disabled="${this.loading}"
@click="${this.onFillRequestData}"
title="Fills the request fields with their examples"
>
FILL EXAMPLE
</button>`
: ""
}
<button
class="btn btn-outline"
part="btn btn-outline btn-clear"
?disabled="${this.loading || !this.hasValueToClear}"
@click="${this.onClearRequestData}"
>
CLEAR
</button>`
: ""
}
<button
class="btn btn-primary"
part="btn btn-try"
?disabled="${this.loading}"
aria-busy="${this.loading}"
@click="${this.onTryClick}"
>
${this.loading ? "TRYING..." : "TRY"}
</button>
</div>
</div>
</div>
<div class="row" style="font-size:var(--font-size-small); margin:5px 0">
${this.showCurlBeforeTry === "true" ? curlSyntaxTemplate.call(this) : ""}
</div>
${this.responseMessage === "" ? "" : apiResponseTabTemplate.call(this)} `;
}
export default apiCallTemplate;