diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 489396df6..2fc64b236 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -29,14 +29,17 @@ class HomeController extends Controller public function index() { $activity = Activity::latest(10); - $recents = $this->signedIn ? Views::getUserRecentlyViewed(12, 0) : $this->entityRepo->getRecentlyCreatedBooks(10); + $draftPages = $this->signedIn ? $this->entityRepo->getUserDraftPages(6) : []; + $recentFactor = count($draftPages) > 0 ? 0.5 : 1; + $recents = $this->signedIn ? Views::getUserRecentlyViewed(12*$recentFactor, 0) : $this->entityRepo->getRecentlyCreatedBooks(10*$recentFactor); $recentlyCreatedPages = $this->entityRepo->getRecentlyCreatedPages(5); $recentlyUpdatedPages = $this->entityRepo->getRecentlyUpdatedPages(5); return view('home', [ 'activity' => $activity, 'recents' => $recents, 'recentlyCreatedPages' => $recentlyCreatedPages, - 'recentlyUpdatedPages' => $recentlyUpdatedPages + 'recentlyUpdatedPages' => $recentlyUpdatedPages, + 'draftPages' => $draftPages ]); } diff --git a/app/Http/Controllers/ImageController.php b/app/Http/Controllers/ImageController.php index 48e89ee41..36e44c755 100644 --- a/app/Http/Controllers/ImageController.php +++ b/app/Http/Controllers/ImageController.php @@ -32,7 +32,6 @@ class ImageController extends Controller parent::__construct(); } - /** * Get all images for a specific type, Paginated * @param int $page @@ -55,7 +54,6 @@ class ImageController extends Controller return response()->json($imgData); } - /** * Handles image uploads for use on pages. * @param string $type @@ -113,7 +111,6 @@ class ImageController extends Controller return response()->json($image); } - /** * Deletes an image and all thumbnail/image files * @param PageRepo $pageRepo diff --git a/app/Http/Controllers/PageController.php b/app/Http/Controllers/PageController.php index 04065996e..e2b10d3d3 100644 --- a/app/Http/Controllers/PageController.php +++ b/app/Http/Controllers/PageController.php @@ -49,33 +49,54 @@ class PageController extends Controller public function create($bookSlug, $chapterSlug = false) { $book = $this->bookRepo->getBySlug($bookSlug); - $chapter = $chapterSlug ? $this->chapterRepo->getBySlug($chapterSlug, $book->id) : false; + $chapter = $chapterSlug ? $this->chapterRepo->getBySlug($chapterSlug, $book->id) : null; $parent = $chapter ? $chapter : $book; $this->checkOwnablePermission('page-create', $parent); $this->setPageTitle('Create New Page'); - return view('pages/create', ['book' => $book, 'chapter' => $chapter]); + + $draft = $this->pageRepo->getDraftPage($book, $chapter); + return redirect($draft->getUrl()); } /** - * Store a newly created page in storage. + * Show form to continue editing a draft page. + * @param $bookSlug + * @param $pageId + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + */ + public function editDraft($bookSlug, $pageId) + { + $book = $this->bookRepo->getBySlug($bookSlug); + $draft = $this->pageRepo->getById($pageId, true); + $this->checkOwnablePermission('page-create', $draft); + $this->setPageTitle('Edit Page Draft'); + + return view('pages/create', ['draft' => $draft, 'book' => $book]); + } + + /** + * Store a new page by changing a draft into a page. * @param Request $request - * @param $bookSlug + * @param string $bookSlug * @return Response */ - public function store(Request $request, $bookSlug) + public function store(Request $request, $bookSlug, $pageId) { $this->validate($request, [ - 'name' => 'required|string|max:255' + 'name' => 'required|string|max:255' ]); $input = $request->all(); $book = $this->bookRepo->getBySlug($bookSlug); - $chapterId = ($request->has('chapter') && $this->chapterRepo->idExists($request->get('chapter'))) ? $request->get('chapter') : null; - $parent = $chapterId !== null ? $this->chapterRepo->getById($chapterId) : $book; - $this->checkOwnablePermission('page-create', $parent); $input['priority'] = $this->bookRepo->getNewPriority($book); - $page = $this->pageRepo->saveNew($input, $book, $chapterId); + $draftPage = $this->pageRepo->getById($pageId, true); + + $chapterId = $draftPage->chapter_id; + $parent = $chapterId !== 0 ? $this->chapterRepo->getById($chapterId) : $book; + $this->checkOwnablePermission('page-create', $parent); + + $page = $this->pageRepo->publishDraft($draftPage, $input); Activity::add($page, 'page_create', $book->id); return redirect($page->getUrl()); @@ -132,12 +153,13 @@ class PageController extends Controller $this->setPageTitle('Editing Page ' . $page->getShortName()); $page->isDraft = false; - // Check for active editing and drafts + // Check for active editing $warnings = []; if ($this->pageRepo->isPageEditingActive($page, 60)) { $warnings[] = $this->pageRepo->getPageEditingActiveMessage($page, 60); } + // Check for a current draft version for this user if ($this->pageRepo->hasUserGotPageDraft($page, $this->currentUser->id)) { $draft = $this->pageRepo->getUserPageDraft($page, $this->currentUser->id); $page->name = $draft->name; @@ -161,7 +183,7 @@ class PageController extends Controller public function update(Request $request, $bookSlug, $pageSlug) { $this->validate($request, [ - 'name' => 'required|string|max:255' + 'name' => 'required|string|max:255' ]); $book = $this->bookRepo->getBySlug($bookSlug); $page = $this->pageRepo->getBySlug($pageSlug, $book->id); @@ -177,14 +199,15 @@ class PageController extends Controller * @param $pageId * @return \Illuminate\Http\JsonResponse */ - public function saveUpdateDraft(Request $request, $pageId) + public function saveDraft(Request $request, $pageId) { - $this->validate($request, [ - 'name' => 'required|string|max:255' - ]); - $page = $this->pageRepo->getById($pageId); + $page = $this->pageRepo->getById($pageId, true); $this->checkOwnablePermission('page-update', $page); - $draft = $this->pageRepo->saveUpdateDraft($page, $request->only(['name', 'html'])); + if ($page->draft) { + $draft = $this->pageRepo->updateDraftPage($page, $request->only(['name', 'html'])); + } else { + $draft = $this->pageRepo->saveUpdateDraft($page, $request->only(['name', 'html'])); + } $updateTime = $draft->updated_at->format('H:i'); return response()->json(['status' => 'success', 'message' => 'Draft saved at ' . $updateTime]); } @@ -216,9 +239,25 @@ class PageController extends Controller return view('pages/delete', ['book' => $book, 'page' => $page, 'current' => $page]); } + + /** + * Show the deletion page for the specified page. + * @param $bookSlug + * @param $pageId + * @return \Illuminate\View\View + * @throws NotFoundException + */ + public function showDeleteDraft($bookSlug, $pageId) + { + $book = $this->bookRepo->getBySlug($bookSlug); + $page = $this->pageRepo->getById($pageId, true); + $this->checkOwnablePermission('page-update', $page); + $this->setPageTitle('Delete Draft Page ' . $page->getShortName()); + return view('pages/delete', ['book' => $book, 'page' => $page, 'current' => $page]); + } + /** * Remove the specified page from storage. - * * @param $bookSlug * @param $pageSlug * @return Response @@ -230,6 +269,24 @@ class PageController extends Controller $page = $this->pageRepo->getBySlug($pageSlug, $book->id); $this->checkOwnablePermission('page-delete', $page); Activity::addMessage('page_delete', $book->id, $page->name); + session()->flash('success', 'Page deleted'); + $this->pageRepo->destroy($page); + return redirect($book->getUrl()); + } + + /** + * Remove the specified draft page from storage. + * @param $bookSlug + * @param $pageId + * @return Response + * @throws NotFoundException + */ + public function destroyDraft($bookSlug, $pageId) + { + $book = $this->bookRepo->getBySlug($bookSlug); + $page = $this->pageRepo->getById($pageId, true); + $this->checkOwnablePermission('page-update', $page); + session()->flash('success', 'Draft deleted'); $this->pageRepo->destroy($page); return redirect($book->getUrl()); } @@ -295,8 +352,8 @@ class PageController extends Controller $page = $this->pageRepo->getBySlug($pageSlug, $book->id); $pdfContent = $this->exportService->pageToPdf($page); return response()->make($pdfContent, 200, [ - 'Content-Type' => 'application/octet-stream', - 'Content-Disposition' => 'attachment; filename="'.$pageSlug.'.pdf' + 'Content-Type' => 'application/octet-stream', + 'Content-Disposition' => 'attachment; filename="' . $pageSlug . '.pdf' ]); } @@ -312,8 +369,8 @@ class PageController extends Controller $page = $this->pageRepo->getBySlug($pageSlug, $book->id); $containedHtml = $this->exportService->pageToContainedHtml($page); return response()->make($containedHtml, 200, [ - 'Content-Type' => 'application/octet-stream', - 'Content-Disposition' => 'attachment; filename="'.$pageSlug.'.html' + 'Content-Type' => 'application/octet-stream', + 'Content-Disposition' => 'attachment; filename="' . $pageSlug . '.html' ]); } @@ -329,8 +386,8 @@ class PageController extends Controller $page = $this->pageRepo->getBySlug($pageSlug, $book->id); $containedHtml = $this->exportService->pageToPlainText($page); return response()->make($containedHtml, 200, [ - 'Content-Type' => 'application/octet-stream', - 'Content-Disposition' => 'attachment; filename="'.$pageSlug.'.txt' + 'Content-Type' => 'application/octet-stream', + 'Content-Disposition' => 'attachment; filename="' . $pageSlug . '.txt' ]); } @@ -373,7 +430,7 @@ class PageController extends Controller $this->checkOwnablePermission('restrictions-manage', $page); $roles = $this->userRepo->getRestrictableRoles(); return view('pages/restrictions', [ - 'page' => $page, + 'page' => $page, 'roles' => $roles ]); } diff --git a/app/Http/routes.php b/app/Http/routes.php index 48765be88..0be901231 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -27,17 +27,20 @@ Route::group(['middleware' => 'auth'], function () { // Pages Route::get('/{bookSlug}/page/create', 'PageController@create'); - Route::post('/{bookSlug}/page', 'PageController@store'); + Route::get('/{bookSlug}/draft/{pageId}', 'PageController@editDraft'); + Route::post('/{bookSlug}/page/{pageId}', 'PageController@store'); Route::get('/{bookSlug}/page/{pageSlug}', 'PageController@show'); Route::get('/{bookSlug}/page/{pageSlug}/export/pdf', 'PageController@exportPdf'); Route::get('/{bookSlug}/page/{pageSlug}/export/html', 'PageController@exportHtml'); Route::get('/{bookSlug}/page/{pageSlug}/export/plaintext', 'PageController@exportPlainText'); Route::get('/{bookSlug}/page/{pageSlug}/edit', 'PageController@edit'); Route::get('/{bookSlug}/page/{pageSlug}/delete', 'PageController@showDelete'); + Route::get('/{bookSlug}/draft/{pageId}/delete', 'PageController@showDeleteDraft'); Route::get('/{bookSlug}/page/{pageSlug}/restrict', 'PageController@showRestrict'); Route::put('/{bookSlug}/page/{pageSlug}/restrict', 'PageController@restrict'); Route::put('/{bookSlug}/page/{pageSlug}', 'PageController@update'); Route::delete('/{bookSlug}/page/{pageSlug}', 'PageController@destroy'); + Route::delete('/{bookSlug}/draft/{pageId}', 'PageController@destroyDraft'); // Revisions Route::get('/{bookSlug}/page/{pageSlug}/revisions', 'PageController@showRevisions'); @@ -76,8 +79,9 @@ Route::group(['middleware' => 'auth'], function () { }); // Ajax routes - Route::put('/ajax/page/{id}/save-draft', 'PageController@saveUpdateDraft'); + Route::put('/ajax/page/{id}/save-draft', 'PageController@saveDraft'); Route::get('/ajax/page/{id}', 'PageController@getPageAjax'); + Route::delete('/ajax/page/{id}', 'PageController@ajaxDestroy'); // Links Route::get('/link/{id}', 'PageController@redirectFromLink'); diff --git a/app/Page.php b/app/Page.php index 34dee2f2f..84e37d519 100644 --- a/app/Page.php +++ b/app/Page.php @@ -40,7 +40,9 @@ class Page extends Entity public function getUrl() { $bookSlug = $this->getAttribute('bookSlug') ? $this->getAttribute('bookSlug') : $this->book->slug; - return '/books/' . $bookSlug . '/page/' . $this->slug; + $midText = $this->draft ? '/draft/' : '/page/'; + $idComponent = $this->draft ? $this->id : $this->slug; + return '/books/' . $bookSlug . $midText . $idComponent; } public function getExcerpt($length = 100) diff --git a/app/Repos/BookRepo.php b/app/Repos/BookRepo.php index 2ec9a4c25..b74821d31 100644 --- a/app/Repos/BookRepo.php +++ b/app/Repos/BookRepo.php @@ -213,15 +213,27 @@ class BookRepo extends EntityRepo $chapters = $chapterQuery->get(); $children = $pages->merge($chapters); $bookSlug = $book->slug; + $children->each(function ($child) use ($bookSlug) { $child->setAttribute('bookSlug', $bookSlug); if ($child->isA('chapter')) { $child->pages->each(function ($page) use ($bookSlug) { $page->setAttribute('bookSlug', $bookSlug); }); + $child->pages = $child->pages->sortBy(function($child, $key) { + $score = $child->priority; + if ($child->draft) $score -= 100; + return $score; + }); } }); - return $children->sortBy('priority'); + + // Sort items with drafts first then by priority. + return $children->sortBy(function($child, $key) { + $score = $child->priority; + if ($child->isA('page') && $child->draft) $score -= 100; + return $score; + }); } /** diff --git a/app/Repos/ChapterRepo.php b/app/Repos/ChapterRepo.php index 5d1d6437f..f9f31a7aa 100644 --- a/app/Repos/ChapterRepo.php +++ b/app/Repos/ChapterRepo.php @@ -66,7 +66,13 @@ class ChapterRepo extends EntityRepo */ public function getChildren(Chapter $chapter) { - return $this->restrictionService->enforcePageRestrictions($chapter->pages())->get(); + $pages = $this->restrictionService->enforcePageRestrictions($chapter->pages())->get(); + // Sort items with drafts first then by priority. + return $pages->sortBy(function($child, $key) { + $score = $child->priority; + if ($child->draft) $score -= 100; + return $score; + }); } /** diff --git a/app/Repos/EntityRepo.php b/app/Repos/EntityRepo.php index ea2805855..1a798e53b 100644 --- a/app/Repos/EntityRepo.php +++ b/app/Repos/EntityRepo.php @@ -5,6 +5,7 @@ use BookStack\Chapter; use BookStack\Entity; use BookStack\Page; use BookStack\Services\RestrictionService; +use BookStack\User; class EntityRepo { @@ -79,7 +80,7 @@ class EntityRepo public function getRecentlyCreatedPages($count = 20, $page = 0, $additionalQuery = false) { $query = $this->restrictionService->enforcePageRestrictions($this->page) - ->orderBy('created_at', 'desc'); + ->orderBy('created_at', 'desc')->where('draft', '=', false); if ($additionalQuery !== false && is_callable($additionalQuery)) { $additionalQuery($query); } @@ -112,9 +113,24 @@ class EntityRepo public function getRecentlyUpdatedPages($count = 20, $page = 0) { return $this->restrictionService->enforcePageRestrictions($this->page) + ->where('draft', '=', false) ->orderBy('updated_at', 'desc')->skip($page * $count)->take($count)->get(); } + /** + * Get draft pages owned by the current user. + * @param int $count + * @param int $page + */ + public function getUserDraftPages($count = 20, $page = 0) + { + $user = auth()->user(); + return $this->page->where('draft', '=', true) + ->where('created_by', '=', $user->id) + ->orderBy('updated_at', 'desc') + ->skip($count * $page)->take($count)->get(); + } + /** * Updates entity restrictions from a request * @param $request diff --git a/app/Repos/PageRepo.php b/app/Repos/PageRepo.php index 776d1eadf..547f3e4a6 100644 --- a/app/Repos/PageRepo.php +++ b/app/Repos/PageRepo.php @@ -1,8 +1,8 @@ restrictionService->enforcePageRestrictions($this->page, 'view'); + $query = $this->restrictionService->enforcePageRestrictions($this->page, 'view'); + if (!$allowDrafts) { + $query = $query->where('draft', '=', false); + } + return $query; } /** * Get a page via a specific ID. * @param $id + * @param bool $allowDrafts * @return mixed */ - public function getById($id) + public function getById($id, $allowDrafts = false) { - return $this->pageQuery()->findOrFail($id); + return $this->pageQuery($allowDrafts)->findOrFail($id); } /** @@ -123,6 +130,47 @@ class PageRepo extends EntityRepo return $page; } + + /** + * Publish a draft page to make it a normal page. + * Sets the slug and updates the content. + * @param Page $draftPage + * @param array $input + * @return Page + */ + public function publishDraft(Page $draftPage, array $input) + { + $draftPage->fill($input); + + $draftPage->slug = $this->findSuitableSlug($draftPage->name, $draftPage->book->id); + $draftPage->html = $this->formatHtml($input['html']); + $draftPage->text = strip_tags($draftPage->html); + $draftPage->draft = false; + + $draftPage->save(); + return $draftPage; + } + + /** + * Get a new draft page instance. + * @param Book $book + * @param Chapter|null $chapter + * @return static + */ + public function getDraftPage(Book $book, $chapter) + { + $page = $this->page->newInstance(); + $page->name = 'New Page'; + $page->created_by = auth()->user()->id; + $page->updated_by = auth()->user()->id; + $page->draft = true; + + if ($chapter) $page->chapter_id = $chapter->id; + + $book->pages()->save($page); + return $page; + } + /** * Formats a page's html to be tagged correctly * within the system. @@ -342,6 +390,24 @@ class PageRepo extends EntityRepo return $draft; } + /** + * Update a draft page. + * @param Page $page + * @param array $data + * @return Page + */ + public function updateDraftPage(Page $page, $data = []) + { + $page->fill($data); + + if (isset($data['html'])) { + $page->text = strip_tags($data['html']); + } + + $page->save(); + return $page; + } + /** * The base query for getting user update drafts. * @param Page $page diff --git a/app/Services/RestrictionService.php b/app/Services/RestrictionService.php index f7838bf88..6bc612bb0 100644 --- a/app/Services/RestrictionService.php +++ b/app/Services/RestrictionService.php @@ -8,15 +8,16 @@ class RestrictionService protected $userRoles; protected $isAdmin; protected $currentAction; + protected $currentUser; /** * RestrictionService constructor. */ public function __construct() { - $user = auth()->user(); - $this->userRoles = $user ? auth()->user()->roles->pluck('id') : []; - $this->isAdmin = $user ? auth()->user()->hasRole('admin') : false; + $this->currentUser = auth()->user(); + $this->userRoles = $this->currentUser ? $this->currentUser->roles->pluck('id') : []; + $this->isAdmin = $this->currentUser ? $this->currentUser->hasRole('admin') : false; } /** @@ -48,6 +49,16 @@ class RestrictionService */ public function enforcePageRestrictions($query, $action = 'view') { + // Prevent drafts being visible to others. + $query = $query->where(function($query) { + $query->where('draft', '=', false); + if ($this->currentUser) { + $query->orWhere(function($query) { + $query->where('draft', '=', true)->where('created_by', '=', $this->currentUser->id); + }); + } + }); + if ($this->isAdmin) return $query; $this->currentAction = $action; return $this->pageRestrictionQuery($query); diff --git a/database/migrations/2016_03_13_082138_image_entities_and_page_drafts.php b/database/migrations/2016_03_13_082138_image_entities_and_page_drafts.php new file mode 100644 index 000000000..0852372f1 --- /dev/null +++ b/database/migrations/2016_03_13_082138_image_entities_and_page_drafts.php @@ -0,0 +1,44 @@ +string('entity_type', 100); + $table->integer('entity_id'); + $table->index(['entity_type', 'entity_id']); + }); + + Schema::table('pages', function(Blueprint $table) { + $table->boolean('draft')->default(false); + $table->index('draft'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('images', function (Blueprint $table) { + $table->dropIndex(['entity_type', 'entity_id']); + $table->dropColumn('entity_type'); + $table->dropColumn('entity_id'); + }); + + Schema::table('pages', function (Blueprint $table) { + $table->dropColumn('draft'); + }); + } +} diff --git a/resources/assets/js/controllers.js b/resources/assets/js/controllers.js index 76b8cc67d..f3c80f73e 100644 --- a/resources/assets/js/controllers.js +++ b/resources/assets/js/controllers.js @@ -4,6 +4,7 @@ module.exports = function (ngApp, events) { ngApp.controller('ImageManagerController', ['$scope', '$attrs', '$http', '$timeout', 'imageManagerService', function ($scope, $attrs, $http, $timeout, imageManagerService) { + $scope.images = []; $scope.imageType = $attrs.imageType; $scope.selectedImage = false; @@ -12,6 +13,7 @@ module.exports = function (ngApp, events) { $scope.hasMore = false; $scope.imageUpdateSuccess = false; $scope.imageDeleteSuccess = false; + var page = 0; var previousClickTime = 0; var dataLoaded = false; @@ -221,8 +223,13 @@ module.exports = function (ngApp, events) { var pageId = Number($attrs.pageId); var isEdit = pageId !== 0; var autosaveFrequency = 30; // AutoSave interval in seconds. - $scope.isDraft = Number($attrs.pageDraft) === 1; - if ($scope.isDraft) $scope.draftText = 'Editing Draft'; + $scope.isUpdateDraft = Number($attrs.pageUpdateDraft) === 1; + $scope.isNewPageDraft = Number($attrs.pageNewDraft) === 1; + if ($scope.isUpdateDraft || $scope.isNewPageDraft) { + $scope.draftText = 'Editing Draft' + } else { + $scope.draftText = 'Editing Page' + }; var autoSave = false; @@ -254,7 +261,7 @@ module.exports = function (ngApp, events) { if (newTitle !== currentContent.title || newHtml !== currentContent.html) { currentContent.html = newHtml; currentContent.title = newTitle; - saveDraftUpdate(newTitle, newHtml); + saveDraft(newTitle, newHtml); } }, 1000 * autosaveFrequency); } @@ -264,16 +271,22 @@ module.exports = function (ngApp, events) { * @param title * @param html */ - function saveDraftUpdate(title, html) { + function saveDraft(title, html) { $http.put('/ajax/page/' + pageId + '/save-draft', { name: title, html: html }).then((responseData) => { $scope.draftText = responseData.data.message; - $scope.isDraft = true; + if (!$scope.isNewPageDraft) $scope.isUpdateDraft = true; }); } + $scope.forceDraftSave = function() { + var newTitle = $('#name').val(); + var newHtml = $scope.editorHtml; + saveDraft(newTitle, newHtml); + }; + /** * Discard the current draft and grab the current page * content from the system via an AJAX request. @@ -281,10 +294,10 @@ module.exports = function (ngApp, events) { $scope.discardDraft = function () { $http.get('/ajax/page/' + pageId).then((responseData) => { if (autoSave) $interval.cancel(autoSave); - $scope.draftText = ''; - $scope.isDraft = false; + $scope.draftText = 'Editing Page'; + $scope.isUpdateDraft = false; $scope.$broadcast('html-update', responseData.data.html); - $('#name').val(currentContent.title); + $('#name').val(responseData.data.name); $timeout(() => { startAutoSave(); }, 1000); diff --git a/resources/assets/sass/_header.scss b/resources/assets/sass/_header.scss index 8fed6aef7..95d353498 100644 --- a/resources/assets/sass/_header.scss +++ b/resources/assets/sass/_header.scss @@ -164,7 +164,6 @@ form.search-box { .faded span.faded-text { display: inline-block; padding: $-s; - opacity: 0.5; } .faded-small { diff --git a/resources/assets/sass/_lists.scss b/resources/assets/sass/_lists.scss index 09707ebc4..e0ba2ae42 100644 --- a/resources/assets/sass/_lists.scss +++ b/resources/assets/sass/_lists.scss @@ -26,6 +26,12 @@ .page { border-left: 5px solid $color-page; } + .page.draft { + border-left: 5px solid $color-page-draft; + .text-page { + color: $color-page-draft; + } + } .chapter { border-left: 5px solid $color-chapter; } @@ -182,6 +188,12 @@ background-color: rgba($color-page, 0.1); } } + .list-item-page.draft { + border-left: 5px solid $color-page-draft; + } + .page.draft .page, .list-item-page.draft a.page { + color: $color-page-draft !important; + } .sub-menu { display: none; padding-left: 0; @@ -234,7 +246,6 @@ position: absolute; } - .activity-list-item { padding: $-s 0; color: #888; @@ -304,6 +315,9 @@ ul.pagination { font-size: 0.75em; margin-top: $-xs; } + .page.draft .text-page { + color: $color-page-draft; + } } .entity-list.compact { font-size: 0.6em; diff --git a/resources/assets/sass/_variables.scss b/resources/assets/sass/_variables.scss index cb6cec9c1..4f8ea0f08 100644 --- a/resources/assets/sass/_variables.scss +++ b/resources/assets/sass/_variables.scss @@ -45,6 +45,7 @@ $primary-faded: rgba(21, 101, 192, 0.15); $color-book: #009688; $color-chapter: #ef7c3c; $color-page: $primary; +$color-page-draft: #9A60DA; // Text colours $text-dark: #444; diff --git a/resources/views/chapters/show.blade.php b/resources/views/chapters/show.blade.php index f053edc1c..dc20d144e 100644 --- a/resources/views/chapters/show.blade.php +++ b/resources/views/chapters/show.blade.php @@ -7,7 +7,7 @@
Are you sure you want to delete this page?
+Are you sure you want to delete this {{ $page->draft ? 'draft' : '' }} page?