Dan Brown

Merge branch 'master' into release

...@@ -110,7 +110,11 @@ class ImageController extends Controller ...@@ -110,7 +110,11 @@ class ImageController extends Controller
110 public function upload(Request $request) 110 public function upload(Request $request)
111 { 111 {
112 $this->checkPermission('image-create'); 112 $this->checkPermission('image-create');
113 + $this->validate($request, [
114 + 'file' => 'image|mimes:jpeg,gif,png'
115 + ]);
113 $imageUpload = $request->file('file'); 116 $imageUpload = $request->file('file');
117 +
114 $name = str_replace(' ', '-', $imageUpload->getClientOriginalName()); 118 $name = str_replace(' ', '-', $imageUpload->getClientOriginalName());
115 $storageName = substr(sha1(time()), 0, 10) . '-' . $name; 119 $storageName = substr(sha1(time()), 0, 10) . '-' . $name;
116 $imagePath = '/uploads/images/' . Date('Y-m-M') . '/'; 120 $imagePath = '/uploads/images/' . Date('Y-m-M') . '/';
......
...@@ -27,6 +27,7 @@ class ViewService ...@@ -27,6 +27,7 @@ class ViewService
27 */ 27 */
28 public function add(Entity $entity) 28 public function add(Entity $entity)
29 { 29 {
30 + if($this->user === null) return 0;
30 $view = $entity->views()->where('user_id', '=', $this->user->id)->first(); 31 $view = $entity->views()->where('user_id', '=', $this->user->id)->first();
31 // Add view if model exists 32 // Add view if model exists
32 if ($view) { 33 if ($view) {
...@@ -52,6 +53,7 @@ class ViewService ...@@ -52,6 +53,7 @@ class ViewService
52 */ 53 */
53 public function getUserRecentlyViewed($count = 10, $page = 0, $filterModel = false) 54 public function getUserRecentlyViewed($count = 10, $page = 0, $filterModel = false)
54 { 55 {
56 + if($this->user === null) return collect();
55 $skipCount = $count * $page; 57 $skipCount = $count * $page;
56 $query = $this->view->where('user_id', '=', auth()->user()->id); 58 $query = $this->view->where('user_id', '=', auth()->user()->id);
57 59
......
...@@ -2,35 +2,40 @@ ...@@ -2,35 +2,40 @@
2 2
3 A platform to create documentation/wiki content. General information about BookStack can be found at https://www.bookstackapp.com/ 3 A platform to create documentation/wiki content. General information about BookStack can be found at https://www.bookstackapp.com/
4 4
5 -**BookStack is currently in rapid development so use now is heavily cautioned as future updates my break existing installations.**
6 5
7 ## Requirements 6 ## Requirements
8 7
9 -BookStack has the similar requirements to Laravel. On top of those are some front-end build tools which the requirement of will be removed once out of beta release. 8 +BookStack has the similar requirements to Laravel. On top of those are some front-end build tools which are only required when developing.
10 9
11 * PHP >= 5.5.9 10 * PHP >= 5.5.9
12 * OpenSSL PHP Extension 11 * OpenSSL PHP Extension
13 * PDO PHP Extension 12 * PDO PHP Extension
14 -* Mbstring PHP Extension 13 +* MBstring PHP Extension
15 * Tokenizer PHP Extension 14 * Tokenizer PHP Extension
16 * MySQL >= 5.6 15 * MySQL >= 5.6
16 +* Git (Not strictly required but helps manage updates)
17 * [Composer](https://getcomposer.org/) 17 * [Composer](https://getcomposer.org/)
18 -* [Node.js](https://nodejs.org/en/) **To be removed in future** 18 +* [Node.js](https://nodejs.org/en/) **Development Only**
19 -* [Bower](http://bower.io/) **To be removed in future** 19 +* [Gulp](http://gulpjs.com/) **Development Only**
20 -* [Gulp](http://gulpjs.com/) **To be removed in future**
21 20
22 21
23 ## Installation 22 ## Installation
24 23
25 Ensure the requirements are met before installing. 24 Ensure the requirements are met before installing.
26 25
27 -The installation is currently somewhat complicated. Some PHP/Laravel experience will benefit. This will be streamlined in the future. 26 +This project currently uses the `release` branch of this repository as a stable channel for providing updates.
28 27
29 -1. Clone the repository into a folder. 28 +The installation is currently somewhat complicated. Some PHP/Laravel experience will benefit.
30 -2. `cd` into folder and run `composer install` followed by `npm install` and `bower install`. 29 +
31 -3. Run `gulp --production` to compile the JavaScript and css files. 30 +1. Clone the release branch of this repository into a folder.
32 -4. Copy the `.env.example` file to `.env` and fill with your own database and mail details. 31 +
33 -5. Ensure the `storage` & `bootstrap/cache` folders are writable by the web server. 32 +```
33 +git clone https://github.com/ssddanbrown/BookStack.git --branch release --single-branch
34 +```
35 +
36 +2. `cd` into the application folder and run `composer install`.
37 +3. Copy the `.env.example` file to `.env` and fill with your own database and mail details.
38 +4. Ensure the `storage` & `bootstrap/cache` folders are writable by the web server.
34 5. In the application root, Run `php artisan key:generate` to generate a unique application key. 39 5. In the application root, Run `php artisan key:generate` to generate a unique application key.
35 6. If not using apache or `.htaccess` files are disable you will have to create some URL rewrite rules as shown below. 40 6. If not using apache or `.htaccess` files are disable you will have to create some URL rewrite rules as shown below.
36 7. Run `php migrate` to update the database. 41 7. Run `php migrate` to update the database.
......
...@@ -110,6 +110,12 @@ ...@@ -110,6 +110,12 @@
110 dz.removeFile(file); 110 dz.removeFile(file);
111 }); 111 });
112 }); 112 });
113 + this.on('error', function(file, errorMessage, xhr) {
114 + if(errorMessage.file) {
115 + $(file.previewElement).find('[data-dz-errormessage]').text(errorMessage.file[0]);
116 + }
117 + console.log(errorMessage);
118 + });
113 } 119 }
114 }); 120 });
115 }, 121 },
......
...@@ -19,12 +19,16 @@ ...@@ -19,12 +19,16 @@
19 max-width: 840px; 19 max-width: 840px;
20 overflow-wrap: break-word; 20 overflow-wrap: break-word;
21 .align-left { 21 .align-left {
22 - float: left !important;
23 text-align: left; 22 text-align: left;
23 + }
24 + img.align-left, table.align-left {
25 + float: left !important;
24 margin: $-xs $-s $-xs 0; 26 margin: $-xs $-s $-xs 0;
25 } 27 }
26 .align-right { 28 .align-right {
27 float: right !important; 29 float: right !important;
30 + }
31 + img.align-right, table.align-right {
28 text-align: right; 32 text-align: right;
29 margin: $-xs 0 $-xs $-s; 33 margin: $-xs 0 $-xs $-s;
30 } 34 }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
3 <head> 3 <head>
4 <title>BookStack</title> 4 <title>BookStack</title>
5 5
6 - <!-- Meta--> 6 + <!-- Meta -->
7 <meta name="viewport" content="width=device-width"> 7 <meta name="viewport" content="width=device-width">
8 <meta name="token" content="{{ csrf_token() }}"> 8 <meta name="token" content="{{ csrf_token() }}">
9 <meta charset="utf-8"> 9 <meta charset="utf-8">
...@@ -21,17 +21,7 @@ ...@@ -21,17 +21,7 @@
21 </head> 21 </head>
22 <body class="@yield('body-class')" id="app"> 22 <body class="@yield('body-class')" id="app">
23 23
24 - @if(Session::has('success')) 24 + @include('partials/notifications')
25 - <div class="notification anim pos">
26 - <i class="zmdi zmdi-mood"></i> <span>{{ Session::get('success') }}</span>
27 - </div>
28 - @endif
29 -
30 - @if(Session::has('error'))
31 - <div class="notification anim neg stopped">
32 - <i class="zmdi zmdi-alert-circle"></i> <span>{{ Session::get('error') }}</span>
33 - </div>
34 - @endif
35 25
36 <header id="header"> 26 <header id="header">
37 <div class="container"> 27 <div class="container">
......
1 +@if(Session::has('success'))
2 + <div class="notification anim pos">
3 + <i class="zmdi zmdi-mood"></i> <span>{{ Session::get('success') }}</span>
4 + </div>
5 +@endif
6 +
7 +@if(Session::has('error'))
8 + <div class="notification anim neg stopped">
9 + <i class="zmdi zmdi-alert-circle"></i> <span>{{ Session::get('error') }}</span>
10 + </div>
11 +@endif
...\ No newline at end of file ...\ No newline at end of file
...@@ -2,27 +2,24 @@ ...@@ -2,27 +2,24 @@
2 <html> 2 <html>
3 <head> 3 <head>
4 <title>BookStack</title> 4 <title>BookStack</title>
5 +
6 + <!-- Meta -->
5 <meta name="viewport" content="width=device-width"> 7 <meta name="viewport" content="width=device-width">
8 + <meta charset="utf-8">
9 +
10 + <!-- Styles and Fonts -->
6 <link rel="stylesheet" href="{{ elixir('css/styles.css') }}"> 11 <link rel="stylesheet" href="{{ elixir('css/styles.css') }}">
12 + <link rel="stylesheet" media="print" href="{{ elixir('css/print-styles.css') }}">
7 <link href='//fonts.googleapis.com/css?family=Roboto:400,400italic,500,500italic,700,700italic,300italic,100,300' rel='stylesheet' type='text/css'> 13 <link href='//fonts.googleapis.com/css?family=Roboto:400,400italic,500,500italic,700,700italic,300italic,100,300' rel='stylesheet' type='text/css'>
8 - <link rel="stylesheet" href="/bower/material-design-iconic-font/dist/css/material-design-iconic-font.min.css"> 14 + <link rel="stylesheet" href="/libs/material-design-iconic-font/css/material-design-iconic-font.min.css">
9 15
10 <!-- Scripts --> 16 <!-- Scripts -->
11 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> 17 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
18 +
12 </head> 19 </head>
13 <body class="@yield('body-class')" id="app"> 20 <body class="@yield('body-class')" id="app">
14 21
15 -@if(Session::has('success')) 22 +@include('partials/notifications')
16 - <div class="notification anim pos">
17 - <i class="zmdi zmdi-mood"></i> <span>{{ Session::get('success') }}</span>
18 - </div>
19 -@endif
20 -
21 -@if(Session::has('error'))
22 - <div class="notification anim neg stopped">
23 - <i class="zmdi zmdi-alert-circle"></i> <span>{{ Session::get('error') }}</span>
24 - </div>
25 -@endif
26 23
27 <header id="header"> 24 <header id="header">
28 <div class="container"> 25 <div class="container">
......
1 +<?php
2 +
3 +class PublicViewTest extends TestCase
4 +{
5 +
6 + public function testBooksViewable()
7 + {
8 + $this->setSettings(['app-public' => 'true']);
9 + $books = \BookStack\Book::orderBy('name', 'asc')->take(10)->get();
10 + $bookToVisit = $books[1];
11 +
12 + // Check books index page is showing
13 + $this->visit('/books')
14 + ->seeStatusCode(200)
15 + ->see($books[0]->name)
16 + // Check indavidual book page is showing and it's child contents are visible.
17 + ->click($bookToVisit->name)
18 + ->seePageIs($bookToVisit->getUrl())
19 + ->see($bookToVisit->name)
20 + ->see($bookToVisit->chapters()->first()->name);
21 + }
22 +
23 + public function testChaptersViewable()
24 + {
25 + $this->setSettings(['app-public' => 'true']);
26 + $chapterToVisit = \BookStack\Chapter::first();
27 + $pageToVisit = $chapterToVisit->pages()->first();
28 +
29 + // Check chapters index page is showing
30 + $this->visit($chapterToVisit->getUrl())
31 + ->seeStatusCode(200)
32 + ->see($chapterToVisit->name)
33 + // Check indavidual chapter page is showing and it's child contents are visible.
34 + ->see($pageToVisit->name)
35 + ->click($pageToVisit->name)
36 + ->see($chapterToVisit->book->name)
37 + ->see($chapterToVisit->name)
38 + ->seePageIs($pageToVisit->getUrl());
39 + }
40 +
41 +}
...\ No newline at end of file ...\ No newline at end of file