Toggle navigation
Toggle navigation
This project
Loading...
Sign in
Зуев Егор
/
wiki.dev
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
Authored by
Dan Brown
2016-06-25 15:31:38 +0100
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
Commit
9baa96d41ce6b4f7949c5a1f4b2b9fa699d3d679
9baa96d4
1 parent
e584b492
Added chapter move actions. Closes #86
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
167 additions
and
17 deletions
app/Http/Controllers/ChapterController.php
app/Http/Controllers/PageController.php
app/Http/routes.php
app/Repos/ChapterRepo.php
resources/lang/en/activities.php
resources/views/chapters/move.blade.php
resources/views/chapters/show.blade.php
resources/views/pages/move.blade.php
resources/views/partials/entity-selector.blade.php
tests/Entity/SortTest.php
app/Http/Controllers/ChapterController.php
View file @
9baa96d
...
...
@@ -155,6 +155,55 @@ class ChapterController extends Controller
}
/**
* Show the page for moving a chapter.
* @param $bookSlug
* @param $chapterSlug
* @return mixed
* @throws \BookStack\Exceptions\NotFoundException
*/
public
function
showMove
(
$bookSlug
,
$chapterSlug
)
{
$book
=
$this
->
bookRepo
->
getBySlug
(
$bookSlug
);
$chapter
=
$this
->
chapterRepo
->
getBySlug
(
$chapterSlug
,
$book
->
id
);
$this
->
checkOwnablePermission
(
'chapter-update'
,
$chapter
);
return
view
(
'chapters/move'
,
[
'chapter'
=>
$chapter
,
'book'
=>
$book
]);
}
public
function
move
(
$bookSlug
,
$chapterSlug
,
Request
$request
)
{
$book
=
$this
->
bookRepo
->
getBySlug
(
$bookSlug
);
$chapter
=
$this
->
chapterRepo
->
getBySlug
(
$chapterSlug
,
$book
->
id
);
$this
->
checkOwnablePermission
(
'chapter-update'
,
$chapter
);
$entitySelection
=
$request
->
get
(
'entity_selection'
,
null
);
if
(
$entitySelection
===
null
||
$entitySelection
===
''
)
{
return
redirect
(
$chapter
->
getUrl
());
}
$stringExploded
=
explode
(
':'
,
$entitySelection
);
$entityType
=
$stringExploded
[
0
];
$entityId
=
intval
(
$stringExploded
[
1
]);
$parent
=
false
;
if
(
$entityType
==
'book'
)
{
$parent
=
$this
->
bookRepo
->
getById
(
$entityId
);
}
if
(
$parent
===
false
||
$parent
===
null
)
{
session
()
->
flash
(
'The selected Book was not found'
);
return
redirect
()
->
back
();
}
$this
->
chapterRepo
->
changeBook
(
$parent
->
id
,
$chapter
);
Activity
::
add
(
$chapter
,
'chapter_move'
,
$chapter
->
book
->
id
);
session
()
->
flash
(
'success'
,
sprintf
(
'Chapter moved to "%s"'
,
$parent
->
name
));
return
redirect
(
$chapter
->
getUrl
());
}
/**
* Show the Restrictions view.
* @param $bookSlug
* @param $chapterSlug
...
...
app/Http/Controllers/PageController.php
View file @
9baa96d
...
...
@@ -468,6 +468,14 @@ class PageController extends Controller
]);
}
/**
* Does the action of moving the location of a page
* @param $bookSlug
* @param $pageSlug
* @param Request $request
* @return mixed
* @throws NotFoundException
*/
public
function
move
(
$bookSlug
,
$pageSlug
,
Request
$request
)
{
$book
=
$this
->
bookRepo
->
getBySlug
(
$bookSlug
);
...
...
app/Http/routes.php
View file @
9baa96d
...
...
@@ -55,6 +55,8 @@ Route::group(['middleware' => 'auth'], function () {
Route
::
post
(
'/{bookSlug}/chapter/create'
,
'ChapterController@store'
);
Route
::
get
(
'/{bookSlug}/chapter/{chapterSlug}'
,
'ChapterController@show'
);
Route
::
put
(
'/{bookSlug}/chapter/{chapterSlug}'
,
'ChapterController@update'
);
Route
::
get
(
'/{bookSlug}/chapter/{chapterSlug}/move'
,
'ChapterController@showMove'
);
Route
::
put
(
'/{bookSlug}/chapter/{chapterSlug}/move'
,
'ChapterController@move'
);
Route
::
get
(
'/{bookSlug}/chapter/{chapterSlug}/edit'
,
'ChapterController@edit'
);
Route
::
get
(
'/{bookSlug}/chapter/{chapterSlug}/permissions'
,
'ChapterController@showRestrict'
);
Route
::
put
(
'/{bookSlug}/chapter/{chapterSlug}/permissions'
,
'ChapterController@restrict'
);
...
...
app/Repos/ChapterRepo.php
View file @
9baa96d
...
...
@@ -9,6 +9,18 @@ use BookStack\Chapter;
class
ChapterRepo
extends
EntityRepo
{
protected
$pageRepo
;
/**
* ChapterRepo constructor.
* @param $pageRepo
*/
public
function
__construct
(
PageRepo
$pageRepo
)
{
$this
->
pageRepo
=
$pageRepo
;
parent
::
__construct
();
}
/**
* Base query for getting chapters, Takes permissions into account.
* @return mixed
...
...
@@ -189,12 +201,21 @@ class ChapterRepo extends EntityRepo
public
function
changeBook
(
$bookId
,
Chapter
$chapter
)
{
$chapter
->
book_id
=
$bookId
;
// Update related activity
foreach
(
$chapter
->
activity
as
$activity
)
{
$activity
->
book_id
=
$bookId
;
$activity
->
save
();
}
$chapter
->
slug
=
$this
->
findSuitableSlug
(
$chapter
->
name
,
$bookId
,
$chapter
->
id
);
$chapter
->
save
();
// Update all child pages
foreach
(
$chapter
->
pages
as
$page
)
{
$this
->
pageRepo
->
changeBook
(
$bookId
,
$page
);
}
// Update permissions
$chapter
->
load
(
'book'
);
$this
->
permissionService
->
buildJointPermissionsForEntity
(
$chapter
->
book
);
return
$chapter
;
}
...
...
resources/lang/en/activities.php
View file @
9baa96d
...
...
@@ -4,7 +4,7 @@ return [
/**
* Activity text strings.
* Is used for all the text within activity logs.
* Is used for all the text within activity logs
& notifications
.
*/
// Pages
...
...
@@ -25,6 +25,7 @@ return [
'chapter_update_notification'
=>
'Chapter Successfully Updated'
,
'chapter_delete'
=>
'deleted chapter'
,
'chapter_delete_notification'
=>
'Chapter Successfully Deleted'
,
'chapter_move'
=>
'moved chapter'
,
// Books
'book_create'
=>
'created book'
,
...
...
resources/views/chapters/move.blade.php
0 → 100644
View file @
9baa96d
@extends('base')
@section('content')
<div
class=
"faded-small toolbar"
>
<div
class=
"container"
>
<div
class=
"row"
>
<div
class=
"col-sm-12 faded"
>
<div
class=
"breadcrumbs"
>
<a
href=
"{{$book->getUrl()}}"
class=
"text-book text-button"
><i
class=
"zmdi zmdi-book"
></i>
{{ $book->getShortName() }}
</a>
<span
class=
"sep"
>
»
</span>
<a
href=
"{{$chapter->getUrl()}}"
class=
"text-page text-button"
><i
class=
"zmdi zmdi-file-text"
></i>
{{ $chapter->getShortName() }}
</a>
</div>
</div>
</div>
</div>
</div>
<div
class=
"container"
>
<h1>
Move Chapter
<small
class=
"subheader"
>
{{$chapter->name}}
</small></h1>
<form
action=
"{{ $chapter->getUrl() }}/move"
method=
"POST"
>
{!! csrf_field() !!}
<input
type=
"hidden"
name=
"_method"
value=
"PUT"
>
@include('partials/entity-selector', ['name' => 'entity_selection', 'selectorSize' => 'large', 'entityTypes' => 'book'])
<a
href=
"{{ $chapter->getUrl() }}"
class=
"button muted"
>
Cancel
</a>
<button
type=
"submit"
class=
"button pos"
>
Move Chapter
</button>
</form>
</div>
@stop
resources/views/chapters/show.blade.php
View file @
9baa96d
...
...
@@ -2,15 +2,15 @@
@section('content')
<div
class=
"faded-small toolbar"
ng-non-bindable
>
<div
class=
"faded-small toolbar"
>
<div
class=
"container"
>
<div
class=
"row"
>
<div
class=
"col-
md-4 faded"
>
<div
class=
"col-
sm-8 faded"
ng-non-bindable
>
<div
class=
"breadcrumbs"
>
<a
href=
"{{$book->getUrl()}}"
class=
"text-book text-button"
><i
class=
"zmdi zmdi-book"
></i>
{{ $book->getShortName() }}
</a>
</div>
</div>
<div
class=
"col-
md-8
faded"
>
<div
class=
"col-
sm-4
faded"
>
<div
class=
"action-buttons"
>
@if(userCan('page-create', $chapter))
<a
href=
"{{$chapter->getUrl() . '/create-page'}}"
class=
"text-pos text-button"
><i
class=
"zmdi zmdi-plus"
></i>
New Page
</a>
...
...
@@ -18,11 +18,21 @@
@if(userCan('chapter-update', $chapter))
<a
href=
"{{$chapter->getUrl() . '/edit'}}"
class=
"text-primary text-button"
><i
class=
"zmdi zmdi-edit"
></i>
Edit
</a>
@endif
@if(userCan('restrictions-manage', $chapter))
<a
href=
"{{$chapter->getUrl()}}/permissions"
class=
"text-primary text-button"
><i
class=
"zmdi zmdi-lock-outline"
></i>
Permissions
</a>
@endif
@if(userCan('chapter-delete', $chapter))
<a
href=
"{{$chapter->getUrl() . '/delete'}}"
class=
"text-neg text-button"
><i
class=
"zmdi zmdi-delete"
></i>
Delete
</a>
@if(userCan('chapter-update', $chapter) || userCan('restrictions-manage', $chapter) || userCan('chapter-delete', $chapter))
<div
dropdown
class=
"dropdown-container"
>
<a
dropdown-toggle
class=
"text-primary text-button"
><i
class=
"zmdi zmdi-more-vert"
></i></a>
<ul>
@if(userCan('chapter-update', $chapter))
<li><a
href=
"{{$chapter->getUrl() . '/move'}}"
class=
"text-primary"
><i
class=
"zmdi zmdi-folder"
></i>
Move
</a></li>
@endif
@if(userCan('restrictions-manage', $chapter))
<li><a
href=
"{{$chapter->getUrl()}}/permissions"
class=
"text-primary"
><i
class=
"zmdi zmdi-lock-outline"
></i>
Permissions
</a></li>
@endif
@if(userCan('chapter-delete', $chapter))
<li><a
href=
"{{$chapter->getUrl() . '/delete'}}"
class=
"text-neg"
><i
class=
"zmdi zmdi-delete"
></i>
Delete
</a></li>
@endif
</ul>
</div>
@endif
</div>
</div>
...
...
resources/views/pages/move.blade.php
View file @
9baa96d
...
...
@@ -30,14 +30,7 @@
{!! csrf_field() !!}
<input
type=
"hidden"
name=
"_method"
value=
"PUT"
>
<div
class=
"form-group"
>
<div
entity-selector
class=
"entity-selector large"
entity-types=
"book,chapter"
>
<input
type=
"hidden"
entity-selector-input
name=
"entity_selection"
value=
""
>
<input
type=
"text"
placeholder=
"Search"
ng-model=
"search"
ng-model-options=
"{debounce: 200}"
ng-change=
"searchEntities()"
>
<div
class=
"text-center loading"
ng-show=
"loading"
>
@include('partials/loading-icon')
</div>
<div
ng-show=
"!loading"
ng-bind-html=
"entityResults"
></div>
</div>
</div>
@include('partials/entity-selector', ['name' => 'entity_selection', 'selectorSize' => 'large', 'entityTypes' => 'book,chapter'])
<a
href=
"{{ $page->getUrl() }}"
class=
"button muted"
>
Cancel
</a>
<button
type=
"submit"
class=
"button pos"
>
Move Page
</button>
...
...
resources/views/partials/entity-selector.blade.php
0 → 100644
View file @
9baa96d
<div
class=
"form-group"
>
<div
entity-selector
class=
"entity-selector {{$selectorSize or ''}}"
entity-types=
"{{ $entityTypes or 'book,chapter,page' }}"
>
<input
type=
"hidden"
entity-selector-input
name=
"{{$name}}"
value=
""
>
<input
type=
"text"
placeholder=
"Search"
ng-model=
"search"
ng-model-options=
"{debounce: 200}"
ng-change=
"searchEntities()"
>
<div
class=
"text-center loading"
ng-show=
"loading"
>
@include('partials/loading-icon')
</div>
<div
ng-show=
"!loading"
ng-bind-html=
"entityResults"
></div>
</div>
</div>
\ No newline at end of file
tests/Entity/SortTest.php
View file @
9baa96d
...
...
@@ -40,4 +40,29 @@ class SortTest extends TestCase
->
seeInNthElement
(
'.activity-list-item'
,
0
,
$page
->
name
);
}
public
function
test_chapter_move
()
{
$chapter
=
\BookStack\Chapter
::
first
();
$currentBook
=
$chapter
->
book
;
$pageToCheck
=
$chapter
->
pages
->
first
();
$newBook
=
\BookStack\Book
::
where
(
'id'
,
'!='
,
$currentBook
->
id
)
->
first
();
$this
->
asAdmin
()
->
visit
(
$chapter
->
getUrl
()
.
'/move'
)
->
see
(
'Move Chapter'
)
->
see
(
$chapter
->
name
)
->
type
(
'book:'
.
$newBook
->
id
,
'entity_selection'
)
->
press
(
'Move Chapter'
);
$chapter
=
\BookStack\Chapter
::
find
(
$chapter
->
id
);
$this
->
seePageIs
(
$chapter
->
getUrl
());
$this
->
assertTrue
(
$chapter
->
book
->
id
===
$newBook
->
id
,
'Chapter Book is now the new book'
);
$this
->
visit
(
$newBook
->
getUrl
())
->
seeInNthElement
(
'.activity-list-item'
,
0
,
'moved chapter'
)
->
seeInNthElement
(
'.activity-list-item'
,
0
,
$chapter
->
name
);
$pageToCheck
=
\BookStack\Page
::
find
(
$pageToCheck
->
id
);
$this
->
assertTrue
(
$pageToCheck
->
book_id
===
$newBook
->
id
,
'Chapter child page\'s book id has changed to the new book'
);
$this
->
visit
(
$pageToCheck
->
getUrl
())
->
see
(
$newBook
->
name
);
}
}
\ No newline at end of file
...
...
Please
register
or
sign in
to post a comment