mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-04-21 05:26:10 +03:00
Input WYSIWYG: Updated API to show/accept html descriptions
Also aligned books, shelves and chapters to return description content and some relations (where not breaking API) in create/update responses also so that information can be seen direct from that input in a request. API docs and tests not yet updated to match.
This commit is contained in:
parent
ed5d67e609
commit
00ae04e0bd
@ -45,7 +45,7 @@ class BookApiController extends ApiController
|
|||||||
|
|
||||||
$book = $this->bookRepo->create($requestData);
|
$book = $this->bookRepo->create($requestData);
|
||||||
|
|
||||||
return response()->json($book);
|
return response()->json($this->forJsonDisplay($book));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,9 +56,9 @@ class BookApiController extends ApiController
|
|||||||
*/
|
*/
|
||||||
public function read(string $id)
|
public function read(string $id)
|
||||||
{
|
{
|
||||||
$book = Book::visible()
|
$book = Book::visible()->findOrFail($id);
|
||||||
->with(['tags', 'cover', 'createdBy', 'updatedBy', 'ownedBy'])
|
$book = $this->forJsonDisplay($book);
|
||||||
->findOrFail($id);
|
$book->load(['createdBy', 'updatedBy', 'ownedBy']);
|
||||||
|
|
||||||
$contents = (new BookContents($book))->getTree(true, false)->all();
|
$contents = (new BookContents($book))->getTree(true, false)->all();
|
||||||
$contentsApiData = (new ApiEntityListFormatter($contents))
|
$contentsApiData = (new ApiEntityListFormatter($contents))
|
||||||
@ -89,7 +89,7 @@ class BookApiController extends ApiController
|
|||||||
$requestData = $this->validate($request, $this->rules()['update']);
|
$requestData = $this->validate($request, $this->rules()['update']);
|
||||||
$book = $this->bookRepo->update($book, $requestData);
|
$book = $this->bookRepo->update($book, $requestData);
|
||||||
|
|
||||||
return response()->json($book);
|
return response()->json($this->forJsonDisplay($book));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -108,21 +108,35 @@ class BookApiController extends ApiController
|
|||||||
return response('', 204);
|
return response('', 204);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function forJsonDisplay(Book $book): Book
|
||||||
|
{
|
||||||
|
$book = clone $book;
|
||||||
|
$book->unsetRelations()->refresh();
|
||||||
|
|
||||||
|
$book->load(['tags', 'cover']);
|
||||||
|
$book->makeVisible('description_html')
|
||||||
|
->setAttribute('description_html', $book->descriptionHtml());
|
||||||
|
|
||||||
|
return $book;
|
||||||
|
}
|
||||||
|
|
||||||
protected function rules(): array
|
protected function rules(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'create' => [
|
'create' => [
|
||||||
'name' => ['required', 'string', 'max:255'],
|
'name' => ['required', 'string', 'max:255'],
|
||||||
'description' => ['string', 'max:1000'],
|
'description' => ['string', 'max:1900'],
|
||||||
'tags' => ['array'],
|
'description_html' => ['string', 'max:2000'],
|
||||||
'image' => array_merge(['nullable'], $this->getImageValidationRules()),
|
'tags' => ['array'],
|
||||||
|
'image' => array_merge(['nullable'], $this->getImageValidationRules()),
|
||||||
'default_template_id' => ['nullable', 'integer'],
|
'default_template_id' => ['nullable', 'integer'],
|
||||||
],
|
],
|
||||||
'update' => [
|
'update' => [
|
||||||
'name' => ['string', 'min:1', 'max:255'],
|
'name' => ['string', 'min:1', 'max:255'],
|
||||||
'description' => ['string', 'max:1000'],
|
'description' => ['string', 'max:1900'],
|
||||||
'tags' => ['array'],
|
'description_html' => ['string', 'max:2000'],
|
||||||
'image' => array_merge(['nullable'], $this->getImageValidationRules()),
|
'tags' => ['array'],
|
||||||
|
'image' => array_merge(['nullable'], $this->getImageValidationRules()),
|
||||||
'default_template_id' => ['nullable', 'integer'],
|
'default_template_id' => ['nullable', 'integer'],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
@ -12,11 +12,9 @@ use Illuminate\Validation\ValidationException;
|
|||||||
|
|
||||||
class BookshelfApiController extends ApiController
|
class BookshelfApiController extends ApiController
|
||||||
{
|
{
|
||||||
protected BookshelfRepo $bookshelfRepo;
|
public function __construct(
|
||||||
|
protected BookshelfRepo $bookshelfRepo
|
||||||
public function __construct(BookshelfRepo $bookshelfRepo)
|
) {
|
||||||
{
|
|
||||||
$this->bookshelfRepo = $bookshelfRepo;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,7 +46,7 @@ class BookshelfApiController extends ApiController
|
|||||||
$bookIds = $request->get('books', []);
|
$bookIds = $request->get('books', []);
|
||||||
$shelf = $this->bookshelfRepo->create($requestData, $bookIds);
|
$shelf = $this->bookshelfRepo->create($requestData, $bookIds);
|
||||||
|
|
||||||
return response()->json($shelf);
|
return response()->json($this->forJsonDisplay($shelf));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,12 +54,14 @@ class BookshelfApiController extends ApiController
|
|||||||
*/
|
*/
|
||||||
public function read(string $id)
|
public function read(string $id)
|
||||||
{
|
{
|
||||||
$shelf = Bookshelf::visible()->with([
|
$shelf = Bookshelf::visible()->findOrFail($id);
|
||||||
'tags', 'cover', 'createdBy', 'updatedBy', 'ownedBy',
|
$shelf = $this->forJsonDisplay($shelf);
|
||||||
|
$shelf->load([
|
||||||
|
'createdBy', 'updatedBy', 'ownedBy',
|
||||||
'books' => function (BelongsToMany $query) {
|
'books' => function (BelongsToMany $query) {
|
||||||
$query->scopes('visible')->get(['id', 'name', 'slug']);
|
$query->scopes('visible')->get(['id', 'name', 'slug']);
|
||||||
},
|
},
|
||||||
])->findOrFail($id);
|
]);
|
||||||
|
|
||||||
return response()->json($shelf);
|
return response()->json($shelf);
|
||||||
}
|
}
|
||||||
@ -86,7 +86,7 @@ class BookshelfApiController extends ApiController
|
|||||||
|
|
||||||
$shelf = $this->bookshelfRepo->update($shelf, $requestData, $bookIds);
|
$shelf = $this->bookshelfRepo->update($shelf, $requestData, $bookIds);
|
||||||
|
|
||||||
return response()->json($shelf);
|
return response()->json($this->forJsonDisplay($shelf));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -105,22 +105,36 @@ class BookshelfApiController extends ApiController
|
|||||||
return response('', 204);
|
return response('', 204);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function forJsonDisplay(Bookshelf $shelf): Bookshelf
|
||||||
|
{
|
||||||
|
$shelf = clone $shelf;
|
||||||
|
$shelf->unsetRelations()->refresh();
|
||||||
|
|
||||||
|
$shelf->load(['tags', 'cover']);
|
||||||
|
$shelf->makeVisible('description_html')
|
||||||
|
->setAttribute('description_html', $shelf->descriptionHtml());
|
||||||
|
|
||||||
|
return $shelf;
|
||||||
|
}
|
||||||
|
|
||||||
protected function rules(): array
|
protected function rules(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'create' => [
|
'create' => [
|
||||||
'name' => ['required', 'string', 'max:255'],
|
'name' => ['required', 'string', 'max:255'],
|
||||||
'description' => ['string', 'max:1000'],
|
'description' => ['string', 'max:1900'],
|
||||||
'books' => ['array'],
|
'description_html' => ['string', 'max:2000'],
|
||||||
'tags' => ['array'],
|
'books' => ['array'],
|
||||||
'image' => array_merge(['nullable'], $this->getImageValidationRules()),
|
'tags' => ['array'],
|
||||||
|
'image' => array_merge(['nullable'], $this->getImageValidationRules()),
|
||||||
],
|
],
|
||||||
'update' => [
|
'update' => [
|
||||||
'name' => ['string', 'min:1', 'max:255'],
|
'name' => ['string', 'min:1', 'max:255'],
|
||||||
'description' => ['string', 'max:1000'],
|
'description' => ['string', 'max:1900'],
|
||||||
'books' => ['array'],
|
'description_html' => ['string', 'max:2000'],
|
||||||
'tags' => ['array'],
|
'books' => ['array'],
|
||||||
'image' => array_merge(['nullable'], $this->getImageValidationRules()),
|
'tags' => ['array'],
|
||||||
|
'image' => array_merge(['nullable'], $this->getImageValidationRules()),
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -15,18 +15,20 @@ class ChapterApiController extends ApiController
|
|||||||
{
|
{
|
||||||
protected $rules = [
|
protected $rules = [
|
||||||
'create' => [
|
'create' => [
|
||||||
'book_id' => ['required', 'integer'],
|
'book_id' => ['required', 'integer'],
|
||||||
'name' => ['required', 'string', 'max:255'],
|
'name' => ['required', 'string', 'max:255'],
|
||||||
'description' => ['string', 'max:1000'],
|
'description' => ['string', 'max:1900'],
|
||||||
'tags' => ['array'],
|
'description_html' => ['string', 'max:2000'],
|
||||||
'priority' => ['integer'],
|
'tags' => ['array'],
|
||||||
|
'priority' => ['integer'],
|
||||||
],
|
],
|
||||||
'update' => [
|
'update' => [
|
||||||
'book_id' => ['integer'],
|
'book_id' => ['integer'],
|
||||||
'name' => ['string', 'min:1', 'max:255'],
|
'name' => ['string', 'min:1', 'max:255'],
|
||||||
'description' => ['string', 'max:1000'],
|
'description' => ['string', 'max:1900'],
|
||||||
'tags' => ['array'],
|
'description_html' => ['string', 'max:2000'],
|
||||||
'priority' => ['integer'],
|
'tags' => ['array'],
|
||||||
|
'priority' => ['integer'],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -61,7 +63,7 @@ class ChapterApiController extends ApiController
|
|||||||
|
|
||||||
$chapter = $this->chapterRepo->create($requestData, $book);
|
$chapter = $this->chapterRepo->create($requestData, $book);
|
||||||
|
|
||||||
return response()->json($chapter->load(['tags']));
|
return response()->json($this->forJsonDisplay($chapter));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -69,9 +71,15 @@ class ChapterApiController extends ApiController
|
|||||||
*/
|
*/
|
||||||
public function read(string $id)
|
public function read(string $id)
|
||||||
{
|
{
|
||||||
$chapter = Chapter::visible()->with(['tags', 'createdBy', 'updatedBy', 'ownedBy', 'pages' => function (HasMany $query) {
|
$chapter = Chapter::visible()->findOrFail($id);
|
||||||
$query->scopes('visible')->get(['id', 'name', 'slug']);
|
$chapter = $this->forJsonDisplay($chapter);
|
||||||
}])->findOrFail($id);
|
|
||||||
|
$chapter->load([
|
||||||
|
'createdBy', 'updatedBy', 'ownedBy',
|
||||||
|
'pages' => function (HasMany $query) {
|
||||||
|
$query->scopes('visible')->get(['id', 'name', 'slug']);
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
return response()->json($chapter);
|
return response()->json($chapter);
|
||||||
}
|
}
|
||||||
@ -93,7 +101,7 @@ class ChapterApiController extends ApiController
|
|||||||
try {
|
try {
|
||||||
$this->chapterRepo->move($chapter, "book:{$requestData['book_id']}");
|
$this->chapterRepo->move($chapter, "book:{$requestData['book_id']}");
|
||||||
} catch (Exception $exception) {
|
} catch (Exception $exception) {
|
||||||
if ($exception instanceof PermissionsException) {
|
if ($exception instanceof PermissionsException) {
|
||||||
$this->showPermissionError();
|
$this->showPermissionError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +111,7 @@ class ChapterApiController extends ApiController
|
|||||||
|
|
||||||
$updatedChapter = $this->chapterRepo->update($chapter, $requestData);
|
$updatedChapter = $this->chapterRepo->update($chapter, $requestData);
|
||||||
|
|
||||||
return response()->json($updatedChapter->load(['tags']));
|
return response()->json($this->forJsonDisplay($updatedChapter));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -119,4 +127,16 @@ class ChapterApiController extends ApiController
|
|||||||
|
|
||||||
return response('', 204);
|
return response('', 204);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function forJsonDisplay(Chapter $chapter): Chapter
|
||||||
|
{
|
||||||
|
$chapter = clone $chapter;
|
||||||
|
$chapter->unsetRelations()->refresh();
|
||||||
|
|
||||||
|
$chapter->load(['tags']);
|
||||||
|
$chapter->makeVisible('description_html')
|
||||||
|
->setAttribute('description_html', $chapter->descriptionHtml());
|
||||||
|
|
||||||
|
return $chapter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ class Book extends Entity implements HasCoverImage
|
|||||||
public float $searchFactor = 1.2;
|
public float $searchFactor = 1.2;
|
||||||
|
|
||||||
protected $fillable = ['name'];
|
protected $fillable = ['name'];
|
||||||
protected $hidden = ['pivot', 'image_id', 'deleted_at'];
|
protected $hidden = ['pivot', 'image_id', 'deleted_at', 'description_html'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the url for this book.
|
* Get the url for this book.
|
||||||
|
@ -19,7 +19,7 @@ class Bookshelf extends Entity implements HasCoverImage
|
|||||||
|
|
||||||
protected $fillable = ['name', 'description', 'image_id'];
|
protected $fillable = ['name', 'description', 'image_id'];
|
||||||
|
|
||||||
protected $hidden = ['image_id', 'deleted_at'];
|
protected $hidden = ['image_id', 'deleted_at', 'description_html'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the books in this shelf.
|
* Get the books in this shelf.
|
||||||
|
@ -20,7 +20,7 @@ class Chapter extends BookChild
|
|||||||
public float $searchFactor = 1.2;
|
public float $searchFactor = 1.2;
|
||||||
|
|
||||||
protected $fillable = ['name', 'description', 'priority'];
|
protected $fillable = ['name', 'description', 'priority'];
|
||||||
protected $hidden = ['pivot', 'deleted_at'];
|
protected $hidden = ['pivot', 'deleted_at', 'description_html'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the pages that this chapter contains.
|
* Get the pages that this chapter contains.
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
"name": "My own book",
|
"name": "My own book",
|
||||||
"slug": "my-own-book",
|
"slug": "my-own-book",
|
||||||
"description": "This is my own little book",
|
"description": "This is my own little book",
|
||||||
|
"description_html": "<p>This is my own <em>little</em> book</p>",
|
||||||
"created_at": "2020-01-12T14:09:59.000000Z",
|
"created_at": "2020-01-12T14:09:59.000000Z",
|
||||||
"updated_at": "2020-01-12T14:11:51.000000Z",
|
"updated_at": "2020-01-12T14:11:51.000000Z",
|
||||||
"created_by": {
|
"created_by": {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
"slug": "content-creation",
|
"slug": "content-creation",
|
||||||
"name": "Content Creation",
|
"name": "Content Creation",
|
||||||
"description": "How to create documentation on whatever subject you need to write about.",
|
"description": "How to create documentation on whatever subject you need to write about.",
|
||||||
|
"description_html": "<p>How to create <strong>documentation</strong> on whatever subject you need to write about.</p>",
|
||||||
"priority": 3,
|
"priority": 3,
|
||||||
"created_at": "2019-05-05T21:49:56.000000Z",
|
"created_at": "2019-05-05T21:49:56.000000Z",
|
||||||
"updated_at": "2019-09-28T11:24:23.000000Z",
|
"updated_at": "2019-09-28T11:24:23.000000Z",
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
"name": "My shelf",
|
"name": "My shelf",
|
||||||
"slug": "my-shelf",
|
"slug": "my-shelf",
|
||||||
"description": "This is my shelf with some books",
|
"description": "This is my shelf with some books",
|
||||||
|
"description_html": "<p>This is my shelf with some books</p>",
|
||||||
"created_by": {
|
"created_by": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"name": "Admin",
|
"name": "Admin",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user