mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-01 01:36:00 -04:00
Added a view for the API docs
This commit is contained in:
parent
bed2498667
commit
45b5e631e2
@ -106,7 +106,7 @@ class ApiDocsGenerator
|
|||||||
return strpos($route->uri, 'api/') === 0;
|
return strpos($route->uri, 'api/') === 0;
|
||||||
})->map(function ($route) {
|
})->map(function ($route) {
|
||||||
[$controller, $controllerMethod] = explode('@', $route->action['uses']);
|
[$controller, $controllerMethod] = explode('@', $route->action['uses']);
|
||||||
$baseModelName = explode('/', $route->uri)[1];
|
$baseModelName = explode('.', explode('/', $route->uri)[1])[0];
|
||||||
$shortName = $baseModelName . '-' . $controllerMethod;
|
$shortName = $baseModelName . '-' . $controllerMethod;
|
||||||
return [
|
return [
|
||||||
'name' => $shortName,
|
'name' => $shortName,
|
||||||
|
@ -13,9 +13,9 @@ class ApiDocsController extends ApiController
|
|||||||
public function display()
|
public function display()
|
||||||
{
|
{
|
||||||
$docs = $this->getDocs();
|
$docs = $this->getDocs();
|
||||||
dd($docs);
|
return view('api-docs.index', [
|
||||||
// TODO - Build view for API docs
|
'docs' => $docs,
|
||||||
return view('');
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,8 +2,11 @@
|
|||||||
|
|
||||||
use BookStack\Entities\Book;
|
use BookStack\Entities\Book;
|
||||||
use BookStack\Entities\Repos\BookRepo;
|
use BookStack\Entities\Repos\BookRepo;
|
||||||
|
use BookStack\Exceptions\NotifyException;
|
||||||
use BookStack\Facades\Activity;
|
use BookStack\Facades\Activity;
|
||||||
|
use Illuminate\Contracts\Container\BindingResolutionException;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
class BooksApiController extends ApiController
|
class BooksApiController extends ApiController
|
||||||
{
|
{
|
||||||
@ -41,8 +44,8 @@ class BooksApiController extends ApiController
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new book.
|
* Create a new book in the system.
|
||||||
* @throws \Illuminate\Validation\ValidationException
|
* @throws ValidationException
|
||||||
*/
|
*/
|
||||||
public function create(Request $request)
|
public function create(Request $request)
|
||||||
{
|
{
|
||||||
@ -66,7 +69,7 @@ class BooksApiController extends ApiController
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the details of a single book.
|
* Update the details of a single book.
|
||||||
* @throws \Illuminate\Validation\ValidationException
|
* @throws ValidationException
|
||||||
*/
|
*/
|
||||||
public function update(Request $request, string $id)
|
public function update(Request $request, string $id)
|
||||||
{
|
{
|
||||||
@ -81,9 +84,9 @@ class BooksApiController extends ApiController
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a book from the system.
|
* Delete a single book from the system.
|
||||||
* @throws \BookStack\Exceptions\NotifyException
|
* @throws NotifyException
|
||||||
* @throws \Illuminate\Contracts\Container\BindingResolutionException
|
* @throws BindingResolutionException
|
||||||
*/
|
*/
|
||||||
public function delete(string $id)
|
public function delete(string $id)
|
||||||
{
|
{
|
||||||
|
18
resources/js/components/details-highlighter.js
Normal file
18
resources/js/components/details-highlighter.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import Code from "../services/code"
|
||||||
|
class DetailsHighlighter {
|
||||||
|
|
||||||
|
constructor(elem) {
|
||||||
|
this.elem = elem;
|
||||||
|
this.dealtWith = false;
|
||||||
|
elem.addEventListener('toggle', this.onToggle.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
onToggle() {
|
||||||
|
if (this.dealtWith) return;
|
||||||
|
|
||||||
|
Code.highlightWithin(this.elem);
|
||||||
|
this.dealtWith = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DetailsHighlighter;
|
@ -30,6 +30,7 @@ import settingColorPicker from "./setting-color-picker";
|
|||||||
import entityPermissionsEditor from "./entity-permissions-editor";
|
import entityPermissionsEditor from "./entity-permissions-editor";
|
||||||
import templateManager from "./template-manager";
|
import templateManager from "./template-manager";
|
||||||
import newUserPassword from "./new-user-password";
|
import newUserPassword from "./new-user-password";
|
||||||
|
import detailsHighlighter from "./details-highlighter";
|
||||||
|
|
||||||
const componentMapping = {
|
const componentMapping = {
|
||||||
'dropdown': dropdown,
|
'dropdown': dropdown,
|
||||||
@ -64,6 +65,7 @@ const componentMapping = {
|
|||||||
'entity-permissions-editor': entityPermissionsEditor,
|
'entity-permissions-editor': entityPermissionsEditor,
|
||||||
'template-manager': templateManager,
|
'template-manager': templateManager,
|
||||||
'new-user-password': newUserPassword,
|
'new-user-password': newUserPassword,
|
||||||
|
'details-highlighter': detailsHighlighter,
|
||||||
};
|
};
|
||||||
|
|
||||||
window.components = {};
|
window.components = {};
|
||||||
|
@ -87,9 +87,20 @@ const modeMap = {
|
|||||||
* Highlight pre elements on a page
|
* Highlight pre elements on a page
|
||||||
*/
|
*/
|
||||||
function highlight() {
|
function highlight() {
|
||||||
let codeBlocks = document.querySelectorAll('.page-content pre, .comment-box .content pre');
|
const codeBlocks = document.querySelectorAll('.page-content pre, .comment-box .content pre');
|
||||||
for (let i = 0; i < codeBlocks.length; i++) {
|
for (const codeBlock of codeBlocks) {
|
||||||
highlightElem(codeBlocks[i]);
|
highlightElem(codeBlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Highlight all code blocks within the given parent element
|
||||||
|
* @param {HTMLElement} parent
|
||||||
|
*/
|
||||||
|
function highlightWithin(parent) {
|
||||||
|
const codeBlocks = parent.querySelectorAll('pre');
|
||||||
|
for (const codeBlock of codeBlocks) {
|
||||||
|
highlightElem(codeBlock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,6 +319,7 @@ function getMetaKey() {
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
highlight: highlight,
|
highlight: highlight,
|
||||||
|
highlightWithin: highlightWithin,
|
||||||
wysiwygView: wysiwygView,
|
wysiwygView: wysiwygView,
|
||||||
popupEditor: popupEditor,
|
popupEditor: popupEditor,
|
||||||
setMode: setMode,
|
setMode: setMode,
|
||||||
|
@ -236,4 +236,26 @@
|
|||||||
|
|
||||||
.tag-list div:last-child .tag-item {
|
.tag-list div:last-child .tag-item {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API Docs
|
||||||
|
*/
|
||||||
|
.api-method {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
background-color: #888;
|
||||||
|
padding: $-xs;
|
||||||
|
line-height: 1.3;
|
||||||
|
opacity: 0.7;
|
||||||
|
vertical-align: top;
|
||||||
|
border-radius: 3px;
|
||||||
|
color: #FFF;
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 60px;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
&[data-method="GET"] { background-color: #077b70 }
|
||||||
|
&[data-method="POST"] { background-color: #cf4d03 }
|
||||||
|
&[data-method="PUT"] { background-color: #0288D1 }
|
||||||
|
&[data-method="DELETE"] { background-color: #ab0f0e }
|
||||||
}
|
}
|
@ -213,6 +213,18 @@ blockquote {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-mono {
|
||||||
|
font-family: $mono;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-uppercase {
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-capitals {
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
.code-base {
|
.code-base {
|
||||||
background-color: #F8F8F8;
|
background-color: #F8F8F8;
|
||||||
font-size: 0.80em;
|
font-size: 0.80em;
|
||||||
|
51
resources/views/api-docs/index.blade.php
Normal file
51
resources/views/api-docs/index.blade.php
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
@extends('simple-layout')
|
||||||
|
|
||||||
|
@section('body')
|
||||||
|
|
||||||
|
<div class="container pt-xl">
|
||||||
|
|
||||||
|
<div class="grid right-focus reverse-collapse">
|
||||||
|
|
||||||
|
<div>
|
||||||
|
@foreach($docs as $model => $endpoints)
|
||||||
|
<p class="text-uppercase text-muted mb-xm mt-l"><strong>{{ $model }}</strong></p>
|
||||||
|
|
||||||
|
@foreach($endpoints as $endpoint)
|
||||||
|
<div class="mb-xs">
|
||||||
|
<a href="#{{ $endpoint['name'] }}" class="text-mono">
|
||||||
|
<span class="api-method" data-method="{{ $endpoint['method'] }}">{{ $endpoint['method'] }}</span>
|
||||||
|
/{{ $endpoint['uri'] }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
@foreach($docs as $model => $endpoints)
|
||||||
|
<section class="card content-wrap auto-height">
|
||||||
|
<h1 class="list-heading text-capitals">{{ $model }}</h1>
|
||||||
|
|
||||||
|
@foreach($endpoints as $endpoint)
|
||||||
|
<h5 id="{{ $endpoint['name'] }}" class="text-mono mb-m">
|
||||||
|
<span class="api-method" data-method="{{ $endpoint['method'] }}">{{ $endpoint['method'] }}</span>
|
||||||
|
{{ url($endpoint['uri']) }}
|
||||||
|
</h5>
|
||||||
|
<p class="mb-m">{{ $endpoint['description'] ?? '' }}</p>
|
||||||
|
@if($endpoint['example_response'] ?? false)
|
||||||
|
<details details-highlighter>
|
||||||
|
<summary class="text-muted">Example Response</summary>
|
||||||
|
<pre><code class="language-json">{{ $endpoint['example_response'] }}</code></pre>
|
||||||
|
</details>
|
||||||
|
<hr class="mt-m">
|
||||||
|
@endif
|
||||||
|
@endforeach
|
||||||
|
</section>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
@stop
|
Loading…
Reference in New Issue
Block a user