diff --git a/app/Book.php b/app/Book.php index 5385052..fed6023 100644 --- a/app/Book.php +++ b/app/Book.php @@ -3,7 +3,7 @@ class Book extends Entity { - protected $fillable = ['name', 'description', 'image']; + protected $fillable = ['name', 'description', 'image_id']; /** * Get the url for this book. @@ -17,30 +17,45 @@ public function getUrl($path = false) } return baseUrl('/books/' . urlencode($this->slug)); } - - public function getBookCover() + + /** + * Returns book cover image, if book cover not exists return default cover image. + * @param int $height - Height of the image + * @param type $width - Width of the image + * @return type string + */ + public function getBookCover($height = 170, $width = 300) { - $default = baseUrl('/default.png'); - $image = $this->image; + $default = baseUrl('/book_default_cover.png'); + $image = $this->image_id; if ($image === 0 || $image === '0' || $image === null) return $default; try { - $cover = $this->cover ? baseUrl($this->cover->getThumb(120, 192, false)) : $default; + $cover = $this->cover ? baseUrl($this->cover->getThumb($width, $height, false)) : $default; } catch (\Exception $err) { $cover = $default; } return $cover; } - + + /** + * Get an excerpt of this book's name to the specified length or less. + * @param int $length + * @return string + */ public function getHeadingExcerpt($length = 35) { $bookHeading = $this->name; return strlen($bookHeading) > $length ? substr($bookHeading, 0, $length-3) . '...' : $bookHeading; } + /** + * Get the cover image of the book + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ public function cover() { - return $this->belongsTo(Image::class, 'image'); + return $this->belongsTo(Image::class, 'image_id'); } /* * Get the edit url for this book. @@ -88,5 +103,14 @@ public function entityRawQuery() { return "'BookStack\\\\Book' as entity_type, id, id as entity_id, slug, name, {$this->textField} as text,'' as html, '0' as book_id, '0' as priority, '0' as chapter_id, '0' as draft, created_by, updated_by, updated_at, created_at"; } + + /** + * Get the user that created the page revision + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function createdBy() + { + return $this->belongsTo(User::class, 'created_by'); + } } diff --git a/app/Http/Controllers/BookController.php b/app/Http/Controllers/BookController.php index d515d83..b6175d8 100644 --- a/app/Http/Controllers/BookController.php +++ b/app/Http/Controllers/BookController.php @@ -40,12 +40,14 @@ public function index() $recents = $this->signedIn ? $this->entityRepo->getRecentlyViewed('book', 4, 0) : false; $popular = $this->entityRepo->getPopular('book', 4, 0); $new = $this->entityRepo->getRecentlyCreated('book', 4, 0); + $booksViewType = $this->currentUser->books_view_type; $this->setPageTitle('Books'); return view('books/index', [ 'books' => $books, 'recents' => $recents, 'popular' => $popular, - 'new' => $new + 'new' => $new, + 'booksViewType' => $booksViewType ]); } diff --git a/app/User.php b/app/User.php index 703322c..264723b 100644 --- a/app/User.php +++ b/app/User.php @@ -22,7 +22,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon * The attributes that are mass assignable. * @var array */ - protected $fillable = ['name', 'email', 'image_id', 'books_display' ]; + protected $fillable = ['name', 'email', 'image_id', 'books_view_type' ]; /** * The attributes excluded from the model's JSON form. diff --git a/bootstrap/autoload.php b/bootstrap/autoload.php index 29f66ac..90a8f4e 100644 --- a/bootstrap/autoload.php +++ b/bootstrap/autoload.php @@ -1,6 +1,7 @@ env('APP_DEBUG', false), + 'debug' => env('APP_DEBUG', true), /* |-------------------------------------------------------------------------- diff --git a/public/book_default_cover.png b/public/book_default_cover.png new file mode 100644 index 0000000..7b6c995 Binary files /dev/null and b/public/book_default_cover.png differ diff --git a/public/default.png b/public/default.png deleted file mode 100644 index 1147e23..0000000 Binary files a/public/default.png and /dev/null differ diff --git a/resources/assets/js/global.js b/resources/assets/js/global.js index 176aff7..26dbf9a 100644 --- a/resources/assets/js/global.js +++ b/resources/assets/js/global.js @@ -102,64 +102,6 @@ jQuery.expr[":"].contains = $.expr.createPseudo(function (arg) { }; }); -// Global jQuery Elements -let notifications = $('.notification'); -let successNotification = notifications.filter('.pos'); -let errorNotification = notifications.filter('.neg'); -let warningNotification = notifications.filter('.warning'); -// Notification Events -window.Events.listen('success', function (text) { - successNotification.hide(); - successNotification.find('span').text(text); - setTimeout(() => { - successNotification.show(); - }, 1); -}); -window.Events.listen('warning', function (text) { - warningNotification.find('span').text(text); - warningNotification.show(); -}); -window.Events.listen('error', function (text) { - errorNotification.find('span').text(text); - errorNotification.show(); -}); - -// Notification hiding -notifications.click(function () { - $(this).fadeOut(100); -}); - -// Chapter page list toggles -$('.chapter-toggle').click(function (e) { - e.preventDefault(); - $(this).toggleClass('open'); - $(this).closest('.chapter').find('.inset-list').slideToggle(180); -}); - -// Back to top button -$('#back-to-top').click(function() { - $('#header').smoothScrollTo(); -}); -let scrollTopShowing = false; -let scrollTop = document.getElementById('back-to-top'); -let scrollTopBreakpoint = 1200; -window.addEventListener('scroll', function() { - let scrollTopPos = document.documentElement.scrollTop || document.body.scrollTop || 0; - if (!scrollTopShowing && scrollTopPos > scrollTopBreakpoint) { - scrollTop.style.display = 'block'; - scrollTopShowing = true; - setTimeout(() => { - scrollTop.style.opacity = 0.4; - }, 1); - } else if (scrollTopShowing && scrollTopPos < scrollTopBreakpoint) { - scrollTop.style.opacity = 0; - scrollTopShowing = false; - setTimeout(() => { - scrollTop.style.display = 'none'; - }, 500); - } -}); - // Common jQuery actions $('[data-action="expand-entity-list-details"]').click(function() { $('.entity-list.compact').find('p').not('.empty-text').slideToggle(240); @@ -172,14 +114,6 @@ $(document).ready(function(){ }); }); -// Popup close -$('.popup-close').click(function() { - $(this).closest('.overlay').fadeOut(240); -}); -$('.overlay').click(function(event) { - if (!$(event.target).hasClass('overlay')) return; - $(this).fadeOut(240); -}); // Detect IE for css if(navigator.userAgent.indexOf('MSIE')!==-1 diff --git a/resources/assets/sass/styles.scss b/resources/assets/sass/styles.scss index b0b41af..04aa0d9 100644 --- a/resources/assets/sass/styles.scss +++ b/resources/assets/sass/styles.scss @@ -228,39 +228,73 @@ $btt-size: 40px; } } +// styles for Books grid view +.cover { + width: 290px; + border-radius: 3px; + } +.featured-image-container { + position: relative; + overflow: hidden; + background: #F2F2F2; + border: 1px solid #ddd; + border-bottom: 0px; +} -.gallery-item { - margin-bottom: 32px; - height: 350px; - overflow: hidden; - border: 1px solid #ccc; - h4 { - font-size: 1.2em; - text-align: center; - height: 55px; - padding: 0px 12px; - } - p { - font-size: 0.8em; - text-align: center; - padding: 0px 12px; - } - &.collapse { - height: 150px; - } +.featured-image-container img { + display: block; + max-width: 100%; + height: auto; + -webkit-transition: all .5s ease; + -moz-transition: all .5s ease; + -ms-transition: all .5s ease; + -o-transition: all .5s ease; + transition: all .5s ease; } -.gallery-image { - margin-top: 5%; - text-align: center; - img { - border-radius: 3px; - } +.book-content { + padding: 30px; + border: 1px solid #ddd; + border-top: 0px; + border-bottom-width: 2px; +} +.book-content h2 { + font-size: 1.5em; + line-height: 1.2; + margin: 0 0 10px; } -.cover { - height: 192px; - width: 120px; - border-radius: 3px; - } \ No newline at end of file +.book-content h2 a { + display: block; + color: #009688;; + text-decoration: none; +} + +.book-content p { + font-size: .85em; + margin: 0 0 10px; + line-height: 1.6em; +} + +.featured-image-container img:hover { + -webkit-transform: scale(1.15); + -moz-transform: scale(1.15); + -ms-transform: scale(1.15); + -o-transform: scale(1.15); + transform: scale(1.15); + opacity: .5; +} +.books-grid-div { + margin-bottom : 20px; +} + +@media (min-width:992px){ + .row.auto-clear .col-md-4:nth-child(3n+1){clear:left;} +} +@media (min-width:992px){ + .row.auto-clear .col-md-4:nth-child(3n+1){clear:left;} +} +@media (max-width:991px){ + .row.auto-clear .col-xs-6:nth-child(2n+1){clear:left;} +} \ No newline at end of file diff --git a/resources/lang/de/settings.php b/resources/lang/de/settings.php index 598f9f6..2da5172 100644 --- a/resources/lang/de/settings.php +++ b/resources/lang/de/settings.php @@ -96,7 +96,7 @@ 'users_delete_warning' => 'Der Benutzer ":userName" wird aus dem System gelöscht.', 'users_delete_confirm' => 'Sind Sie sicher, dass Sie diesen Benutzer löschen möchten?', 'users_delete_success' => 'Benutzer erfolgreich gelöscht.', - 'users_books_display_type' => 'Bevorzugtes Display-Layout für Bücher', + 'users_books_view_type' => 'Bevorzugtes Display-Layout für Bücher', 'users_edit' => 'Benutzer bearbeiten', 'users_edit_profile' => 'Profil bearbeiten', 'users_edit_success' => 'Benutzer erfolgreich aktualisisert', diff --git a/resources/lang/en/settings.php b/resources/lang/en/settings.php index 14b5371..644ca3a 100644 --- a/resources/lang/en/settings.php +++ b/resources/lang/en/settings.php @@ -94,7 +94,7 @@ 'users_external_auth_id' => 'External Authentication ID', 'users_password_warning' => 'Only fill the below if you would like to change your password:', 'users_system_public' => 'This user represents any guest users that visit your instance. It cannot be used to log in but is assigned automatically.', - 'users_books_display_type' => 'Preferred layout for books viewing', + 'users_books_view_type' => 'Preferred layout for books viewing', 'users_delete' => 'Delete User', 'users_delete_named' => 'Delete user :userName', 'users_delete_warning' => 'This will fully delete this user with the name \':userName\' from the system.', diff --git a/resources/lang/es/settings.php b/resources/lang/es/settings.php index 4651247..9535d3f 100644 --- a/resources/lang/es/settings.php +++ b/resources/lang/es/settings.php @@ -91,7 +91,7 @@ 'users_external_auth_id' => 'ID externo de autenticación', 'users_password_warning' => 'Solo rellene a continuación si desea cambiar su password:', 'users_system_public' => 'Este usuario representa cualquier usuario invitado que visita la aplicación. No puede utilizarse para hacer login sio que es asignado automáticamente.', - 'users_books_display_type' => 'Diseño de pantalla preferido para libros', + 'users_books_view_type' => 'Diseño de pantalla preferido para libros', 'users_delete' => 'Borrar usuario', 'users_delete_named' => 'Borrar usuario :userName', 'users_delete_warning' => 'Se borrará completamente el usuario con el nombre \':userName\' del sistema.', diff --git a/resources/lang/fr/settings.php b/resources/lang/fr/settings.php index 5516e66..399afdc 100644 --- a/resources/lang/fr/settings.php +++ b/resources/lang/fr/settings.php @@ -91,7 +91,7 @@ 'users_external_auth_id' => 'Identifiant d\'authentification externe', 'users_password_warning' => 'Remplissez ce fomulaire uniquement si vous souhaitez changer de mot de passe:', 'users_system_public' => 'Cet utilisateur représente les invités visitant votre instance. Il est assigné automatiquement aux invités.', - 'users_books_display_type' => 'Disposition d\'affichage préférée pour les livres', + 'users_books_view_type' => 'Disposition d\'affichage préférée pour les livres', 'users_delete' => 'Supprimer un utilisateur', 'users_delete_named' => 'Supprimer l\'utilisateur :userName', 'users_delete_warning' => 'Ceci va supprimer \':userName\' du système.', diff --git a/resources/lang/nl/settings.php b/resources/lang/nl/settings.php index 0323d87..7b8adf6 100644 --- a/resources/lang/nl/settings.php +++ b/resources/lang/nl/settings.php @@ -91,7 +91,7 @@ 'users_external_auth_id' => 'External Authentication ID', 'users_password_warning' => 'Vul onderstaande formulier alleen in als je het wachtwoord wilt aanpassen:', 'users_system_public' => 'De eigenschappen van deze gebruiker worden voor elke gastbezoeker gebruikt. Er kan niet mee ingelogd worden en wordt automatisch toegewezen.', - 'users_books_display_type' => 'Voorkeursuitleg voor het weergeven van boeken', + 'users_books_view_type' => 'Voorkeursuitleg voor het weergeven van boeken', 'users_delete' => 'Verwijder gebruiker', 'users_delete_named' => 'Verwijder gebruiker :userName', 'users_delete_warning' => 'Dit zal de gebruiker \':userName\' volledig uit het systeem verwijderen.', diff --git a/resources/lang/pt_BR/settings.php b/resources/lang/pt_BR/settings.php index 6c8ff30..8ebd2b7 100644 --- a/resources/lang/pt_BR/settings.php +++ b/resources/lang/pt_BR/settings.php @@ -91,7 +91,7 @@ 'users_external_auth_id' => 'ID de Autenticação Externa', 'users_password_warning' => 'Preencha os dados abaixo caso queira modificar a sua senha:', 'users_system_public' => 'Esse usuário representa quaisquer convidados que visitam o aplicativo. Ele não pode ser usado para login.', - 'users_books_display_type' => 'Layout preferido para mostrar livros', + 'users_books_view_type' => 'Layout preferido para mostrar livros', 'users_delete' => 'Excluir Usuário', 'users_delete_named' => 'Excluir :userName', 'users_delete_warning' => 'A ação vai excluir completamente o usuário de nome \':userName\' do sistema.', diff --git a/resources/lang/sk/settings.php b/resources/lang/sk/settings.php index 8a8d93e..4438f80 100644 --- a/resources/lang/sk/settings.php +++ b/resources/lang/sk/settings.php @@ -91,7 +91,7 @@ 'users_external_auth_id' => 'Externé autentifikačné ID', 'users_password_warning' => 'Pole nižšie vyplňte iba ak chcete zmeniť heslo:', 'users_system_public' => 'Tento účet reprezentuje každého hosťovského používateľa, ktorý navštívi Vašu inštanciu. Nedá sa pomocou neho prihlásiť a je priradený automaticky.', - 'users_books_display_type' => 'Preferované rozloženie pre prezeranie kníh', + 'users_books_view_type' => 'Preferované rozloženie pre prezeranie kníh', 'users_delete' => 'Zmazať používateľa', 'users_delete_named' => 'Zmazať používateľa :userName', 'users_delete_warning' => ' Toto úplne odstráni používateľa menom \':userName\' zo systému.', diff --git a/resources/views/books/form.blade.php b/resources/views/books/form.blade.php index fc30093..6356da7 100644 --- a/resources/views/books/form.blade.php +++ b/resources/views/books/form.blade.php @@ -14,13 +14,13 @@

{{ trans('common.cover_image_description') }}

@include('components.image-picker', [ - 'resizeHeight' => '192', - 'resizeWidth' => '120', + 'resizeHeight' => '512', + 'resizeWidth' => '512', 'showRemove' => true, 'defaultImage' => baseUrl('/default.png'), - 'currentImage' => @isset($model) ? $model->getBookCover(80) : baseUrl('/default.png') , - 'currentId' => @isset($model) ? $model->image : 0, - 'name' => 'image', + 'currentImage' => @isset($model) ? $model->getBookCover() : baseUrl('/default.png') , + 'currentId' => @isset($model) ? $model->image_id : 0, + 'name' => 'image_id', 'imageClass' => 'cover' ]) diff --git a/resources/views/books/grid-item.blade.php b/resources/views/books/grid-item.blade.php index 3c0ec1e..74801ec 100644 --- a/resources/views/books/grid-item.blade.php +++ b/resources/views/books/grid-item.blade.php @@ -1,19 +1,18 @@ -
-
diff --git a/tests/UserProfileTest.php b/tests/UserProfileTest.php index e0c87d9..eabfce0 100644 --- a/tests/UserProfileTest.php +++ b/tests/UserProfileTest.php @@ -95,26 +95,26 @@ public function test_guest_profile_cannot_be_deleted() ->see('cannot delete the guest user'); } - public function test_books_display_is_list() + public function test_books_view_is_list() { $editor = $this->getEditor([ - 'books_display' => 'list' + 'books_view_type' => 'list' ]); $this->actingAs($editor) ->visit('/books') - ->pageNotHasElement('.gallery-item') + ->pageNotHasElement('.featured-image-container') ->pageHasElement('.entity-list-item'); } - public function test_books_display_is_grid() + public function test_books_view_is_grid() { $editor = $this->getEditor([ - 'books_display' => 'grid' + 'books_view_type' => 'grid' ]); $this->actingAs($editor) ->visit('/books') - ->pageHasElement('.gallery-item'); + ->pageHasElement('.featured-image-container'); } }