-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
WIP: Default page templates #3918
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
3599a96
1dbc358
99ae759
ec3b06d
ac519b3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -148,6 +148,12 @@ public function getNewDraftPage(Entity $parent) | |
$page->book_id = $parent->id; | ||
} | ||
|
||
if ($page->book->defaultTemplate) { | ||
$page->forceFill([ | ||
'html' => $page->book->defaultTemplate->html, | ||
]); | ||
} | ||
|
||
Comment on lines
+151
to
+156
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We do need to support markdown also here, and probably the original used editor. |
||
$page->save(); | ||
$page->refresh()->rebuildPermissions(); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ | |
use BookStack\Actions\ActivityType; | ||
use BookStack\Actions\View; | ||
use BookStack\Entities\Models\Bookshelf; | ||
use BookStack\Entities\Models\Page; | ||
use BookStack\Entities\Repos\BookRepo; | ||
use BookStack\Entities\Tools\BookContents; | ||
use BookStack\Entities\Tools\Cloner; | ||
|
@@ -79,8 +80,14 @@ public function create(string $shelfSlug = null) | |
|
||
$this->setPageTitle(trans('entities.books_create')); | ||
|
||
$templates = Page::visible() | ||
->where('template', '=', true) | ||
->orderBy('name', 'asc') | ||
->get(); | ||
Comment on lines
+83
to
+86
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right now, this'll be loading in all template pages, with all their properties (including html, markdown & text) into memory for use in a list. Probably fine for the majority of use-cases but I'm uncomfortable with the scalability of this. It's a pain but ideally template selection would be done via front-end querying, much like what's shown when using the "Move" or "Copy" interfaces, to prevent requiring load of all options on form load. |
||
|
||
return view('books.create', [ | ||
'bookshelf' => $bookshelf, | ||
'templates' => $templates, | ||
]); | ||
} | ||
|
||
|
@@ -98,6 +105,7 @@ public function store(Request $request, string $shelfSlug = null) | |
'description' => ['string', 'max:1000'], | ||
'image' => array_merge(['nullable'], $this->getImageValidationRules()), | ||
'tags' => ['array'], | ||
'default_template' => ['nullable', 'exists:pages,id'], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right now there's nothing stopping a user from setting a page template they don't have access to. This exists validation check could also be abused to check the existence of a certain page id what the user may not have access to. Not sure how well we currently defend against that in other areas of the app, but probably would be something I'd attempt to avoid where possible. |
||
]); | ||
|
||
$bookshelf = null; | ||
|
@@ -151,7 +159,12 @@ public function edit(string $slug) | |
$this->checkOwnablePermission('book-update', $book); | ||
$this->setPageTitle(trans('entities.books_edit_named', ['bookName' => $book->getShortName()])); | ||
|
||
return view('books.edit', ['book' => $book, 'current' => $book]); | ||
$templates = Page::visible() | ||
->where('template', '=', true) | ||
->orderBy('name', 'asc') | ||
->get(); | ||
Comment on lines
+162
to
+165
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As per create method comment. |
||
|
||
return view('books.edit', ['book' => $book, 'current' => $book, 'templates' => $templates]); | ||
} | ||
|
||
/** | ||
|
@@ -171,6 +184,7 @@ public function update(Request $request, string $slug) | |
'description' => ['string', 'max:1000'], | ||
'image' => array_merge(['nullable'], $this->getImageValidationRules()), | ||
'tags' => ['array'], | ||
'default_template' => ['nullable', 'exists:pages,id'], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As per create method comment. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Currently, if the template option is removed when editing a book the column value will end up as |
||
]); | ||
|
||
if ($request->has('image_reset')) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
namespace BookStack\Http\Controllers; | ||
|
||
use BookStack\Actions\View; | ||
use BookStack\Entities\Models\Book; | ||
use BookStack\Entities\Models\Page; | ||
use BookStack\Entities\Repos\PageRepo; | ||
use BookStack\Entities\Tools\BookContents; | ||
|
@@ -74,7 +75,6 @@ public function createAsGuest(Request $request, string $bookSlug, string $chapte | |
$page = $this->pageRepo->getNewDraftPage($parent); | ||
$this->pageRepo->publishDraft($page, [ | ||
'name' => $request->get('name'), | ||
'html' => '', | ||
]); | ||
|
||
return redirect($page->getUrl('/edit')); | ||
|
@@ -266,11 +266,13 @@ public function showDelete(string $bookSlug, string $pageSlug) | |
$page = $this->pageRepo->getBySlug($bookSlug, $pageSlug); | ||
$this->checkOwnablePermission('page-delete', $page); | ||
$this->setPageTitle(trans('entities.pages_delete_named', ['pageName' => $page->getShortName()])); | ||
$times_used_as_template = Book::where('default_template', '=', $page->id)->count(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Variable name does not follow project conventions, but use may be redundant (lang file comments). |
||
|
||
return view('pages.delete', [ | ||
'book' => $page->book, | ||
'page' => $page, | ||
'current' => $page, | ||
'times_used_as_template' => $times_used_as_template, | ||
]); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<?php | ||
|
||
use Illuminate\Database\Migrations\Migration; | ||
use Illuminate\Database\Schema\Blueprint; | ||
use Illuminate\Support\Facades\Schema; | ||
|
||
class AddDefaultTemplateToBooks extends Migration | ||
{ | ||
/** | ||
* Run the migrations. | ||
* | ||
* @return void | ||
*/ | ||
public function up() | ||
{ | ||
Schema::table('books', function (Blueprint $table) { | ||
$table->integer('default_template')->nullable(); | ||
}); | ||
} | ||
|
||
/** | ||
* Reverse the migrations. | ||
* | ||
* @return void | ||
*/ | ||
public function down() | ||
{ | ||
Schema::table('books', function (Blueprint $table) { | ||
$table->dropColumn('default_template'); | ||
}); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -192,6 +192,7 @@ | |
'pages_delete_draft' => 'Delete Draft Page', | ||
'pages_delete_success' => 'Page deleted', | ||
'pages_delete_draft_success' => 'Draft page deleted', | ||
'pages_delete_warning_template' => '{0}|{1}Be careful: this page is used as a template for :count book.|[2,*]Be careful: this page is used as a template for :count books.', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we need to show the count here (Which again can complicate matters when permissions are in play) but I just think we need the user to be aware of the consequences, something like:
|
||
'pages_delete_confirm' => 'Are you sure you want to delete this page?', | ||
'pages_delete_draft_confirm' => 'Are you sure you want to delete this draft page?', | ||
'pages_editing_named' => 'Editing Page :pageName', | ||
|
@@ -328,6 +329,8 @@ | |
'templates_replace_content' => 'Replace page content', | ||
'templates_append_content' => 'Append to page content', | ||
'templates_prepend_content' => 'Prepend to page content', | ||
'default_template' => 'Default Page Template', | ||
'default_template_explain' => "Assign a default template that will be used for all new pages in this book.", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should probably include a note on permissions, advising that the page template will only be used if the page creator has view permission for the page template. |
||
|
||
// Profile View | ||
'profile_user_for_x' => 'User for :time', | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<p class="text-muted small"> | ||
{!! nl2br(e(trans('entities.default_template_explain'))) !!} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's no newlines in the source string so this can be a simple non-escaped template tag. If there are multiple clear lines I try to split the translation itself these days. |
||
</p> | ||
|
||
<select name="default_template" id="default_template"> | ||
<option value="">---</option> | ||
@foreach ($templates as $template) | ||
<option @if(isset($entity) && $entity->default_template === $template->id) selected @endif value="{{ $template->id }}">{{ $template->name }}</option> | ||
@endforeach | ||
</select> |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,7 +14,7 @@ | |
<div class="search-box flexible mb-m" style="display: {{ count($templates) > 0 ? 'block' : 'none' }}"> | ||
<input refs="template-manager@searchInput" type="text" name="template-search" placeholder="{{ trans('common.search') }}"> | ||
<button refs="template-manager@searchButton" tabindex="-1" type="button">@icon('search')</button> | ||
<button refs="template-manager@searchCancel" class="search-box-cancel text-neg" type="button" style="display: none">@icon('close')</button> | ||
<button refs="template-manager@searchCancel" class="search-box-cancel text-neg" tabindex="-1" type="button" style="display: none">@icon('close')</button> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd generally advise slipping small fixes into larger works otherwise they get blocked by the larger feature and/or conflict if the fix gets applied in the meantime. |
||
</div> | ||
|
||
<div refs="template-manager@list"> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This currently ignores permissions. I think we'll need to respect page permissions, so view access is required for the template to be used, otherwise other side-effects will be introduced (Image access permissions for example).