Dan Brown

Added page editing

...@@ -3,4 +3,5 @@ ...@@ -3,4 +3,5 @@
3 Homestead.yaml 3 Homestead.yaml
4 .env 4 .env
5 /public/dist 5 /public/dist
6 -.idea
...\ No newline at end of file ...\ No newline at end of file
6 +.idea
7 +/public/plugins
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -19,4 +19,9 @@ class Book extends Model ...@@ -19,4 +19,9 @@ class Book extends Model
19 return $this->getUrl() . '/edit'; 19 return $this->getUrl() . '/edit';
20 } 20 }
21 21
22 + public function pages()
23 + {
24 + return $this->hasMany('Oxbow\Page');
25 + }
26 +
22 } 27 }
......
...@@ -7,19 +7,23 @@ use Illuminate\Http\Request; ...@@ -7,19 +7,23 @@ use Illuminate\Http\Request;
7 use Illuminate\Support\Str; 7 use Illuminate\Support\Str;
8 use Oxbow\Http\Requests; 8 use Oxbow\Http\Requests;
9 use Oxbow\Repos\BookRepo; 9 use Oxbow\Repos\BookRepo;
10 +use Oxbow\Repos\PageRepo;
10 11
11 class BookController extends Controller 12 class BookController extends Controller
12 { 13 {
13 14
14 protected $bookRepo; 15 protected $bookRepo;
16 + protected $pageRepo;
15 17
16 /** 18 /**
17 * BookController constructor. 19 * BookController constructor.
18 * @param BookRepo $bookRepo 20 * @param BookRepo $bookRepo
21 + * @param PageRepo $pageRepo
19 */ 22 */
20 - public function __construct(BookRepo $bookRepo) 23 + public function __construct(BookRepo $bookRepo, PageRepo $pageRepo)
21 { 24 {
22 $this->bookRepo = $bookRepo; 25 $this->bookRepo = $bookRepo;
26 + $this->pageRepo = $pageRepo;
23 } 27 }
24 28
25 /** 29 /**
...@@ -58,7 +62,7 @@ class BookController extends Controller ...@@ -58,7 +62,7 @@ class BookController extends Controller
58 $book = $this->bookRepo->newFromInput($request->all()); 62 $book = $this->bookRepo->newFromInput($request->all());
59 $slug = Str::slug($book->name); 63 $slug = Str::slug($book->name);
60 while($this->bookRepo->countBySlug($slug) > 0) { 64 while($this->bookRepo->countBySlug($slug) > 0) {
61 - $slug += '1'; 65 + $slug .= '1';
62 } 66 }
63 $book->slug = $slug; 67 $book->slug = $slug;
64 $book->save(); 68 $book->save();
......
...@@ -4,11 +4,29 @@ namespace Oxbow\Http\Controllers; ...@@ -4,11 +4,29 @@ namespace Oxbow\Http\Controllers;
4 4
5 use Illuminate\Http\Request; 5 use Illuminate\Http\Request;
6 6
7 +use Illuminate\Support\Str;
7 use Oxbow\Http\Requests; 8 use Oxbow\Http\Requests;
8 -use Oxbow\Http\Controllers\Controller; 9 +use Oxbow\Repos\BookRepo;
10 +use Oxbow\Repos\PageRepo;
9 11
10 class PageController extends Controller 12 class PageController extends Controller
11 { 13 {
14 +
15 + protected $pageRepo;
16 + protected $bookRepo;
17 +
18 + /**
19 + * PageController constructor.
20 + * @param $pageRepo
21 + * @param $bookRepo
22 + */
23 + public function __construct(PageRepo $pageRepo, BookRepo $bookRepo)
24 + {
25 + $this->pageRepo = $pageRepo;
26 + $this->bookRepo = $bookRepo;
27 + }
28 +
29 +
12 /** 30 /**
13 * Display a listing of the resource. 31 * Display a listing of the resource.
14 * 32 *
...@@ -22,56 +40,88 @@ class PageController extends Controller ...@@ -22,56 +40,88 @@ class PageController extends Controller
22 /** 40 /**
23 * Show the form for creating a new resource. 41 * Show the form for creating a new resource.
24 * 42 *
43 + * @param $bookSlug
25 * @return Response 44 * @return Response
26 */ 45 */
27 - public function create() 46 + public function create($bookSlug)
28 { 47 {
29 - // 48 + $book = $this->bookRepo->getBySlug($bookSlug);
49 + return view('pages/create', ['book' => $book]);
30 } 50 }
31 51
32 /** 52 /**
33 * Store a newly created resource in storage. 53 * Store a newly created resource in storage.
34 * 54 *
35 - * @param Request $request 55 + * @param Request $request
56 + * @param $bookSlug
36 * @return Response 57 * @return Response
37 */ 58 */
38 - public function store(Request $request) 59 + public function store(Request $request, $bookSlug)
39 { 60 {
40 - // 61 + $this->validate($request, [
62 + 'name' => 'required|string|max:255',
63 + 'html' => 'required|string',
64 + 'priority' => 'integer'
65 + ]);
66 + $book = $this->bookRepo->getBySlug($bookSlug);
67 + $page = $this->pageRepo->newFromInput($request->all());
68 + $slug = Str::slug($page->name);
69 + while($this->pageRepo->countBySlug($slug, $book->id) > 0) {
70 + $slug .= '1';
71 + }
72 + $page->slug =$slug;
73 + $page->book_id = $book->id;
74 + $page->text = strip_tags($page->html);
75 + $page->save();
76 + return redirect($page->getUrl());
41 } 77 }
42 78
43 /** 79 /**
44 * Display the specified resource. 80 * Display the specified resource.
45 * 81 *
46 - * @param int $id 82 + * @param $bookSlug
83 + * @param $pageSlug
47 * @return Response 84 * @return Response
48 */ 85 */
49 - public function show($id) 86 + public function show($bookSlug, $pageSlug)
50 { 87 {
51 - // 88 + $page = $this->pageRepo->getBySlug($pageSlug);
89 + return view('pages/show', ['page' => $page]);
52 } 90 }
53 91
54 /** 92 /**
55 * Show the form for editing the specified resource. 93 * Show the form for editing the specified resource.
56 * 94 *
57 - * @param int $id 95 + * @param $bookSlug
96 + * @param $pageSlug
58 * @return Response 97 * @return Response
59 */ 98 */
60 - public function edit($id) 99 + public function edit($bookSlug, $pageSlug)
61 { 100 {
62 - // 101 + $page = $this->pageRepo->getBySlug($pageSlug);
102 + return view('pages/edit', ['page' => $page]);
63 } 103 }
64 104
65 /** 105 /**
66 * Update the specified resource in storage. 106 * Update the specified resource in storage.
67 * 107 *
68 - * @param Request $request 108 + * @param Request $request
69 - * @param int $id 109 + * @param $bookSlug
110 + * @param $pageSlug
70 * @return Response 111 * @return Response
71 */ 112 */
72 - public function update(Request $request, $id) 113 + public function update(Request $request, $bookSlug, $pageSlug)
73 { 114 {
74 - // 115 + $page = $this->pageRepo->getBySlug($pageSlug);
116 + $book = $this->bookRepo->getBySlug($bookSlug);
117 + $page->fill($request->all());
118 + $slug = Str::slug($page->name);
119 + while($this->pageRepo->countBySlug($slug, $book->id) > 0 && $slug != $pageSlug) {
120 + $slug .= '1';
121 + }
122 + $page->text = strip_tags($page->html);
123 + $page->save();
124 + return redirect($page->getUrl());
75 } 125 }
76 126
77 /** 127 /**
......
...@@ -21,6 +21,12 @@ Route::group(['prefix' => 'books'], function() { ...@@ -21,6 +21,12 @@ Route::group(['prefix' => 'books'], function() {
21 Route::put('/{slug}', 'BookController@update'); 21 Route::put('/{slug}', 'BookController@update');
22 Route::delete('/{id}/destroy', 'BookController@destroy'); 22 Route::delete('/{id}/destroy', 'BookController@destroy');
23 Route::get('/{slug}', 'BookController@show'); 23 Route::get('/{slug}', 'BookController@show');
24 +
25 + Route::get('/{bookSlug}/page/create', 'PageController@create');
26 + Route::post('/{bookSlug}/page', 'PageController@store');
27 + Route::get('/{bookSlug}/{pageSlug}', 'PageController@show');
28 + Route::get('/{bookSlug}/{pageSlug}/edit', 'PageController@edit');
29 + Route::put('/{bookSlug}/{pageSlug}', 'PageController@update');
24 }); 30 });
25 31
26 Route::get('/', function () { 32 Route::get('/', function () {
......
...@@ -6,5 +6,15 @@ use Illuminate\Database\Eloquent\Model; ...@@ -6,5 +6,15 @@ use Illuminate\Database\Eloquent\Model;
6 6
7 class Page extends Model 7 class Page extends Model
8 { 8 {
9 - // 9 + protected $fillable = ['name', 'html', 'priority'];
10 +
11 + public function book()
12 + {
13 + return $this->belongsTo('Oxbow\Book');
14 + }
15 +
16 + public function getUrl()
17 + {
18 + return '/books/' . $this->book->slug . '/' . $this->slug;
19 + }
10 } 20 }
......
...@@ -6,14 +6,17 @@ class BookRepo ...@@ -6,14 +6,17 @@ class BookRepo
6 { 6 {
7 7
8 protected $book; 8 protected $book;
9 + protected $pageRepo;
9 10
10 /** 11 /**
11 * BookRepo constructor. 12 * BookRepo constructor.
12 - * @param $book 13 + * @param Book $book
14 + * @param PageRepo $pageRepo
13 */ 15 */
14 - public function __construct(Book $book) 16 + public function __construct(Book $book, PageRepo $pageRepo)
15 { 17 {
16 $this->book = $book; 18 $this->book = $book;
19 + $this->pageRepo = $pageRepo;
17 } 20 }
18 21
19 public function getById($id) 22 public function getById($id)
...@@ -44,6 +47,9 @@ class BookRepo ...@@ -44,6 +47,9 @@ class BookRepo
44 public function destroyById($id) 47 public function destroyById($id)
45 { 48 {
46 $book = $this->getById($id); 49 $book = $this->getById($id);
50 + foreach($book->pages as $page) {
51 + $this->pageRepo->destroyById($page->id);
52 + }
47 $book->delete(); 53 $book->delete();
48 } 54 }
49 55
......
1 +<?php namespace Oxbow\Repos;
2 +
3 +
4 +use Illuminate\Support\Str;
5 +use Oxbow\Page;
6 +
7 +class PageRepo
8 +{
9 + protected $page;
10 +
11 + /**
12 + * PageRepo constructor.
13 + * @param $page
14 + */
15 + public function __construct(Page $page)
16 + {
17 + $this->page = $page;
18 + }
19 +
20 + public function getById($id)
21 + {
22 + return $this->page->findOrFail($id);
23 + }
24 +
25 + public function getAll()
26 + {
27 + return $this->page->all();
28 + }
29 +
30 + public function getBySlug($slug)
31 + {
32 + return $this->page->where('slug', '=', $slug)->first();
33 + }
34 +
35 + public function newFromInput($input)
36 + {
37 + $page = $this->page->fill($input);
38 + return $page;
39 + }
40 +
41 + public function countBySlug($slug, $bookId)
42 + {
43 + return $this->page->where('slug', '=', $slug)->where('book_id', '=', $bookId)->count();
44 + }
45 +
46 + public function destroyById($id)
47 + {
48 + $page = $this->getById($id);
49 + $page->delete();
50 + }
51 +
52 +}
...\ No newline at end of file ...\ No newline at end of file
...@@ -14,6 +14,13 @@ class CreatePagesTable extends Migration ...@@ -14,6 +14,13 @@ class CreatePagesTable extends Migration
14 { 14 {
15 Schema::create('pages', function (Blueprint $table) { 15 Schema::create('pages', function (Blueprint $table) {
16 $table->increments('id'); 16 $table->increments('id');
17 + $table->integer('book_id');
18 + $table->integer('page_id');
19 + $table->string('name');
20 + $table->string('slug')->indexed();
21 + $table->longText('html');
22 + $table->longText('text');
23 + $table->integer('priority');
17 $table->timestamps(); 24 $table->timestamps();
18 }); 25 });
19 } 26 }
......
...@@ -941,4 +941,9 @@ header .menu { ...@@ -941,4 +941,9 @@ header .menu {
941 display: inline-block; 941 display: inline-block;
942 margin-left: 16px; } 942 margin-left: 16px; }
943 943
944 +.page-title input {
945 + display: block;
946 + width: 100%;
947 + font-size: 1.4em; }
948 +
944 /*# sourceMappingURL=app.css.map */ 949 /*# sourceMappingURL=app.css.map */
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -19,4 +19,10 @@ header .menu { ...@@ -19,4 +19,10 @@ header .menu {
19 display: inline-block; 19 display: inline-block;
20 margin-left: $-m; 20 margin-left: $-m;
21 } 21 }
22 +}
23 +
24 +.page-title input {
25 + display: block;
26 + width: 100%;
27 + font-size: 1.4em;
22 } 28 }
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -5,7 +5,9 @@ ...@@ -5,7 +5,9 @@
5 <meta name="viewport" content="width=device-width"> 5 <meta name="viewport" content="width=device-width">
6 <link rel="stylesheet" href="/css/app.css"> 6 <link rel="stylesheet" href="/css/app.css">
7 <link href='http://fonts.googleapis.com/css?family=Roboto:400,400italic,500,500italic,700,700italic,300italic,100,300' rel='stylesheet' type='text/css'> 7 <link href='http://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="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
8 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> 9 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
10 + @yield('head')
9 </head> 11 </head>
10 <body> 12 <body>
11 13
......
...@@ -4,4 +4,14 @@ ...@@ -4,4 +4,14 @@
4 4
5 <h2>{{$book->name}}</h2> 5 <h2>{{$book->name}}</h2>
6 <p class="text-muted">{{$book->description}}</p> 6 <p class="text-muted">{{$book->description}}</p>
7 + <a href="{{$book->getUrl() . '/page/create'}}">+ New Page</a>
8 +
9 + <h4>Pages:</h4>
10 + @if(count($book->pages) > 0)
11 + @foreach($book->pages as $page)
12 + <a href="{{$page->getUrl()}}">{{$page->name}}</a><br>
13 + @endforeach
14 + @else
15 + <p class="text-muted">This book has no pages</p>
16 + @endif
7 @stop 17 @stop
...\ No newline at end of file ...\ No newline at end of file
......
1 <input type="text" id="{{ $name }}" name="{{ $name }}" 1 <input type="text" id="{{ $name }}" name="{{ $name }}"
2 @if($errors->has($name)) class="neg" @endif 2 @if($errors->has($name)) class="neg" @endif
3 + @if(isset($placeholder)) placeholder="{{$placeholder}}" @endif
3 @if(isset($model) || old($name)) value="{{ old($name) ? old($name) : $model->$name}}" @endif> 4 @if(isset($model) || old($name)) value="{{ old($name) ? old($name) : $model->$name}}" @endif>
4 @if($errors->has($name)) 5 @if($errors->has($name))
5 <div class="text-neg text-small">{{ $errors->first($name) }}</div> 6 <div class="text-neg text-small">{{ $errors->first($name) }}</div>
......
1 +@extends('base')
2 +
3 +@section('head')
4 + <link rel="stylesheet" href="/plugins/css/froala_editor.min.css">
5 + <link rel="stylesheet" href="/plugins/css/froala_style.min.css">
6 + <script src="/plugins/js/froala_editor.min.js"></script>
7 +@stop
8 +
9 +@section('content')
10 + <form action="{{$book->getUrl() . '/page'}}" method="POST">
11 + @include('pages/form')
12 + </form>
13 +
14 + <script>
15 + $(function() {
16 + $('#html').editable({inlineMode: false});
17 + });
18 + </script>
19 +@stop
...\ No newline at end of file ...\ No newline at end of file
1 +@extends('base')
2 +
3 +@section('head')
4 + <link rel="stylesheet" href="/plugins/css/froala_editor.min.css">
5 + <link rel="stylesheet" href="/plugins/css/froala_style.min.css">
6 + <script src="/plugins/js/froala_editor.min.js"></script>
7 +@stop
8 +
9 +@section('content')
10 + <form action="{{$page->getUrl()}}" method="POST">
11 + <input type="hidden" name="_method" value="PUT">
12 + @include('pages/form', ['model' => $page])
13 + </form>
14 +
15 + <script>
16 + $(function() {
17 + $('#html').editable({inlineMode: false});
18 + });
19 + </script>
20 +@stop
...\ No newline at end of file ...\ No newline at end of file
1 +{{ csrf_field() }}
2 +<div class="page-title row">
3 + <div class="col-md-10">
4 + @include('form/text', ['name' => 'name', 'placeholder' => 'Enter Page Title'])
5 + </div>
6 + <div class="col-md-2">
7 + <button type="submit" class="button pos">Save</button>
8 + </div>
9 +</div>
10 +<div class="edit-area">
11 + @include('form/textarea', ['name' => 'html'])
12 +</div>
13 +
1 +@extends('base')
2 +
3 +@section('content')
4 +
5 + <a href="{{$page->getUrl() . '/edit'}}" class="button primary float right">Edit Page</a>
6 +
7 + <h1>{{$page->name}}</h1>
8 +
9 + <div class="page-content">
10 + {!! $page->html !!}
11 + </div>
12 +@stop