Showing
15 changed files
with
244 additions
and
19 deletions
| ... | @@ -468,6 +468,41 @@ class PageController extends Controller | ... | @@ -468,6 +468,41 @@ class PageController extends Controller |
| 468 | ]); | 468 | ]); |
| 469 | } | 469 | } |
| 470 | 470 | ||
| 471 | + public function move($bookSlug, $pageSlug, Request $request) | ||
| 472 | + { | ||
| 473 | + $book = $this->bookRepo->getBySlug($bookSlug); | ||
| 474 | + $page = $this->pageRepo->getBySlug($pageSlug, $book->id); | ||
| 475 | + $this->checkOwnablePermission('page-update', $page); | ||
| 476 | + | ||
| 477 | + $entitySelection = $request->get('entity_selection', null); | ||
| 478 | + if ($entitySelection === null || $entitySelection === '') { | ||
| 479 | + return redirect($page->getUrl()); | ||
| 480 | + } | ||
| 481 | + | ||
| 482 | + $stringExploded = explode(':', $entitySelection); | ||
| 483 | + $entityType = $stringExploded[0]; | ||
| 484 | + $entityId = intval($stringExploded[1]); | ||
| 485 | + | ||
| 486 | + $parent = false; | ||
| 487 | + | ||
| 488 | + if ($entityType == 'chapter') { | ||
| 489 | + $parent = $this->chapterRepo->getById($entityId); | ||
| 490 | + } else if ($entityType == 'book') { | ||
| 491 | + $parent = $this->bookRepo->getById($entityId); | ||
| 492 | + } | ||
| 493 | + | ||
| 494 | + if ($parent === false || $parent === null) { | ||
| 495 | + session()->flash('The selected Book or Chapter was not found'); | ||
| 496 | + return redirect()->back(); | ||
| 497 | + } | ||
| 498 | + | ||
| 499 | + $this->pageRepo->changePageParent($page, $parent); | ||
| 500 | + Activity::add($page, 'page_move', $page->book->id); | ||
| 501 | + session()->flash('success', sprintf('Page moved to "%s"', $parent->name)); | ||
| 502 | + | ||
| 503 | + return redirect($page->getUrl()); | ||
| 504 | + } | ||
| 505 | + | ||
| 471 | /** | 506 | /** |
| 472 | * Set the permissions for this page. | 507 | * Set the permissions for this page. |
| 473 | * @param $bookSlug | 508 | * @param $bookSlug | ... | ... |
| ... | @@ -2,10 +2,10 @@ | ... | @@ -2,10 +2,10 @@ |
| 2 | 2 | ||
| 3 | namespace BookStack\Http\Controllers; | 3 | namespace BookStack\Http\Controllers; |
| 4 | 4 | ||
| 5 | +use BookStack\Services\ViewService; | ||
| 5 | use Illuminate\Http\Request; | 6 | use Illuminate\Http\Request; |
| 6 | 7 | ||
| 7 | use BookStack\Http\Requests; | 8 | use BookStack\Http\Requests; |
| 8 | -use BookStack\Http\Controllers\Controller; | ||
| 9 | use BookStack\Repos\BookRepo; | 9 | use BookStack\Repos\BookRepo; |
| 10 | use BookStack\Repos\ChapterRepo; | 10 | use BookStack\Repos\ChapterRepo; |
| 11 | use BookStack\Repos\PageRepo; | 11 | use BookStack\Repos\PageRepo; |
| ... | @@ -15,18 +15,21 @@ class SearchController extends Controller | ... | @@ -15,18 +15,21 @@ class SearchController extends Controller |
| 15 | protected $pageRepo; | 15 | protected $pageRepo; |
| 16 | protected $bookRepo; | 16 | protected $bookRepo; |
| 17 | protected $chapterRepo; | 17 | protected $chapterRepo; |
| 18 | + protected $viewService; | ||
| 18 | 19 | ||
| 19 | /** | 20 | /** |
| 20 | * SearchController constructor. | 21 | * SearchController constructor. |
| 21 | - * @param $pageRepo | 22 | + * @param PageRepo $pageRepo |
| 22 | - * @param $bookRepo | 23 | + * @param BookRepo $bookRepo |
| 23 | - * @param $chapterRepo | 24 | + * @param ChapterRepo $chapterRepo |
| 25 | + * @param ViewService $viewService | ||
| 24 | */ | 26 | */ |
| 25 | - public function __construct(PageRepo $pageRepo, BookRepo $bookRepo, ChapterRepo $chapterRepo) | 27 | + public function __construct(PageRepo $pageRepo, BookRepo $bookRepo, ChapterRepo $chapterRepo, ViewService $viewService) |
| 26 | { | 28 | { |
| 27 | $this->pageRepo = $pageRepo; | 29 | $this->pageRepo = $pageRepo; |
| 28 | $this->bookRepo = $bookRepo; | 30 | $this->bookRepo = $bookRepo; |
| 29 | $this->chapterRepo = $chapterRepo; | 31 | $this->chapterRepo = $chapterRepo; |
| 32 | + $this->viewService = $viewService; | ||
| 30 | parent::__construct(); | 33 | parent::__construct(); |
| 31 | } | 34 | } |
| 32 | 35 | ||
| ... | @@ -134,4 +137,35 @@ class SearchController extends Controller | ... | @@ -134,4 +137,35 @@ class SearchController extends Controller |
| 134 | return view('search/book', ['pages' => $pages, 'chapters' => $chapters, 'searchTerm' => $searchTerm]); | 137 | return view('search/book', ['pages' => $pages, 'chapters' => $chapters, 'searchTerm' => $searchTerm]); |
| 135 | } | 138 | } |
| 136 | 139 | ||
| 140 | + | ||
| 141 | + /** | ||
| 142 | + * Search for a list of entities and return a partial HTML response of matching entities. | ||
| 143 | + * Returns the most popular entities if no search is provided. | ||
| 144 | + * @param Request $request | ||
| 145 | + * @return mixed | ||
| 146 | + */ | ||
| 147 | + public function searchEntitiesAjax(Request $request) | ||
| 148 | + { | ||
| 149 | + $entities = collect(); | ||
| 150 | + $entityTypes = $request->has('types') ? collect(explode(',', $request->get('types'))) : collect(['page', 'chapter', 'book']); | ||
| 151 | + $searchTerm = ($request->has('term') && trim($request->get('term')) !== '') ? $request->get('term') : false; | ||
| 152 | + | ||
| 153 | + // Search for entities otherwise show most popular | ||
| 154 | + if ($searchTerm !== false) { | ||
| 155 | + if ($entityTypes->contains('page')) $entities = $entities->merge($this->pageRepo->getBySearch($searchTerm)->items()); | ||
| 156 | + if ($entityTypes->contains('chapter')) $entities = $entities->merge($this->chapterRepo->getBySearch($searchTerm)->items()); | ||
| 157 | + if ($entityTypes->contains('book')) $entities = $entities->merge($this->bookRepo->getBySearch($searchTerm)->items()); | ||
| 158 | + $entities = $entities->sortByDesc('title_relevance'); | ||
| 159 | + } else { | ||
| 160 | + $entityNames = $entityTypes->map(function ($type) { | ||
| 161 | + return 'BookStack\\' . ucfirst($type); | ||
| 162 | + })->toArray(); | ||
| 163 | + $entities = $this->viewService->getPopular(20, 0, $entityNames); | ||
| 164 | + } | ||
| 165 | + | ||
| 166 | + return view('partials/entity-list', ['entities' => $entities]); | ||
| 167 | + } | ||
| 168 | + | ||
| 137 | } | 169 | } |
| 170 | + | ||
| 171 | + | ... | ... |
| ... | @@ -35,6 +35,7 @@ Route::group(['middleware' => 'auth'], function () { | ... | @@ -35,6 +35,7 @@ Route::group(['middleware' => 'auth'], function () { |
| 35 | Route::get('/{bookSlug}/page/{pageSlug}/export/plaintext', 'PageController@exportPlainText'); | 35 | Route::get('/{bookSlug}/page/{pageSlug}/export/plaintext', 'PageController@exportPlainText'); |
| 36 | Route::get('/{bookSlug}/page/{pageSlug}/edit', 'PageController@edit'); | 36 | Route::get('/{bookSlug}/page/{pageSlug}/edit', 'PageController@edit'); |
| 37 | Route::get('/{bookSlug}/page/{pageSlug}/move', 'PageController@showMove'); | 37 | Route::get('/{bookSlug}/page/{pageSlug}/move', 'PageController@showMove'); |
| 38 | + Route::put('/{bookSlug}/page/{pageSlug}/move', 'PageController@move'); | ||
| 38 | Route::get('/{bookSlug}/page/{pageSlug}/delete', 'PageController@showDelete'); | 39 | Route::get('/{bookSlug}/page/{pageSlug}/delete', 'PageController@showDelete'); |
| 39 | Route::get('/{bookSlug}/draft/{pageId}/delete', 'PageController@showDeleteDraft'); | 40 | Route::get('/{bookSlug}/draft/{pageId}/delete', 'PageController@showDeleteDraft'); |
| 40 | Route::get('/{bookSlug}/page/{pageSlug}/permissions', 'PageController@showRestrict'); | 41 | Route::get('/{bookSlug}/page/{pageSlug}/permissions', 'PageController@showRestrict'); |
| ... | @@ -94,6 +95,8 @@ Route::group(['middleware' => 'auth'], function () { | ... | @@ -94,6 +95,8 @@ Route::group(['middleware' => 'auth'], function () { |
| 94 | Route::post('/update/{entityType}/{entityId}', 'TagController@updateForEntity'); | 95 | Route::post('/update/{entityType}/{entityId}', 'TagController@updateForEntity'); |
| 95 | }); | 96 | }); |
| 96 | 97 | ||
| 98 | + Route::get('/ajax/search/entities', 'SearchController@searchEntitiesAjax'); | ||
| 99 | + | ||
| 97 | // Links | 100 | // Links |
| 98 | Route::get('/link/{id}', 'PageController@redirectFromLink'); | 101 | Route::get('/link/{id}', 'PageController@redirectFromLink'); |
| 99 | 102 | ... | ... |
| ... | @@ -3,6 +3,7 @@ | ... | @@ -3,6 +3,7 @@ |
| 3 | use Activity; | 3 | use Activity; |
| 4 | use BookStack\Book; | 4 | use BookStack\Book; |
| 5 | use BookStack\Chapter; | 5 | use BookStack\Chapter; |
| 6 | +use BookStack\Entity; | ||
| 6 | use BookStack\Exceptions\NotFoundException; | 7 | use BookStack\Exceptions\NotFoundException; |
| 7 | use Carbon\Carbon; | 8 | use Carbon\Carbon; |
| 8 | use DOMDocument; | 9 | use DOMDocument; |
| ... | @@ -572,6 +573,22 @@ class PageRepo extends EntityRepo | ... | @@ -572,6 +573,22 @@ class PageRepo extends EntityRepo |
| 572 | return $page; | 573 | return $page; |
| 573 | } | 574 | } |
| 574 | 575 | ||
| 576 | + | ||
| 577 | + /** | ||
| 578 | + * Change the page's parent to the given entity. | ||
| 579 | + * @param Page $page | ||
| 580 | + * @param Entity $parent | ||
| 581 | + */ | ||
| 582 | + public function changePageParent(Page $page, Entity $parent) | ||
| 583 | + { | ||
| 584 | + $book = $parent->isA('book') ? $parent : $parent->book; | ||
| 585 | + $page->chapter_id = $parent->isA('chapter') ? $parent->id : 0; | ||
| 586 | + $page->save(); | ||
| 587 | + $page = $this->changeBook($book->id, $page); | ||
| 588 | + $page->load('book'); | ||
| 589 | + $this->permissionService->buildJointPermissionsForEntity($book); | ||
| 590 | + } | ||
| 591 | + | ||
| 575 | /** | 592 | /** |
| 576 | * Gets a suitable slug for the resource | 593 | * Gets a suitable slug for the resource |
| 577 | * @param $name | 594 | * @param $name | ... | ... |
| ... | @@ -50,7 +50,7 @@ class ViewService | ... | @@ -50,7 +50,7 @@ class ViewService |
| 50 | * Get the entities with the most views. | 50 | * Get the entities with the most views. |
| 51 | * @param int $count | 51 | * @param int $count |
| 52 | * @param int $page | 52 | * @param int $page |
| 53 | - * @param bool|false $filterModel | 53 | + * @param bool|false|array $filterModel |
| 54 | */ | 54 | */ |
| 55 | public function getPopular($count = 10, $page = 0, $filterModel = false) | 55 | public function getPopular($count = 10, $page = 0, $filterModel = false) |
| 56 | { | 56 | { |
| ... | @@ -60,7 +60,11 @@ class ViewService | ... | @@ -60,7 +60,11 @@ class ViewService |
| 60 | ->groupBy('viewable_id', 'viewable_type') | 60 | ->groupBy('viewable_id', 'viewable_type') |
| 61 | ->orderBy('view_count', 'desc'); | 61 | ->orderBy('view_count', 'desc'); |
| 62 | 62 | ||
| 63 | - if ($filterModel) $query->where('viewable_type', '=', get_class($filterModel)); | 63 | + if ($filterModel && is_array($filterModel)) { |
| 64 | + $query->whereIn('viewable_type', $filterModel); | ||
| 65 | + } else if ($filterModel) { | ||
| 66 | + $query->where('viewable_type', '=', get_class($filterModel)); | ||
| 67 | + }; | ||
| 64 | 68 | ||
| 65 | return $query->with('viewable')->skip($skipCount)->take($count)->get()->pluck('viewable'); | 69 | return $query->with('viewable')->skip($skipCount)->take($count)->get()->pluck('viewable'); |
| 66 | } | 70 | } | ... | ... |
| ... | @@ -584,12 +584,62 @@ module.exports = function (ngApp, events) { | ... | @@ -584,12 +584,62 @@ module.exports = function (ngApp, events) { |
| 584 | }]); | 584 | }]); |
| 585 | 585 | ||
| 586 | 586 | ||
| 587 | - ngApp.directive('entitySelector', ['$http', function ($http) { | 587 | + ngApp.directive('entitySelector', ['$http', '$sce', function ($http, $sce) { |
| 588 | return { | 588 | return { |
| 589 | restrict: 'A', | 589 | restrict: 'A', |
| 590 | + scope: true, | ||
| 590 | link: function (scope, element, attrs) { | 591 | link: function (scope, element, attrs) { |
| 591 | scope.loading = true; | 592 | scope.loading = true; |
| 593 | + scope.entityResults = false; | ||
| 594 | + scope.search = ''; | ||
| 595 | + | ||
| 596 | + // Add input for forms | ||
| 597 | + const input = element.find('[entity-selector-input]').first(); | ||
| 598 | + | ||
| 599 | + // Listen to entity item clicks | ||
| 600 | + element.on('click', '.entity-list a', function(event) { | ||
| 601 | + event.preventDefault(); | ||
| 602 | + event.stopPropagation(); | ||
| 603 | + let item = $(this).closest('[data-entity-type]'); | ||
| 604 | + itemSelect(item); | ||
| 605 | + }); | ||
| 606 | + element.on('click', '[data-entity-type]', function(event) { | ||
| 607 | + itemSelect($(this)); | ||
| 608 | + }); | ||
| 609 | + | ||
| 610 | + // Select entity action | ||
| 611 | + function itemSelect(item) { | ||
| 612 | + let entityType = item.attr('data-entity-type'); | ||
| 613 | + let entityId = item.attr('data-entity-id'); | ||
| 614 | + let isSelected = !item.hasClass('selected'); | ||
| 615 | + element.find('.selected').removeClass('selected').removeClass('primary-background'); | ||
| 616 | + if (isSelected) item.addClass('selected').addClass('primary-background'); | ||
| 617 | + let newVal = isSelected ? `${entityType}:${entityId}` : ''; | ||
| 618 | + input.val(newVal); | ||
| 619 | + } | ||
| 592 | 620 | ||
| 621 | + // Get search url with correct types | ||
| 622 | + function getSearchUrl() { | ||
| 623 | + let types = (attrs.entityTypes) ? encodeURIComponent(attrs.entityTypes) : encodeURIComponent('page,book,chapter'); | ||
| 624 | + return `/ajax/search/entities?types=${types}`; | ||
| 625 | + } | ||
| 626 | + | ||
| 627 | + // Get initial contents | ||
| 628 | + $http.get(getSearchUrl()).then(resp => { | ||
| 629 | + scope.entityResults = $sce.trustAsHtml(resp.data); | ||
| 630 | + scope.loading = false; | ||
| 631 | + }); | ||
| 632 | + | ||
| 633 | + // Search when typing | ||
| 634 | + scope.searchEntities = function() { | ||
| 635 | + scope.loading = true; | ||
| 636 | + input.val(''); | ||
| 637 | + let url = getSearchUrl() + '&term=' + encodeURIComponent(scope.search); | ||
| 638 | + $http.get(url).then(resp => { | ||
| 639 | + scope.entityResults = $sce.trustAsHtml(resp.data); | ||
| 640 | + scope.loading = false; | ||
| 641 | + }); | ||
| 642 | + }; | ||
| 593 | } | 643 | } |
| 594 | }; | 644 | }; |
| 595 | }]); | 645 | }]); | ... | ... |
| ... | @@ -20,6 +20,9 @@ | ... | @@ -20,6 +20,9 @@ |
| 20 | &.disabled, &[disabled] { | 20 | &.disabled, &[disabled] { |
| 21 | background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAMUlEQVQIW2NkwAGuXbv2nxGbHEhCS0uLEUMSJgHShCKJLIEiiS4Bl8QmAZbEJQGSBAC62BuJ+tt7zgAAAABJRU5ErkJggg==); | 21 | background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAMUlEQVQIW2NkwAGuXbv2nxGbHEhCS0uLEUMSJgHShCKJLIEiiS4Bl8QmAZbEJQGSBAC62BuJ+tt7zgAAAABJRU5ErkJggg==); |
| 22 | } | 22 | } |
| 23 | + &:focus { | ||
| 24 | + outline: 0; | ||
| 25 | + } | ||
| 23 | } | 26 | } |
| 24 | 27 | ||
| 25 | #html-editor { | 28 | #html-editor { | ... | ... |
| ... | @@ -207,3 +207,59 @@ $btt-size: 40px; | ... | @@ -207,3 +207,59 @@ $btt-size: 40px; |
| 207 | color: #EEE; | 207 | color: #EEE; |
| 208 | } | 208 | } |
| 209 | } | 209 | } |
| 210 | + | ||
| 211 | +.entity-selector { | ||
| 212 | + border: 1px solid #DDD; | ||
| 213 | + border-radius: 3px; | ||
| 214 | + overflow: hidden; | ||
| 215 | + font-size: 0.8em; | ||
| 216 | + input[type="text"] { | ||
| 217 | + width: 100%; | ||
| 218 | + display: block; | ||
| 219 | + border-radius: 0; | ||
| 220 | + border: 0; | ||
| 221 | + border-bottom: 1px solid #DDD; | ||
| 222 | + font-size: 16px; | ||
| 223 | + padding: $-s $-m; | ||
| 224 | + } | ||
| 225 | + .entity-list { | ||
| 226 | + overflow-y: scroll; | ||
| 227 | + height: 400px; | ||
| 228 | + background-color: #EEEEEE; | ||
| 229 | + } | ||
| 230 | + .loading { | ||
| 231 | + height: 400px; | ||
| 232 | + padding-top: $-l; | ||
| 233 | + } | ||
| 234 | + .entity-list > p { | ||
| 235 | + text-align: center; | ||
| 236 | + padding-top: $-l; | ||
| 237 | + font-size: 1.333em; | ||
| 238 | + } | ||
| 239 | + .entity-list > div { | ||
| 240 | + padding-left: $-m; | ||
| 241 | + padding-right: $-m; | ||
| 242 | + background-color: #FFF; | ||
| 243 | + transition: all ease-in-out 120ms; | ||
| 244 | + cursor: pointer; | ||
| 245 | + } | ||
| 246 | +} | ||
| 247 | + | ||
| 248 | +.entity-list-item.selected { | ||
| 249 | + h3, i, p ,a { | ||
| 250 | + color: #EEE; | ||
| 251 | + } | ||
| 252 | +} | ||
| 253 | + | ||
| 254 | + | ||
| 255 | + | ||
| 256 | + | ||
| 257 | + | ||
| 258 | + | ||
| 259 | + | ||
| 260 | + | ||
| 261 | + | ||
| 262 | + | ||
| 263 | + | ||
| 264 | + | ||
| 265 | + | ... | ... |
| ... | @@ -16,6 +16,7 @@ return [ | ... | @@ -16,6 +16,7 @@ return [ |
| 16 | 'page_delete_notification' => 'Page Successfully Deleted', | 16 | 'page_delete_notification' => 'Page Successfully Deleted', |
| 17 | 'page_restore' => 'restored page', | 17 | 'page_restore' => 'restored page', |
| 18 | 'page_restore_notification' => 'Page Successfully Restored', | 18 | 'page_restore_notification' => 'Page Successfully Restored', |
| 19 | + 'page_move' => 'moved page', | ||
| 19 | 20 | ||
| 20 | // Chapters | 21 | // Chapters |
| 21 | 'chapter_create' => 'created chapter', | 22 | 'chapter_create' => 'created chapter', | ... | ... |
| 1 | -<div class="book" data-entity-type="book" data-entity-id="{{$book->id}}"> | 1 | +<div class="book entity-list-item" data-entity-type="book" data-entity-id="{{$book->id}}"> |
| 2 | <h3 class="text-book"><a class="text-book" href="{{$book->getUrl()}}"><i class="zmdi zmdi-book"></i>{{$book->name}}</a></h3> | 2 | <h3 class="text-book"><a class="text-book" href="{{$book->getUrl()}}"><i class="zmdi zmdi-book"></i>{{$book->name}}</a></h3> |
| 3 | @if(isset($book->searchSnippet)) | 3 | @if(isset($book->searchSnippet)) |
| 4 | <p class="text-muted">{!! $book->searchSnippet !!}</p> | 4 | <p class="text-muted">{!! $book->searchSnippet !!}</p> | ... | ... |
| 1 | -<div class="chapter" data-entity-type="chapter" data-entity-id="{{$chapter->id}}"> | 1 | +<div class="chapter entity-list-item" data-entity-type="chapter" data-entity-id="{{$chapter->id}}"> |
| 2 | <h3> | 2 | <h3> |
| 3 | <a href="{{ $chapter->getUrl() }}" class="text-chapter"> | 3 | <a href="{{ $chapter->getUrl() }}" class="text-chapter"> |
| 4 | <i class="zmdi zmdi-collection-bookmark"></i>{{ $chapter->name }} | 4 | <i class="zmdi zmdi-collection-bookmark"></i>{{ $chapter->name }} | ... | ... |
| 1 | -<div class="page {{$page->draft ? 'draft' : ''}}" data-entity-type="page" data-entity-id="{{$page->id}}"> | 1 | +<div class="page {{$page->draft ? 'draft' : ''}} entity-list-item" data-entity-type="page" data-entity-id="{{$page->id}}"> |
| 2 | <h3> | 2 | <h3> |
| 3 | <a href="{{ $page->getUrl() }}" class="text-page"><i class="zmdi zmdi-file-text"></i>{{ $page->name }}</a> | 3 | <a href="{{ $page->getUrl() }}" class="text-page"><i class="zmdi zmdi-file-text"></i>{{ $page->name }}</a> |
| 4 | </h3> | 4 | </h3> | ... | ... |
| ... | @@ -26,10 +26,22 @@ | ... | @@ -26,10 +26,22 @@ |
| 26 | <div class="container"> | 26 | <div class="container"> |
| 27 | <h1>Move Page <small class="subheader">{{$page->name}}</small></h1> | 27 | <h1>Move Page <small class="subheader">{{$page->name}}</small></h1> |
| 28 | 28 | ||
| 29 | - <div class="bordered" ng-cloak entity-selector> | 29 | + <form action="{{ $page->getUrl() }}/move" method="POST"> |
| 30 | - <input type="text" placeholder="Search"> | 30 | + {!! csrf_field() !!} |
| 31 | - <div class="text-center" ng-if="loading">@include('partials/loading-icon')</div> | 31 | + <input type="hidden" name="_method" value="PUT"> |
| 32 | + | ||
| 33 | + <div class="form-group"> | ||
| 34 | + <div entity-selector class="entity-selector large" entity-types="book,chapter"> | ||
| 35 | + <input type="hidden" entity-selector-input name="entity_selection"> | ||
| 36 | + <input type="text" placeholder="Search" ng-model="search" ng-model-options="{debounce: 200}" ng-change="searchEntities()"> | ||
| 37 | + <div class="text-center loading" ng-show="loading">@include('partials/loading-icon')</div> | ||
| 38 | + <div ng-show="!loading" ng-bind-html="entityResults"></div> | ||
| 39 | + </div> | ||
| 32 | </div> | 40 | </div> |
| 41 | + | ||
| 42 | + <a href="{{ $page->getUrl() }}" class="button muted">Cancel</a> | ||
| 43 | + <button type="submit" class="button pos">Move Page</button> | ||
| 44 | + </form> | ||
| 33 | </div> | 45 | </div> |
| 34 | 46 | ||
| 35 | @stop | 47 | @stop | ... | ... |
| ... | @@ -28,16 +28,26 @@ | ... | @@ -28,16 +28,26 @@ |
| 28 | </ul> | 28 | </ul> |
| 29 | </span> | 29 | </span> |
| 30 | @if(userCan('page-update', $page)) | 30 | @if(userCan('page-update', $page)) |
| 31 | - <a href="{{$page->getUrl()}}/revisions" class="text-primary text-button"><i class="zmdi zmdi-replay"></i>Revisions</a> | ||
| 32 | <a href="{{$page->getUrl()}}/edit" class="text-primary text-button" ><i class="zmdi zmdi-edit"></i>Edit</a> | 31 | <a href="{{$page->getUrl()}}/edit" class="text-primary text-button" ><i class="zmdi zmdi-edit"></i>Edit</a> |
| 33 | - <a href="{{$page->getUrl()}}/move" class="text-primary text-button" ><i class="zmdi zmdi-folder"></i>Move</a> | 32 | + @endif |
| 33 | + @if(userCan('page-update', $page) || userCan('restrictions-manage', $page) || userCan('page-delete', $page)) | ||
| 34 | + <div dropdown class="dropdown-container"> | ||
| 35 | + <a dropdown-toggle class="text-primary text-button"><i class="zmdi zmdi-more-vert"></i></a> | ||
| 36 | + <ul> | ||
| 37 | + @if(userCan('page-update', $page)) | ||
| 38 | + <li><a href="{{$page->getUrl()}}/move" class="text-primary" ><i class="zmdi zmdi-folder"></i>Move</a></li> | ||
| 39 | + <li><a href="{{$page->getUrl()}}/revisions" class="text-primary"><i class="zmdi zmdi-replay"></i>Revisions</a></li> | ||
| 34 | @endif | 40 | @endif |
| 35 | @if(userCan('restrictions-manage', $page)) | 41 | @if(userCan('restrictions-manage', $page)) |
| 36 | - <a href="{{$page->getUrl()}}/permissions" class="text-primary text-button"><i class="zmdi zmdi-lock-outline"></i>Permissions</a> | 42 | + <li><a href="{{$page->getUrl()}}/permissions" class="text-primary"><i class="zmdi zmdi-lock-outline"></i>Permissions</a></li> |
| 37 | @endif | 43 | @endif |
| 38 | @if(userCan('page-delete', $page)) | 44 | @if(userCan('page-delete', $page)) |
| 39 | - <a href="{{$page->getUrl()}}/delete" class="text-neg text-button"><i class="zmdi zmdi-delete"></i>Delete</a> | 45 | + <li><a href="{{$page->getUrl()}}/delete" class="text-neg"><i class="zmdi zmdi-delete"></i>Delete</a></li> |
| 46 | + @endif | ||
| 47 | + </ul> | ||
| 48 | + </div> | ||
| 40 | @endif | 49 | @endif |
| 50 | + | ||
| 41 | </div> | 51 | </div> |
| 42 | </div> | 52 | </div> |
| 43 | </div> | 53 | </div> | ... | ... |
| 1 | @if(Setting::get('app-color')) | 1 | @if(Setting::get('app-color')) |
| 2 | <style> | 2 | <style> |
| 3 | header, #back-to-top, .primary-background { | 3 | header, #back-to-top, .primary-background { |
| 4 | - background-color: {{ Setting::get('app-color') }}; | 4 | + background-color: {{ Setting::get('app-color') }} !important; |
| 5 | } | 5 | } |
| 6 | .faded-small, .primary-background-light { | 6 | .faded-small, .primary-background-light { |
| 7 | background-color: {{ Setting::get('app-color-light') }}; | 7 | background-color: {{ Setting::get('app-color-light') }}; | ... | ... |
-
Please register or sign in to post a comment