From: Dan Brown Date: Wed, 6 Dec 2017 15:52:54 +0000 (+0000) Subject: Merge branch 'BookStackApp-master' of git://github.com/OsmosysSoftware/BookStack... X-Git-Tag: v0.19.0~1^2~15 X-Git-Url: http://source.bookstackapp.com/bookstack/commitdiff_plain/bc1302a8d8c9c7facb16b28e1cf1da4409e7ede0?ds=inline;hp=-c Merge branch 'BookStackApp-master' of git://github.com/OsmosysSoftware/BookStack into OsmosysSoftware-BookStackApp-master --- bc1302a8d8c9c7facb16b28e1cf1da4409e7ede0 diff --combined app/Http/Controllers/BookController.php index 7e4b3fd81,b6175d859..2d961355b --- a/app/Http/Controllers/BookController.php +++ b/app/Http/Controllers/BookController.php @@@ -40,12 -40,14 +40,14 @@@ class BookController extends Controlle $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 ]); } @@@ -125,9 -127,9 +127,9 @@@ 'name' => 'required|string|max:255', 'description' => 'string|max:1000' ]); - $book = $this->entityRepo->updateFromInput('book', $book, $request->all()); - Activity::add($book, 'book_update', $book->id); - return redirect($book->getUrl()); + $book = $this->entityRepo->updateFromInput('book', $book, $request->all()); + Activity::add($book, 'book_update', $book->id); + return redirect($book->getUrl()); } /** @@@ -183,7 -185,7 +185,7 @@@ $this->checkOwnablePermission('book-update', $book); // Return if no map sent - if (!$request->has('sort-tree')) { + if (!$request->filled('sort-tree')) { return redirect($book->getUrl()); } diff --combined resources/assets/js/global.js index 352616c5a,26dbf9a5e..f746b2861 --- a/resources/assets/js/global.js +++ b/resources/assets/js/global.js @@@ -58,57 -58,40 +58,57 @@@ window.$http = axiosInstance Vue.prototype.$http = axiosInstance; Vue.prototype.$events = window.$events; - -// AngularJS - Create application and load components -const angular = require("angular"); -require("angular-resource"); -require("angular-animate"); -require("angular-sanitize"); -require("angular-ui-sortable"); - -let ngApp = angular.module('bookStack', ['ngResource', 'ngAnimate', 'ngSanitize', 'ui.sortable']); - // Translation setup // Creates a global function with name 'trans' to be used in the same way as Laravel's translation system const Translations = require("./translations"); let translator = new Translations(window.translations); window.trans = translator.get.bind(translator); +window.trans_choice = translator.getPlural.bind(translator); require("./vues/vues"); require("./components"); -// Load in angular specific items -const Directives = require('./directives'); -const Controllers = require('./controllers'); -Directives(ngApp, window.$events); -Controllers(ngApp, window.$events); //Global jQuery Config & Extensions +/** + * Scroll the view to a specific element. + * @param {HTMLElement} element + */ +window.scrollToElement = function(element) { + if (!element) return; + let offset = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop; + let top = element.getBoundingClientRect().top + offset; + $('html, body').animate({ + scrollTop: top - 60 // Adjust to change final scroll position top margin + }, 300); +}; + +/** + * Scroll and highlight an element. + * @param {HTMLElement} element + */ +window.scrollAndHighlight = function(element) { + if (!element) return; + window.scrollToElement(element); + let color = document.getElementById('custom-styles').getAttribute('data-color-light'); + let initColor = window.getComputedStyle(element).getPropertyValue('background-color'); + element.style.backgroundColor = color; + setTimeout(() => { + element.classList.add('selectFade'); + element.style.backgroundColor = initColor; + }, 10); + setTimeout(() => { + element.classList.remove('selectFade'); + element.style.backgroundColor = ''; + }, 3000); +}; + // Smooth scrolling jQuery.fn.smoothScrollTo = function () { if (this.length === 0) return; - $('html, body').animate({ - scrollTop: this.offset().top - 60 // Adjust to change final scroll position top margin - }, 300); // Adjust to change animations speed (ms) + window.scrollToElement(this[0]); return this; }; @@@ -119,6 -102,19 +119,19 @@@ jQuery.expr[":"].contains = $.expr.crea }; }); + // Common jQuery actions + $('[data-action="expand-entity-list-details"]').click(function() { + $('.entity-list.compact').find('p').not('.empty-text').slideToggle(240); + }); + + // Toggle thumbnail::hide image and reduce grid size + $(document).ready(function(){ + $('[data-action="expand-thumbnail"]').click(function(){ + $('.gallery-item').toggleClass("collapse").find('img').slideToggle(50); + }); + }); + + // Detect IE for css if(navigator.userAgent.indexOf('MSIE')!==-1 || navigator.appVersion.indexOf('Trident/') > 0 diff --combined resources/assets/sass/styles.scss index e8d87d520,04aa0d968..730cc8a65 --- a/resources/assets/sass/styles.scss +++ b/resources/assets/sass/styles.scss @@@ -15,6 -15,7 +15,6 @@@ @import "header"; @import "lists"; @import "pages"; -@import "comments"; [v-cloak] { display: none; opacity: 0; @@@ -68,6 -69,7 +68,6 @@@ $loadingSize: 10px .loading-container { position: relative; display: block; - height: $loadingSize; margin: $-xl auto; > div { width: $loadingSize; @@@ -75,8 -77,7 +75,8 @@@ border-radius: $loadingSize; display: inline-block; vertical-align: top; - transform: translate3d(0, 0, 0); + transform: translate3d(-10px, 0, 0); + margin-top: $-xs; animation-name: loadingBob; animation-duration: 1.4s; animation-iteration-count: infinite; @@@ -90,17 -91,11 +90,17 @@@ background-color: $color-book; animation-delay: 0s; } - > div:last-child { + > div:last-of-type { left: $loadingSize+$-xs; background-color: $color-chapter; animation-delay: 0.6s; } + > span { + margin-left: $-s; + font-style: italic; + color: #888; + vertical-align: top; + } } @@@ -233,5 -228,73 +233,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; + } + + .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; + } + + .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; + } + + .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;} + } diff --combined resources/lang/en/common.php index 269905a59,1b05a229d..70cfc5701 --- a/resources/lang/en/common.php +++ b/resources/lang/en/common.php @@@ -18,7 -18,9 +18,9 @@@ return 'name' => 'Name', 'description' => 'Description', 'role' => 'Role', - + 'cover_image' => 'Cover image', + 'cover_image_description' => 'This image should be approx 300x170px.', + /** * Actions */ @@@ -29,7 -31,6 +31,7 @@@ 'edit' => 'Edit', 'sort' => 'Sort', 'move' => 'Move', + 'reply' => 'Reply', 'delete' => 'Delete', 'search' => 'Search', 'search_clear' => 'Clear Search', @@@ -45,8 -46,8 +47,8 @@@ 'no_items' => 'No items available', 'back_to_top' => 'Back to top', 'toggle_details' => 'Toggle Details', + 'toggle_thumbnails' => 'Toggle Thumbnails', 'details' => 'Details', - /** * Header */ diff --combined resources/lang/en/settings.php index 468c5981f,644ca3a31..4153055eb mode 100755,100644..100755 --- a/resources/lang/en/settings.php +++ b/resources/lang/en/settings.php @@@ -94,6 -94,7 +94,7 @@@ return '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_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.', @@@ -120,15 -121,12 +121,15 @@@ 'en' => 'English', 'de' => 'Deutsch', 'es' => 'Español', + 'es_AR' => 'Español Argentina', 'fr' => 'Français', 'nl' => 'Nederlands', 'pt_BR' => 'Português do Brasil', 'sk' => 'Slovensky', 'ja' => '日本語', 'pl' => 'Polski', + 'it' => 'Italian', + 'ru' => 'Русский' ] /////////////////////////////////// ]; diff --combined resources/lang/nl/common.php index 1ae0ade7c,096676130..fdfb90fb2 --- a/resources/lang/nl/common.php +++ b/resources/lang/nl/common.php @@@ -10,7 -10,6 +10,7 @@@ return 'save' => 'Opslaan', 'continue' => 'Doorgaan', 'select' => 'Kies', + 'more' => 'Meer', /** * Form Labels @@@ -18,7 -17,8 +18,8 @@@ 'name' => 'Naam', 'description' => 'Beschrijving', 'role' => 'Rol', - + 'cover_image' => 'Omslagfoto', + 'cover_image_description' => 'Deze afbeelding moet ongeveer 300x170px zijn.', /** * Actions */ @@@ -34,7 -34,7 +35,7 @@@ 'search_clear' => 'Zoekopdracht wissen', 'reset' => 'Reset', 'remove' => 'Verwijderen', - + 'add' => 'Toevoegen', /** * Misc @@@ -44,6 -44,7 +45,7 @@@ 'no_items' => 'Geen items beschikbaar', 'back_to_top' => 'Terug naar boven', 'toggle_details' => 'Details Weergeven', + 'toggle_thumbnails' => 'Thumbnails Weergeven', /** * Header diff --combined resources/lang/pt_BR/common.php index 632a1a078,97b6a93c4..991cb0b7e --- a/resources/lang/pt_BR/common.php +++ b/resources/lang/pt_BR/common.php @@@ -10,7 -10,6 +10,7 @@@ return 'save' => 'Salvar', 'continue' => 'Continuar', 'select' => 'Selecionar', + 'more' => 'Mais', /** * Form Labels @@@ -18,7 -17,8 +18,8 @@@ 'name' => 'Nome', 'description' => 'Descrição', 'role' => 'Regra', - + 'cover_image' => 'Imagem de capa', + 'cover_image_description' => 'Esta imagem deve ser aproximadamente 300x170px.', /** * Actions */ @@@ -29,13 -29,12 +30,13 @@@ 'edit' => 'Editar', 'sort' => 'Ordenar', 'move' => 'Mover', + 'reply' => 'Responder', 'delete' => 'Excluir', 'search' => 'Pesquisar', 'search_clear' => 'Limpar Pesquisa', 'reset' => 'Resetar', 'remove' => 'Remover', - + 'add' => 'Adicionar', /** * Misc @@@ -45,7 -44,7 +46,8 @@@ 'no_items' => 'Nenhum item disponível', 'back_to_top' => 'Voltar ao topo', 'toggle_details' => 'Alternar Detalhes', + 'toggle_thumbnails' => 'Alternar Miniaturas', + 'details' => 'Detalhes', /** * Header diff --combined resources/lang/pt_BR/settings.php index 5513c217f,8ebd2b728..0da798557 --- a/resources/lang/pt_BR/settings.php +++ b/resources/lang/pt_BR/settings.php @@@ -1,13 -1,13 +1,13 @@@ 'Configurações', 'settings_save' => 'Salvar Configurações', 'settings_save_success' => 'Configurações Salvas', @@@ -31,9 -31,6 +31,9 @@@ 'app_logo_desc' => 'A imagem deve ter 43px de altura.
Imagens mais largas devem ser reduzidas.', 'app_primary_color' => 'Cor primária da Aplicação', 'app_primary_color_desc' => 'Esse valor deverá ser Hexadecimal.
Deixe em branco para que o Bookstack assuma a cor padrão.', + 'app_homepage' => 'Página incial', + 'app_homepage_desc' => 'Selecione a página para ser usada como página inicial em vez da padrão. Permissões da página serão ignoradas.', + 'app_homepage_default' => 'Escolhida página inicial padrão', /** * Registration settings @@@ -94,6 -91,7 +94,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_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.', @@@ -104,7 -102,6 +105,7 @@@ 'users_edit_success' => 'Usuário atualizado com sucesso', 'users_avatar' => 'Imagem de Usuário', 'users_avatar_desc' => 'Essa imagem deve ser um quadrado com aproximadamente 256px de altura e largura.', + 'users_preferred_language' => 'Linguagem de Preferência', 'users_social_accounts' => 'Contas Sociais', 'users_social_accounts_info' => 'Aqui você pode conectar outras contas para acesso mais rápido. Desconectar uma conta não retira a possibilidade de acesso usando-a. Para revogar o acesso ao perfil através da conta social, você deverá fazê-lo na sua conta social.', 'users_social_connect' => 'Contas conectadas', diff --combined tests/UserProfileTest.php index 54671bbf6,eabfce004..4636fc76c --- a/tests/UserProfileTest.php +++ b/tests/UserProfileTest.php @@@ -33,7 -33,7 +33,7 @@@ class UserProfileTest extends BrowserKi public function test_profile_page_shows_created_content_counts() { - $newUser = $this->getEditor(); + $newUser = $this->getNewBlankUser(); $this->asAdmin()->visit('/user/' . $newUser->id) ->see($newUser->name) @@@ -52,7 -52,7 +52,7 @@@ public function test_profile_page_shows_recent_activity() { - $newUser = $this->getEditor(); + $newUser = $this->getNewBlankUser(); $this->actingAs($newUser); $entities = $this->createEntityChainBelongingToUser($newUser, $newUser); \Activity::add($entities['book'], 'book_update', $entities['book']->id); @@@ -66,7 -66,7 +66,7 @@@ public function test_clicking_user_name_in_activity_leads_to_profile_page() { - $newUser = $this->getEditor(); + $newUser = $this->getNewBlankUser(); $this->actingAs($newUser); $entities = $this->createEntityChainBelongingToUser($newUser, $newUser); \Activity::add($entities['book'], 'book_update', $entities['book']->id); @@@ -94,5 -94,27 +94,27 @@@ ->seePageIs('/settings/users/' . $guestUser->id) ->see('cannot delete the guest user'); } - + + public function test_books_view_is_list() + { + $editor = $this->getEditor([ + 'books_view_type' => 'list' + ]); + + $this->actingAs($editor) + ->visit('/books') + ->pageNotHasElement('.featured-image-container') + ->pageHasElement('.entity-list-item'); + } + + public function test_books_view_is_grid() + { + $editor = $this->getEditor([ + 'books_view_type' => 'grid' + ]); + + $this->actingAs($editor) + ->visit('/books') + ->pageHasElement('.featured-image-container'); + } }