mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-30 07:32:39 +01:00
Got the tree view working
This commit is contained in:
parent
52cf7e4483
commit
da2ba4d9f3
@ -78,7 +78,9 @@ class BookController extends Controller
|
|||||||
public function show($slug)
|
public function show($slug)
|
||||||
{
|
{
|
||||||
$book = $this->bookRepo->getBySlug($slug);
|
$book = $this->bookRepo->getBySlug($slug);
|
||||||
return view('books/show', ['book' => $book]);
|
$pageTree = $this->pageRepo->getTreeByBookId($book->id);
|
||||||
|
// dd($pageTree);
|
||||||
|
return view('books/show', ['book' => $book, 'pageTree' => $pageTree]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,12 +41,14 @@ class PageController extends Controller
|
|||||||
* Show the form for creating a new resource.
|
* Show the form for creating a new resource.
|
||||||
*
|
*
|
||||||
* @param $bookSlug
|
* @param $bookSlug
|
||||||
|
* @param bool $pageSlug
|
||||||
* @return Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function create($bookSlug)
|
public function create($bookSlug, $pageSlug = false)
|
||||||
{
|
{
|
||||||
$book = $this->bookRepo->getBySlug($bookSlug);
|
$book = $this->bookRepo->getBySlug($bookSlug);
|
||||||
return view('pages/create', ['book' => $book]);
|
$page = $pageSlug ? $this->pageRepo->getBySlug($pageSlug, $book->id) : false;
|
||||||
|
return view('pages/create', ['book' => $book, 'parentPage' => $page]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -61,7 +63,8 @@ class PageController extends Controller
|
|||||||
$this->validate($request, [
|
$this->validate($request, [
|
||||||
'name' => 'required|string|max:255',
|
'name' => 'required|string|max:255',
|
||||||
'html' => 'required|string',
|
'html' => 'required|string',
|
||||||
'priority' => 'integer'
|
'priority' => 'integer',
|
||||||
|
'parent' => 'integer|exists:pages,id'
|
||||||
]);
|
]);
|
||||||
$book = $this->bookRepo->getBySlug($bookSlug);
|
$book = $this->bookRepo->getBySlug($bookSlug);
|
||||||
$page = $this->pageRepo->newFromInput($request->all());
|
$page = $this->pageRepo->newFromInput($request->all());
|
||||||
@ -70,6 +73,11 @@ class PageController extends Controller
|
|||||||
$slug .= '1';
|
$slug .= '1';
|
||||||
}
|
}
|
||||||
$page->slug =$slug;
|
$page->slug =$slug;
|
||||||
|
|
||||||
|
if($request->has('parent')) {
|
||||||
|
$page->page_id = $request->get('parent');
|
||||||
|
}
|
||||||
|
|
||||||
$page->book_id = $book->id;
|
$page->book_id = $book->id;
|
||||||
$page->text = strip_tags($page->html);
|
$page->text = strip_tags($page->html);
|
||||||
$page->save();
|
$page->save();
|
||||||
@ -87,7 +95,8 @@ class PageController extends Controller
|
|||||||
{
|
{
|
||||||
$book = $this->bookRepo->getBySlug($bookSlug);
|
$book = $this->bookRepo->getBySlug($bookSlug);
|
||||||
$page = $this->pageRepo->getBySlug($pageSlug, $book->id);
|
$page = $this->pageRepo->getBySlug($pageSlug, $book->id);
|
||||||
return view('pages/show', ['page' => $page]);
|
$breadCrumbs = $this->pageRepo->getBreadCrumbs($page);
|
||||||
|
return view('pages/show', ['page' => $page, 'breadCrumbs' => $breadCrumbs, 'book' => $book]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,6 +25,7 @@ Route::group(['prefix' => 'books'], function() {
|
|||||||
Route::get('/{bookSlug}/page/create', 'PageController@create');
|
Route::get('/{bookSlug}/page/create', 'PageController@create');
|
||||||
Route::post('/{bookSlug}/page', 'PageController@store');
|
Route::post('/{bookSlug}/page', 'PageController@store');
|
||||||
Route::get('/{bookSlug}/{pageSlug}', 'PageController@show');
|
Route::get('/{bookSlug}/{pageSlug}', 'PageController@show');
|
||||||
|
Route::get('/{bookSlug}/{pageSlug}/create', 'PageController@create');
|
||||||
Route::get('/{bookSlug}/{pageSlug}/edit', 'PageController@edit');
|
Route::get('/{bookSlug}/{pageSlug}/edit', 'PageController@edit');
|
||||||
Route::put('/{bookSlug}/{pageSlug}', 'PageController@update');
|
Route::put('/{bookSlug}/{pageSlug}', 'PageController@update');
|
||||||
});
|
});
|
||||||
|
20
app/Page.php
20
app/Page.php
@ -8,13 +8,33 @@ class Page extends Model
|
|||||||
{
|
{
|
||||||
protected $fillable = ['name', 'html', 'priority'];
|
protected $fillable = ['name', 'html', 'priority'];
|
||||||
|
|
||||||
|
protected $simpleAttributes = ['name', 'id', 'slug'];
|
||||||
|
|
||||||
|
public function toSimpleArray()
|
||||||
|
{
|
||||||
|
$array = array_intersect_key($this->toArray(), array_flip($this->simpleAttributes));
|
||||||
|
$array['url'] = $this->getUrl();
|
||||||
|
return $array;
|
||||||
|
}
|
||||||
|
|
||||||
public function book()
|
public function book()
|
||||||
{
|
{
|
||||||
return $this->belongsTo('Oxbow\Book');
|
return $this->belongsTo('Oxbow\Book');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function children()
|
||||||
|
{
|
||||||
|
return $this->hasMany('Oxbow\Page');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parent()
|
||||||
|
{
|
||||||
|
return $this->belongsTo('Oxbow\Page', 'page_id');
|
||||||
|
}
|
||||||
|
|
||||||
public function getUrl()
|
public function getUrl()
|
||||||
{
|
{
|
||||||
return '/books/' . $this->book->slug . '/' . $this->slug;
|
return '/books/' . $this->book->slug . '/' . $this->slug;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -53,4 +53,11 @@ class BookRepo
|
|||||||
$book->delete();
|
$book->delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getTree($book)
|
||||||
|
{
|
||||||
|
$tree = $book->toArray();
|
||||||
|
$tree['pages'] = $this->pageRepo->getTreeByBookId($book->id);
|
||||||
|
return $tree;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -59,4 +59,62 @@ class PageRepo
|
|||||||
return $query->get();
|
return $query->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getBreadCrumbs($page)
|
||||||
|
{
|
||||||
|
$tree = [];
|
||||||
|
$cPage = $page;
|
||||||
|
while($cPage->parent && $cPage->parent->id !== 0) {
|
||||||
|
$cPage = $cPage->parent;
|
||||||
|
$tree[] = $cPage;
|
||||||
|
}
|
||||||
|
return count($tree) > 0 ? array_reverse($tree) : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a tree of child pages, Nested by their
|
||||||
|
* set parent pages.
|
||||||
|
* @param $bookId
|
||||||
|
* @param bool $currentPageId
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getTreeByBookId($bookId, $currentPageId = false)
|
||||||
|
{
|
||||||
|
$topLevelPages = $this->getTopLevelPages($bookId);
|
||||||
|
$pageTree = [];
|
||||||
|
|
||||||
|
foreach($topLevelPages as $key => $topPage) {
|
||||||
|
$pageTree[$key] = $this->toArrayTree($topPage, $currentPageId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $pageTree;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a page tree array with the supplied page
|
||||||
|
* as the parent of the tree.
|
||||||
|
* @param $page
|
||||||
|
* @param bool $currentPageId
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
private function toArrayTree($page, $currentPageId = false)
|
||||||
|
{
|
||||||
|
$cPage = $page->toSimpleArray();
|
||||||
|
$cPage['current'] = ($currentPageId !== false && $cPage['id'] === $currentPageId);
|
||||||
|
$cPage['pages'] = [];
|
||||||
|
foreach($page->children as $key => $childPage) {
|
||||||
|
$cPage['pages'][$key] = $this->toArrayTree($childPage);
|
||||||
|
}
|
||||||
|
$cPage['hasChildren'] = count($cPage['pages']) > 0;
|
||||||
|
return $cPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the pages at the top of the page hierarchy.
|
||||||
|
* @param $bookId
|
||||||
|
*/
|
||||||
|
private function getTopLevelPages($bookId)
|
||||||
|
{
|
||||||
|
return $this->page->where('book_id', '=', $bookId)->where('page_id', '=', 0)->get();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -200,3 +200,7 @@ ul {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.list > * {
|
||||||
|
display: block;
|
||||||
|
}
|
@ -72,6 +72,9 @@ header .menu {
|
|||||||
&.left {
|
&.left {
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
h1 {
|
||||||
|
margin-top: 0.2em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-list {
|
.page-list {
|
||||||
@ -205,3 +208,64 @@ h1, h2, h3, h4, h5, h6 {
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.breadcrumbs {
|
||||||
|
margin-top: $-s;
|
||||||
|
a, span {
|
||||||
|
color: #666;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
i {
|
||||||
|
padding-right: 4px;
|
||||||
|
}
|
||||||
|
span.sep {
|
||||||
|
color: #888;
|
||||||
|
padding: 0 $-xs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.nested-page-list {
|
||||||
|
list-style: none;
|
||||||
|
margin-left: 0;
|
||||||
|
li {
|
||||||
|
border-top: 3px dotted #BBB;
|
||||||
|
padding: $-s 0;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
li:last-child {
|
||||||
|
border-bottom: 3px dotted #BBB;
|
||||||
|
}
|
||||||
|
.nested-page-list {
|
||||||
|
margin-top: $-xs;
|
||||||
|
display: none;
|
||||||
|
margin: $-xs 0 $-xs 9px;
|
||||||
|
font-size: $fs-m * 0.9;
|
||||||
|
border-left: 2px solid #EEE;
|
||||||
|
}
|
||||||
|
.nested-page-list li {
|
||||||
|
border: none;
|
||||||
|
padding-right: $-m;
|
||||||
|
padding-left: $-m;
|
||||||
|
&.expanded.has-children {
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i.arrow {
|
||||||
|
font-size: 0.8em;
|
||||||
|
padding: $-xs;
|
||||||
|
margin-top: -$-xs;
|
||||||
|
margin-bottom: -$-xs;
|
||||||
|
transform-origin: 50% 50%;
|
||||||
|
transition: transform ease-in-out 180ms;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
li.expanded {
|
||||||
|
> i.arrow {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
>.nested-page-list {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -20,24 +20,24 @@
|
|||||||
<h4 class="float">Pages</h4>
|
<h4 class="float">Pages</h4>
|
||||||
<a href="{{$book->getUrl() . '/page/create'}}" class="text-pos float right">+ New Page</a>
|
<a href="{{$book->getUrl() . '/page/create'}}" class="text-pos float right">+ New Page</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="page-list">
|
|
||||||
@if(count($book->pages) > 0)
|
|
||||||
@foreach($book->pages as $page)
|
|
||||||
<a href="{{$page->getUrl()}}">{{$page->name}}</a>
|
|
||||||
@endforeach
|
|
||||||
@else
|
|
||||||
<p class="text-muted">This book has no pages</p>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
@include('pages/page-tree-list', ['pageTree' => $pageTree])
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(function() {
|
||||||
|
|
||||||
|
$('.nested-page-list i.arrow').click(function() {
|
||||||
|
var list = $(this).closest('.nested-page-list');
|
||||||
|
var listItem = $(this).closest('li');
|
||||||
|
listItem.toggleClass('expanded');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
@stop
|
@stop
|
@ -9,6 +9,9 @@
|
|||||||
@section('content')
|
@section('content')
|
||||||
<form action="{{$book->getUrl() . '/page'}}" method="POST">
|
<form action="{{$book->getUrl() . '/page'}}" method="POST">
|
||||||
@include('pages/form')
|
@include('pages/form')
|
||||||
|
@if($parentPage)
|
||||||
|
<input type="hidden" name="parent" value="{{$parentPage->id}}">
|
||||||
|
@endif
|
||||||
</form>
|
</form>
|
||||||
@stop
|
@stop
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
{{ csrf_field() }}
|
{{ csrf_field() }}
|
||||||
<div class="title-input page-title">
|
<div class="title-input page-title">
|
||||||
@include('form/text', ['name' => 'name', 'placeholder' => 'Enter Page Title'])
|
@include('form/text', ['name' => 'name', 'placeholder' => 'Enter Page Title'])
|
||||||
</div>
|
</div>
|
||||||
<div class="edit-area">
|
<div class="edit-area">
|
||||||
@include('form/textarea', ['name' => 'html'])
|
@include('form/textarea', ['name' => 'html'])
|
||||||
|
15
resources/views/pages/page-tree-list.blade.php
Normal file
15
resources/views/pages/page-tree-list.blade.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
|
||||||
|
<ul class="nested-page-list">
|
||||||
|
@foreach($pageTree as $subPage)
|
||||||
|
<li @if($subPage['hasChildren'])class="has-children"@endif>
|
||||||
|
@if($subPage['hasChildren'])
|
||||||
|
<i class="fa fa-chevron-right arrow"></i>
|
||||||
|
@endif
|
||||||
|
<a href="{{$subPage['url']}}">{{$subPage['name']}}</a>
|
||||||
|
@if($subPage['hasChildren'])
|
||||||
|
@include('pages/page-tree-list', ['pageTree' => $subPage['pages']])
|
||||||
|
@endif
|
||||||
|
</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
@ -10,12 +10,32 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="page-actions">
|
<div class="page-actions">
|
||||||
<h4>Actions</h4>
|
<h4>Actions</h4>
|
||||||
<a href="{{$page->getUrl() . '/edit'}}" class="muted"><i class="fa fa-pencil"></i>Edit this page</a>
|
<div class="list">
|
||||||
|
<a href="{{$page->getUrl() . '/edit'}}" class="muted"><i class="fa fa-pencil"></i>Edit this page</a>
|
||||||
|
<a href="{{$page->getUrl() . '/create'}}" class="muted"><i class="fa fa-file-o"></i>Create Sub-page</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="page-content right col-md-9">
|
<div class="page-content right col-md-9">
|
||||||
|
<div class="breadcrumbs">
|
||||||
|
<a href="{{$book->getUrl()}}"><i class="fa fa-book"></i>{{ $book->name }}</a>
|
||||||
|
@if($breadCrumbs)
|
||||||
|
@foreach($breadCrumbs as $parentPage)
|
||||||
|
<span class="sep">></span>
|
||||||
|
<a href="{{$parentPage->getUrl()}}">{{ $parentPage->name }}</a>
|
||||||
|
@endforeach
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
<h1>{{$page->name}}</h1>
|
<h1>{{$page->name}}</h1>
|
||||||
|
@if(count($page->pages) > 0)
|
||||||
|
<h4 class="text-muted">Sub-pages</h4>
|
||||||
|
<div class="page-list">
|
||||||
|
@foreach($page->pages as $childPage)
|
||||||
|
<a href="{{ $childPage->getUrl() }}">{{ $childPage->name }}</a>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
{!! $page->html !!}
|
{!! $page->html !!}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -37,7 +57,6 @@
|
|||||||
var pageNav = $('.page-nav-list');
|
var pageNav = $('.page-nav-list');
|
||||||
var pageContent = $('.page-content');
|
var pageContent = $('.page-content');
|
||||||
var headers = pageContent.find('h1, h2, h3, h4, h5, h6');
|
var headers = pageContent.find('h1, h2, h3, h4, h5, h6');
|
||||||
var sortedHeaders = [];
|
|
||||||
headers.each(function() {
|
headers.each(function() {
|
||||||
var header = $(this);
|
var header = $(this);
|
||||||
var tag = header.prop('tagName');
|
var tag = header.prop('tagName');
|
||||||
|
Loading…
Reference in New Issue
Block a user