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-12 12:48:19 +0100
Browse Files
Options
Browse Files
Tag
Download
Plain Diff
Commit
991dd8a558456b5aa669a60fd06a35270697a2ab
991dd8a5
2 parents
61596a8e
bc497847
Merged branch add_page_move into master
References #86
Show whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
364 additions
and
20 deletions
app/Http/Controllers/PageController.php
app/Http/Controllers/SearchController.php
app/Http/routes.php
app/Repos/PageRepo.php
app/Services/ViewService.php
resources/assets/js/directives.js
resources/assets/sass/_forms.scss
resources/assets/sass/_text.scss
resources/assets/sass/styles.scss
resources/lang/en/activities.php
resources/views/books/list-item.blade.php
resources/views/chapters/list-item.blade.php
resources/views/pages/list-item.blade.php
resources/views/pages/move.blade.php
resources/views/pages/show.blade.php
resources/views/partials/custom-styles.blade.php
tests/Entity/EntitySearchTest.php
tests/Entity/SortTest.php
app/Http/Controllers/PageController.php
View file @
991dd8a
...
...
@@ -451,6 +451,59 @@ class PageController extends Controller
}
/**
* Show the view to choose a new parent to move a page into.
* @param $bookSlug
* @param $pageSlug
* @return mixed
* @throws NotFoundException
*/
public
function
showMove
(
$bookSlug
,
$pageSlug
)
{
$book
=
$this
->
bookRepo
->
getBySlug
(
$bookSlug
);
$page
=
$this
->
pageRepo
->
getBySlug
(
$pageSlug
,
$book
->
id
);
$this
->
checkOwnablePermission
(
'page-update'
,
$page
);
return
view
(
'pages/move'
,
[
'book'
=>
$book
,
'page'
=>
$page
]);
}
public
function
move
(
$bookSlug
,
$pageSlug
,
Request
$request
)
{
$book
=
$this
->
bookRepo
->
getBySlug
(
$bookSlug
);
$page
=
$this
->
pageRepo
->
getBySlug
(
$pageSlug
,
$book
->
id
);
$this
->
checkOwnablePermission
(
'page-update'
,
$page
);
$entitySelection
=
$request
->
get
(
'entity_selection'
,
null
);
if
(
$entitySelection
===
null
||
$entitySelection
===
''
)
{
return
redirect
(
$page
->
getUrl
());
}
$stringExploded
=
explode
(
':'
,
$entitySelection
);
$entityType
=
$stringExploded
[
0
];
$entityId
=
intval
(
$stringExploded
[
1
]);
$parent
=
false
;
if
(
$entityType
==
'chapter'
)
{
$parent
=
$this
->
chapterRepo
->
getById
(
$entityId
);
}
else
if
(
$entityType
==
'book'
)
{
$parent
=
$this
->
bookRepo
->
getById
(
$entityId
);
}
if
(
$parent
===
false
||
$parent
===
null
)
{
session
()
->
flash
(
'The selected Book or Chapter was not found'
);
return
redirect
()
->
back
();
}
$this
->
pageRepo
->
changePageParent
(
$page
,
$parent
);
Activity
::
add
(
$page
,
'page_move'
,
$page
->
book
->
id
);
session
()
->
flash
(
'success'
,
sprintf
(
'Page moved to "%s"'
,
$parent
->
name
));
return
redirect
(
$page
->
getUrl
());
}
/**
* Set the permissions for this page.
* @param $bookSlug
* @param $pageSlug
...
...
app/Http/Controllers/SearchController.php
View file @
991dd8a
...
...
@@ -2,10 +2,10 @@
namespace
BookStack\Http\Controllers
;
use
BookStack\Services\ViewService
;
use
Illuminate\Http\Request
;
use
BookStack\Http\Requests
;
use
BookStack\Http\Controllers\Controller
;
use
BookStack\Repos\BookRepo
;
use
BookStack\Repos\ChapterRepo
;
use
BookStack\Repos\PageRepo
;
...
...
@@ -15,18 +15,21 @@ class SearchController extends Controller
protected
$pageRepo
;
protected
$bookRepo
;
protected
$chapterRepo
;
protected
$viewService
;
/**
* SearchController constructor.
* @param $pageRepo
* @param $bookRepo
* @param $chapterRepo
* @param PageRepo $pageRepo
* @param BookRepo $bookRepo
* @param ChapterRepo $chapterRepo
* @param ViewService $viewService
*/
public
function
__construct
(
PageRepo
$pageRepo
,
BookRepo
$bookRepo
,
ChapterRepo
$chapterRepo
)
public
function
__construct
(
PageRepo
$pageRepo
,
BookRepo
$bookRepo
,
ChapterRepo
$chapterRepo
,
ViewService
$viewService
)
{
$this
->
pageRepo
=
$pageRepo
;
$this
->
bookRepo
=
$bookRepo
;
$this
->
chapterRepo
=
$chapterRepo
;
$this
->
viewService
=
$viewService
;
parent
::
__construct
();
}
...
...
@@ -134,4 +137,35 @@ class SearchController extends Controller
return
view
(
'search/book'
,
[
'pages'
=>
$pages
,
'chapters'
=>
$chapters
,
'searchTerm'
=>
$searchTerm
]);
}
/**
* Search for a list of entities and return a partial HTML response of matching entities.
* Returns the most popular entities if no search is provided.
* @param Request $request
* @return mixed
*/
public
function
searchEntitiesAjax
(
Request
$request
)
{
$entities
=
collect
();
$entityTypes
=
$request
->
has
(
'types'
)
?
collect
(
explode
(
','
,
$request
->
get
(
'types'
)))
:
collect
([
'page'
,
'chapter'
,
'book'
]);
$searchTerm
=
(
$request
->
has
(
'term'
)
&&
trim
(
$request
->
get
(
'term'
))
!==
''
)
?
$request
->
get
(
'term'
)
:
false
;
// Search for entities otherwise show most popular
if
(
$searchTerm
!==
false
)
{
if
(
$entityTypes
->
contains
(
'page'
))
$entities
=
$entities
->
merge
(
$this
->
pageRepo
->
getBySearch
(
$searchTerm
)
->
items
());
if
(
$entityTypes
->
contains
(
'chapter'
))
$entities
=
$entities
->
merge
(
$this
->
chapterRepo
->
getBySearch
(
$searchTerm
)
->
items
());
if
(
$entityTypes
->
contains
(
'book'
))
$entities
=
$entities
->
merge
(
$this
->
bookRepo
->
getBySearch
(
$searchTerm
)
->
items
());
$entities
=
$entities
->
sortByDesc
(
'title_relevance'
);
}
else
{
$entityNames
=
$entityTypes
->
map
(
function
(
$type
)
{
return
'BookStack\\'
.
ucfirst
(
$type
);
})
->
toArray
();
$entities
=
$this
->
viewService
->
getPopular
(
20
,
0
,
$entityNames
);
}
return
view
(
'partials/entity-list'
,
[
'entities'
=>
$entities
]);
}
}
...
...
app/Http/routes.php
View file @
991dd8a
...
...
@@ -34,6 +34,8 @@ Route::group(['middleware' => 'auth'], function () {
Route
::
get
(
'/{bookSlug}/page/{pageSlug}/export/html'
,
'PageController@exportHtml'
);
Route
::
get
(
'/{bookSlug}/page/{pageSlug}/export/plaintext'
,
'PageController@exportPlainText'
);
Route
::
get
(
'/{bookSlug}/page/{pageSlug}/edit'
,
'PageController@edit'
);
Route
::
get
(
'/{bookSlug}/page/{pageSlug}/move'
,
'PageController@showMove'
);
Route
::
put
(
'/{bookSlug}/page/{pageSlug}/move'
,
'PageController@move'
);
Route
::
get
(
'/{bookSlug}/page/{pageSlug}/delete'
,
'PageController@showDelete'
);
Route
::
get
(
'/{bookSlug}/draft/{pageId}/delete'
,
'PageController@showDeleteDraft'
);
Route
::
get
(
'/{bookSlug}/page/{pageSlug}/permissions'
,
'PageController@showRestrict'
);
...
...
@@ -93,6 +95,8 @@ Route::group(['middleware' => 'auth'], function () {
Route
::
post
(
'/update/{entityType}/{entityId}'
,
'TagController@updateForEntity'
);
});
Route
::
get
(
'/ajax/search/entities'
,
'SearchController@searchEntitiesAjax'
);
// Links
Route
::
get
(
'/link/{id}'
,
'PageController@redirectFromLink'
);
...
...
app/Repos/PageRepo.php
View file @
991dd8a
...
...
@@ -3,6 +3,7 @@
use
Activity
;
use
BookStack\Book
;
use
BookStack\Chapter
;
use
BookStack\Entity
;
use
BookStack\Exceptions\NotFoundException
;
use
Carbon\Carbon
;
use
DOMDocument
;
...
...
@@ -572,6 +573,22 @@ class PageRepo extends EntityRepo
return
$page
;
}
/**
* Change the page's parent to the given entity.
* @param Page $page
* @param Entity $parent
*/
public
function
changePageParent
(
Page
$page
,
Entity
$parent
)
{
$book
=
$parent
->
isA
(
'book'
)
?
$parent
:
$parent
->
book
;
$page
->
chapter_id
=
$parent
->
isA
(
'chapter'
)
?
$parent
->
id
:
0
;
$page
->
save
();
$page
=
$this
->
changeBook
(
$book
->
id
,
$page
);
$page
->
load
(
'book'
);
$this
->
permissionService
->
buildJointPermissionsForEntity
(
$book
);
}
/**
* Gets a suitable slug for the resource
* @param $name
...
...
app/Services/ViewService.php
View file @
991dd8a
...
...
@@ -50,7 +50,7 @@ class ViewService
* Get the entities with the most views.
* @param int $count
* @param int $page
* @param bool|false $filterModel
* @param bool|false
|array
$filterModel
*/
public
function
getPopular
(
$count
=
10
,
$page
=
0
,
$filterModel
=
false
)
{
...
...
@@ -60,7 +60,11 @@ class ViewService
->
groupBy
(
'viewable_id'
,
'viewable_type'
)
->
orderBy
(
'view_count'
,
'desc'
);
if
(
$filterModel
)
$query
->
where
(
'viewable_type'
,
'='
,
get_class
(
$filterModel
));
if
(
$filterModel
&&
is_array
(
$filterModel
))
{
$query
->
whereIn
(
'viewable_type'
,
$filterModel
);
}
else
if
(
$filterModel
)
{
$query
->
where
(
'viewable_type'
,
'='
,
get_class
(
$filterModel
));
};
return
$query
->
with
(
'viewable'
)
->
skip
(
$skipCount
)
->
take
(
$count
)
->
get
()
->
pluck
(
'viewable'
);
}
...
...
resources/assets/js/directives.js
View file @
991dd8a
...
...
@@ -149,7 +149,10 @@ module.exports = function (ngApp, events) {
};
}]);
/**
* Dropdown
* Provides some simple logic to create small dropdown menus
*/
ngApp
.
directive
(
'dropdown'
,
[
function
()
{
return
{
restrict
:
'A'
,
...
...
@@ -166,6 +169,10 @@ module.exports = function (ngApp, events) {
};
}]);
/**
* TinyMCE
* An angular wrapper around the tinyMCE editor.
*/
ngApp
.
directive
(
'tinymce'
,
[
'$timeout'
,
function
(
$timeout
)
{
return
{
restrict
:
'A'
,
...
...
@@ -231,6 +238,10 @@ module.exports = function (ngApp, events) {
}
}]);
/**
* Markdown input
* Handles the logic for just the editor input field.
*/
ngApp
.
directive
(
'markdownInput'
,
[
'$timeout'
,
function
(
$timeout
)
{
return
{
restrict
:
'A'
,
...
...
@@ -263,6 +274,10 @@ module.exports = function (ngApp, events) {
}
}]);
/**
* Markdown Editor
* Handles all functionality of the markdown editor.
*/
ngApp
.
directive
(
'markdownEditor'
,
[
'$timeout'
,
function
(
$timeout
)
{
return
{
restrict
:
'A'
,
...
...
@@ -342,6 +357,11 @@ module.exports = function (ngApp, events) {
}
}]);
/**
* Page Editor Toolbox
* Controls all functionality for the sliding toolbox
* on the page edit view.
*/
ngApp
.
directive
(
'toolbox'
,
[
function
()
{
return
{
restrict
:
'A'
,
...
...
@@ -378,6 +398,11 @@ module.exports = function (ngApp, events) {
}
}]);
/**
* Tag Autosuggestions
* Listens to child inputs and provides autosuggestions depending on field type
* and input. Suggestions provided by server.
*/
ngApp
.
directive
(
'tagAutosuggestions'
,
[
'$http'
,
function
(
$http
)
{
return
{
restrict
:
'A'
,
...
...
@@ -557,6 +582,67 @@ module.exports = function (ngApp, events) {
}
}
}]);
ngApp
.
directive
(
'entitySelector'
,
[
'$http'
,
'$sce'
,
function
(
$http
,
$sce
)
{
return
{
restrict
:
'A'
,
scope
:
true
,
link
:
function
(
scope
,
element
,
attrs
)
{
scope
.
loading
=
true
;
scope
.
entityResults
=
false
;
scope
.
search
=
''
;
// Add input for forms
const
input
=
element
.
find
(
'[entity-selector-input]'
).
first
();
// Listen to entity item clicks
element
.
on
(
'click'
,
'.entity-list a'
,
function
(
event
)
{
event
.
preventDefault
();
event
.
stopPropagation
();
let
item
=
$
(
this
).
closest
(
'[data-entity-type]'
);
itemSelect
(
item
);
});
element
.
on
(
'click'
,
'[data-entity-type]'
,
function
(
event
)
{
itemSelect
(
$
(
this
));
});
// Select entity action
function
itemSelect
(
item
)
{
let
entityType
=
item
.
attr
(
'data-entity-type'
);
let
entityId
=
item
.
attr
(
'data-entity-id'
);
let
isSelected
=
!
item
.
hasClass
(
'selected'
);
element
.
find
(
'.selected'
).
removeClass
(
'selected'
).
removeClass
(
'primary-background'
);
if
(
isSelected
)
item
.
addClass
(
'selected'
).
addClass
(
'primary-background'
);
let
newVal
=
isSelected
?
`
${
entityType
}
:
${
entityId
}
`
:
''
;
input
.
val
(
newVal
);
}
// Get search url with correct types
function
getSearchUrl
()
{
let
types
=
(
attrs
.
entityTypes
)
?
encodeURIComponent
(
attrs
.
entityTypes
)
:
encodeURIComponent
(
'page,book,chapter'
);
return
`/ajax/search/entities?types=
${
types
}
`
;
}
// Get initial contents
$http
.
get
(
getSearchUrl
()).
then
(
resp
=>
{
scope
.
entityResults
=
$sce
.
trustAsHtml
(
resp
.
data
);
scope
.
loading
=
false
;
});
// Search when typing
scope
.
searchEntities
=
function
()
{
scope
.
loading
=
true
;
input
.
val
(
''
);
let
url
=
getSearchUrl
()
+
'&term='
+
encodeURIComponent
(
scope
.
search
);
$http
.
get
(
url
).
then
(
resp
=>
{
scope
.
entityResults
=
$sce
.
trustAsHtml
(
resp
.
data
);
scope
.
loading
=
false
;
});
};
}
};
}]);
};
...
...
resources/assets/sass/_forms.scss
View file @
991dd8a
...
...
@@ -20,6 +20,9 @@
&
.disabled
,
&
[
disabled
]
{
background
:
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAMUlEQVQIW2NkwAGuXbv2nxGbHEhCS0uLEUMSJgHShCKJLIEiiS4Bl8QmAZbEJQGSBAC62BuJ+tt7zgAAAABJRU5ErkJggg==)
;
}
&
:focus
{
outline
:
0
;
}
}
#html-editor
{
...
...
resources/assets/sass/_text.scss
View file @
991dd8a
...
...
@@ -3,7 +3,7 @@
*/
h1
{
font-size
:
3
.
6
25em
;
font-size
:
3
.
4
25em
;
line-height
:
1
.22222222em
;
margin-top
:
0
.48888889em
;
margin-bottom
:
0
.48888889em
;
...
...
@@ -33,10 +33,10 @@ h1, h2, h3, h4 {
display
:
block
;
color
:
#555
;
.subheader
{
display
:
block
;
//
display: block;
font-size
:
0
.5em
;
line-height
:
1em
;
color
:
lighten
(
$text-dark
,
16
%
);
color
:
lighten
(
$text-dark
,
32
%
);
}
}
...
...
resources/assets/sass/styles.scss
View file @
991dd8a
...
...
@@ -207,3 +207,59 @@ $btt-size: 40px;
color
:
#EEE
;
}
}
.entity-selector
{
border
:
1px
solid
#DDD
;
border-radius
:
3px
;
overflow
:
hidden
;
font-size
:
0
.8em
;
input
[
type
=
"text"
]
{
width
:
100%
;
display
:
block
;
border-radius
:
0
;
border
:
0
;
border-bottom
:
1px
solid
#DDD
;
font-size
:
16px
;
padding
:
$-s
$-m
;
}
.entity-list
{
overflow-y
:
scroll
;
height
:
400px
;
background-color
:
#EEEEEE
;
}
.loading
{
height
:
400px
;
padding-top
:
$-l
;
}
.entity-list
>
p
{
text-align
:
center
;
padding-top
:
$-l
;
font-size
:
1
.333em
;
}
.entity-list
>
div
{
padding-left
:
$-m
;
padding-right
:
$-m
;
background-color
:
#FFF
;
transition
:
all
ease-in-out
120ms
;
cursor
:
pointer
;
}
}
.entity-list-item.selected
{
h3
,
i
,
p
,
a
{
color
:
#EEE
;
}
}
...
...
resources/lang/en/activities.php
View file @
991dd8a
...
...
@@ -16,6 +16,7 @@ return [
'page_delete_notification'
=>
'Page Successfully Deleted'
,
'page_restore'
=>
'restored page'
,
'page_restore_notification'
=>
'Page Successfully Restored'
,
'page_move'
=>
'moved page'
,
// Chapters
'chapter_create'
=>
'created chapter'
,
...
...
resources/views/books/list-item.blade.php
View file @
991dd8a
<div
class=
"book"
>
<div
class=
"book
entity-list-item"
data-entity-type=
"book"
data-entity-id=
"{{$book->id}}
"
>
<h3
class=
"text-book"
><a
class=
"text-book"
href=
"{{$book->getUrl()}}"
><i
class=
"zmdi zmdi-book"
></i>
{{$book->name}}
</a></h3>
@if(isset($book->searchSnippet))
<p
class=
"text-muted"
>
{!! $book->searchSnippet !!}
</p>
...
...
resources/views/chapters/list-item.blade.php
View file @
991dd8a
<div
class=
"chapter"
>
<div
class=
"chapter
entity-list-item"
data-entity-type=
"chapter"
data-entity-id=
"{{$chapter->id}}
"
>
<h3>
<a
href=
"{{ $chapter->getUrl() }}"
class=
"text-chapter"
>
<i
class=
"zmdi zmdi-collection-bookmark"
></i>
{{ $chapter->name }}
...
...
resources/views/pages/list-item.blade.php
View file @
991dd8a
<div
class=
"page {{$page->draft ? 'draft' : ''}}"
>
<div
class=
"page {{$page->draft ? 'draft' : ''}}
entity-list-item"
data-entity-type=
"page"
data-entity-id=
"{{$page->id}}
"
>
<h3>
<a
href=
"{{ $page->getUrl() }}"
class=
"text-page"
><i
class=
"zmdi zmdi-file-text"
></i>
{{ $page->name }}
</a>
</h3>
...
...
@@ -11,11 +11,11 @@
@if(isset($style)
&&
$style === 'detailed')
<div
class=
"row meta text-muted text-small"
>
<div
class=
"col-md-
4
"
>
<div
class=
"col-md-
6
"
>
Created {{$page->created_at->diffForHumans()}} @if($page->createdBy)by {{$page->createdBy->name}}@endif
<br>
Last updated {{ $page->updated_at->diffForHumans() }} @if($page->updatedBy)by {{$page->updatedBy->name}} @endif
</div>
<div
class=
"col-md-
8
"
>
<div
class=
"col-md-
6
"
>
<a
class=
"text-book"
href=
"{{ $page->book->getUrl() }}"
><i
class=
"zmdi zmdi-book"
></i>
{{ $page->book->getShortName(30) }}
</a>
<br>
@if($page->chapter)
...
...
resources/views/pages/move.blade.php
0 → 100644
View file @
991dd8a
@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>
@if($page->hasChapter())
<span
class=
"sep"
>
»
</span>
<a
href=
"{{ $page->chapter->getUrl() }}"
class=
"text-chapter text-button"
>
<i
class=
"zmdi zmdi-collection-bookmark"
></i>
{{$page->chapter->getShortName()}}
</a>
@endif
<span
class=
"sep"
>
»
</span>
<a
href=
"{{$page->getUrl()}}"
class=
"text-page text-button"
><i
class=
"zmdi zmdi-file-text"
></i>
{{ $page->getShortName() }}
</a>
</div>
</div>
</div>
</div>
</div>
<div
class=
"container"
>
<h1>
Move Page
<small
class=
"subheader"
>
{{$page->name}}
</small></h1>
<form
action=
"{{ $page->getUrl() }}/move"
method=
"POST"
>
{!! 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>
<a
href=
"{{ $page->getUrl() }}"
class=
"button muted"
>
Cancel
</a>
<button
type=
"submit"
class=
"button pos"
>
Move Page
</button>
</form>
</div>
@stop
resources/views/pages/show.blade.php
View file @
991dd8a
...
...
@@ -28,15 +28,26 @@
</ul>
</span>
@if(userCan('page-update', $page))
<a
href=
"{{$page->getUrl()}}/revisions"
class=
"text-primary text-button"
><i
class=
"zmdi zmdi-replay"
></i>
Revisions
</a>
<a
href=
"{{$page->getUrl()}}/edit"
class=
"text-primary text-button"
><i
class=
"zmdi zmdi-edit"
></i>
Edit
</a>
@endif
@if(userCan('page-update', $page) || userCan('restrictions-manage', $page) || userCan('page-delete', $page))
<div
dropdown
class=
"dropdown-container"
>
<a
dropdown-toggle
class=
"text-primary text-button"
><i
class=
"zmdi zmdi-more-vert"
></i></a>
<ul>
@if(userCan('page-update', $page))
<li><a
href=
"{{$page->getUrl()}}/move"
class=
"text-primary"
><i
class=
"zmdi zmdi-folder"
></i>
Move
</a></li>
<li><a
href=
"{{$page->getUrl()}}/revisions"
class=
"text-primary"
><i
class=
"zmdi zmdi-replay"
></i>
Revisions
</a></li>
@endif
@if(userCan('restrictions-manage', $page))
<a
href=
"{{$page->getUrl()}}/permissions"
class=
"text-primary text-button"
><i
class=
"zmdi zmdi-lock-outline"
></i>
Permissions
</a
>
<li><a
href=
"{{$page->getUrl()}}/permissions"
class=
"text-primary"
><i
class=
"zmdi zmdi-lock-outline"
></i>
Permissions
</a></li
>
@endif
@if(userCan('page-delete', $page))
<a
href=
"{{$page->getUrl()}}/delete"
class=
"text-neg text-button"
><i
class=
"zmdi zmdi-delete"
></i>
Delete
</a>
<li><a
href=
"{{$page->getUrl()}}/delete"
class=
"text-neg"
><i
class=
"zmdi zmdi-delete"
></i>
Delete
</a></li>
@endif
</ul>
</div>
@endif
</div>
</div>
</div>
...
...
resources/views/partials/custom-styles.blade.php
View file @
991dd8a
@if(Setting::get('app-color'))
<style>
header
,
#back-to-top
,
.primary-background
{
background-color
:
{{
Setting
::
get
(
'app-color'
)
}
}
;
background-color
:
{{
Setting
::
get
(
'app-color'
)
}
}
!
important
;
}
.faded-small
,
.primary-background-light
{
background-color
:
{{
Setting
::
get
(
'app-color-light'
)
}
}
;
...
...
tests/Entity/EntitySearchTest.php
View file @
991dd8a
...
...
@@ -82,4 +82,14 @@ class EntitySearchTest extends TestCase
$this
->
asAdmin
()
->
visit
(
'/search/books?term='
.
$book
->
name
)
->
see
(
'Book Search Results'
)
->
see
(
'.entity-list'
,
$book
->
name
);
}
public
function
test_ajax_entity_search
()
{
$page
=
\BookStack\Page
::
all
()
->
last
();
$notVisitedPage
=
\BookStack\Page
::
first
();
$this
->
visit
(
$page
->
getUrl
());
$this
->
asAdmin
()
->
visit
(
'/ajax/search/entities?term='
.
$page
->
name
)
->
see
(
'.entity-list'
,
$page
->
name
);
$this
->
asAdmin
()
->
visit
(
'/ajax/search/entities?types=book&term='
.
$page
->
name
)
->
dontSee
(
'.entity-list'
,
$page
->
name
);
$this
->
asAdmin
()
->
visit
(
'/ajax/search/entities'
)
->
see
(
'.entity-list'
,
$page
->
name
)
->
dontSee
(
$notVisitedPage
->
name
);
}
}
...
...
tests/Entity/SortTest.php
View file @
991dd8a
...
...
@@ -22,4 +22,22 @@ class SortTest extends TestCase
->
dontSee
(
$draft
->
name
);
}
public
function
test_page_move
()
{
$page
=
\BookStack\Page
::
first
();
$currentBook
=
$page
->
book
;
$newBook
=
\BookStack\Book
::
where
(
'id'
,
'!='
,
$currentBook
->
id
)
->
first
();
$this
->
asAdmin
()
->
visit
(
$page
->
getUrl
()
.
'/move'
)
->
see
(
'Move Page'
)
->
see
(
$page
->
name
)
->
type
(
'book:'
.
$newBook
->
id
,
'entity_selection'
)
->
press
(
'Move Page'
);
$page
=
\BookStack\Page
::
find
(
$page
->
id
);
$this
->
seePageIs
(
$page
->
getUrl
());
$this
->
assertTrue
(
$page
->
book
->
id
==
$newBook
->
id
,
'Page book is now the new book'
);
$this
->
visit
(
$newBook
->
getUrl
())
->
seeInNthElement
(
'.activity-list-item'
,
0
,
'moved page'
)
->
seeInNthElement
(
'.activity-list-item'
,
0
,
$page
->
name
);
}
}
\ No newline at end of file
...
...
Please
register
or
sign in
to post a comment