public function show($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]);
}
/**
* Show the form for creating a new resource.
*
* @param $bookSlug
+ * @param bool $pageSlug
* @return Response
*/
- public function create($bookSlug)
+ public function create($bookSlug, $pageSlug = false)
{
$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]);
}
/**
$this->validate($request, [
'name' => 'required|string|max:255',
'html' => 'required|string',
- 'priority' => 'integer'
+ 'priority' => 'integer',
+ 'parent' => 'integer|exists:pages,id'
]);
$book = $this->bookRepo->getBySlug($bookSlug);
$page = $this->pageRepo->newFromInput($request->all());
$slug .= '1';
}
$page->slug =$slug;
+
+ if($request->has('parent')) {
+ $page->page_id = $request->get('parent');
+ }
+
$page->book_id = $book->id;
$page->text = strip_tags($page->html);
$page->save();
{
$book = $this->bookRepo->getBySlug($bookSlug);
$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]);
}
/**
Route::get('/{bookSlug}/page/create', 'PageController@create');
Route::post('/{bookSlug}/page', 'PageController@store');
Route::get('/{bookSlug}/{pageSlug}', 'PageController@show');
+ Route::get('/{bookSlug}/{pageSlug}/create', 'PageController@create');
Route::get('/{bookSlug}/{pageSlug}/edit', 'PageController@edit');
Route::put('/{bookSlug}/{pageSlug}', 'PageController@update');
});
{
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()
{
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()
{
return '/books/' . $this->book->slug . '/' . $this->slug;
}
+
}
$book->delete();
}
+ public function getTree($book)
+ {
+ $tree = $book->toArray();
+ $tree['pages'] = $this->pageRepo->getTreeByBookId($book->id);
+ return $tree;
+ }
+
}
\ No newline at end of file
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();
+ }
+
}
\ No newline at end of file
h1, h2, h3, h4, h5, h6 {
margin: 0;
}
+}
+
+.list > * {
+ display: block;
}
\ No newline at end of file
&.left {
float: left;
}
+ h1 {
+ margin-top: 0.2em;
+ }
}
.page-list {
&:hover a.link-hook {
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;
+ }
+ }
}
\ No newline at end of file
<h4 class="float">Pages</h4>
<a href="{{$book->getUrl() . '/page/create'}}" class="text-pos float right">+ New Page</a>
</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>
+ <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
\ No newline at end of file
@section('content')
<form action="{{$book->getUrl() . '/page'}}" method="POST">
@include('pages/form')
+ @if($parentPage)
+ <input type="hidden" name="parent" value="{{$parentPage->id}}">
+ @endif
</form>
@stop
{{ csrf_field() }}
<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 class="edit-area">
@include('form/textarea', ['name' => 'html'])
--- /dev/null
+
+
+<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>
\ No newline at end of file
</div>
<div class="page-actions">
<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 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>
+ @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 !!}
</div>
</div>
var pageNav = $('.page-nav-list');
var pageContent = $('.page-content');
var headers = pageContent.find('h1, h2, h3, h4, h5, h6');
- var sortedHeaders = [];
headers.each(function() {
var header = $(this);
var tag = header.prop('tagName');