endpoint.blade.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. @php
  2. use Knuckles\Scribe\Tools\Utils as u;
  3. /** @var Knuckles\Camel\Output\OutputEndpointData $endpoint */
  4. @endphp
  5. <div class="sl-stack sl-stack--vertical sl-stack--8 HttpOperation sl-flex sl-flex-col sl-items-stretch sl-w-full">
  6. <div class="sl-stack sl-stack--vertical sl-stack--5 sl-flex sl-flex-col sl-items-stretch">
  7. <div class="sl-relative">
  8. <div class="sl-stack sl-stack--horizontal sl-stack--5 sl-flex sl-flex-row sl-items-center">
  9. <h2 class="sl-text-3xl sl-leading-tight sl-font-prose sl-text-heading sl-mt-5 sl-mb-1"
  10. id="{!! $endpoint->fullSlug() !!}">
  11. {{ $endpoint->name() }}
  12. </h2>
  13. </div>
  14. </div>
  15. <div class="sl-relative">
  16. <div title="{{ rtrim($baseUrl, '/') . '/'. ltrim($endpoint->uri, '/') }}"
  17. class="sl-stack sl-stack--horizontal sl-stack--3 sl-inline-flex sl-flex-row sl-items-center sl-max-w-full sl-font-mono sl-py-2 sl-pr-4 sl-bg-canvas-50 sl-rounded-lg"
  18. >
  19. @foreach($endpoint->httpMethods as $method)
  20. <div class="sl-text-lg sl-font-semibold sl-px-2.5 sl-py-1 sl-text-on-primary sl-rounded-lg"
  21. style="background-color: {{ \Knuckles\Scribe\Tools\WritingUtils::$httpMethodToCssColour[$method] }};"
  22. >
  23. {{ $method }}
  24. </div>
  25. @endforeach
  26. <div class="sl-flex sl-overflow-x-hidden sl-text-lg sl-select-all">
  27. <div dir="rtl"
  28. class="sl-overflow-x-hidden sl-truncate sl-text-muted">{{ rtrim($baseUrl, '/') }}</div>
  29. <div class="sl-flex-1 sl-font-semibold">/{{ ltrim($endpoint->uri, '/') }}</div>
  30. </div>
  31. @if($endpoint->metadata->authenticated)
  32. <div class="sl-font-prose sl-font-semibold sl-px-1.5 sl-py-0.5 sl-text-on-primary sl-rounded-lg"
  33. style="background-color: darkred"
  34. >requires authentication
  35. </div>
  36. @endif
  37. </div>
  38. </div>
  39. {!! Parsedown::instance()->text($endpoint->metadata->description ?: '') !!}
  40. </div>
  41. <div class="sl-flex">
  42. <div data-testid="two-column-left" class="sl-flex-1 sl-w-0">
  43. <div class="sl-stack sl-stack--vertical sl-stack--10 sl-flex sl-flex-col sl-items-stretch">
  44. <div class="sl-stack sl-stack--vertical sl-stack--8 sl-flex sl-flex-col sl-items-stretch">
  45. @if(count($endpoint->headers))
  46. <div class="sl-stack sl-stack--vertical sl-stack--5 sl-flex sl-flex-col sl-items-stretch">
  47. <h3 class="sl-text-2xl sl-leading-snug sl-font-prose">
  48. {{ u::trans("scribe::endpoint.headers") }}
  49. </h3>
  50. <div class="sl-text-sm">
  51. @foreach($endpoint->headers as $header => $value)
  52. @component('scribe::themes.elements.components.field-details', [
  53. 'name' => $header,
  54. 'type' => null,
  55. 'required' => false,
  56. 'description' => null,
  57. 'example' => $value,
  58. 'endpointId' => $endpoint->endpointId(),
  59. 'component' => 'header',
  60. 'isInput' => true,
  61. ])
  62. @endcomponent
  63. @endforeach
  64. </div>
  65. </div>
  66. @endif
  67. @if(count($endpoint->urlParameters))
  68. <div class="sl-stack sl-stack--vertical sl-stack--6 sl-flex sl-flex-col sl-items-stretch">
  69. <h3 class="sl-text-2xl sl-leading-snug sl-font-prose">{{ u::trans("scribe::endpoint.url_parameters") }}</h3>
  70. <div class="sl-text-sm">
  71. @foreach($endpoint->urlParameters as $attribute => $parameter)
  72. @component('scribe::themes.elements.components.field-details', [
  73. 'name' => $parameter->name,
  74. 'type' => $parameter->type ?? 'string',
  75. 'required' => $parameter->required,
  76. 'description' => $parameter->description,
  77. 'example' => $parameter->example ?? '',
  78. 'enumValues' => $parameter->enumValues,
  79. 'endpointId' => $endpoint->endpointId(),
  80. 'component' => 'url',
  81. 'isInput' => true,
  82. ])
  83. @endcomponent
  84. @endforeach
  85. </div>
  86. </div>
  87. @endif
  88. @if(count($endpoint->queryParameters))
  89. <div class="sl-stack sl-stack--vertical sl-stack--6 sl-flex sl-flex-col sl-items-stretch">
  90. <h3 class="sl-text-2xl sl-leading-snug sl-font-prose">{{ u::trans("scribe::endpoint.query_parameters") }}</h3>
  91. <div class="sl-text-sm">
  92. @foreach($endpoint->queryParameters as $attribute => $parameter)
  93. @component('scribe::themes.elements.components.field-details', [
  94. 'name' => $parameter->name,
  95. 'type' => $parameter->type,
  96. 'required' => $parameter->required,
  97. 'description' => $parameter->description,
  98. 'example' => $parameter->example ?? '',
  99. 'enumValues' => $parameter->enumValues,
  100. 'endpointId' => $endpoint->endpointId(),
  101. 'component' => 'query',
  102. 'isInput' => true,
  103. ])
  104. @endcomponent
  105. @endforeach
  106. </div>
  107. </div>
  108. @endif
  109. @if(count($endpoint->nestedBodyParameters))
  110. <div class="sl-stack sl-stack--vertical sl-stack--6 sl-flex sl-flex-col sl-items-stretch">
  111. <h3 class="sl-text-2xl sl-leading-snug sl-font-prose">{{ u::trans("scribe::endpoint.body_parameters") }}</h3>
  112. <div class="sl-text-sm">
  113. @component('scribe::themes.elements.components.nested-fields', [
  114. 'fields' => $endpoint->nestedBodyParameters,
  115. 'endpointId' => $endpoint->endpointId(),
  116. ])
  117. @endcomponent
  118. </div>
  119. </div>
  120. @endif
  121. @if(count($endpoint->responseFields))
  122. <div class="sl-stack sl-stack--vertical sl-stack--6 sl-flex sl-flex-col sl-items-stretch">
  123. <h3 class="sl-text-2xl sl-leading-snug sl-font-prose">{{ u::trans("scribe::endpoint.response_fields") }}</h3>
  124. <div class="sl-text-sm">
  125. @component('scribe::themes.elements.components.nested-fields', [
  126. 'fields' => $endpoint->nestedResponseFields,
  127. 'endpointId' => $endpoint->endpointId(),
  128. 'isInput' => false,
  129. ])
  130. @endcomponent
  131. </div>
  132. </div>
  133. @endif
  134. </div>
  135. </div>
  136. </div>
  137. <div data-testid="two-column-right" class="sl-relative sl-w-2/5 sl-ml-16" style="max-width: 500px;">
  138. <div class="sl-stack sl-stack--vertical sl-stack--6 sl-flex sl-flex-col sl-items-stretch">
  139. @if($metadata['try_it_out']['enabled'] ?? false)
  140. @include("scribe::themes.elements.try_it_out")
  141. @endif
  142. @if($metadata['example_languages'])
  143. <div class="sl-panel sl-outline-none sl-w-full sl-rounded-lg">
  144. <div class="sl-panel__titlebar sl-flex sl-items-center sl-relative focus:sl-z-10 sl-text-base sl-leading-none sl-pr-3 sl-pl-4 sl-bg-canvas-200 sl-text-body sl-border-input focus:sl-border-primary sl-select-none">
  145. <div class="sl-flex sl-flex-1 sl-items-center sl-h-lg">
  146. <div class="sl--ml-2">
  147. {{ u::trans("scribe::endpoint.example_request") }}:
  148. <select class="example-request-lang-toggle sl-text-base"
  149. aria-label="Request Sample Language"
  150. onchange="switchExampleLanguage(event.target.value);">
  151. @foreach($metadata['example_languages'] as $language)
  152. <option>{{ $language }}</option>
  153. @endforeach
  154. </select>
  155. </div>
  156. </div>
  157. </div>
  158. @foreach($metadata['example_languages'] as $index => $language)
  159. <div class="sl-bg-canvas-100 example-request example-request-{{ $language }}"
  160. style="{{ $index == 0 ? '' : 'display: none;' }}">
  161. <div class="sl-px-0 sl-py-1">
  162. <div style="max-height: 400px;" class="sl-overflow-y-auto sl-rounded">
  163. @include("scribe::partials.example-requests.$language")
  164. </div>
  165. </div>
  166. </div>
  167. @endforeach
  168. </div>
  169. @endif
  170. @if($endpoint->isGet() || $endpoint->hasResponses())
  171. <div class="sl-panel sl-outline-none sl-w-full sl-rounded-lg">
  172. <div class="sl-panel__titlebar sl-flex sl-items-center sl-relative focus:sl-z-10 sl-text-base sl-leading-none sl-pr-3 sl-pl-4 sl-bg-canvas-200 sl-text-body sl-border-input focus:sl-border-primary sl-select-none">
  173. <div class="sl-flex sl-flex-1 sl-items-center sl-py-2">
  174. <div class="sl--ml-2">
  175. <div class="sl-h-sm sl-text-base sl-font-medium sl-px-1.5 sl-text-muted sl-rounded sl-border-transparent sl-border">
  176. <div class="sl-mb-2 sl-inline-block">{{ u::trans("scribe::endpoint.example_response") }}:</div>
  177. <div class="sl-mb-2 sl-inline-block">
  178. <select
  179. class="example-response-{{ $endpoint->endpointId() }}-toggle sl-text-base"
  180. aria-label="Response sample"
  181. onchange="switchExampleResponse('{{ $endpoint->endpointId() }}', event.target.value);">
  182. @foreach($endpoint->responses as $index => $response)
  183. <option value="{{ $index }}">{{ $response->fullDescription() }}</option>
  184. @endforeach
  185. </select></div>
  186. </div>
  187. </div>
  188. </div>
  189. <button type="button"
  190. class="sl-button sl-h-sm sl-text-base sl-font-medium sl-px-1.5 hover:sl-bg-canvas-50 active:sl-bg-canvas-100 sl-text-muted hover:sl-text-body focus:sl-text-body sl-rounded sl-border-transparent sl-border disabled:sl-opacity-70">
  191. <div class="sl-mx-0">
  192. <svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="copy"
  193. class="svg-inline--fa fa-copy fa-fw fa-sm sl-icon" role="img"
  194. xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
  195. <path fill="currentColor"
  196. d="M384 96L384 0h-112c-26.51 0-48 21.49-48 48v288c0 26.51 21.49 48 48 48H464c26.51 0 48-21.49 48-48V128h-95.1C398.4 128 384 113.6 384 96zM416 0v96h96L416 0zM192 352V128h-144c-26.51 0-48 21.49-48 48v288c0 26.51 21.49 48 48 48h192c26.51 0 48-21.49 48-48L288 416h-32C220.7 416 192 387.3 192 352z"></path>
  197. </svg>
  198. </div>
  199. </button>
  200. </div>
  201. @foreach($endpoint->responses as $index => $response)
  202. <div class="sl-panel__content-wrapper sl-bg-canvas-100 example-response-{{ $endpoint->endpointId() }} example-response-{{ $endpoint->endpointId() }}-{{ $index }}"
  203. style=" {{ $index == 0 ? '' : 'display: none;' }}"
  204. >
  205. <div class="sl-panel__content sl-p-0">@if(count($response->headers))
  206. <details class="sl-pl-2">
  207. <summary style="cursor: pointer; list-style: none;">
  208. <small>
  209. <span class="expansion-chevrons">
  210. <svg aria-hidden="true" focusable="false" data-prefix="fas"
  211. data-icon="chevron-right"
  212. class="svg-inline--fa fa-chevron-right fa-fw sl-icon sl-text-muted"
  213. xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512">
  214. <path fill="currentColor"
  215. d="M96 480c-8.188 0-16.38-3.125-22.62-9.375c-12.5-12.5-12.5-32.75 0-45.25L242.8 256L73.38 86.63c-12.5-12.5-12.5-32.75 0-45.25s32.75-12.5 45.25 0l192 192c12.5 12.5 12.5 32.75 0 45.25l-192 192C112.4 476.9 104.2 480 96 480z"></path>
  216. </svg>
  217. </span>
  218. Headers
  219. </small>
  220. </summary>
  221. <pre><code class="language-http">@foreach($response->headers as $header => $value)
  222. {{ $header }}
  223. : {{ is_array($value) ? implode('; ', $value) : $value }}
  224. @endforeach </code></pre>
  225. </details>
  226. @endif
  227. @if(is_string($response->content) && Str::startsWith($response->content, "<<binary>>"))
  228. <pre><code>[{{ u::trans("scribe::endpoint.responses.binary") }}] - {{ htmlentities(str_replace("<<binary>>", "", $response->content)) }}</code></pre>
  229. @elseif($response->status == 204)
  230. <pre><code>[{{ u::trans("scribe::endpoint.responses.empty") }}]</code></pre>
  231. @else
  232. @php($parsed = json_decode($response->content))
  233. {{-- If response is a JSON string, prettify it. Otherwise, just print it --}}
  234. <pre><code style="max-height: 300px;"
  235. class="language-json sl-overflow-x-auto sl-overflow-y-auto">{!! htmlentities($parsed != null ? json_encode($parsed, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) : $response->content) !!}</code></pre>
  236. @endif
  237. </div>
  238. </div>
  239. @endforeach
  240. </div>
  241. @endif
  242. </div>
  243. </div>
  244. </div>