$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
]);
}
'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());
}
/**
$this->checkOwnablePermission('book-update', $book);
// Return if no map sent
- if (!$request->has('sort-tree')) {
+ if (!$request->filled('sort-tree')) {
return redirect($book->getUrl());
}
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;
};
};
});
+ // 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
@import "header";
@import "lists";
@import "pages";
-@import "comments";
[v-cloak] {
display: none; opacity: 0;
.loading-container {
position: relative;
display: block;
- height: $loadingSize;
margin: $-xl auto;
> div {
width: $loadingSize;
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;
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;
+ }
}
}
}
+ // 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;}
+ }
'name' => 'Name',
'description' => 'Description',
'role' => 'Role',
-
+ 'cover_image' => 'Cover image',
+ 'cover_image_description' => 'This image should be approx 300x170px.',
+
/**
* Actions
*/
'edit' => 'Edit',
'sort' => 'Sort',
'move' => 'Move',
+ 'reply' => 'Reply',
'delete' => 'Delete',
'search' => 'Search',
'search_clear' => 'Clear Search',
'no_items' => 'No items available',
'back_to_top' => 'Back to top',
'toggle_details' => 'Toggle Details',
+ 'toggle_thumbnails' => 'Toggle Thumbnails',
'details' => 'Details',
-
/**
* Header
*/
'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.',
'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' => 'Русский'
]
///////////////////////////////////
];
'save' => 'Opslaan',
'continue' => 'Doorgaan',
'select' => 'Kies',
+ 'more' => 'Meer',
/**
* Form Labels
'name' => 'Naam',
'description' => 'Beschrijving',
'role' => 'Rol',
-
+ 'cover_image' => 'Omslagfoto',
+ 'cover_image_description' => 'Deze afbeelding moet ongeveer 300x170px zijn.',
/**
* Actions
*/
'search_clear' => 'Zoekopdracht wissen',
'reset' => 'Reset',
'remove' => 'Verwijderen',
-
+ 'add' => 'Toevoegen',
/**
* Misc
'no_items' => 'Geen items beschikbaar',
'back_to_top' => 'Terug naar boven',
'toggle_details' => 'Details Weergeven',
+ 'toggle_thumbnails' => 'Thumbnails Weergeven',
/**
* Header
'save' => 'Salvar',
'continue' => 'Continuar',
'select' => 'Selecionar',
+ 'more' => 'Mais',
/**
* Form Labels
'name' => 'Nome',
'description' => 'Descrição',
'role' => 'Regra',
-
+ 'cover_image' => 'Imagem de capa',
+ 'cover_image_description' => 'Esta imagem deve ser aproximadamente 300x170px.',
/**
* Actions
*/
'edit' => 'Editar',
'sort' => 'Ordenar',
'move' => 'Mover',
+ 'reply' => 'Responder',
'delete' => 'Excluir',
'search' => 'Pesquisar',
'search_clear' => 'Limpar Pesquisa',
'reset' => 'Resetar',
'remove' => 'Remover',
-
+ 'add' => 'Adicionar',
/**
* Misc
'no_items' => 'Nenhum item disponível',
'back_to_top' => 'Voltar ao topo',
'toggle_details' => 'Alternar Detalhes',
+ 'toggle_thumbnails' => 'Alternar Miniaturas',
+ 'details' => 'Detalhes',
/**
* Header
<?php
return [
-
+
/**
* Settings text strings
* Contains all text strings used in the general settings sections of BookStack
* including users and roles.
*/
-
+
'settings' => 'Configurações',
'settings_save' => 'Salvar Configurações',
'settings_save_success' => 'Configurações Salvas',
'app_logo_desc' => 'A imagem deve ter 43px de altura. <br>Imagens mais largas devem ser reduzidas.',
'app_primary_color' => 'Cor primária da Aplicação',
'app_primary_color_desc' => 'Esse valor deverá ser Hexadecimal. <br>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
'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.',
'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',
public function test_profile_page_shows_created_content_counts()
{
- $newUser = $this->getEditor();
+ $newUser = $this->getNewBlankUser();
$this->asAdmin()->visit('/user/' . $newUser->id)
->see($newUser->name)
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);
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);
->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');
+ }
}