mirror of
https://github.com/BookStackApp/BookStack.git
synced 2026-02-18 03:09:40 +03:00
Compare commits
68 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3903fda6ca | ||
|
|
441e46ebaa | ||
|
|
f99c8ff99a | ||
|
|
1f4260f359 | ||
|
|
dc0bf8ad4e | ||
|
|
75981c2412 | ||
|
|
102e326e6a | ||
|
|
2b25bf6f3b | ||
|
|
f8ae4c335e | ||
|
|
5570e858e5 | ||
|
|
1859a4d356 | ||
|
|
ad4642c2c4 | ||
|
|
92108d710d | ||
|
|
f93280696d | ||
|
|
1787391b07 | ||
|
|
44347ee353 | ||
|
|
9e704fcae4 | ||
|
|
fdd816b17d | ||
|
|
82e2c523e6 | ||
|
|
a323b0d49c | ||
|
|
4c985aac7e | ||
|
|
87e18b8068 | ||
|
|
607a2c91fc | ||
|
|
fde970ba59 | ||
|
|
ec7be1b08b | ||
|
|
746a760a23 | ||
|
|
1a09d88891 | ||
|
|
46c01ecba2 | ||
|
|
544ece03a5 | ||
|
|
5fee7c4db1 | ||
|
|
8ed9f75d57 | ||
|
|
a15b179676 | ||
|
|
73844b9eeb | ||
|
|
dcde599709 | ||
|
|
0e0945ef84 | ||
|
|
ad125327c0 | ||
|
|
dfaf20dd83 | ||
|
|
786262db3b | ||
|
|
29a4110d8f | ||
|
|
9b639f715f | ||
|
|
46f3d78c8a | ||
|
|
1338ae2fc3 | ||
|
|
37813a223a | ||
|
|
b488e969bb | ||
|
|
1377296ef4 | ||
|
|
01cb22af37 | ||
|
|
331305333d | ||
|
|
0651eae7ec | ||
|
|
1552417598 | ||
|
|
a74a8ee483 | ||
|
|
7fa5405cb7 | ||
|
|
cc0ce7c630 | ||
|
|
070d4aeb6c | ||
|
|
668ce26269 | ||
|
|
6725ddcc41 | ||
|
|
bce941db3f | ||
|
|
4499ae84bb | ||
|
|
d4e790d3cf | ||
|
|
9b35aa42a2 | ||
|
|
7163997367 | ||
|
|
2385a6c29b | ||
|
|
36173eb47d | ||
|
|
f7645824d9 | ||
|
|
6d926048ec | ||
|
|
5335c973b4 | ||
|
|
bcafa73faf | ||
|
|
4214fcd2fa | ||
|
|
b2b64fb853 |
9
.gitignore
vendored
9
.gitignore
vendored
@@ -13,4 +13,11 @@ _ide_helper.php
|
||||
/storage/debugbar
|
||||
.phpstorm.meta.php
|
||||
yarn.lock
|
||||
/bin
|
||||
/bin
|
||||
.buildpath
|
||||
|
||||
.project
|
||||
|
||||
.settings/org.eclipse.wst.common.project.facet.core.xml
|
||||
|
||||
.settings/org.eclipse.php.core.prefs
|
||||
|
||||
@@ -56,4 +56,13 @@ class Book extends Entity
|
||||
return strlen($description) > $length ? substr($description, 0, $length-3) . '...' : $description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a generalised, common raw query that can be 'unioned' across entities.
|
||||
* @return string
|
||||
*/
|
||||
public function entityRawQuery()
|
||||
{
|
||||
return "'BookStack\\\\Book' as entity_type, id, id as entity_id, slug, name, {$this->textField} as text,'' as html, '0' as book_id, '0' as priority, '0' as chapter_id, '0' as draft, created_by, updated_by, updated_at, created_at";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -51,4 +51,13 @@ class Chapter extends Entity
|
||||
return strlen($description) > $length ? substr($description, 0, $length-3) . '...' : $description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a generalised, common raw query that can be 'unioned' across entities.
|
||||
* @return string
|
||||
*/
|
||||
public function entityRawQuery()
|
||||
{
|
||||
return "'BookStack\\\\Chapter' as entity_type, id, id as entity_id, slug, name, {$this->textField} as text, '' as html, book_id, priority, '0' as chapter_id, '0' as draft, created_by, updated_by, updated_at, created_at";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ class RegeneratePermissions extends Command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'bookstack:regenerate-permissions';
|
||||
protected $signature = 'bookstack:regenerate-permissions {--database= : The database connection to use.}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
@@ -46,7 +46,15 @@ class RegeneratePermissions extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$connection = \DB::getDefaultConnection();
|
||||
if ($this->option('database') !== null) {
|
||||
\DB::setDefaultConnection($this->option('database'));
|
||||
$this->permissionService->setConnection(\DB::connection($this->option('database')));
|
||||
}
|
||||
|
||||
$this->permissionService->buildJointPermissions();
|
||||
|
||||
\DB::setDefaultConnection($connection);
|
||||
$this->comment('Permissions regenerated');
|
||||
}
|
||||
}
|
||||
|
||||
54
app/Console/Commands/RegenerateSearch.php
Normal file
54
app/Console/Commands/RegenerateSearch.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Console\Commands;
|
||||
|
||||
use BookStack\Services\SearchService;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class RegenerateSearch extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'bookstack:regenerate-search {--database= : The database connection to use.}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Command description';
|
||||
|
||||
protected $searchService;
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @param SearchService $searchService
|
||||
*/
|
||||
public function __construct(SearchService $searchService)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->searchService = $searchService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$connection = \DB::getDefaultConnection();
|
||||
if ($this->option('database') !== null) {
|
||||
\DB::setDefaultConnection($this->option('database'));
|
||||
$this->searchService->setConnection(\DB::connection($this->option('database')));
|
||||
}
|
||||
|
||||
$this->searchService->indexAllEntities();
|
||||
\DB::setDefaultConnection($connection);
|
||||
$this->comment('Search index regenerated');
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Console;
|
||||
<?php namespace BookStack\Console;
|
||||
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
@@ -13,10 +11,11 @@ class Kernel extends ConsoleKernel
|
||||
* @var array
|
||||
*/
|
||||
protected $commands = [
|
||||
\BookStack\Console\Commands\ClearViews::class,
|
||||
\BookStack\Console\Commands\ClearActivity::class,
|
||||
\BookStack\Console\Commands\ClearRevisions::class,
|
||||
\BookStack\Console\Commands\RegeneratePermissions::class,
|
||||
Commands\ClearViews::class,
|
||||
Commands\ClearActivity::class,
|
||||
Commands\ClearRevisions::class,
|
||||
Commands\RegeneratePermissions::class,
|
||||
Commands\RegenerateSearch::class
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
class Entity extends Ownable
|
||||
{
|
||||
|
||||
protected $fieldsToSearch = ['name', 'description'];
|
||||
public $textField = 'description';
|
||||
|
||||
/**
|
||||
* Compares this entity to another given entity.
|
||||
@@ -65,6 +65,15 @@ class Entity extends Ownable
|
||||
return $this->morphMany(Tag::class, 'entity')->orderBy('order', 'asc');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the related search terms.
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphMany
|
||||
*/
|
||||
public function searchTerms()
|
||||
{
|
||||
return $this->morphMany(SearchTerm::class, 'entity');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get this entities restrictions.
|
||||
*/
|
||||
@@ -85,17 +94,6 @@ class Entity extends Ownable
|
||||
->where('action', '=', $action)->count() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this entity has live (active) restrictions in place.
|
||||
* @param $role_id
|
||||
* @param $action
|
||||
* @return bool
|
||||
*/
|
||||
public function hasActiveRestriction($role_id, $action)
|
||||
{
|
||||
return $this->getRawAttribute('restricted') && $this->hasRestriction($role_id, $action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the entity jointPermissions this is connected to.
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphMany
|
||||
@@ -153,67 +151,25 @@ class Entity extends Ownable
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a full-text search on this entity.
|
||||
* @param string[] $fieldsToSearch
|
||||
* @param string[] $terms
|
||||
* @param string[] array $wheres
|
||||
* Get the body text of this entity.
|
||||
* @return mixed
|
||||
*/
|
||||
public function fullTextSearchQuery($terms, $wheres = [])
|
||||
public function getText()
|
||||
{
|
||||
$exactTerms = [];
|
||||
$fuzzyTerms = [];
|
||||
$search = static::newQuery();
|
||||
|
||||
foreach ($terms as $key => $term) {
|
||||
$term = htmlentities($term, ENT_QUOTES);
|
||||
$term = preg_replace('/[+\-><\(\)~*\"@]+/', ' ', $term);
|
||||
if (preg_match('/".*?"/', $term) || is_numeric($term)) {
|
||||
$term = str_replace('"', '', $term);
|
||||
$exactTerms[] = '%' . $term . '%';
|
||||
} else {
|
||||
$term = '' . $term . '*';
|
||||
if ($term !== '*') $fuzzyTerms[] = $term;
|
||||
}
|
||||
}
|
||||
|
||||
$isFuzzy = count($exactTerms) === 0 && count($fuzzyTerms) > 0;
|
||||
|
||||
|
||||
// Perform fulltext search if relevant terms exist.
|
||||
if ($isFuzzy) {
|
||||
$termString = implode(' ', $fuzzyTerms);
|
||||
$fields = implode(',', $this->fieldsToSearch);
|
||||
$search = $search->selectRaw('*, MATCH(name) AGAINST(? IN BOOLEAN MODE) AS title_relevance', [$termString]);
|
||||
$search = $search->whereRaw('MATCH(' . $fields . ') AGAINST(? IN BOOLEAN MODE)', [$termString]);
|
||||
}
|
||||
|
||||
// Ensure at least one exact term matches if in search
|
||||
if (count($exactTerms) > 0) {
|
||||
$search = $search->where(function ($query) use ($exactTerms) {
|
||||
foreach ($exactTerms as $exactTerm) {
|
||||
foreach ($this->fieldsToSearch as $field) {
|
||||
$query->orWhere($field, 'like', $exactTerm);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$orderBy = $isFuzzy ? 'title_relevance' : 'updated_at';
|
||||
|
||||
// Add additional where terms
|
||||
foreach ($wheres as $whereTerm) {
|
||||
$search->where($whereTerm[0], $whereTerm[1], $whereTerm[2]);
|
||||
}
|
||||
|
||||
// Load in relations
|
||||
if ($this->isA('page')) {
|
||||
$search = $search->with('book', 'chapter', 'createdBy', 'updatedBy');
|
||||
} else if ($this->isA('chapter')) {
|
||||
$search = $search->with('book');
|
||||
}
|
||||
|
||||
return $search->orderBy($orderBy, 'desc');
|
||||
return $this->{$this->textField};
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a generalised, common raw query that can be 'unioned' across entities.
|
||||
* @return string
|
||||
*/
|
||||
public function entityRawQuery(){return '';}
|
||||
|
||||
/**
|
||||
* Get the url of this entity
|
||||
* @param $path
|
||||
* @return string
|
||||
*/
|
||||
public function getUrl($path){return '/';}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php namespace BookStack\Http\Controllers;
|
||||
|
||||
use Activity;
|
||||
use BookStack\Book;
|
||||
use BookStack\Repos\EntityRepo;
|
||||
use BookStack\Repos\UserRepo;
|
||||
use BookStack\Services\ExportService;
|
||||
@@ -207,13 +208,12 @@ class BookController extends Controller
|
||||
|
||||
// Add activity for books
|
||||
foreach ($sortedBooks as $bookId) {
|
||||
/** @var Book $updatedBook */
|
||||
$updatedBook = $this->entityRepo->getById('book', $bookId);
|
||||
$this->entityRepo->buildJointPermissionsForBook($updatedBook);
|
||||
Activity::add($updatedBook, 'book_sort', $updatedBook->id);
|
||||
}
|
||||
|
||||
// Update permissions on changed models
|
||||
if (count($updatedModels) === 0) $this->entityRepo->buildJointPermissions($updatedModels);
|
||||
|
||||
return redirect($book->getUrl());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Http\Controllers;
|
||||
<?php namespace BookStack\Http\Controllers;
|
||||
|
||||
use Activity;
|
||||
use BookStack\Repos\EntityRepo;
|
||||
use BookStack\Http\Requests;
|
||||
use Illuminate\Http\Response;
|
||||
use Views;
|
||||
|
||||
@@ -49,7 +46,7 @@ class HomeController extends Controller
|
||||
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function getTranslations() {
|
||||
$locale = trans()->getLocale();
|
||||
$locale = app()->getLocale();
|
||||
$cacheKey = 'GLOBAL_TRANSLATIONS_' . $locale;
|
||||
if (cache()->has($cacheKey) && config('app.env') !== 'development') {
|
||||
$resp = cache($cacheKey);
|
||||
@@ -63,10 +60,10 @@ class HomeController extends Controller
|
||||
];
|
||||
if ($locale !== 'en') {
|
||||
$enTrans = [
|
||||
'common' => trans('common', [], null, 'en'),
|
||||
'components' => trans('components', [], null, 'en'),
|
||||
'entities' => trans('entities', [], null, 'en'),
|
||||
'errors' => trans('errors', [], null, 'en')
|
||||
'common' => trans('common', [], 'en'),
|
||||
'components' => trans('components', [], 'en'),
|
||||
'entities' => trans('entities', [], 'en'),
|
||||
'errors' => trans('errors', [], 'en')
|
||||
];
|
||||
$translations = array_replace_recursive($enTrans, $translations);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php namespace BookStack\Http\Controllers;
|
||||
|
||||
use BookStack\Repos\EntityRepo;
|
||||
use BookStack\Services\SearchService;
|
||||
use BookStack\Services\ViewService;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
@@ -8,16 +9,19 @@ class SearchController extends Controller
|
||||
{
|
||||
protected $entityRepo;
|
||||
protected $viewService;
|
||||
protected $searchService;
|
||||
|
||||
/**
|
||||
* SearchController constructor.
|
||||
* @param EntityRepo $entityRepo
|
||||
* @param ViewService $viewService
|
||||
* @param SearchService $searchService
|
||||
*/
|
||||
public function __construct(EntityRepo $entityRepo, ViewService $viewService)
|
||||
public function __construct(EntityRepo $entityRepo, ViewService $viewService, SearchService $searchService)
|
||||
{
|
||||
$this->entityRepo = $entityRepo;
|
||||
$this->viewService = $viewService;
|
||||
$this->searchService = $searchService;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
@@ -27,84 +31,26 @@ class SearchController extends Controller
|
||||
* @return \Illuminate\View\View
|
||||
* @internal param string $searchTerm
|
||||
*/
|
||||
public function searchAll(Request $request)
|
||||
public function search(Request $request)
|
||||
{
|
||||
if (!$request->has('term')) {
|
||||
return redirect()->back();
|
||||
}
|
||||
$searchTerm = $request->get('term');
|
||||
$paginationAppends = $request->only('term');
|
||||
$pages = $this->entityRepo->getBySearch('page', $searchTerm, [], 20, $paginationAppends);
|
||||
$books = $this->entityRepo->getBySearch('book', $searchTerm, [], 10, $paginationAppends);
|
||||
$chapters = $this->entityRepo->getBySearch('chapter', $searchTerm, [], 10, $paginationAppends);
|
||||
$this->setPageTitle(trans('entities.search_for_term', ['term' => $searchTerm]));
|
||||
|
||||
$page = $request->has('page') && is_int(intval($request->get('page'))) ? intval($request->get('page')) : 1;
|
||||
$nextPageLink = baseUrl('/search?term=' . urlencode($searchTerm) . '&page=' . ($page+1));
|
||||
|
||||
$results = $this->searchService->searchEntities($searchTerm, 'all', $page, 20);
|
||||
$hasNextPage = $this->searchService->searchEntities($searchTerm, 'all', $page+1, 20)['count'] > 0;
|
||||
|
||||
return view('search/all', [
|
||||
'pages' => $pages,
|
||||
'books' => $books,
|
||||
'chapters' => $chapters,
|
||||
'searchTerm' => $searchTerm
|
||||
'entities' => $results['results'],
|
||||
'totalResults' => $results['total'],
|
||||
'searchTerm' => $searchTerm,
|
||||
'hasNextPage' => $hasNextPage,
|
||||
'nextPageLink' => $nextPageLink
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search only the pages in the system.
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
|
||||
*/
|
||||
public function searchPages(Request $request)
|
||||
{
|
||||
if (!$request->has('term')) return redirect()->back();
|
||||
|
||||
$searchTerm = $request->get('term');
|
||||
$paginationAppends = $request->only('term');
|
||||
$pages = $this->entityRepo->getBySearch('page', $searchTerm, [], 20, $paginationAppends);
|
||||
$this->setPageTitle(trans('entities.search_page_for_term', ['term' => $searchTerm]));
|
||||
return view('search/entity-search-list', [
|
||||
'entities' => $pages,
|
||||
'title' => trans('entities.search_results_page'),
|
||||
'searchTerm' => $searchTerm
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search only the chapters in the system.
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
|
||||
*/
|
||||
public function searchChapters(Request $request)
|
||||
{
|
||||
if (!$request->has('term')) return redirect()->back();
|
||||
|
||||
$searchTerm = $request->get('term');
|
||||
$paginationAppends = $request->only('term');
|
||||
$chapters = $this->entityRepo->getBySearch('chapter', $searchTerm, [], 20, $paginationAppends);
|
||||
$this->setPageTitle(trans('entities.search_chapter_for_term', ['term' => $searchTerm]));
|
||||
return view('search/entity-search-list', [
|
||||
'entities' => $chapters,
|
||||
'title' => trans('entities.search_results_chapter'),
|
||||
'searchTerm' => $searchTerm
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search only the books in the system.
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
|
||||
*/
|
||||
public function searchBooks(Request $request)
|
||||
{
|
||||
if (!$request->has('term')) return redirect()->back();
|
||||
|
||||
$searchTerm = $request->get('term');
|
||||
$paginationAppends = $request->only('term');
|
||||
$books = $this->entityRepo->getBySearch('book', $searchTerm, [], 20, $paginationAppends);
|
||||
$this->setPageTitle(trans('entities.search_book_for_term', ['term' => $searchTerm]));
|
||||
return view('search/entity-search-list', [
|
||||
'entities' => $books,
|
||||
'title' => trans('entities.search_results_book'),
|
||||
'searchTerm' => $searchTerm
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches all entities within a book.
|
||||
@@ -115,16 +61,24 @@ class SearchController extends Controller
|
||||
*/
|
||||
public function searchBook(Request $request, $bookId)
|
||||
{
|
||||
if (!$request->has('term')) {
|
||||
return redirect()->back();
|
||||
}
|
||||
$searchTerm = $request->get('term');
|
||||
$searchWhereTerms = [['book_id', '=', $bookId]];
|
||||
$pages = $this->entityRepo->getBySearch('page', $searchTerm, $searchWhereTerms);
|
||||
$chapters = $this->entityRepo->getBySearch('chapter', $searchTerm, $searchWhereTerms);
|
||||
return view('search/book', ['pages' => $pages, 'chapters' => $chapters, 'searchTerm' => $searchTerm]);
|
||||
$term = $request->get('term', '');
|
||||
$results = $this->searchService->searchBook($bookId, $term);
|
||||
return view('partials/entity-list', ['entities' => $results]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches all entities within a chapter.
|
||||
* @param Request $request
|
||||
* @param integer $chapterId
|
||||
* @return \Illuminate\View\View
|
||||
* @internal param string $searchTerm
|
||||
*/
|
||||
public function searchChapter(Request $request, $chapterId)
|
||||
{
|
||||
$term = $request->get('term', '');
|
||||
$results = $this->searchService->searchChapter($chapterId, $term);
|
||||
return view('partials/entity-list', ['entities' => $results]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for a list of entities and return a partial HTML response of matching entities.
|
||||
@@ -134,18 +88,13 @@ class SearchController extends Controller
|
||||
*/
|
||||
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) {
|
||||
foreach (['page', 'chapter', 'book'] as $entityType) {
|
||||
if ($entityTypes->contains($entityType)) {
|
||||
$entities = $entities->merge($this->entityRepo->getBySearch($entityType, $searchTerm)->items());
|
||||
}
|
||||
}
|
||||
$entities = $entities->sortByDesc('title_relevance');
|
||||
$searchTerm .= ' {type:'. implode('|', $entityTypes->toArray()) .'}';
|
||||
$entities = $this->searchService->searchEntities($searchTerm)['results'];
|
||||
} else {
|
||||
$entityNames = $entityTypes->map(function ($type) {
|
||||
return 'BookStack\\' . ucfirst($type);
|
||||
|
||||
@@ -15,7 +15,17 @@ class Localization
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
$defaultLang = config('app.locale');
|
||||
$locale = setting()->getUser(user(), 'language', $defaultLang);
|
||||
if (user()->isDefault()) {
|
||||
$locale = $defaultLang;
|
||||
$availableLocales = config('app.locales');
|
||||
foreach ($request->getLanguages() as $lang) {
|
||||
if (!in_array($lang, $availableLocales)) continue;
|
||||
$locale = $lang;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
$locale = setting()->getUser(user(), 'language', $defaultLang);
|
||||
}
|
||||
app()->setLocale($locale);
|
||||
Carbon::setLocale($locale);
|
||||
return $next($request);
|
||||
|
||||
@@ -2,12 +2,16 @@
|
||||
|
||||
namespace BookStack\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
|
||||
class ConfirmEmail extends Notification
|
||||
class ConfirmEmail extends Notification implements ShouldQueue
|
||||
{
|
||||
|
||||
use Queueable;
|
||||
|
||||
public $token;
|
||||
|
||||
/**
|
||||
|
||||
13
app/Page.php
13
app/Page.php
@@ -8,8 +8,7 @@ class Page extends Entity
|
||||
protected $simpleAttributes = ['name', 'id', 'slug'];
|
||||
|
||||
protected $with = ['book'];
|
||||
|
||||
protected $fieldsToSearch = ['name', 'text'];
|
||||
public $textField = 'text';
|
||||
|
||||
/**
|
||||
* Converts this page into a simplified array.
|
||||
@@ -96,4 +95,14 @@ class Page extends Entity
|
||||
return mb_convert_encoding($text, 'UTF-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a generalised, common raw query that can be 'unioned' across entities.
|
||||
* @param bool $withContent
|
||||
* @return string
|
||||
*/
|
||||
public function entityRawQuery($withContent = false)
|
||||
{ $htmlQuery = $withContent ? 'html' : "'' as html";
|
||||
return "'BookStack\\\\Page' as entity_type, id, id as entity_id, slug, name, {$this->textField} as text, {$htmlQuery}, book_id, priority, chapter_id, draft, created_by, updated_by, updated_at, created_at";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ use BookStack\Page;
|
||||
use BookStack\PageRevision;
|
||||
use BookStack\Services\AttachmentService;
|
||||
use BookStack\Services\PermissionService;
|
||||
use BookStack\Services\SearchService;
|
||||
use BookStack\Services\ViewService;
|
||||
use Carbon\Carbon;
|
||||
use DOMDocument;
|
||||
@@ -59,13 +60,12 @@ class EntityRepo
|
||||
protected $tagRepo;
|
||||
|
||||
/**
|
||||
* Acceptable operators to be used in a query
|
||||
* @var array
|
||||
* @var SearchService
|
||||
*/
|
||||
protected $queryOperators = ['<=', '>=', '=', '<', '>', 'like', '!='];
|
||||
protected $searchService;
|
||||
|
||||
/**
|
||||
* EntityService constructor.
|
||||
* EntityRepo constructor.
|
||||
* @param Book $book
|
||||
* @param Chapter $chapter
|
||||
* @param Page $page
|
||||
@@ -73,10 +73,12 @@ class EntityRepo
|
||||
* @param ViewService $viewService
|
||||
* @param PermissionService $permissionService
|
||||
* @param TagRepo $tagRepo
|
||||
* @param SearchService $searchService
|
||||
*/
|
||||
public function __construct(
|
||||
Book $book, Chapter $chapter, Page $page, PageRevision $pageRevision,
|
||||
ViewService $viewService, PermissionService $permissionService, TagRepo $tagRepo
|
||||
ViewService $viewService, PermissionService $permissionService,
|
||||
TagRepo $tagRepo, SearchService $searchService
|
||||
)
|
||||
{
|
||||
$this->book = $book;
|
||||
@@ -91,6 +93,7 @@ class EntityRepo
|
||||
$this->viewService = $viewService;
|
||||
$this->permissionService = $permissionService;
|
||||
$this->tagRepo = $tagRepo;
|
||||
$this->searchService = $searchService;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -216,6 +219,7 @@ class EntityRepo
|
||||
* @param int $count
|
||||
* @param int $page
|
||||
* @param bool|callable $additionalQuery
|
||||
* @return Collection
|
||||
*/
|
||||
public function getRecentlyCreated($type, $count = 20, $page = 0, $additionalQuery = false)
|
||||
{
|
||||
@@ -234,6 +238,7 @@ class EntityRepo
|
||||
* @param int $count
|
||||
* @param int $page
|
||||
* @param bool|callable $additionalQuery
|
||||
* @return Collection
|
||||
*/
|
||||
public function getRecentlyUpdated($type, $count = 20, $page = 0, $additionalQuery = false)
|
||||
{
|
||||
@@ -327,7 +332,7 @@ class EntityRepo
|
||||
if ($rawEntity->entity_type === 'BookStack\\Page') {
|
||||
$entities[$index] = $this->page->newFromBuilder($rawEntity);
|
||||
if ($renderPages) {
|
||||
$entities[$index]->html = $rawEntity->description;
|
||||
$entities[$index]->html = $rawEntity->html;
|
||||
$entities[$index]->html = $this->renderPage($entities[$index]);
|
||||
};
|
||||
} else if ($rawEntity->entity_type === 'BookStack\\Chapter') {
|
||||
@@ -343,6 +348,10 @@ class EntityRepo
|
||||
foreach ($entities as $entity) {
|
||||
if ($entity->chapter_id === 0 || $entity->chapter_id === '0') continue;
|
||||
$parentKey = 'BookStack\\Chapter:' . $entity->chapter_id;
|
||||
if (!isset($parents[$parentKey])) {
|
||||
$tree[] = $entity;
|
||||
continue;
|
||||
}
|
||||
$chapter = $parents[$parentKey];
|
||||
$chapter->pages->push($entity);
|
||||
}
|
||||
@@ -354,6 +363,7 @@ class EntityRepo
|
||||
* Get the child items for a chapter sorted by priority but
|
||||
* with draft items floated to the top.
|
||||
* @param Chapter $chapter
|
||||
* @return \Illuminate\Database\Eloquent\Collection|static[]
|
||||
*/
|
||||
public function getChapterChildren(Chapter $chapter)
|
||||
{
|
||||
@@ -361,56 +371,6 @@ class EntityRepo
|
||||
->orderBy('draft', 'DESC')->orderBy('priority', 'ASC')->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Search entities of a type via a given query.
|
||||
* @param string $type
|
||||
* @param string $term
|
||||
* @param array $whereTerms
|
||||
* @param int $count
|
||||
* @param array $paginationAppends
|
||||
* @return mixed
|
||||
*/
|
||||
public function getBySearch($type, $term, $whereTerms = [], $count = 20, $paginationAppends = [])
|
||||
{
|
||||
$terms = $this->prepareSearchTerms($term);
|
||||
$q = $this->permissionService->enforceEntityRestrictions($type, $this->getEntity($type)->fullTextSearchQuery($terms, $whereTerms));
|
||||
$q = $this->addAdvancedSearchQueries($q, $term);
|
||||
$entities = $q->paginate($count)->appends($paginationAppends);
|
||||
$words = join('|', explode(' ', preg_quote(trim($term), '/')));
|
||||
|
||||
// Highlight page content
|
||||
if ($type === 'page') {
|
||||
//lookahead/behind assertions ensures cut between words
|
||||
$s = '\s\x00-/:-@\[-`{-~'; //character set for start/end of words
|
||||
|
||||
foreach ($entities as $page) {
|
||||
preg_match_all('#(?<=[' . $s . ']).{1,30}((' . $words . ').{1,30})+(?=[' . $s . '])#uis', $page->text, $matches, PREG_SET_ORDER);
|
||||
//delimiter between occurrences
|
||||
$results = [];
|
||||
foreach ($matches as $line) {
|
||||
$results[] = htmlspecialchars($line[0], 0, 'UTF-8');
|
||||
}
|
||||
$matchLimit = 6;
|
||||
if (count($results) > $matchLimit) $results = array_slice($results, 0, $matchLimit);
|
||||
$result = join('... ', $results);
|
||||
|
||||
//highlight
|
||||
$result = preg_replace('#' . $words . '#iu', "<span class=\"highlight\">\$0</span>", $result);
|
||||
if (strlen($result) < 5) $result = $page->getExcerpt(80);
|
||||
|
||||
$page->searchSnippet = $result;
|
||||
}
|
||||
return $entities;
|
||||
}
|
||||
|
||||
// Highlight chapter/book content
|
||||
foreach ($entities as $entity) {
|
||||
//highlight
|
||||
$result = preg_replace('#' . $words . '#iu', "<span class=\"highlight\">\$0</span>", $entity->getExcerpt(100));
|
||||
$entity->searchSnippet = $result;
|
||||
}
|
||||
return $entities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next sequential priority for a new child element in the given book.
|
||||
@@ -492,104 +452,7 @@ class EntityRepo
|
||||
$this->permissionService->buildJointPermissionsForEntity($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a string of search terms by turning
|
||||
* it into an array of terms.
|
||||
* Keeps quoted terms together.
|
||||
* @param $termString
|
||||
* @return array
|
||||
*/
|
||||
public function prepareSearchTerms($termString)
|
||||
{
|
||||
$termString = $this->cleanSearchTermString($termString);
|
||||
preg_match_all('/(".*?")/', $termString, $matches);
|
||||
$terms = [];
|
||||
if (count($matches[1]) > 0) {
|
||||
foreach ($matches[1] as $match) {
|
||||
$terms[] = $match;
|
||||
}
|
||||
$termString = trim(preg_replace('/"(.*?)"/', '', $termString));
|
||||
}
|
||||
if (!empty($termString)) $terms = array_merge($terms, explode(' ', $termString));
|
||||
return $terms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes any special search notation that should not
|
||||
* be used in a full-text search.
|
||||
* @param $termString
|
||||
* @return mixed
|
||||
*/
|
||||
protected function cleanSearchTermString($termString)
|
||||
{
|
||||
// Strip tag searches
|
||||
$termString = preg_replace('/\[.*?\]/', '', $termString);
|
||||
// Reduced multiple spacing into single spacing
|
||||
$termString = preg_replace("/\s{2,}/", " ", $termString);
|
||||
return $termString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the available query operators as a regex escaped list.
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getRegexEscapedOperators()
|
||||
{
|
||||
$escapedOperators = [];
|
||||
foreach ($this->queryOperators as $operator) {
|
||||
$escapedOperators[] = preg_quote($operator);
|
||||
}
|
||||
return join('|', $escapedOperators);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses advanced search notations and adds them to the db query.
|
||||
* @param $query
|
||||
* @param $termString
|
||||
* @return mixed
|
||||
*/
|
||||
protected function addAdvancedSearchQueries($query, $termString)
|
||||
{
|
||||
$escapedOperators = $this->getRegexEscapedOperators();
|
||||
// Look for tag searches
|
||||
preg_match_all("/\[(.*?)((${escapedOperators})(.*?))?\]/", $termString, $tags);
|
||||
if (count($tags[0]) > 0) {
|
||||
$this->applyTagSearches($query, $tags);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply extracted tag search terms onto a entity query.
|
||||
* @param $query
|
||||
* @param $tags
|
||||
* @return mixed
|
||||
*/
|
||||
protected function applyTagSearches($query, $tags) {
|
||||
$query->where(function($query) use ($tags) {
|
||||
foreach ($tags[1] as $index => $tagName) {
|
||||
$query->whereHas('tags', function($query) use ($tags, $index, $tagName) {
|
||||
$tagOperator = $tags[3][$index];
|
||||
$tagValue = $tags[4][$index];
|
||||
if (!empty($tagOperator) && !empty($tagValue) && in_array($tagOperator, $this->queryOperators)) {
|
||||
if (is_numeric($tagValue) && $tagOperator !== 'like') {
|
||||
// We have to do a raw sql query for this since otherwise PDO will quote the value and MySQL will
|
||||
// search the value as a string which prevents being able to do number-based operations
|
||||
// on the tag values. We ensure it has a numeric value and then cast it just to be sure.
|
||||
$tagValue = (float) trim($query->getConnection()->getPdo()->quote($tagValue), "'");
|
||||
$query->where('name', '=', $tagName)->whereRaw("value ${tagOperator} ${tagValue}");
|
||||
} else {
|
||||
$query->where('name', '=', $tagName)->where('value', $tagOperator, $tagValue);
|
||||
}
|
||||
} else {
|
||||
$query->where('name', '=', $tagName);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new entity from request input.
|
||||
@@ -608,12 +471,13 @@ class EntityRepo
|
||||
$entity->updated_by = user()->id;
|
||||
$isChapter ? $book->chapters()->save($entity) : $entity->save();
|
||||
$this->permissionService->buildJointPermissionsForEntity($entity);
|
||||
$this->searchService->indexEntity($entity);
|
||||
return $entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update entity details from request input.
|
||||
* Use for books and chapters
|
||||
* Used for books and chapters
|
||||
* @param string $type
|
||||
* @param Entity $entityModel
|
||||
* @param array $input
|
||||
@@ -628,6 +492,7 @@ class EntityRepo
|
||||
$entityModel->updated_by = user()->id;
|
||||
$entityModel->save();
|
||||
$this->permissionService->buildJointPermissionsForEntity($entityModel);
|
||||
$this->searchService->indexEntity($entityModel);
|
||||
return $entityModel;
|
||||
}
|
||||
|
||||
@@ -668,11 +533,11 @@ class EntityRepo
|
||||
|
||||
/**
|
||||
* Alias method to update the book jointPermissions in the PermissionService.
|
||||
* @param Collection $collection collection on entities
|
||||
* @param Book $book
|
||||
*/
|
||||
public function buildJointPermissions(Collection $collection)
|
||||
public function buildJointPermissionsForBook(Book $book)
|
||||
{
|
||||
$this->permissionService->buildJointPermissionsForEntities($collection);
|
||||
$this->permissionService->buildJointPermissionsForEntity($book);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -708,10 +573,11 @@ class EntityRepo
|
||||
$draftPage->html = $this->formatHtml($input['html']);
|
||||
$draftPage->text = strip_tags($draftPage->html);
|
||||
$draftPage->draft = false;
|
||||
$draftPage->revision_count = 1;
|
||||
|
||||
$draftPage->save();
|
||||
$this->savePageRevision($draftPage, trans('entities.pages_initial_revision'));
|
||||
|
||||
$this->searchService->indexEntity($draftPage);
|
||||
return $draftPage;
|
||||
}
|
||||
|
||||
@@ -732,6 +598,7 @@ class EntityRepo
|
||||
$revision->created_at = $page->updated_at;
|
||||
$revision->type = 'version';
|
||||
$revision->summary = $summary;
|
||||
$revision->revision_number = $page->revision_count;
|
||||
$revision->save();
|
||||
|
||||
// Clear old revisions
|
||||
@@ -863,6 +730,7 @@ class EntityRepo
|
||||
if ($chapter) $page->chapter_id = $chapter->id;
|
||||
|
||||
$book->pages()->save($page);
|
||||
$page = $this->page->find($page->id);
|
||||
$this->permissionService->buildJointPermissionsForEntity($page);
|
||||
return $page;
|
||||
}
|
||||
@@ -951,6 +819,7 @@ class EntityRepo
|
||||
$page->text = strip_tags($page->html);
|
||||
if (setting('app-editor') !== 'markdown') $page->markdown = '';
|
||||
$page->updated_by = $userId;
|
||||
$page->revision_count++;
|
||||
$page->save();
|
||||
|
||||
// Remove all update drafts for this user & page.
|
||||
@@ -961,6 +830,8 @@ class EntityRepo
|
||||
$this->savePageRevision($page, $input['summary']);
|
||||
}
|
||||
|
||||
$this->searchService->indexEntity($page);
|
||||
|
||||
return $page;
|
||||
}
|
||||
|
||||
@@ -1057,13 +928,15 @@ class EntityRepo
|
||||
*/
|
||||
public function restorePageRevision(Page $page, Book $book, $revisionId)
|
||||
{
|
||||
$page->revision_count++;
|
||||
$this->savePageRevision($page);
|
||||
$revision = $this->getById('page_revision', $revisionId);
|
||||
$revision = $page->revisions()->where('id', '=', $revisionId)->first();
|
||||
$page->fill($revision->toArray());
|
||||
$page->slug = $this->findSuitableSlug('page', $page->name, $page->id, $book->id);
|
||||
$page->text = strip_tags($page->html);
|
||||
$page->updated_by = user()->id;
|
||||
$page->save();
|
||||
$this->searchService->indexEntity($page);
|
||||
return $page;
|
||||
}
|
||||
|
||||
@@ -1156,6 +1029,7 @@ class EntityRepo
|
||||
$book->views()->delete();
|
||||
$book->permissions()->delete();
|
||||
$this->permissionService->deleteJointPermissionsForEntity($book);
|
||||
$this->searchService->deleteEntityTerms($book);
|
||||
$book->delete();
|
||||
}
|
||||
|
||||
@@ -1175,6 +1049,7 @@ class EntityRepo
|
||||
$chapter->views()->delete();
|
||||
$chapter->permissions()->delete();
|
||||
$this->permissionService->deleteJointPermissionsForEntity($chapter);
|
||||
$this->searchService->deleteEntityTerms($chapter);
|
||||
$chapter->delete();
|
||||
}
|
||||
|
||||
@@ -1190,6 +1065,7 @@ class EntityRepo
|
||||
$page->revisions()->delete();
|
||||
$page->permissions()->delete();
|
||||
$this->permissionService->deleteJointPermissionsForEntity($page);
|
||||
$this->searchService->deleteEntityTerms($page);
|
||||
|
||||
// Delete Attached Files
|
||||
$attachmentService = app(AttachmentService::class);
|
||||
|
||||
18
app/SearchTerm.php
Normal file
18
app/SearchTerm.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php namespace BookStack;
|
||||
|
||||
class SearchTerm extends Model
|
||||
{
|
||||
|
||||
protected $fillable = ['term', 'entity_id', 'entity_type', 'score'];
|
||||
public $timestamps = false;
|
||||
|
||||
/**
|
||||
* Get the entity that this term belongs to
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
|
||||
*/
|
||||
public function entity()
|
||||
{
|
||||
return $this->morphTo('entity');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
use BookStack\Book;
|
||||
use BookStack\Chapter;
|
||||
use BookStack\Entity;
|
||||
use BookStack\EntityPermission;
|
||||
use BookStack\JointPermission;
|
||||
use BookStack\Ownable;
|
||||
use BookStack\Page;
|
||||
@@ -10,6 +11,7 @@ use BookStack\Role;
|
||||
use BookStack\User;
|
||||
use Illuminate\Database\Connection;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Query\Builder as QueryBuilder;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class PermissionService
|
||||
@@ -28,22 +30,25 @@ class PermissionService
|
||||
|
||||
protected $jointPermission;
|
||||
protected $role;
|
||||
protected $entityPermission;
|
||||
|
||||
protected $entityCache;
|
||||
|
||||
/**
|
||||
* PermissionService constructor.
|
||||
* @param JointPermission $jointPermission
|
||||
* @param EntityPermission $entityPermission
|
||||
* @param Connection $db
|
||||
* @param Book $book
|
||||
* @param Chapter $chapter
|
||||
* @param Page $page
|
||||
* @param Role $role
|
||||
*/
|
||||
public function __construct(JointPermission $jointPermission, Connection $db, Book $book, Chapter $chapter, Page $page, Role $role)
|
||||
public function __construct(JointPermission $jointPermission, EntityPermission $entityPermission, Connection $db, Book $book, Chapter $chapter, Page $page, Role $role)
|
||||
{
|
||||
$this->db = $db;
|
||||
$this->jointPermission = $jointPermission;
|
||||
$this->entityPermission = $entityPermission;
|
||||
$this->role = $role;
|
||||
$this->book = $book;
|
||||
$this->chapter = $chapter;
|
||||
@@ -51,6 +56,15 @@ class PermissionService
|
||||
// TODO - Update so admin still goes through filters
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the database connection
|
||||
* @param Connection $connection
|
||||
*/
|
||||
public function setConnection(Connection $connection)
|
||||
{
|
||||
$this->db = $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the local entity cache and ensure it's empty
|
||||
*/
|
||||
@@ -133,22 +147,48 @@ class PermissionService
|
||||
$this->readyEntityCache();
|
||||
|
||||
// Get all roles (Should be the most limited dimension)
|
||||
$roles = $this->role->with('permissions')->get();
|
||||
$roles = $this->role->with('permissions')->get()->all();
|
||||
|
||||
// Chunk through all books
|
||||
$this->book->with('permissions')->chunk(500, function ($books) use ($roles) {
|
||||
$this->createManyJointPermissions($books, $roles);
|
||||
$this->bookFetchQuery()->chunk(5, function ($books) use ($roles) {
|
||||
$this->buildJointPermissionsForBooks($books, $roles);
|
||||
});
|
||||
}
|
||||
|
||||
// Chunk through all chapters
|
||||
$this->chapter->with('book', 'permissions')->chunk(500, function ($chapters) use ($roles) {
|
||||
$this->createManyJointPermissions($chapters, $roles);
|
||||
});
|
||||
/**
|
||||
* Get a query for fetching a book with it's children.
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
protected function bookFetchQuery()
|
||||
{
|
||||
return $this->book->newQuery()->select(['id', 'restricted', 'created_by'])->with(['chapters' => function($query) {
|
||||
$query->select(['id', 'restricted', 'created_by', 'book_id']);
|
||||
}, 'pages' => function($query) {
|
||||
$query->select(['id', 'restricted', 'created_by', 'book_id', 'chapter_id']);
|
||||
}]);
|
||||
}
|
||||
|
||||
// Chunk through all pages
|
||||
$this->page->with('book', 'chapter', 'permissions')->chunk(500, function ($pages) use ($roles) {
|
||||
$this->createManyJointPermissions($pages, $roles);
|
||||
});
|
||||
/**
|
||||
* Build joint permissions for an array of books
|
||||
* @param Collection $books
|
||||
* @param array $roles
|
||||
* @param bool $deleteOld
|
||||
*/
|
||||
protected function buildJointPermissionsForBooks($books, $roles, $deleteOld = false) {
|
||||
$entities = clone $books;
|
||||
|
||||
/** @var Book $book */
|
||||
foreach ($books->all() as $book) {
|
||||
foreach ($book->getRelation('chapters') as $chapter) {
|
||||
$entities->push($chapter);
|
||||
}
|
||||
foreach ($book->getRelation('pages') as $page) {
|
||||
$entities->push($page);
|
||||
}
|
||||
}
|
||||
|
||||
if ($deleteOld) $this->deleteManyJointPermissionsForEntities($entities->all());
|
||||
$this->createManyJointPermissions($entities, $roles);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -157,18 +197,22 @@ class PermissionService
|
||||
*/
|
||||
public function buildJointPermissionsForEntity(Entity $entity)
|
||||
{
|
||||
$roles = $this->role->get();
|
||||
$entities = collect([$entity]);
|
||||
|
||||
$entities = [$entity];
|
||||
if ($entity->isA('book')) {
|
||||
$entities = $entities->merge($entity->chapters);
|
||||
$entities = $entities->merge($entity->pages);
|
||||
} elseif ($entity->isA('chapter')) {
|
||||
$entities = $entities->merge($entity->pages);
|
||||
$books = $this->bookFetchQuery()->where('id', '=', $entity->id)->get();
|
||||
$this->buildJointPermissionsForBooks($books, $this->role->newQuery()->get(), true);
|
||||
return;
|
||||
}
|
||||
|
||||
$entities[] = $entity->book;
|
||||
if ($entity->isA('page') && $entity->chapter_id) $entities[] = $entity->chapter;
|
||||
if ($entity->isA('chapter')) {
|
||||
foreach ($entity->pages as $page) {
|
||||
$entities[] = $page;
|
||||
}
|
||||
}
|
||||
$this->deleteManyJointPermissionsForEntities($entities);
|
||||
$this->createManyJointPermissions($entities, $roles);
|
||||
$this->buildJointPermissionsForEntities(collect($entities));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -177,8 +221,8 @@ class PermissionService
|
||||
*/
|
||||
public function buildJointPermissionsForEntities(Collection $entities)
|
||||
{
|
||||
$roles = $this->role->get();
|
||||
$this->deleteManyJointPermissionsForEntities($entities);
|
||||
$roles = $this->role->newQuery()->get();
|
||||
$this->deleteManyJointPermissionsForEntities($entities->all());
|
||||
$this->createManyJointPermissions($entities, $roles);
|
||||
}
|
||||
|
||||
@@ -188,23 +232,12 @@ class PermissionService
|
||||
*/
|
||||
public function buildJointPermissionForRole(Role $role)
|
||||
{
|
||||
$roles = collect([$role]);
|
||||
|
||||
$roles = [$role];
|
||||
$this->deleteManyJointPermissionsForRoles($roles);
|
||||
|
||||
// Chunk through all books
|
||||
$this->book->with('permissions')->chunk(500, function ($books) use ($roles) {
|
||||
$this->createManyJointPermissions($books, $roles);
|
||||
});
|
||||
|
||||
// Chunk through all chapters
|
||||
$this->chapter->with('book', 'permissions')->chunk(500, function ($books) use ($roles) {
|
||||
$this->createManyJointPermissions($books, $roles);
|
||||
});
|
||||
|
||||
// Chunk through all pages
|
||||
$this->page->with('book', 'chapter', 'permissions')->chunk(500, function ($books) use ($roles) {
|
||||
$this->createManyJointPermissions($books, $roles);
|
||||
$this->bookFetchQuery()->chunk(5, function ($books) use ($roles) {
|
||||
$this->buildJointPermissionsForBooks($books, $roles);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -223,9 +256,10 @@ class PermissionService
|
||||
*/
|
||||
protected function deleteManyJointPermissionsForRoles($roles)
|
||||
{
|
||||
foreach ($roles as $role) {
|
||||
$role->jointPermissions()->delete();
|
||||
}
|
||||
$roleIds = array_map(function($role) {
|
||||
return $role->id;
|
||||
}, $roles);
|
||||
$this->jointPermission->newQuery()->whereIn('role_id', $roleIds)->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -244,53 +278,88 @@ class PermissionService
|
||||
protected function deleteManyJointPermissionsForEntities($entities)
|
||||
{
|
||||
if (count($entities) === 0) return;
|
||||
$query = $this->jointPermission->newQuery();
|
||||
foreach ($entities as $entity) {
|
||||
$query->orWhere(function($query) use ($entity) {
|
||||
$query->where('entity_id', '=', $entity->id)
|
||||
->where('entity_type', '=', $entity->getMorphClass());
|
||||
});
|
||||
|
||||
$this->db->transaction(function() use ($entities) {
|
||||
|
||||
foreach (array_chunk($entities, 1000) as $entityChunk) {
|
||||
$query = $this->db->table('joint_permissions');
|
||||
foreach ($entityChunk as $entity) {
|
||||
$query->orWhere(function(QueryBuilder $query) use ($entity) {
|
||||
$query->where('entity_id', '=', $entity->id)
|
||||
->where('entity_type', '=', $entity->getMorphClass());
|
||||
});
|
||||
}
|
||||
$query->delete();
|
||||
}
|
||||
$query->delete();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create & Save entity jointPermissions for many entities and jointPermissions.
|
||||
* @param Collection $entities
|
||||
* @param Collection $roles
|
||||
* @param array $roles
|
||||
*/
|
||||
protected function createManyJointPermissions($entities, $roles)
|
||||
{
|
||||
$this->readyEntityCache();
|
||||
$jointPermissions = [];
|
||||
|
||||
// Fetch Entity Permissions and create a mapping of entity restricted statuses
|
||||
$entityRestrictedMap = [];
|
||||
$permissionFetch = $this->entityPermission->newQuery();
|
||||
foreach ($entities as $entity) {
|
||||
$entityRestrictedMap[$entity->getMorphClass() . ':' . $entity->id] = boolval($entity->getRawAttribute('restricted'));
|
||||
$permissionFetch->orWhere(function($query) use ($entity) {
|
||||
$query->where('restrictable_id', '=', $entity->id)->where('restrictable_type', '=', $entity->getMorphClass());
|
||||
});
|
||||
}
|
||||
$permissions = $permissionFetch->get();
|
||||
|
||||
// Create a mapping of explicit entity permissions
|
||||
$permissionMap = [];
|
||||
foreach ($permissions as $permission) {
|
||||
$key = $permission->restrictable_type . ':' . $permission->restrictable_id . ':' . $permission->role_id . ':' . $permission->action;
|
||||
$isRestricted = $entityRestrictedMap[$permission->restrictable_type . ':' . $permission->restrictable_id];
|
||||
$permissionMap[$key] = $isRestricted;
|
||||
}
|
||||
|
||||
// Create a mapping of role permissions
|
||||
$rolePermissionMap = [];
|
||||
foreach ($roles as $role) {
|
||||
foreach ($role->getRelationValue('permissions') as $permission) {
|
||||
$rolePermissionMap[$role->getRawAttribute('id') . ':' . $permission->getRawAttribute('name')] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Create Joint Permission Data
|
||||
foreach ($entities as $entity) {
|
||||
foreach ($roles as $role) {
|
||||
foreach ($this->getActions($entity) as $action) {
|
||||
$jointPermissions[] = $this->createJointPermissionData($entity, $role, $action);
|
||||
$jointPermissions[] = $this->createJointPermissionData($entity, $role, $action, $permissionMap, $rolePermissionMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->jointPermission->insert($jointPermissions);
|
||||
|
||||
$this->db->transaction(function() use ($jointPermissions) {
|
||||
foreach (array_chunk($jointPermissions, 1000) as $jointPermissionChunk) {
|
||||
$this->db->table('joint_permissions')->insert($jointPermissionChunk);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the actions related to an entity.
|
||||
* @param $entity
|
||||
* @param Entity $entity
|
||||
* @return array
|
||||
*/
|
||||
protected function getActions($entity)
|
||||
protected function getActions(Entity $entity)
|
||||
{
|
||||
$baseActions = ['view', 'update', 'delete'];
|
||||
|
||||
if ($entity->isA('chapter')) {
|
||||
$baseActions[] = 'page-create';
|
||||
} else if ($entity->isA('book')) {
|
||||
$baseActions[] = 'page-create';
|
||||
$baseActions[] = 'chapter-create';
|
||||
}
|
||||
|
||||
return $baseActions;
|
||||
if ($entity->isA('chapter') || $entity->isA('book')) $baseActions[] = 'page-create';
|
||||
if ($entity->isA('book')) $baseActions[] = 'chapter-create';
|
||||
return $baseActions;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -298,14 +367,16 @@ class PermissionService
|
||||
* for a particular action.
|
||||
* @param Entity $entity
|
||||
* @param Role $role
|
||||
* @param $action
|
||||
* @param string $action
|
||||
* @param array $permissionMap
|
||||
* @param array $rolePermissionMap
|
||||
* @return array
|
||||
*/
|
||||
protected function createJointPermissionData(Entity $entity, Role $role, $action)
|
||||
protected function createJointPermissionData(Entity $entity, Role $role, $action, $permissionMap, $rolePermissionMap)
|
||||
{
|
||||
$permissionPrefix = (strpos($action, '-') === false ? ($entity->getType() . '-') : '') . $action;
|
||||
$roleHasPermission = $role->hasPermission($permissionPrefix . '-all');
|
||||
$roleHasPermissionOwn = $role->hasPermission($permissionPrefix . '-own');
|
||||
$roleHasPermission = isset($rolePermissionMap[$role->getRawAttribute('id') . ':' . $permissionPrefix . '-all']);
|
||||
$roleHasPermissionOwn = isset($rolePermissionMap[$role->getRawAttribute('id') . ':' . $permissionPrefix . '-own']);
|
||||
$explodedAction = explode('-', $action);
|
||||
$restrictionAction = end($explodedAction);
|
||||
|
||||
@@ -313,54 +384,46 @@ class PermissionService
|
||||
return $this->createJointPermissionDataArray($entity, $role, $action, true, true);
|
||||
}
|
||||
|
||||
if ($entity->isA('book')) {
|
||||
|
||||
if (!$entity->restricted) {
|
||||
return $this->createJointPermissionDataArray($entity, $role, $action, $roleHasPermission, $roleHasPermissionOwn);
|
||||
} else {
|
||||
$hasAccess = $entity->hasActiveRestriction($role->id, $restrictionAction);
|
||||
return $this->createJointPermissionDataArray($entity, $role, $action, $hasAccess, $hasAccess);
|
||||
}
|
||||
|
||||
} elseif ($entity->isA('chapter')) {
|
||||
|
||||
if (!$entity->restricted) {
|
||||
$book = $this->getBook($entity->book_id);
|
||||
$hasExplicitAccessToBook = $book->hasActiveRestriction($role->id, $restrictionAction);
|
||||
$hasPermissiveAccessToBook = !$book->restricted;
|
||||
return $this->createJointPermissionDataArray($entity, $role, $action,
|
||||
($hasExplicitAccessToBook || ($roleHasPermission && $hasPermissiveAccessToBook)),
|
||||
($hasExplicitAccessToBook || ($roleHasPermissionOwn && $hasPermissiveAccessToBook)));
|
||||
} else {
|
||||
$hasAccess = $entity->hasActiveRestriction($role->id, $restrictionAction);
|
||||
return $this->createJointPermissionDataArray($entity, $role, $action, $hasAccess, $hasAccess);
|
||||
}
|
||||
|
||||
} elseif ($entity->isA('page')) {
|
||||
|
||||
if (!$entity->restricted) {
|
||||
$book = $this->getBook($entity->book_id);
|
||||
$hasExplicitAccessToBook = $book->hasActiveRestriction($role->id, $restrictionAction);
|
||||
$hasPermissiveAccessToBook = !$book->restricted;
|
||||
|
||||
$chapter = $this->getChapter($entity->chapter_id);
|
||||
$hasExplicitAccessToChapter = $chapter && $chapter->hasActiveRestriction($role->id, $restrictionAction);
|
||||
$hasPermissiveAccessToChapter = $chapter && !$chapter->restricted;
|
||||
$acknowledgeChapter = ($chapter && $chapter->restricted);
|
||||
|
||||
$hasExplicitAccessToParents = $acknowledgeChapter ? $hasExplicitAccessToChapter : $hasExplicitAccessToBook;
|
||||
$hasPermissiveAccessToParents = $acknowledgeChapter ? $hasPermissiveAccessToChapter : $hasPermissiveAccessToBook;
|
||||
|
||||
return $this->createJointPermissionDataArray($entity, $role, $action,
|
||||
($hasExplicitAccessToParents || ($roleHasPermission && $hasPermissiveAccessToParents)),
|
||||
($hasExplicitAccessToParents || ($roleHasPermissionOwn && $hasPermissiveAccessToParents))
|
||||
);
|
||||
} else {
|
||||
$hasAccess = $entity->hasRestriction($role->id, $action);
|
||||
return $this->createJointPermissionDataArray($entity, $role, $action, $hasAccess, $hasAccess);
|
||||
}
|
||||
|
||||
if ($entity->restricted) {
|
||||
$hasAccess = $this->mapHasActiveRestriction($permissionMap, $entity, $role, $restrictionAction);
|
||||
return $this->createJointPermissionDataArray($entity, $role, $action, $hasAccess, $hasAccess);
|
||||
}
|
||||
|
||||
if ($entity->isA('book')) {
|
||||
return $this->createJointPermissionDataArray($entity, $role, $action, $roleHasPermission, $roleHasPermissionOwn);
|
||||
}
|
||||
|
||||
// For chapters and pages, Check if explicit permissions are set on the Book.
|
||||
$book = $this->getBook($entity->book_id);
|
||||
$hasExplicitAccessToParents = $this->mapHasActiveRestriction($permissionMap, $book, $role, $restrictionAction);
|
||||
$hasPermissiveAccessToParents = !$book->restricted;
|
||||
|
||||
// For pages with a chapter, Check if explicit permissions are set on the Chapter
|
||||
if ($entity->isA('page') && $entity->chapter_id !== 0 && $entity->chapter_id !== '0') {
|
||||
$chapter = $this->getChapter($entity->chapter_id);
|
||||
$hasPermissiveAccessToParents = $hasPermissiveAccessToParents && !$chapter->restricted;
|
||||
if ($chapter->restricted) {
|
||||
$hasExplicitAccessToParents = $this->mapHasActiveRestriction($permissionMap, $chapter, $role, $restrictionAction);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->createJointPermissionDataArray($entity, $role, $action,
|
||||
($hasExplicitAccessToParents || ($roleHasPermission && $hasPermissiveAccessToParents)),
|
||||
($hasExplicitAccessToParents || ($roleHasPermissionOwn && $hasPermissiveAccessToParents))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for an active restriction in an entity map.
|
||||
* @param $entityMap
|
||||
* @param Entity $entity
|
||||
* @param Role $role
|
||||
* @param $action
|
||||
* @return bool
|
||||
*/
|
||||
protected function mapHasActiveRestriction($entityMap, Entity $entity, Role $role, $action) {
|
||||
$key = $entity->getMorphClass() . ':' . $entity->getRawAttribute('id') . ':' . $role->getRawAttribute('id') . ':' . $action;
|
||||
return isset($entityMap[$key]) ? $entityMap[$key] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -375,11 +438,10 @@ class PermissionService
|
||||
*/
|
||||
protected function createJointPermissionDataArray(Entity $entity, Role $role, $action, $permissionAll, $permissionOwn)
|
||||
{
|
||||
$entityClass = get_class($entity);
|
||||
return [
|
||||
'role_id' => $role->getRawAttribute('id'),
|
||||
'entity_id' => $entity->getRawAttribute('id'),
|
||||
'entity_type' => $entityClass,
|
||||
'entity_type' => $entity->getMorphClass(),
|
||||
'action' => $action,
|
||||
'has_permission' => $permissionAll,
|
||||
'has_permission_own' => $permissionOwn,
|
||||
@@ -476,11 +538,10 @@ class PermissionService
|
||||
* @param integer $book_id
|
||||
* @param bool $filterDrafts
|
||||
* @param bool $fetchPageContent
|
||||
* @return \Illuminate\Database\Query\Builder
|
||||
* @return QueryBuilder
|
||||
*/
|
||||
public function bookChildrenQuery($book_id, $filterDrafts = false, $fetchPageContent = false) {
|
||||
$pageContentSelect = $fetchPageContent ? 'html' : "''";
|
||||
$pageSelect = $this->db->table('pages')->selectRaw("'BookStack\\\\Page' as entity_type, id, slug, name, text, {$pageContentSelect} as description, book_id, priority, chapter_id, draft")->where('book_id', '=', $book_id)->where(function($query) use ($filterDrafts) {
|
||||
$pageSelect = $this->db->table('pages')->selectRaw($this->page->entityRawQuery($fetchPageContent))->where('book_id', '=', $book_id)->where(function($query) use ($filterDrafts) {
|
||||
$query->where('draft', '=', 0);
|
||||
if (!$filterDrafts) {
|
||||
$query->orWhere(function($query) {
|
||||
@@ -488,7 +549,7 @@ class PermissionService
|
||||
});
|
||||
}
|
||||
});
|
||||
$chapterSelect = $this->db->table('chapters')->selectRaw("'BookStack\\\\Chapter' as entity_type, id, slug, name, '' as text, description, book_id, priority, 0 as chapter_id, 0 as draft")->where('book_id', '=', $book_id);
|
||||
$chapterSelect = $this->db->table('chapters')->selectRaw($this->chapter->entityRawQuery())->where('book_id', '=', $book_id);
|
||||
$query = $this->db->query()->select('*')->from($this->db->raw("({$pageSelect->toSql()} UNION {$chapterSelect->toSql()}) AS U"))
|
||||
->mergeBindings($pageSelect)->mergeBindings($chapterSelect);
|
||||
|
||||
@@ -514,7 +575,7 @@ class PermissionService
|
||||
* @param string $entityType
|
||||
* @param Builder|Entity $query
|
||||
* @param string $action
|
||||
* @return mixed
|
||||
* @return Builder
|
||||
*/
|
||||
public function enforceEntityRestrictions($entityType, $query, $action = 'view')
|
||||
{
|
||||
@@ -540,7 +601,7 @@ class PermissionService
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter items that have entities set a a polymorphic relation.
|
||||
* Filter items that have entities set as a polymorphic relation.
|
||||
* @param $query
|
||||
* @param string $tableName
|
||||
* @param string $entityIdColumn
|
||||
|
||||
482
app/Services/SearchService.php
Normal file
482
app/Services/SearchService.php
Normal file
@@ -0,0 +1,482 @@
|
||||
<?php namespace BookStack\Services;
|
||||
|
||||
use BookStack\Book;
|
||||
use BookStack\Chapter;
|
||||
use BookStack\Entity;
|
||||
use BookStack\Page;
|
||||
use BookStack\SearchTerm;
|
||||
use Illuminate\Database\Connection;
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class SearchService
|
||||
{
|
||||
protected $searchTerm;
|
||||
protected $book;
|
||||
protected $chapter;
|
||||
protected $page;
|
||||
protected $db;
|
||||
protected $permissionService;
|
||||
protected $entities;
|
||||
|
||||
/**
|
||||
* Acceptable operators to be used in a query
|
||||
* @var array
|
||||
*/
|
||||
protected $queryOperators = ['<=', '>=', '=', '<', '>', 'like', '!='];
|
||||
|
||||
/**
|
||||
* SearchService constructor.
|
||||
* @param SearchTerm $searchTerm
|
||||
* @param Book $book
|
||||
* @param Chapter $chapter
|
||||
* @param Page $page
|
||||
* @param Connection $db
|
||||
* @param PermissionService $permissionService
|
||||
*/
|
||||
public function __construct(SearchTerm $searchTerm, Book $book, Chapter $chapter, Page $page, Connection $db, PermissionService $permissionService)
|
||||
{
|
||||
$this->searchTerm = $searchTerm;
|
||||
$this->book = $book;
|
||||
$this->chapter = $chapter;
|
||||
$this->page = $page;
|
||||
$this->db = $db;
|
||||
$this->entities = [
|
||||
'page' => $this->page,
|
||||
'chapter' => $this->chapter,
|
||||
'book' => $this->book
|
||||
];
|
||||
$this->permissionService = $permissionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the database connection
|
||||
* @param Connection $connection
|
||||
*/
|
||||
public function setConnection(Connection $connection)
|
||||
{
|
||||
$this->db = $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search all entities in the system.
|
||||
* @param string $searchString
|
||||
* @param string $entityType
|
||||
* @param int $page
|
||||
* @param int $count
|
||||
* @return array[int, Collection];
|
||||
*/
|
||||
public function searchEntities($searchString, $entityType = 'all', $page = 1, $count = 20)
|
||||
{
|
||||
$terms = $this->parseSearchString($searchString);
|
||||
$entityTypes = array_keys($this->entities);
|
||||
$entityTypesToSearch = $entityTypes;
|
||||
$results = collect();
|
||||
|
||||
if ($entityType !== 'all') {
|
||||
$entityTypesToSearch = $entityType;
|
||||
} else if (isset($terms['filters']['type'])) {
|
||||
$entityTypesToSearch = explode('|', $terms['filters']['type']);
|
||||
}
|
||||
|
||||
$total = 0;
|
||||
|
||||
foreach ($entityTypesToSearch as $entityType) {
|
||||
if (!in_array($entityType, $entityTypes)) continue;
|
||||
$search = $this->searchEntityTable($terms, $entityType, $page, $count);
|
||||
$total += $this->searchEntityTable($terms, $entityType, $page, $count, true);
|
||||
$results = $results->merge($search);
|
||||
}
|
||||
|
||||
return [
|
||||
'total' => $total,
|
||||
'count' => count($results),
|
||||
'results' => $results->sortByDesc('score')
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Search a book for entities
|
||||
* @param integer $bookId
|
||||
* @param string $searchString
|
||||
* @return Collection
|
||||
*/
|
||||
public function searchBook($bookId, $searchString)
|
||||
{
|
||||
$terms = $this->parseSearchString($searchString);
|
||||
$entityTypes = ['page', 'chapter'];
|
||||
$entityTypesToSearch = isset($terms['filters']['type']) ? explode('|', $terms['filters']['type']) : $entityTypes;
|
||||
|
||||
$results = collect();
|
||||
foreach ($entityTypesToSearch as $entityType) {
|
||||
if (!in_array($entityType, $entityTypes)) continue;
|
||||
$search = $this->buildEntitySearchQuery($terms, $entityType)->where('book_id', '=', $bookId)->take(20)->get();
|
||||
$results = $results->merge($search);
|
||||
}
|
||||
return $results->sortByDesc('score')->take(20);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search a book for entities
|
||||
* @param integer $chapterId
|
||||
* @param string $searchString
|
||||
* @return Collection
|
||||
*/
|
||||
public function searchChapter($chapterId, $searchString)
|
||||
{
|
||||
$terms = $this->parseSearchString($searchString);
|
||||
$pages = $this->buildEntitySearchQuery($terms, 'page')->where('chapter_id', '=', $chapterId)->take(20)->get();
|
||||
return $pages->sortByDesc('score');
|
||||
}
|
||||
|
||||
/**
|
||||
* Search across a particular entity type.
|
||||
* @param array $terms
|
||||
* @param string $entityType
|
||||
* @param int $page
|
||||
* @param int $count
|
||||
* @param bool $getCount Return the total count of the search
|
||||
* @return \Illuminate\Database\Eloquent\Collection|int|static[]
|
||||
*/
|
||||
public function searchEntityTable($terms, $entityType = 'page', $page = 1, $count = 20, $getCount = false)
|
||||
{
|
||||
$query = $this->buildEntitySearchQuery($terms, $entityType);
|
||||
if ($getCount) return $query->count();
|
||||
|
||||
$query = $query->skip(($page-1) * $count)->take($count);
|
||||
return $query->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a search query for an entity
|
||||
* @param array $terms
|
||||
* @param string $entityType
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function buildEntitySearchQuery($terms, $entityType = 'page')
|
||||
{
|
||||
$entity = $this->getEntity($entityType);
|
||||
$entitySelect = $entity->newQuery();
|
||||
|
||||
// Handle normal search terms
|
||||
if (count($terms['search']) > 0) {
|
||||
$subQuery = $this->db->table('search_terms')->select('entity_id', 'entity_type', \DB::raw('SUM(score) as score'));
|
||||
$subQuery->where('entity_type', '=', 'BookStack\\' . ucfirst($entityType));
|
||||
$subQuery->where(function(Builder $query) use ($terms) {
|
||||
foreach ($terms['search'] as $inputTerm) {
|
||||
$query->orWhere('term', 'like', $inputTerm .'%');
|
||||
}
|
||||
})->groupBy('entity_type', 'entity_id');
|
||||
$entitySelect->join(\DB::raw('(' . $subQuery->toSql() . ') as s'), function(JoinClause $join) {
|
||||
$join->on('id', '=', 'entity_id');
|
||||
})->selectRaw($entity->getTable().'.*, s.score')->orderBy('score', 'desc');
|
||||
$entitySelect->mergeBindings($subQuery);
|
||||
}
|
||||
|
||||
// Handle exact term matching
|
||||
if (count($terms['exact']) > 0) {
|
||||
$entitySelect->where(function(\Illuminate\Database\Eloquent\Builder $query) use ($terms, $entity) {
|
||||
foreach ($terms['exact'] as $inputTerm) {
|
||||
$query->where(function (\Illuminate\Database\Eloquent\Builder $query) use ($inputTerm, $entity) {
|
||||
$query->where('name', 'like', '%'.$inputTerm .'%')
|
||||
->orWhere($entity->textField, 'like', '%'.$inputTerm .'%');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Handle tag searches
|
||||
foreach ($terms['tags'] as $inputTerm) {
|
||||
$this->applyTagSearch($entitySelect, $inputTerm);
|
||||
}
|
||||
|
||||
// Handle filters
|
||||
foreach ($terms['filters'] as $filterTerm => $filterValue) {
|
||||
$functionName = camel_case('filter_' . $filterTerm);
|
||||
if (method_exists($this, $functionName)) $this->$functionName($entitySelect, $entity, $filterValue);
|
||||
}
|
||||
|
||||
return $this->permissionService->enforceEntityRestrictions($entityType, $entitySelect, 'view');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse a search string into components.
|
||||
* @param $searchString
|
||||
* @return array
|
||||
*/
|
||||
protected function parseSearchString($searchString)
|
||||
{
|
||||
$terms = [
|
||||
'search' => [],
|
||||
'exact' => [],
|
||||
'tags' => [],
|
||||
'filters' => []
|
||||
];
|
||||
|
||||
$patterns = [
|
||||
'exact' => '/"(.*?)"/',
|
||||
'tags' => '/\[(.*?)\]/',
|
||||
'filters' => '/\{(.*?)\}/'
|
||||
];
|
||||
|
||||
// Parse special terms
|
||||
foreach ($patterns as $termType => $pattern) {
|
||||
$matches = [];
|
||||
preg_match_all($pattern, $searchString, $matches);
|
||||
if (count($matches) > 0) {
|
||||
$terms[$termType] = $matches[1];
|
||||
$searchString = preg_replace($pattern, '', $searchString);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse standard terms
|
||||
foreach (explode(' ', trim($searchString)) as $searchTerm) {
|
||||
if ($searchTerm !== '') $terms['search'][] = $searchTerm;
|
||||
}
|
||||
|
||||
// Split filter values out
|
||||
$splitFilters = [];
|
||||
foreach ($terms['filters'] as $filter) {
|
||||
$explodedFilter = explode(':', $filter, 2);
|
||||
$splitFilters[$explodedFilter[0]] = (count($explodedFilter) > 1) ? $explodedFilter[1] : '';
|
||||
}
|
||||
$terms['filters'] = $splitFilters;
|
||||
|
||||
return $terms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the available query operators as a regex escaped list.
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getRegexEscapedOperators()
|
||||
{
|
||||
$escapedOperators = [];
|
||||
foreach ($this->queryOperators as $operator) {
|
||||
$escapedOperators[] = preg_quote($operator);
|
||||
}
|
||||
return join('|', $escapedOperators);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a tag search term onto a entity query.
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param string $tagTerm
|
||||
* @return mixed
|
||||
*/
|
||||
protected function applyTagSearch(\Illuminate\Database\Eloquent\Builder $query, $tagTerm) {
|
||||
preg_match("/^(.*?)((".$this->getRegexEscapedOperators().")(.*?))?$/", $tagTerm, $tagSplit);
|
||||
$query->whereHas('tags', function(\Illuminate\Database\Eloquent\Builder $query) use ($tagSplit) {
|
||||
$tagName = $tagSplit[1];
|
||||
$tagOperator = count($tagSplit) > 2 ? $tagSplit[3] : '';
|
||||
$tagValue = count($tagSplit) > 3 ? $tagSplit[4] : '';
|
||||
$validOperator = in_array($tagOperator, $this->queryOperators);
|
||||
if (!empty($tagOperator) && !empty($tagValue) && $validOperator) {
|
||||
if (!empty($tagName)) $query->where('name', '=', $tagName);
|
||||
if (is_numeric($tagValue) && $tagOperator !== 'like') {
|
||||
// We have to do a raw sql query for this since otherwise PDO will quote the value and MySQL will
|
||||
// search the value as a string which prevents being able to do number-based operations
|
||||
// on the tag values. We ensure it has a numeric value and then cast it just to be sure.
|
||||
$tagValue = (float) trim($query->getConnection()->getPdo()->quote($tagValue), "'");
|
||||
$query->whereRaw("value ${tagOperator} ${tagValue}");
|
||||
} else {
|
||||
$query->where('value', $tagOperator, $tagValue);
|
||||
}
|
||||
} else {
|
||||
$query->where('name', '=', $tagName);
|
||||
}
|
||||
});
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an entity instance via type.
|
||||
* @param $type
|
||||
* @return Entity
|
||||
*/
|
||||
protected function getEntity($type)
|
||||
{
|
||||
return $this->entities[strtolower($type)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Index the given entity.
|
||||
* @param Entity $entity
|
||||
*/
|
||||
public function indexEntity(Entity $entity)
|
||||
{
|
||||
$this->deleteEntityTerms($entity);
|
||||
$nameTerms = $this->generateTermArrayFromText($entity->name, 5);
|
||||
$bodyTerms = $this->generateTermArrayFromText($entity->getText(), 1);
|
||||
$terms = array_merge($nameTerms, $bodyTerms);
|
||||
foreach ($terms as $index => $term) {
|
||||
$terms[$index]['entity_type'] = $entity->getMorphClass();
|
||||
$terms[$index]['entity_id'] = $entity->id;
|
||||
}
|
||||
$this->searchTerm->newQuery()->insert($terms);
|
||||
}
|
||||
|
||||
/**
|
||||
* Index multiple Entities at once
|
||||
* @param Entity[] $entities
|
||||
*/
|
||||
protected function indexEntities($entities) {
|
||||
$terms = [];
|
||||
foreach ($entities as $entity) {
|
||||
$nameTerms = $this->generateTermArrayFromText($entity->name, 5);
|
||||
$bodyTerms = $this->generateTermArrayFromText($entity->getText(), 1);
|
||||
foreach (array_merge($nameTerms, $bodyTerms) as $term) {
|
||||
$term['entity_id'] = $entity->id;
|
||||
$term['entity_type'] = $entity->getMorphClass();
|
||||
$terms[] = $term;
|
||||
}
|
||||
}
|
||||
|
||||
$chunkedTerms = array_chunk($terms, 500);
|
||||
foreach ($chunkedTerms as $termChunk) {
|
||||
$this->searchTerm->newQuery()->insert($termChunk);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete and re-index the terms for all entities in the system.
|
||||
*/
|
||||
public function indexAllEntities()
|
||||
{
|
||||
$this->searchTerm->truncate();
|
||||
|
||||
// Chunk through all books
|
||||
$this->book->chunk(1000, function ($books) {
|
||||
$this->indexEntities($books);
|
||||
});
|
||||
|
||||
// Chunk through all chapters
|
||||
$this->chapter->chunk(1000, function ($chapters) {
|
||||
$this->indexEntities($chapters);
|
||||
});
|
||||
|
||||
// Chunk through all pages
|
||||
$this->page->chunk(1000, function ($pages) {
|
||||
$this->indexEntities($pages);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete related Entity search terms.
|
||||
* @param Entity $entity
|
||||
*/
|
||||
public function deleteEntityTerms(Entity $entity)
|
||||
{
|
||||
$entity->searchTerms()->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a scored term array from the given text.
|
||||
* @param $text
|
||||
* @param float|int $scoreAdjustment
|
||||
* @return array
|
||||
*/
|
||||
protected function generateTermArrayFromText($text, $scoreAdjustment = 1)
|
||||
{
|
||||
$tokenMap = []; // {TextToken => OccurrenceCount}
|
||||
$splitText = explode(' ', $text);
|
||||
foreach ($splitText as $token) {
|
||||
if ($token === '') continue;
|
||||
if (!isset($tokenMap[$token])) $tokenMap[$token] = 0;
|
||||
$tokenMap[$token]++;
|
||||
}
|
||||
|
||||
$terms = [];
|
||||
foreach ($tokenMap as $token => $count) {
|
||||
$terms[] = [
|
||||
'term' => $token,
|
||||
'score' => $count * $scoreAdjustment
|
||||
];
|
||||
}
|
||||
return $terms;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Custom entity search filters
|
||||
*/
|
||||
|
||||
protected function filterUpdatedAfter(\Illuminate\Database\Eloquent\Builder $query, Entity $model, $input)
|
||||
{
|
||||
try { $date = date_create($input);
|
||||
} catch (\Exception $e) {return;}
|
||||
$query->where('updated_at', '>=', $date);
|
||||
}
|
||||
|
||||
protected function filterUpdatedBefore(\Illuminate\Database\Eloquent\Builder $query, Entity $model, $input)
|
||||
{
|
||||
try { $date = date_create($input);
|
||||
} catch (\Exception $e) {return;}
|
||||
$query->where('updated_at', '<', $date);
|
||||
}
|
||||
|
||||
protected function filterCreatedAfter(\Illuminate\Database\Eloquent\Builder $query, Entity $model, $input)
|
||||
{
|
||||
try { $date = date_create($input);
|
||||
} catch (\Exception $e) {return;}
|
||||
$query->where('created_at', '>=', $date);
|
||||
}
|
||||
|
||||
protected function filterCreatedBefore(\Illuminate\Database\Eloquent\Builder $query, Entity $model, $input)
|
||||
{
|
||||
try { $date = date_create($input);
|
||||
} catch (\Exception $e) {return;}
|
||||
$query->where('created_at', '<', $date);
|
||||
}
|
||||
|
||||
protected function filterCreatedBy(\Illuminate\Database\Eloquent\Builder $query, Entity $model, $input)
|
||||
{
|
||||
if (!is_numeric($input) && $input !== 'me') return;
|
||||
if ($input === 'me') $input = user()->id;
|
||||
$query->where('created_by', '=', $input);
|
||||
}
|
||||
|
||||
protected function filterUpdatedBy(\Illuminate\Database\Eloquent\Builder $query, Entity $model, $input)
|
||||
{
|
||||
if (!is_numeric($input) && $input !== 'me') return;
|
||||
if ($input === 'me') $input = user()->id;
|
||||
$query->where('updated_by', '=', $input);
|
||||
}
|
||||
|
||||
protected function filterInName(\Illuminate\Database\Eloquent\Builder $query, Entity $model, $input)
|
||||
{
|
||||
$query->where('name', 'like', '%' .$input. '%');
|
||||
}
|
||||
|
||||
protected function filterInTitle(\Illuminate\Database\Eloquent\Builder $query, Entity $model, $input) {$this->filterInName($query, $model, $input);}
|
||||
|
||||
protected function filterInBody(\Illuminate\Database\Eloquent\Builder $query, Entity $model, $input)
|
||||
{
|
||||
$query->where($model->textField, 'like', '%' .$input. '%');
|
||||
}
|
||||
|
||||
protected function filterIsRestricted(\Illuminate\Database\Eloquent\Builder $query, Entity $model, $input)
|
||||
{
|
||||
$query->where('restricted', '=', true);
|
||||
}
|
||||
|
||||
protected function filterViewedByMe(\Illuminate\Database\Eloquent\Builder $query, Entity $model, $input)
|
||||
{
|
||||
$query->whereHas('views', function($query) {
|
||||
$query->where('user_id', '=', user()->id);
|
||||
});
|
||||
}
|
||||
|
||||
protected function filterNotViewedByMe(\Illuminate\Database\Eloquent\Builder $query, Entity $model, $input)
|
||||
{
|
||||
$query->whereDoesntHave('views', function($query) {
|
||||
$query->where('user_id', '=', user()->id);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -47,6 +47,14 @@
|
||||
"post-create-project-cmd": [
|
||||
"php artisan key:generate"
|
||||
],
|
||||
"pre-update-cmd": [
|
||||
"php -r \"!file_exists('bootstrap/cache/services.php') || @unlink('bootstrap/cache/services.php');\"",
|
||||
"php -r \"!file_exists('bootstrap/cache/compiled.php') || @unlink('bootstrap/cache/compiled.php');\""
|
||||
],
|
||||
"pre-install-cmd": [
|
||||
"php -r \"!file_exists('bootstrap/cache/services.php') || @unlink('bootstrap/cache/services.php');\"",
|
||||
"php -r \"!file_exists('bootstrap/cache/compiled.php') || @unlink('bootstrap/cache/compiled.php');\""
|
||||
],
|
||||
"post-install-cmd": [
|
||||
"Illuminate\\Foundation\\ComposerScripts::postInstall",
|
||||
"php artisan optimize",
|
||||
@@ -56,6 +64,10 @@
|
||||
"post-update-cmd": [
|
||||
"Illuminate\\Foundation\\ComposerScripts::postUpdate",
|
||||
"php artisan optimize"
|
||||
],
|
||||
"refresh-test-database": [
|
||||
"php artisan migrate:refresh --database=mysql_testing",
|
||||
"php artisan db:seed --class=DummyContentSeeder --database=mysql_testing"
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
|
||||
@@ -58,6 +58,7 @@ return [
|
||||
*/
|
||||
|
||||
'locale' => env('APP_LANG', 'en'),
|
||||
'locales' => ['en', 'de', 'es', 'fr', 'nl', 'pt_BR', 'sk'],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -100,7 +101,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'log' => 'single',
|
||||
'log' => env('APP_LOGGING', 'single'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
||||
@@ -43,7 +43,8 @@ $factory->define(BookStack\Page::class, function ($faker) {
|
||||
'name' => $faker->sentence,
|
||||
'slug' => str_random(10),
|
||||
'html' => $html,
|
||||
'text' => strip_tags($html)
|
||||
'text' => strip_tags($html),
|
||||
'revision_count' => 1
|
||||
];
|
||||
});
|
||||
|
||||
|
||||
@@ -12,9 +12,10 @@ class AddSearchIndexes extends Migration
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
DB::statement('ALTER TABLE pages ADD FULLTEXT search(name, text)');
|
||||
DB::statement('ALTER TABLE books ADD FULLTEXT search(name, description)');
|
||||
DB::statement('ALTER TABLE chapters ADD FULLTEXT search(name, description)');
|
||||
$prefix = DB::getTablePrefix();
|
||||
DB::statement("ALTER TABLE {$prefix}pages ADD FULLTEXT search(name, text)");
|
||||
DB::statement("ALTER TABLE {$prefix}books ADD FULLTEXT search(name, description)");
|
||||
DB::statement("ALTER TABLE {$prefix}chapters ADD FULLTEXT search(name, description)");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,9 +12,10 @@ class FulltextWeighting extends Migration
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
DB::statement('ALTER TABLE pages ADD FULLTEXT name_search(name)');
|
||||
DB::statement('ALTER TABLE books ADD FULLTEXT name_search(name)');
|
||||
DB::statement('ALTER TABLE chapters ADD FULLTEXT name_search(name)');
|
||||
$prefix = DB::getTablePrefix();
|
||||
DB::statement("ALTER TABLE {$prefix}pages ADD FULLTEXT name_search(name)");
|
||||
DB::statement("ALTER TABLE {$prefix}books ADD FULLTEXT name_search(name)");
|
||||
DB::statement("ALTER TABLE {$prefix}chapters ADD FULLTEXT name_search(name)");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateSearchIndexTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('search_terms', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('term', 200);
|
||||
$table->string('entity_type', 100);
|
||||
$table->integer('entity_id');
|
||||
$table->integer('score');
|
||||
|
||||
$table->index('term');
|
||||
$table->index('entity_type');
|
||||
$table->index(['entity_type', 'entity_id']);
|
||||
$table->index('score');
|
||||
});
|
||||
|
||||
// Drop search indexes
|
||||
Schema::table('pages', function(Blueprint $table) {
|
||||
$table->dropIndex('search');
|
||||
$table->dropIndex('name_search');
|
||||
});
|
||||
Schema::table('books', function(Blueprint $table) {
|
||||
$table->dropIndex('search');
|
||||
$table->dropIndex('name_search');
|
||||
});
|
||||
Schema::table('chapters', function(Blueprint $table) {
|
||||
$table->dropIndex('search');
|
||||
$table->dropIndex('name_search');
|
||||
});
|
||||
|
||||
app(\BookStack\Services\SearchService::class)->indexAllEntities();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
$prefix = DB::getTablePrefix();
|
||||
DB::statement("ALTER TABLE {$prefix}pages ADD FULLTEXT search(name, text)");
|
||||
DB::statement("ALTER TABLE {$prefix}books ADD FULLTEXT search(name, description)");
|
||||
DB::statement("ALTER TABLE {$prefix}chapters ADD FULLTEXT search(name, description)");
|
||||
DB::statement("ALTER TABLE {$prefix}pages ADD FULLTEXT name_search(name)");
|
||||
DB::statement("ALTER TABLE {$prefix}books ADD FULLTEXT name_search(name)");
|
||||
DB::statement("ALTER TABLE {$prefix}chapters ADD FULLTEXT name_search(name)");
|
||||
|
||||
Schema::dropIfExists('search_terms');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddRevisionCounts extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('pages', function (Blueprint $table) {
|
||||
$table->integer('revision_count');
|
||||
});
|
||||
Schema::table('page_revisions', function (Blueprint $table) {
|
||||
$table->integer('revision_number');
|
||||
$table->index('revision_number');
|
||||
});
|
||||
|
||||
// Update revision count
|
||||
$pTable = DB::getTablePrefix() . 'pages';
|
||||
$rTable = DB::getTablePrefix() . 'page_revisions';
|
||||
DB::statement("UPDATE ${pTable} SET ${pTable}.revision_count=(SELECT count(*) FROM ${rTable} WHERE ${rTable}.page_id=${pTable}.id)");
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('pages', function (Blueprint $table) {
|
||||
$table->dropColumn('revision_count');
|
||||
});
|
||||
Schema::table('page_revisions', function (Blueprint $table) {
|
||||
$table->dropColumn('revision_number');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ class DummyContentSeeder extends Seeder
|
||||
$user->attachRole($role);
|
||||
|
||||
|
||||
$books = factory(\BookStack\Book::class, 20)->create(['created_by' => $user->id, 'updated_by' => $user->id])
|
||||
factory(\BookStack\Book::class, 20)->create(['created_by' => $user->id, 'updated_by' => $user->id])
|
||||
->each(function($book) use ($user) {
|
||||
$chapters = factory(\BookStack\Chapter::class, 5)->create(['created_by' => $user->id, 'updated_by' => $user->id])
|
||||
->each(function($chapter) use ($user, $book){
|
||||
@@ -28,7 +28,13 @@ class DummyContentSeeder extends Seeder
|
||||
$book->pages()->saveMany($pages);
|
||||
});
|
||||
|
||||
$restrictionService = app(\BookStack\Services\PermissionService::class);
|
||||
$restrictionService->buildJointPermissions();
|
||||
$largeBook = factory(\BookStack\Book::class)->create(['name' => 'Large book' . str_random(10), 'created_by' => $user->id, 'updated_by' => $user->id]);
|
||||
$pages = factory(\BookStack\Page::class, 200)->make(['created_by' => $user->id, 'updated_by' => $user->id]);
|
||||
$chapters = factory(\BookStack\Chapter::class, 50)->make(['created_by' => $user->id, 'updated_by' => $user->id]);
|
||||
$largeBook->pages()->saveMany($pages);
|
||||
$largeBook->chapters()->saveMany($chapters);
|
||||
|
||||
app(\BookStack\Services\PermissionService::class)->buildJointPermissions();
|
||||
app(\BookStack\Services\SearchService::class)->indexAllEntities();
|
||||
}
|
||||
}
|
||||
|
||||
67
gulpfile.js
67
gulpfile.js
@@ -1,8 +1,63 @@
|
||||
var elixir = require('laravel-elixir');
|
||||
const argv = require('yargs').argv;
|
||||
const gulp = require('gulp'),
|
||||
plumber = require('gulp-plumber');
|
||||
const autoprefixer = require('gulp-autoprefixer');
|
||||
const uglify = require('gulp-uglify');
|
||||
const minifycss = require('gulp-clean-css');
|
||||
const sass = require('gulp-sass');
|
||||
const browserify = require("browserify");
|
||||
const source = require('vinyl-source-stream');
|
||||
const buffer = require('vinyl-buffer');
|
||||
const babelify = require("babelify");
|
||||
const watchify = require("watchify");
|
||||
const envify = require("envify");
|
||||
const gutil = require("gulp-util");
|
||||
|
||||
elixir(mix => {
|
||||
mix.sass('styles.scss');
|
||||
mix.sass('print-styles.scss');
|
||||
mix.sass('export-styles.scss');
|
||||
mix.browserify('global.js', './public/js/common.js');
|
||||
if (argv.production) process.env.NODE_ENV = 'production';
|
||||
|
||||
gulp.task('styles', () => {
|
||||
let chain = gulp.src(['resources/assets/sass/**/*.scss'])
|
||||
.pipe(plumber({
|
||||
errorHandler: function (error) {
|
||||
console.log(error.message);
|
||||
this.emit('end');
|
||||
}}))
|
||||
.pipe(sass())
|
||||
.pipe(autoprefixer('last 2 versions'));
|
||||
if (argv.production) chain = chain.pipe(minifycss());
|
||||
return chain.pipe(gulp.dest('public/css/'));
|
||||
});
|
||||
|
||||
|
||||
function scriptTask(watch=false) {
|
||||
|
||||
let props = {
|
||||
basedir: 'resources/assets/js',
|
||||
debug: true,
|
||||
entries: ['global.js']
|
||||
};
|
||||
|
||||
let bundler = watch ? watchify(browserify(props), { poll: true }) : browserify(props);
|
||||
bundler.transform(envify, {global: true}).transform(babelify, {presets: ['es2015']});
|
||||
function rebundle() {
|
||||
let stream = bundler.bundle();
|
||||
stream = stream.pipe(source('common.js'));
|
||||
if (argv.production) stream = stream.pipe(buffer()).pipe(uglify());
|
||||
return stream.pipe(gulp.dest('public/js/'));
|
||||
}
|
||||
bundler.on('update', function() {
|
||||
rebundle();
|
||||
gutil.log('Rebundle...');
|
||||
});
|
||||
bundler.on('log', gutil.log);
|
||||
return rebundle();
|
||||
}
|
||||
|
||||
gulp.task('scripts', () => {scriptTask(false)});
|
||||
gulp.task('scripts-watch', () => {scriptTask(true)});
|
||||
|
||||
gulp.task('default', ['styles', 'scripts-watch'], () => {
|
||||
gulp.watch("resources/assets/sass/**/*.scss", ['styles']);
|
||||
});
|
||||
|
||||
gulp.task('build', ['styles', 'scripts']);
|
||||
42
package.json
42
package.json
@@ -1,24 +1,44 @@
|
||||
{
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "gulp --production",
|
||||
"dev": "gulp watch",
|
||||
"watch": "gulp watch"
|
||||
"build": "gulp build",
|
||||
"production": "gulp build --production",
|
||||
"dev": "gulp",
|
||||
"watch": "gulp"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babelify": "^7.3.0",
|
||||
"browserify": "^14.3.0",
|
||||
"envify": "^4.0.0",
|
||||
"gulp": "3.9.1",
|
||||
"gulp-autoprefixer": "3.1.1",
|
||||
"gulp-clean-css": "^3.0.4",
|
||||
"gulp-minify-css": "1.2.4",
|
||||
"gulp-plumber": "1.1.0",
|
||||
"gulp-sass": "3.1.0",
|
||||
"gulp-uglify": "2.1.2",
|
||||
"vinyl-buffer": "^1.0.0",
|
||||
"vinyl-source-stream": "^1.1.0",
|
||||
"watchify": "^3.9.0",
|
||||
"yargs": "^7.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"angular": "^1.5.5",
|
||||
"angular-animate": "^1.5.5",
|
||||
"angular-resource": "^1.5.5",
|
||||
"angular-sanitize": "^1.5.5",
|
||||
"angular-ui-sortable": "^0.15.0",
|
||||
"angular-ui-sortable": "^0.17.0",
|
||||
"axios": "^0.16.1",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"clipboard": "^1.5.16",
|
||||
"dropzone": "^4.0.1",
|
||||
"gulp": "^3.9.0",
|
||||
"laravel-elixir": "^6.0.0-11",
|
||||
"laravel-elixir-browserify-official": "^0.1.3",
|
||||
"marked": "^0.3.5",
|
||||
"moment": "^2.12.0"
|
||||
"gulp-util": "^3.0.8",
|
||||
"markdown-it": "^8.3.1",
|
||||
"markdown-it-task-lists": "^2.0.0",
|
||||
"moment": "^2.12.0",
|
||||
"vue": "^2.2.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"clipboard": "^1.5.16"
|
||||
"browser": {
|
||||
"vue": "vue/dist/vue.common.js"
|
||||
}
|
||||
}
|
||||
|
||||
2
public/css/export-styles.css
vendored
2
public/css/export-styles.css
vendored
File diff suppressed because one or more lines are too long
2
public/css/print-styles.css
vendored
2
public/css/print-styles.css
vendored
@@ -1 +1 @@
|
||||
.faded-small,.print-hidden,header{display:none}body{font-size:12px}.page-content{margin:0 auto}.print-full-width{width:100%;float:none;display:block}h2{font-size:2em;line-height:1;margin-top:.6em;margin-bottom:.3em}
|
||||
header{display:none}body{font-size:12px}.faded-small{display:none}.page-content{margin:0 auto}.print-hidden{display:none}.print-full-width{width:100%;float:none;display:block}h2{font-size:2em;line-height:1;margin-top:.6em;margin-bottom:.3em}
|
||||
2
public/css/styles.css
vendored
2
public/css/styles.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -43,6 +43,8 @@ Once done you can run `phpunit` in the application root directory to run all tes
|
||||
## Translations
|
||||
|
||||
As part of BookStack v0.14 support for translations has been built in. All text strings can be found in the `resources/lang` folder where each language option has its own folder. To add a new language you should copy the `en` folder to an new folder (eg. `fr` for french) then go through and translate all text strings in those files, leaving the keys and file-names intact. If a language string is missing then the `en` translation will be used. To show the language option in the user preferences language drop-down you will need to add your language to the options found at the bottom of the `resources/lang/en/settings.php` file. A system-wide language can also be set in the `.env` file like so: `APP_LANG=en`.
|
||||
|
||||
You will also need to add the language to the `locales` array in the `config/app.php` file.
|
||||
|
||||
Some strings have colon-prefixed variables in such as `:userName`. Leave these values as they are as they will be replaced at run-time.
|
||||
|
||||
@@ -74,7 +76,7 @@ These are the great projects used to help build BookStack:
|
||||
* [Dropzone.js](http://www.dropzonejs.com/)
|
||||
* [ZeroClipboard](http://zeroclipboard.org/)
|
||||
* [TinyColorPicker](http://www.dematte.at/tinyColorPicker/index.html)
|
||||
* [Marked](https://github.com/chjj/marked)
|
||||
* [markdown-it](https://github.com/markdown-it/markdown-it) and [markdown-it-task-lists](https://github.com/revin/markdown-it-task-lists)
|
||||
* [Moment.js](http://momentjs.com/)
|
||||
* [BarryVD](https://github.com/barryvdh)
|
||||
* [Debugbar](https://github.com/barryvdh/laravel-debugbar)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
"use strict";
|
||||
|
||||
import moment from 'moment';
|
||||
import 'moment/locale/en-gb';
|
||||
import editorOptions from "./pages/page-form";
|
||||
const moment = require('moment');
|
||||
require('moment/locale/en-gb');
|
||||
const editorOptions = require("./pages/page-form");
|
||||
|
||||
moment.locale('en-gb');
|
||||
|
||||
export default function (ngApp, events) {
|
||||
module.exports = function (ngApp, events) {
|
||||
|
||||
ngApp.controller('ImageManagerController', ['$scope', '$attrs', '$http', '$timeout', 'imageManagerService',
|
||||
function ($scope, $attrs, $http, $timeout, imageManagerService) {
|
||||
@@ -259,39 +259,6 @@ export default function (ngApp, events) {
|
||||
|
||||
}]);
|
||||
|
||||
|
||||
ngApp.controller('BookShowController', ['$scope', '$http', '$attrs', '$sce', function ($scope, $http, $attrs, $sce) {
|
||||
$scope.searching = false;
|
||||
$scope.searchTerm = '';
|
||||
$scope.searchResults = '';
|
||||
|
||||
$scope.searchBook = function (e) {
|
||||
e.preventDefault();
|
||||
let term = $scope.searchTerm;
|
||||
if (term.length == 0) return;
|
||||
$scope.searching = true;
|
||||
$scope.searchResults = '';
|
||||
let searchUrl = window.baseUrl('/search/book/' + $attrs.bookId);
|
||||
searchUrl += '?term=' + encodeURIComponent(term);
|
||||
$http.get(searchUrl).then((response) => {
|
||||
$scope.searchResults = $sce.trustAsHtml(response.data);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.checkSearchForm = function () {
|
||||
if ($scope.searchTerm.length < 1) {
|
||||
$scope.searching = false;
|
||||
}
|
||||
};
|
||||
|
||||
$scope.clearSearch = function () {
|
||||
$scope.searching = false;
|
||||
$scope.searchTerm = '';
|
||||
};
|
||||
|
||||
}]);
|
||||
|
||||
|
||||
ngApp.controller('PageEditController', ['$scope', '$http', '$attrs', '$interval', '$timeout', '$sce',
|
||||
function ($scope, $http, $attrs, $interval, $timeout, $sce) {
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
"use strict";
|
||||
import DropZone from "dropzone";
|
||||
import markdown from "marked";
|
||||
const DropZone = require("dropzone");
|
||||
const MarkdownIt = require("markdown-it");
|
||||
const mdTasksLists = require('markdown-it-task-lists');
|
||||
|
||||
export default function (ngApp, events) {
|
||||
module.exports = function (ngApp, events) {
|
||||
|
||||
/**
|
||||
* Common tab controls using simple jQuery functions.
|
||||
@@ -214,18 +215,8 @@ export default function (ngApp, events) {
|
||||
}
|
||||
}]);
|
||||
|
||||
let renderer = new markdown.Renderer();
|
||||
// Custom markdown checkbox list item
|
||||
// Attribution: https://github.com/chjj/marked/issues/107#issuecomment-44542001
|
||||
renderer.listitem = function(text) {
|
||||
if (/^\s*\[[x ]\]\s*/.test(text)) {
|
||||
text = text
|
||||
.replace(/^\s*\[ \]\s*/, '<input type="checkbox"/>')
|
||||
.replace(/^\s*\[x\]\s*/, '<input type="checkbox" checked/>');
|
||||
return `<li class="checkbox-item">${text}</li>`;
|
||||
}
|
||||
return `<li>${text}</li>`;
|
||||
};
|
||||
const md = new MarkdownIt({html: true});
|
||||
md.use(mdTasksLists, {label: true});
|
||||
|
||||
/**
|
||||
* Markdown input
|
||||
@@ -244,20 +235,20 @@ export default function (ngApp, events) {
|
||||
element = element.find('textarea').first();
|
||||
let content = element.val();
|
||||
scope.mdModel = content;
|
||||
scope.mdChange(markdown(content, {renderer: renderer}));
|
||||
scope.mdChange(md.render(content));
|
||||
|
||||
element.on('change input', (event) => {
|
||||
content = element.val();
|
||||
$timeout(() => {
|
||||
scope.mdModel = content;
|
||||
scope.mdChange(markdown(content, {renderer: renderer}));
|
||||
scope.mdChange(md.render(content));
|
||||
});
|
||||
});
|
||||
|
||||
scope.$on('markdown-update', (event, value) => {
|
||||
element.val(value);
|
||||
scope.mdModel = value;
|
||||
scope.mdChange(markdown(value));
|
||||
scope.mdChange(md.render(value));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
// AngularJS - Create application and load components
|
||||
import angular from "angular";
|
||||
import "angular-resource";
|
||||
import "angular-animate";
|
||||
import "angular-sanitize";
|
||||
import "angular-ui-sortable";
|
||||
|
||||
// Url retrieval function
|
||||
window.baseUrl = function(path) {
|
||||
let basePath = document.querySelector('meta[name="base-url"]').getAttribute('content');
|
||||
@@ -15,11 +8,33 @@ window.baseUrl = function(path) {
|
||||
return basePath + '/' + path;
|
||||
};
|
||||
|
||||
const Vue = require("vue");
|
||||
const axios = require("axios");
|
||||
|
||||
let axiosInstance = axios.create({
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name=token]').getAttribute('content'),
|
||||
'baseURL': window.baseUrl('')
|
||||
}
|
||||
});
|
||||
|
||||
Vue.prototype.$http = axiosInstance;
|
||||
|
||||
require("./vues/vues");
|
||||
|
||||
|
||||
// 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
|
||||
import Translations from "./translations"
|
||||
const Translations = require("./translations");
|
||||
let translator = new Translations(window.translations);
|
||||
window.trans = translator.get.bind(translator);
|
||||
|
||||
@@ -47,11 +62,12 @@ class EventManager {
|
||||
}
|
||||
|
||||
window.Events = new EventManager();
|
||||
Vue.prototype.$events = window.Events;
|
||||
|
||||
// Load in angular specific items
|
||||
import Services from './services';
|
||||
import Directives from './directives';
|
||||
import Controllers from './controllers';
|
||||
const Services = require('./services');
|
||||
const Directives = require('./directives');
|
||||
const Controllers = require('./controllers');
|
||||
Services(ngApp, window.Events);
|
||||
Directives(ngApp, window.Events);
|
||||
Controllers(ngApp, window.Events);
|
||||
@@ -154,4 +170,4 @@ if(navigator.userAgent.indexOf('MSIE')!==-1
|
||||
}
|
||||
|
||||
// Page specific items
|
||||
import "./pages/page-show";
|
||||
require("./pages/page-show");
|
||||
|
||||
@@ -60,7 +60,7 @@ function registerEditorShortcuts(editor) {
|
||||
editor.addShortcut('meta+shift+E', '', ['FormatBlock', false, 'code']);
|
||||
}
|
||||
|
||||
export default function() {
|
||||
module.exports = function() {
|
||||
let settings = {
|
||||
selector: '#html-editor',
|
||||
content_css: [
|
||||
@@ -68,6 +68,7 @@ export default function() {
|
||||
window.baseUrl('/libs/material-design-iconic-font/css/material-design-iconic-font.min.css')
|
||||
],
|
||||
body_class: 'page-content',
|
||||
browser_spellcheck: true,
|
||||
relative_urls: false,
|
||||
remove_script_host: false,
|
||||
document_base_url: window.baseUrl('/'),
|
||||
@@ -213,4 +214,4 @@ export default function() {
|
||||
}
|
||||
};
|
||||
return settings;
|
||||
}
|
||||
};
|
||||
@@ -1,8 +1,8 @@
|
||||
"use strict";
|
||||
// Configure ZeroClipboard
|
||||
import Clipboard from "clipboard";
|
||||
const Clipboard = require("clipboard");
|
||||
|
||||
export default window.setupPageShow = function (pageId) {
|
||||
let setupPageShow = window.setupPageShow = function (pageId) {
|
||||
|
||||
// Set up pointer
|
||||
let $pointer = $('#pointer').detach();
|
||||
@@ -81,6 +81,12 @@ export default window.setupPageShow = function (pageId) {
|
||||
let $idElem = $(idElem);
|
||||
let color = $('#custom-styles').attr('data-color-light');
|
||||
$idElem.css('background-color', color).attr('data-highlighted', 'true').smoothScrollTo();
|
||||
setTimeout(() => {
|
||||
$idElem.addClass('anim').addClass('selectFade').css('background-color', '');
|
||||
setTimeout(() => {
|
||||
$idElem.removeClass('selectFade');
|
||||
}, 3000);
|
||||
}, 100);
|
||||
} else {
|
||||
$('.page-content').find(':contains("' + text + '")').smoothScrollTo();
|
||||
}
|
||||
@@ -151,3 +157,5 @@ export default window.setupPageShow = function (pageId) {
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
module.exports = setupPageShow;
|
||||
@@ -44,4 +44,4 @@ class Translator {
|
||||
|
||||
}
|
||||
|
||||
export default Translator
|
||||
module.exports = Translator;
|
||||
|
||||
44
resources/assets/js/vues/entity-search.js
Normal file
44
resources/assets/js/vues/entity-search.js
Normal file
@@ -0,0 +1,44 @@
|
||||
let data = {
|
||||
id: null,
|
||||
type: '',
|
||||
searching: false,
|
||||
searchTerm: '',
|
||||
searchResults: '',
|
||||
};
|
||||
|
||||
let computed = {
|
||||
|
||||
};
|
||||
|
||||
let methods = {
|
||||
|
||||
searchBook() {
|
||||
if (this.searchTerm.trim().length === 0) return;
|
||||
this.searching = true;
|
||||
this.searchResults = '';
|
||||
let url = window.baseUrl(`/search/${this.type}/${this.id}`);
|
||||
url += `?term=${encodeURIComponent(this.searchTerm)}`;
|
||||
this.$http.get(url).then(resp => {
|
||||
this.searchResults = resp.data;
|
||||
});
|
||||
},
|
||||
|
||||
checkSearchForm() {
|
||||
this.searching = this.searchTerm > 0;
|
||||
},
|
||||
|
||||
clearSearch() {
|
||||
this.searching = false;
|
||||
this.searchTerm = '';
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
function mounted() {
|
||||
this.id = Number(this.$el.getAttribute('entity-id'));
|
||||
this.type = this.$el.getAttribute('entity-type');
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
data, computed, methods, mounted
|
||||
};
|
||||
195
resources/assets/js/vues/search.js
Normal file
195
resources/assets/js/vues/search.js
Normal file
@@ -0,0 +1,195 @@
|
||||
const moment = require('moment');
|
||||
|
||||
let data = {
|
||||
terms: '',
|
||||
termString : '',
|
||||
search: {
|
||||
type: {
|
||||
page: true,
|
||||
chapter: true,
|
||||
book: true
|
||||
},
|
||||
exactTerms: [],
|
||||
tagTerms: [],
|
||||
option: {},
|
||||
dates: {
|
||||
updated_after: false,
|
||||
updated_before: false,
|
||||
created_after: false,
|
||||
created_before: false,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let computed = {
|
||||
|
||||
};
|
||||
|
||||
let methods = {
|
||||
|
||||
appendTerm(term) {
|
||||
this.termString += ' ' + term;
|
||||
this.termString = this.termString.replace(/\s{2,}/g, ' ');
|
||||
this.termString = this.termString.replace(/^\s+/, '');
|
||||
this.termString = this.termString.replace(/\s+$/, '');
|
||||
},
|
||||
|
||||
exactParse(searchString) {
|
||||
this.search.exactTerms = [];
|
||||
let exactFilter = /"(.+?)"/g;
|
||||
let matches;
|
||||
while ((matches = exactFilter.exec(searchString)) !== null) {
|
||||
this.search.exactTerms.push(matches[1]);
|
||||
}
|
||||
},
|
||||
|
||||
exactChange() {
|
||||
let exactFilter = /"(.+?)"/g;
|
||||
this.termString = this.termString.replace(exactFilter, '');
|
||||
let matchesTerm = this.search.exactTerms.filter(term => {
|
||||
return term.trim() !== '';
|
||||
}).map(term => {
|
||||
return `"${term}"`
|
||||
}).join(' ');
|
||||
this.appendTerm(matchesTerm);
|
||||
},
|
||||
|
||||
addExact() {
|
||||
this.search.exactTerms.push('');
|
||||
setTimeout(() => {
|
||||
let exactInputs = document.querySelectorAll('.exact-input');
|
||||
exactInputs[exactInputs.length - 1].focus();
|
||||
}, 100);
|
||||
},
|
||||
|
||||
removeExact(index) {
|
||||
this.search.exactTerms.splice(index, 1);
|
||||
this.exactChange();
|
||||
},
|
||||
|
||||
tagParse(searchString) {
|
||||
this.search.tagTerms = [];
|
||||
let tagFilter = /\[(.+?)\]/g;
|
||||
let matches;
|
||||
while ((matches = tagFilter.exec(searchString)) !== null) {
|
||||
this.search.tagTerms.push(matches[1]);
|
||||
}
|
||||
},
|
||||
|
||||
tagChange() {
|
||||
let tagFilter = /\[(.+?)\]/g;
|
||||
this.termString = this.termString.replace(tagFilter, '');
|
||||
let matchesTerm = this.search.tagTerms.filter(term => {
|
||||
return term.trim() !== '';
|
||||
}).map(term => {
|
||||
return `[${term}]`
|
||||
}).join(' ');
|
||||
this.appendTerm(matchesTerm);
|
||||
},
|
||||
|
||||
addTag() {
|
||||
this.search.tagTerms.push('');
|
||||
setTimeout(() => {
|
||||
let tagInputs = document.querySelectorAll('.tag-input');
|
||||
tagInputs[tagInputs.length - 1].focus();
|
||||
}, 100);
|
||||
},
|
||||
|
||||
removeTag(index) {
|
||||
this.search.tagTerms.splice(index, 1);
|
||||
this.tagChange();
|
||||
},
|
||||
|
||||
typeParse(searchString) {
|
||||
let typeFilter = /{\s?type:\s?(.*?)\s?}/;
|
||||
let match = searchString.match(typeFilter);
|
||||
let type = this.search.type;
|
||||
if (!match) {
|
||||
type.page = type.book = type.chapter = true;
|
||||
return;
|
||||
}
|
||||
let splitTypes = match[1].replace(/ /g, '').split('|');
|
||||
type.page = (splitTypes.indexOf('page') !== -1);
|
||||
type.chapter = (splitTypes.indexOf('chapter') !== -1);
|
||||
type.book = (splitTypes.indexOf('book') !== -1);
|
||||
},
|
||||
|
||||
typeChange() {
|
||||
let typeFilter = /{\s?type:\s?(.*?)\s?}/;
|
||||
let type = this.search.type;
|
||||
if (type.page === type.chapter && type.page === type.book) {
|
||||
this.termString = this.termString.replace(typeFilter, '');
|
||||
return;
|
||||
}
|
||||
let selectedTypes = Object.keys(type).filter(type => {return this.search.type[type];}).join('|');
|
||||
let typeTerm = '{type:'+selectedTypes+'}';
|
||||
if (this.termString.match(typeFilter)) {
|
||||
this.termString = this.termString.replace(typeFilter, typeTerm);
|
||||
return;
|
||||
}
|
||||
this.appendTerm(typeTerm);
|
||||
},
|
||||
|
||||
optionParse(searchString) {
|
||||
let optionFilter = /{([a-z_\-:]+?)}/gi;
|
||||
let matches;
|
||||
while ((matches = optionFilter.exec(searchString)) !== null) {
|
||||
this.search.option[matches[1].toLowerCase()] = true;
|
||||
}
|
||||
},
|
||||
|
||||
optionChange(optionName) {
|
||||
let isChecked = this.search.option[optionName];
|
||||
if (isChecked) {
|
||||
this.appendTerm(`{${optionName}}`);
|
||||
} else {
|
||||
this.termString = this.termString.replace(`{${optionName}}`, '');
|
||||
}
|
||||
},
|
||||
|
||||
updateSearch(e) {
|
||||
e.preventDefault();
|
||||
window.location = '/search?term=' + encodeURIComponent(this.termString);
|
||||
},
|
||||
|
||||
enableDate(optionName) {
|
||||
this.search.dates[optionName.toLowerCase()] = moment().format('YYYY-MM-DD');
|
||||
this.dateChange(optionName);
|
||||
},
|
||||
|
||||
dateParse(searchString) {
|
||||
let dateFilter = /{([a-z_\-]+?):([a-z_\-0-9]+?)}/gi;
|
||||
let dateTags = Object.keys(this.search.dates);
|
||||
let matches;
|
||||
while ((matches = dateFilter.exec(searchString)) !== null) {
|
||||
if (dateTags.indexOf(matches[1]) === -1) continue;
|
||||
this.search.dates[matches[1].toLowerCase()] = matches[2];
|
||||
}
|
||||
},
|
||||
|
||||
dateChange(optionName) {
|
||||
let dateFilter = new RegExp('{\\s?'+optionName+'\\s?:([a-z_\\-0-9]+?)}', 'gi');
|
||||
this.termString = this.termString.replace(dateFilter, '');
|
||||
if (!this.search.dates[optionName]) return;
|
||||
this.appendTerm(`{${optionName}:${this.search.dates[optionName]}}`);
|
||||
},
|
||||
|
||||
dateRemove(optionName) {
|
||||
this.search.dates[optionName] = false;
|
||||
this.dateChange(optionName);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
function created() {
|
||||
this.termString = document.querySelector('[name=searchTerm]').value;
|
||||
this.typeParse(this.termString);
|
||||
this.exactParse(this.termString);
|
||||
this.tagParse(this.termString);
|
||||
this.optionParse(this.termString);
|
||||
this.dateParse(this.termString);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
data, computed, methods, created
|
||||
};
|
||||
18
resources/assets/js/vues/vues.js
Normal file
18
resources/assets/js/vues/vues.js
Normal file
@@ -0,0 +1,18 @@
|
||||
const Vue = require("vue");
|
||||
|
||||
function exists(id) {
|
||||
return document.getElementById(id) !== null;
|
||||
}
|
||||
|
||||
let vueMapping = {
|
||||
'search-system': require('./search'),
|
||||
'entity-dashboard': require('./entity-search'),
|
||||
};
|
||||
|
||||
Object.keys(vueMapping).forEach(id => {
|
||||
if (exists(id)) {
|
||||
let config = vueMapping[id];
|
||||
config.el = '#' + id;
|
||||
new Vue(config);
|
||||
}
|
||||
});
|
||||
@@ -2,7 +2,7 @@
|
||||
.anim.fadeIn {
|
||||
opacity: 0;
|
||||
animation-name: fadeIn;
|
||||
animation-duration: 160ms;
|
||||
animation-duration: 180ms;
|
||||
animation-timing-function: ease-in-out;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
@@ -126,4 +126,8 @@
|
||||
animation-duration: 180ms;
|
||||
animation-delay: 0s;
|
||||
animation-timing-function: cubic-bezier(.62, .28, .23, .99);
|
||||
}
|
||||
|
||||
.anim.selectFade {
|
||||
transition: background-color ease-in-out 3000ms;
|
||||
}
|
||||
@@ -98,19 +98,36 @@ label {
|
||||
|
||||
label.radio, label.checkbox {
|
||||
font-weight: 400;
|
||||
user-select: none;
|
||||
input[type="radio"], input[type="checkbox"] {
|
||||
margin-right: $-xs;
|
||||
}
|
||||
}
|
||||
|
||||
label.inline.checkbox {
|
||||
margin-right: $-m;
|
||||
}
|
||||
|
||||
label + p.small {
|
||||
margin-bottom: 0.8em;
|
||||
}
|
||||
|
||||
input[type="text"], input[type="number"], input[type="email"], input[type="search"], input[type="url"], input[type="password"], select, textarea {
|
||||
table.form-table {
|
||||
max-width: 100%;
|
||||
td {
|
||||
overflow: hidden;
|
||||
padding: $-xxs/2 0;
|
||||
}
|
||||
}
|
||||
|
||||
input[type="text"], input[type="number"], input[type="email"], input[type="date"], input[type="search"], input[type="url"], input[type="password"], select, textarea {
|
||||
@extend .input-base;
|
||||
}
|
||||
|
||||
input[type=date] {
|
||||
width: 190px;
|
||||
}
|
||||
|
||||
.toggle-switch {
|
||||
display: inline-block;
|
||||
background-color: #BBB;
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
transition-property: right, border;
|
||||
border-left: 0px solid #FFF;
|
||||
background-color: #FFF;
|
||||
max-width: 320px;
|
||||
&.fixed {
|
||||
background-color: #FFF;
|
||||
z-index: 5;
|
||||
|
||||
@@ -269,19 +269,31 @@ span.highlight {
|
||||
/*
|
||||
* Lists
|
||||
*/
|
||||
ul, ol {
|
||||
overflow: hidden;
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
ul {
|
||||
padding-left: $-m * 1.3;
|
||||
list-style: disc;
|
||||
overflow: hidden;
|
||||
ul {
|
||||
list-style: circle;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
label {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
ol {
|
||||
list-style: decimal;
|
||||
padding-left: $-m * 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
li.checkbox-item {
|
||||
li.checkbox-item, li.task-list-item {
|
||||
list-style: none;
|
||||
margin-left: - ($-m * 1.3);
|
||||
input[type="checkbox"] {
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
@import "grid";
|
||||
@import "blocks";
|
||||
@import "buttons";
|
||||
@import "forms";
|
||||
@import "tables";
|
||||
@import "forms";
|
||||
@import "animations";
|
||||
@import "tinymce";
|
||||
@import "highlightjs";
|
||||
@@ -17,7 +17,11 @@
|
||||
@import "lists";
|
||||
@import "pages";
|
||||
|
||||
[v-cloak], [v-show] {display: none;}
|
||||
[v-cloak], [v-show] {
|
||||
display: none; opacity: 0;
|
||||
animation-name: none !important;
|
||||
}
|
||||
|
||||
|
||||
[ng\:cloak], [ng-cloak], .ng-cloak {
|
||||
display: none !important;
|
||||
@@ -272,8 +276,3 @@ $btt-size: 40px;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -26,6 +26,10 @@ return [
|
||||
'no_pages_viewed' => 'Sie haben bisher keine Seiten angesehen.',
|
||||
'no_pages_recently_created' => 'Sie haben bisher keine Seiten angelegt.',
|
||||
'no_pages_recently_updated' => 'Sie haben bisher keine Seiten aktualisiert.',
|
||||
'export' => 'Exportieren',
|
||||
'export_html' => 'HTML-Datei',
|
||||
'export_pdf' => 'PDF-Datei',
|
||||
'export_text' => 'Text-Datei',
|
||||
|
||||
/**
|
||||
* Permissions and restrictions
|
||||
@@ -39,18 +43,9 @@ return [
|
||||
* Search
|
||||
*/
|
||||
'search_results' => 'Suchergebnisse',
|
||||
'search_results_page' => 'Seiten-Suchergebnisse',
|
||||
'search_results_chapter' => 'Kapitel-Suchergebnisse',
|
||||
'search_results_book' => 'Buch-Suchergebnisse',
|
||||
'search_clear' => 'Suche zurücksetzen',
|
||||
'search_view_pages' => 'Zeige alle passenden Seiten',
|
||||
'search_view_chapters' => 'Zeige alle passenden Kapitel',
|
||||
'search_view_books' => 'Zeige alle passenden Bücher',
|
||||
'search_no_pages' => 'Es wurden keine passenden Suchergebnisse gefunden',
|
||||
'search_for_term' => 'Suche nach :term',
|
||||
'search_page_for_term' => 'Suche nach :term in Seiten',
|
||||
'search_chapter_for_term' => 'Suche nach :term in Kapiteln',
|
||||
'search_book_for_term' => 'Suche nach :term in Büchern',
|
||||
|
||||
/**
|
||||
* Books
|
||||
@@ -160,10 +155,6 @@ return [
|
||||
'pages_revisions_preview' => 'Vorschau',
|
||||
'pages_revisions_restore' => 'Zurück sichern',
|
||||
'pages_revisions_none' => 'Diese Seite hat keine älteren Versionen.',
|
||||
'pages_export' => 'Exportieren',
|
||||
'pages_export_html' => 'HTML-Datei',
|
||||
'pages_export_pdf' => 'PDF-Datei',
|
||||
'pages_export_text' => 'Text-Datei',
|
||||
'pages_copy_link' => 'Link kopieren',
|
||||
'pages_permissions_active' => 'Seiten-Berechtigungen aktiv',
|
||||
'pages_initial_revision' => 'Erste Veröffentlichung',
|
||||
|
||||
@@ -33,6 +33,7 @@ return [
|
||||
'search_clear' => 'Clear Search',
|
||||
'reset' => 'Reset',
|
||||
'remove' => 'Remove',
|
||||
'add' => 'Add',
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,6 +14,7 @@ return [
|
||||
'recent_activity' => 'Recent Activity',
|
||||
'create_now' => 'Create one now',
|
||||
'revisions' => 'Revisions',
|
||||
'meta_revision' => 'Revision #:revisionCount',
|
||||
'meta_created' => 'Created :timeLength',
|
||||
'meta_created_name' => 'Created :timeLength by :user',
|
||||
'meta_updated' => 'Updated :timeLength',
|
||||
@@ -26,6 +27,10 @@ return [
|
||||
'no_pages_viewed' => 'You have not viewed any pages',
|
||||
'no_pages_recently_created' => 'No pages have been recently created',
|
||||
'no_pages_recently_updated' => 'No pages have been recently updated',
|
||||
'export' => 'Export',
|
||||
'export_html' => 'Contained Web File',
|
||||
'export_pdf' => 'PDF File',
|
||||
'export_text' => 'Plain Text File',
|
||||
|
||||
/**
|
||||
* Permissions and restrictions
|
||||
@@ -39,18 +44,26 @@ return [
|
||||
* Search
|
||||
*/
|
||||
'search_results' => 'Search Results',
|
||||
'search_results_page' => 'Page Search Results',
|
||||
'search_results_chapter' => 'Chapter Search Results',
|
||||
'search_results_book' => 'Book Search Results',
|
||||
'search_total_results_found' => ':count result found|:count total results found',
|
||||
'search_clear' => 'Clear Search',
|
||||
'search_view_pages' => 'View all matches pages',
|
||||
'search_view_chapters' => 'View all matches chapters',
|
||||
'search_view_books' => 'View all matches books',
|
||||
'search_no_pages' => 'No pages matched this search',
|
||||
'search_for_term' => 'Search for :term',
|
||||
'search_page_for_term' => 'Page search for :term',
|
||||
'search_chapter_for_term' => 'Chapter search for :term',
|
||||
'search_book_for_term' => 'Books search for :term',
|
||||
'search_more' => 'More Results',
|
||||
'search_filters' => 'Search Filters',
|
||||
'search_content_type' => 'Content Type',
|
||||
'search_exact_matches' => 'Exact Matches',
|
||||
'search_tags' => 'Tag Searches',
|
||||
'search_viewed_by_me' => 'Viewed by me',
|
||||
'search_not_viewed_by_me' => 'Not viewed by me',
|
||||
'search_permissions_set' => 'Permissions set',
|
||||
'search_created_by_me' => 'Created by me',
|
||||
'search_updated_by_me' => 'Updated by me',
|
||||
'search_updated_before' => 'Updated before',
|
||||
'search_updated_after' => 'Updated after',
|
||||
'search_created_before' => 'Created before',
|
||||
'search_created_after' => 'Created after',
|
||||
'search_set_date' => 'Set Date',
|
||||
'search_update' => 'Update Search',
|
||||
|
||||
/**
|
||||
* Books
|
||||
@@ -108,6 +121,7 @@ return [
|
||||
'chapters_empty' => 'No pages are currently in this chapter.',
|
||||
'chapters_permissions_active' => 'Chapter Permissions Active',
|
||||
'chapters_permissions_success' => 'Chapter Permissions Updated',
|
||||
'chapters_search_this' => 'Search this chapter',
|
||||
|
||||
/**
|
||||
* Pages
|
||||
@@ -155,16 +169,13 @@ return [
|
||||
'pages_revision_named' => 'Page Revision for :pageName',
|
||||
'pages_revisions_created_by' => 'Created By',
|
||||
'pages_revisions_date' => 'Revision Date',
|
||||
'pages_revisions_number' => '#',
|
||||
'pages_revisions_changelog' => 'Changelog',
|
||||
'pages_revisions_changes' => 'Changes',
|
||||
'pages_revisions_current' => 'Current Version',
|
||||
'pages_revisions_preview' => 'Preview',
|
||||
'pages_revisions_restore' => 'Restore',
|
||||
'pages_revisions_none' => 'This page has no revisions',
|
||||
'pages_export' => 'Export',
|
||||
'pages_export_html' => 'Contained Web File',
|
||||
'pages_export_pdf' => 'PDF File',
|
||||
'pages_export_text' => 'Plain Text File',
|
||||
'pages_copy_link' => 'Copy Link',
|
||||
'pages_permissions_active' => 'Page Permissions Active',
|
||||
'pages_initial_revision' => 'Initial publish',
|
||||
|
||||
@@ -116,8 +116,11 @@ return [
|
||||
'language_select' => [
|
||||
'en' => 'English',
|
||||
'de' => 'Deutsch',
|
||||
'es' => 'Español',
|
||||
'fr' => 'Français',
|
||||
'pt_BR' => 'Português do Brasil'
|
||||
'nl' => 'Nederlands',
|
||||
'pt_BR' => 'Português do Brasil',
|
||||
'sk' => 'Slovensky',
|
||||
]
|
||||
///////////////////////////////////
|
||||
];
|
||||
|
||||
40
resources/lang/es/activities.php
Normal file
40
resources/lang/es/activities.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/**
|
||||
* Activity text strings.
|
||||
* Is used for all the text within activity logs & notifications.
|
||||
*/
|
||||
|
||||
// Pages
|
||||
'page_create' => 'página creada',
|
||||
'page_create_notification' => 'Página creada exitosamente',
|
||||
'page_update' => 'página actualizada',
|
||||
'page_update_notification' => 'Página actualizada exitosamente',
|
||||
'page_delete' => 'página borrada',
|
||||
'page_delete_notification' => 'Página borrada exitosamente',
|
||||
'page_restore' => 'página restaurada',
|
||||
'page_restore_notification' => 'Página restaurada exitosamente',
|
||||
'page_move' => 'página movida',
|
||||
|
||||
// Chapters
|
||||
'chapter_create' => 'capítulo creado',
|
||||
'chapter_create_notification' => 'Capítulo creado exitosamente',
|
||||
'chapter_update' => 'capítulo actualizado',
|
||||
'chapter_update_notification' => 'Capítulo actualizado exitosamente',
|
||||
'chapter_delete' => 'capítulo borrado',
|
||||
'chapter_delete_notification' => 'Capítulo borrado exitosamente',
|
||||
'chapter_move' => 'capítulo movido',
|
||||
|
||||
// Books
|
||||
'book_create' => 'libro creado',
|
||||
'book_create_notification' => 'Libro creado exitosamente',
|
||||
'book_update' => 'libro actualizado',
|
||||
'book_update_notification' => 'Libro actualizado exitosamente',
|
||||
'book_delete' => 'libro borrado',
|
||||
'book_delete_notification' => 'Libro borrado exitosamente',
|
||||
'book_sort' => 'libro ordenado',
|
||||
'book_sort_notification' => 'Libro re-ordenado exitosamente',
|
||||
|
||||
];
|
||||
74
resources/lang/es/auth.php
Normal file
74
resources/lang/es/auth.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
return [
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Authentication Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are used during authentication for various
|
||||
| messages that we need to display to the user. You are free to modify
|
||||
| these language lines according to your application's requirements.
|
||||
|
|
||||
*/
|
||||
'failed' => 'Las credenciales no concuerdan con nuestros registros.',
|
||||
'throttle' => 'Demasiados intentos fallidos de conexión. Por favor intente nuevamente en :seconds segundos.',
|
||||
|
||||
/**
|
||||
* Login & Register
|
||||
*/
|
||||
'sign_up' => 'Inscribete',
|
||||
'log_in' => 'Log in',
|
||||
'logout' => 'Logout',
|
||||
|
||||
'name' => 'Nombre',
|
||||
'username' => 'Username',
|
||||
'email' => 'Email',
|
||||
'password' => 'Password',
|
||||
'password_confirm' => 'Confirmar Password',
|
||||
'password_hint' => 'Debe contener al menos 5 caracteres',
|
||||
'forgot_password' => 'Olvidó Password?',
|
||||
'remember_me' => 'Recordarme',
|
||||
'ldap_email_hint' => 'Por favor introduzca un mail para utilizar con esta cuenta.',
|
||||
'create_account' => 'Crear una cuenta',
|
||||
'social_login' => 'Login Social',
|
||||
'social_registration' => 'Registro Social',
|
||||
'social_registration_text' => 'Registrar y entrar utilizando otro servicio.',
|
||||
|
||||
'register_thanks' => 'Gracias por registrarse!',
|
||||
'register_confirm' => 'Por favor chequee su email y haga clic en el botón de confirmación enviado para acceder a :appName.',
|
||||
'registrations_disabled' => 'Los registros están deshabilitados actualmente',
|
||||
'registration_email_domain_invalid' => 'Este dominio de Email no tiene acceso a esta aplicación',
|
||||
'register_success' => 'Gracias por registrarse! Ahora se encuentra registrado y logueado.',
|
||||
|
||||
|
||||
/**
|
||||
* Password Reset
|
||||
*/
|
||||
'reset_password' => 'Reset Password',
|
||||
'reset_password_send_instructions' => 'Introduzca su email a continuación y le será enviado un correo con un link para la restauración',
|
||||
'reset_password_send_button' => 'Enviar Link de Reset',
|
||||
'reset_password_sent_success' => 'Un link para resetear password ha sido enviado a :email.',
|
||||
'reset_password_success' => 'Su password ha sido reiniciado de manera éxitosa.',
|
||||
|
||||
'email_reset_subject' => 'Reset de su password de :appName',
|
||||
'email_reset_text' => 'Ud. esta recibiendo este email debido a que recibimos una solicitud de reset de password de su cuenta.',
|
||||
'email_reset_not_requested' => 'Si ud. no solicitó un reset de password, no es requerida ninguna acción.',
|
||||
|
||||
|
||||
/**
|
||||
* Email Confirmation
|
||||
*/
|
||||
'email_confirm_subject' => 'Confirme su email en :appName',
|
||||
'email_confirm_greeting' => 'Gracias por unirse a :appName!',
|
||||
'email_confirm_text' => 'Por favor confirme su dirección de email haciendo click en el siguiente botón:',
|
||||
'email_confirm_action' => 'Confirmar Email',
|
||||
'email_confirm_send_error' => 'Confirmation de email requerida pero el sistema no pudo enviar el mail. Contacte al administrador para asegurarse que el email está seteado correctamente.',
|
||||
'email_confirm_success' => 'Su email hasido confirmado!',
|
||||
'email_confirm_resent' => 'Email de confirmación reenviado, Por favor chequee su Inbox.',
|
||||
|
||||
'email_not_confirmed' => 'Dirección de email no confirmada',
|
||||
'email_not_confirmed_text' => 'Su cuenta de email todavía no ha sido confirmada.',
|
||||
'email_not_confirmed_click_link' => 'Por favor chequee el email con el link de confirmación que ha sido enviado luego de registrarse.',
|
||||
'email_not_confirmed_resend' => 'Si no puede encontrar el email, puede solicitar el renvío del email de confirmación rellenando el formulario a continuación.',
|
||||
'email_not_confirmed_resend_button' => 'Reenviar Email de confirmación',
|
||||
];
|
||||
58
resources/lang/es/common.php
Normal file
58
resources/lang/es/common.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
return [
|
||||
|
||||
/**
|
||||
* Buttons
|
||||
*/
|
||||
'cancel' => 'Cancelar',
|
||||
'confirm' => 'Confirmar',
|
||||
'back' => 'Atrás',
|
||||
'save' => 'Guardar',
|
||||
'continue' => 'Continuar',
|
||||
'select' => 'Seleccionar',
|
||||
|
||||
/**
|
||||
* Form Labels
|
||||
*/
|
||||
'name' => 'Nombre',
|
||||
'description' => 'Descripción',
|
||||
'role' => 'Rol',
|
||||
|
||||
/**
|
||||
* Actions
|
||||
*/
|
||||
'actions' => 'Acciones',
|
||||
'view' => 'Ver',
|
||||
'create' => 'Crear',
|
||||
'update' => 'Actualizar',
|
||||
'edit' => 'Editar',
|
||||
'sort' => 'Ordenar',
|
||||
'move' => 'Mover',
|
||||
'delete' => 'Borrar',
|
||||
'search' => 'Buscar',
|
||||
'search_clear' => 'Limpiar búsqueda',
|
||||
'reset' => 'Reset',
|
||||
'remove' => 'Remover',
|
||||
|
||||
|
||||
/**
|
||||
* Misc
|
||||
*/
|
||||
'deleted_user' => 'Usuario borrado',
|
||||
'no_activity' => 'Ninguna actividad para mostrar',
|
||||
'no_items' => 'No hay items disponibles',
|
||||
'back_to_top' => 'Volver arriba',
|
||||
'toggle_details' => 'Alternar detalles',
|
||||
|
||||
/**
|
||||
* Header
|
||||
*/
|
||||
'view_profile' => 'Ver Perfil',
|
||||
'edit_profile' => 'Editar Perfil',
|
||||
|
||||
/**
|
||||
* Email Content
|
||||
*/
|
||||
'email_action_help' => 'Si está teniendo problemas haga click en el botón ":actionText", copie y pegue la siguiente URL en su navegador web:',
|
||||
'email_rights' => 'Todos los derechos reservados',
|
||||
];
|
||||
24
resources/lang/es/components.php
Normal file
24
resources/lang/es/components.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
return [
|
||||
|
||||
/**
|
||||
* Image Manager
|
||||
*/
|
||||
'image_select' => 'Seleccionar Imagen',
|
||||
'image_all' => 'Todo',
|
||||
'image_all_title' => 'Ver todas las imágenes',
|
||||
'image_book_title' => 'Ver las imágenes subidas a este libro',
|
||||
'image_page_title' => 'Ver las imágenes subidas a esta página',
|
||||
'image_search_hint' => 'Buscar por nombre de imagen',
|
||||
'image_uploaded' => 'Subido el :uploadedDate',
|
||||
'image_load_more' => 'Cargar más',
|
||||
'image_image_name' => 'Nombre de imagen',
|
||||
'image_delete_confirm' => 'Esta imagen esta siendo utilizada en las páginas a continuación, haga click de nuevo para confirmar que quiere borrar esta imagen.',
|
||||
'image_select_image' => 'Seleccionar Imagen',
|
||||
'image_dropzone' => 'Arrastre las imágenes o hacer click aquí para Subir',
|
||||
'images_deleted' => 'Imágenes borradas',
|
||||
'image_preview' => 'Preview de la imagen',
|
||||
'image_upload_success' => 'Imagen subida éxitosamente',
|
||||
'image_update_success' => 'Detalles de la imagen actualizados exitosamente',
|
||||
'image_delete_success' => 'Imagen borrada exitosamente'
|
||||
];
|
||||
217
resources/lang/es/entities.php
Normal file
217
resources/lang/es/entities.php
Normal file
@@ -0,0 +1,217 @@
|
||||
<?php
|
||||
return [
|
||||
|
||||
/**
|
||||
* Shared
|
||||
*/
|
||||
'recently_created' => 'Recientemente creado',
|
||||
'recently_created_pages' => 'Páginas recientemente creadas',
|
||||
'recently_updated_pages' => 'Páginas recientemente actualizadas',
|
||||
'recently_created_chapters' => 'Capítulos recientemente creados',
|
||||
'recently_created_books' => 'Libros recientemente creados',
|
||||
'recently_update' => 'Recientemente actualizado',
|
||||
'recently_viewed' => 'Recientemente visto',
|
||||
'recent_activity' => 'Actividad reciente',
|
||||
'create_now' => 'Crear uno ahora',
|
||||
'revisions' => 'Revisiones',
|
||||
'meta_created' => 'Creado el :timeLength',
|
||||
'meta_created_name' => 'Creado el :timeLength por :user',
|
||||
'meta_updated' => 'Actualizado el :timeLength',
|
||||
'meta_updated_name' => 'Actualizado el :timeLength por :user',
|
||||
'x_pages' => ':count Páginas',
|
||||
'entity_select' => 'Seleccione entidad',
|
||||
'images' => 'Imágenes',
|
||||
'my_recent_drafts' => 'Mis borradores recientes',
|
||||
'my_recently_viewed' => 'Mis visualizaciones recientes',
|
||||
'no_pages_viewed' => 'Ud. no ha visto ninguna página',
|
||||
'no_pages_recently_created' => 'Ninguna página ha sido creada recientemente',
|
||||
'no_pages_recently_updated' => 'Ninguna página ha sido actualizada recientemente',
|
||||
'export' => 'Export',
|
||||
'export_html' => 'Contained Web File',
|
||||
'export_pdf' => 'PDF File',
|
||||
'export_text' => 'Plain Text File',
|
||||
|
||||
/**
|
||||
* Permissions and restrictions
|
||||
*/
|
||||
'permissions' => 'Permisos',
|
||||
'permissions_intro' => 'una vez habilitado, Estos permisos tendrán prioridad por encima de cualquier permiso establecido.',
|
||||
'permissions_enable' => 'Habilitar permisos custom',
|
||||
'permissions_save' => 'Guardar permisos',
|
||||
|
||||
/**
|
||||
* Search
|
||||
*/
|
||||
'search_results' => 'Buscar resultados',
|
||||
'search_clear' => 'Limpiar resultados',
|
||||
'search_no_pages' => 'Ninguna página encontrada para la búsqueda',
|
||||
'search_for_term' => 'Busqueda por :term',
|
||||
|
||||
/**
|
||||
* Books
|
||||
*/
|
||||
'book' => 'Libro',
|
||||
'books' => 'Libros',
|
||||
'books_empty' => 'No hay libros creados',
|
||||
'books_popular' => 'Libros populares',
|
||||
'books_recent' => 'Libros recientes',
|
||||
'books_popular_empty' => 'Los libros más populares aparecerán aquí.',
|
||||
'books_create' => 'Crear nuevo libro',
|
||||
'books_delete' => 'Borrar libro',
|
||||
'books_delete_named' => 'Borrar libro :bookName',
|
||||
'books_delete_explain' => 'Esto borrará el libro con el nombre \':bookName\', Todos las páginas y capítulos serán removios.',
|
||||
'books_delete_confirmation' => '¿Está seguro de que desea borrar este libro?',
|
||||
'books_edit' => 'Editar Libro',
|
||||
'books_edit_named' => 'Editar Libro :bookName',
|
||||
'books_form_book_name' => 'Nombre de libro',
|
||||
'books_save' => 'Guardar libro',
|
||||
'books_permissions' => 'permisos de libro',
|
||||
'books_permissions_updated' => 'Permisos de libro actualizados',
|
||||
'books_empty_contents' => 'Ninguna página o capítulo ha sido creada para este libro.',
|
||||
'books_empty_create_page' => 'Crear una nueva página',
|
||||
'books_empty_or' => 'ó',
|
||||
'books_empty_sort_current_book' => 'Organizar el libro actual',
|
||||
'books_empty_add_chapter' => 'Agregar un capítulo',
|
||||
'books_permissions_active' => 'Permisos de libro activados',
|
||||
'books_search_this' => 'Buscar en este libro',
|
||||
'books_navigation' => 'Navegación de libro',
|
||||
'books_sort' => 'Organizar contenido de libro',
|
||||
'books_sort_named' => 'Organizar libro :bookName',
|
||||
'books_sort_show_other' => 'Mostrar otros libros',
|
||||
'books_sort_save' => 'Guardar nuevo orden',
|
||||
|
||||
/**
|
||||
* Chapters
|
||||
*/
|
||||
'chapter' => 'Capítulo',
|
||||
'chapters' => 'Capítulos',
|
||||
'chapters_popular' => 'Capítulos populares',
|
||||
'chapters_new' => 'Nuevo capítulo',
|
||||
'chapters_create' => 'Crear nuevo capítulo',
|
||||
'chapters_delete' => 'Borrar capítulo',
|
||||
'chapters_delete_named' => 'Borrar capítulo :chapterName',
|
||||
'chapters_delete_explain' => 'Esto borrará el caítulo con el nombre \':chapterName\', todas las páginas serán removidas
|
||||
y agregadas directamente al libro padre.',
|
||||
'chapters_delete_confirm' => 'Está ud. seguro de borrar este capítulo?',
|
||||
'chapters_edit' => 'Editar capítulo',
|
||||
'chapters_edit_named' => 'Editar capítulo :chapterName',
|
||||
'chapters_save' => 'Guardar capítulo',
|
||||
'chapters_move' => 'Mover capítulo',
|
||||
'chapters_move_named' => 'Mover Capítulo :chapterName',
|
||||
'chapter_move_success' => 'Capítulo movido a :bookName',
|
||||
'chapters_permissions' => 'Permisos de capítulo',
|
||||
'chapters_empty' => 'No existen páginas en este capítulo.',
|
||||
'chapters_permissions_active' => 'Permisos de capítulo activado',
|
||||
'chapters_permissions_success' => 'Permisos de capítulo actualizados',
|
||||
|
||||
/**
|
||||
* Pages
|
||||
*/
|
||||
'page' => 'Página',
|
||||
'pages' => 'Páginas',
|
||||
'pages_popular' => 'Páginas populares',
|
||||
'pages_new' => 'Nueva página',
|
||||
'pages_attachments' => 'Adjuntos',
|
||||
'pages_navigation' => 'Navegación de página',
|
||||
'pages_delete' => 'Borrar página',
|
||||
'pages_delete_named' => 'Borrar página :pageName',
|
||||
'pages_delete_draft_named' => 'Borrar borrador de página :pageName',
|
||||
'pages_delete_draft' => 'Borrar borrador de página',
|
||||
'pages_delete_success' => 'Página borrada',
|
||||
'pages_delete_draft_success' => 'Borrador de página borrado',
|
||||
'pages_delete_confirm' => 'Está ud. seguro de borrar esta página ?',
|
||||
'pages_delete_draft_confirm' => 'Está ud. seguro de que desea borrar este borrador de página?',
|
||||
'pages_editing_named' => 'Editando página :pageName',
|
||||
'pages_edit_toggle_header' => 'Toggle Título',
|
||||
'pages_edit_save_draft' => 'Guardar borrador',
|
||||
'pages_edit_draft' => 'Editar borrador de página',
|
||||
'pages_editing_draft' => 'Editando borrador',
|
||||
'pages_editing_page' => 'Editando página',
|
||||
'pages_edit_draft_save_at' => 'Borrador guardado el ',
|
||||
'pages_edit_delete_draft' => 'Borrar borrador',
|
||||
'pages_edit_discard_draft' => 'Descartar borrador',
|
||||
'pages_edit_set_changelog' => 'Set Changelog',
|
||||
'pages_edit_enter_changelog_desc' => 'Introduzca una breve descripción de los cambios que ha realizado',
|
||||
'pages_edit_enter_changelog' => 'Entrar en Changelog',
|
||||
'pages_save' => 'Guardar página',
|
||||
'pages_title' => 'Título de página',
|
||||
'pages_name' => 'Nombre de página',
|
||||
'pages_md_editor' => 'Editor',
|
||||
'pages_md_preview' => 'Preview',
|
||||
'pages_md_insert_image' => 'Insertar Imagen',
|
||||
'pages_md_insert_link' => 'Insertar link de entidad',
|
||||
'pages_not_in_chapter' => 'La página no esá en el caítulo',
|
||||
'pages_move' => 'Mover página',
|
||||
'pages_move_success' => 'Página movida a ":parentName"',
|
||||
'pages_permissions' => 'Permisos de página',
|
||||
'pages_permissions_success' => 'Permisos de página actualizados',
|
||||
'pages_revisions' => 'Revisiones de página',
|
||||
'pages_revisions_named' => 'Revisiones de página para :pageName',
|
||||
'pages_revision_named' => 'Revisión de ágina para :pageName',
|
||||
'pages_revisions_created_by' => 'Creado por',
|
||||
'pages_revisions_date' => 'Fecha de revisión',
|
||||
'pages_revisions_changelog' => 'Changelog',
|
||||
'pages_revisions_changes' => 'Cambios',
|
||||
'pages_revisions_current' => 'Versión actual',
|
||||
'pages_revisions_preview' => 'Preview',
|
||||
'pages_revisions_restore' => 'Restaurar',
|
||||
'pages_revisions_none' => 'Esta página no tiene revisiones',
|
||||
'pages_copy_link' => 'Copiar Link',
|
||||
'pages_permissions_active' => 'Permisos de página activos',
|
||||
'pages_initial_revision' => 'Publicación inicial',
|
||||
'pages_initial_name' => 'Página nueva',
|
||||
'pages_editing_draft_notification' => 'Ud. está actualmente editando un borrador que fue guardado porúltima vez el :timeDiff.',
|
||||
'pages_draft_edited_notification' => 'Esta página ha sido actualizada desde aquel momento. Se recomienda que cancele este borrador.',
|
||||
'pages_draft_edit_active' => [
|
||||
'start_a' => ':count usuarios han comenzado a editar esta página',
|
||||
'start_b' => ':userName ha comenzado a editar esta página',
|
||||
'time_a' => 'desde que las página fue actualizada',
|
||||
'time_b' => 'en los últimos :minCount minutos',
|
||||
'message' => ':start :time. Ten cuidado de no sobreescribir los cambios del otro usuario',
|
||||
],
|
||||
'pages_draft_discarded' => 'Borrador descartado, el editor ha sido actualizado con el contenido de la página actual',
|
||||
|
||||
/**
|
||||
* Editor sidebar
|
||||
*/
|
||||
'page_tags' => 'Etiquetas de página',
|
||||
'tag' => 'Etiqueta',
|
||||
'tags' => 'Etiquetas',
|
||||
'tag_value' => 'Valor de la etiqueta (Opcional)',
|
||||
'tags_explain' => "Agregar algunas etiquetas para mejorar la categorización de su contenido. \n Ud. puede asignar un valor a una etiqueta para una organizacón a mayor detalle.",
|
||||
'tags_add' => 'Agregar otra etiqueta',
|
||||
'attachments' => 'Adjuntos',
|
||||
'attachments_explain' => 'Subir ficheros o agregar links para mostrar en la página. Estos son visibles en la barra lateral de la página.',
|
||||
'attachments_explain_instant_save' => 'Los cambios son guardados de manera instantánea .',
|
||||
'attachments_items' => 'Items adjuntados',
|
||||
'attachments_upload' => 'Fichero adjuntado',
|
||||
'attachments_link' => 'Adjuntar Link',
|
||||
'attachments_set_link' => 'Setear Link',
|
||||
'attachments_delete_confirm' => 'Haga click en borrar nuevamente para confirmar que quiere borrar este adjunto.',
|
||||
'attachments_dropzone' => 'Arrastre ficheros aquío haga click aquípara adjuntar un fichero',
|
||||
'attachments_no_files' => 'Ningún fichero ha sido adjuntado',
|
||||
'attachments_explain_link' => 'Ud. puede agregar un link o si lo prefiere puede agregar un fichero. Esto puede ser un link a otra página o un link a un fichero en la nube.',
|
||||
'attachments_link_name' => 'Nombre de Link',
|
||||
'attachment_link' => 'Link adjunto',
|
||||
'attachments_link_url' => 'Link a fichero',
|
||||
'attachments_link_url_hint' => 'Url del sitio o fichero',
|
||||
'attach' => 'Adjuntar',
|
||||
'attachments_edit_file' => 'Editar fichero',
|
||||
'attachments_edit_file_name' => 'Nombre del fichero',
|
||||
'attachments_edit_drop_upload' => 'Arrastre a los ficheros o haga click aquípara subir o sobreescribir',
|
||||
'attachments_order_updated' => 'Orden de adjuntos actualizado',
|
||||
'attachments_updated_success' => 'Detalles de adjuntos actualizados',
|
||||
'attachments_deleted' => 'Adjunto borrado',
|
||||
'attachments_file_uploaded' => 'Fichero subido éxitosamente',
|
||||
'attachments_file_updated' => 'Fichero actualizado éxitosamente',
|
||||
'attachments_link_attached' => 'Link agregado éxitosamente a la ágina',
|
||||
|
||||
/**
|
||||
* Profile View
|
||||
*/
|
||||
'profile_user_for_x' => 'Usuario para :time',
|
||||
'profile_created_content' => 'Contenido creado',
|
||||
'profile_not_created_pages' => ':userName no ha creado ninguna página',
|
||||
'profile_not_created_chapters' => ':userName no ha creado ningún capítulo',
|
||||
'profile_not_created_books' => ':userName no ha creado ningún libro',
|
||||
];
|
||||
70
resources/lang/es/errors.php
Normal file
70
resources/lang/es/errors.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/**
|
||||
* Error text strings.
|
||||
*/
|
||||
|
||||
// Permissions
|
||||
'permission' => 'Ud. no tiene permisos para visualizar la página solicitada.',
|
||||
'permissionJson' => 'Ud. no tiene permisos para ejecutar la acción solicitada.',
|
||||
|
||||
// Auth
|
||||
'error_user_exists_different_creds' => 'Un usuario con el email :email ya existe pero con credenciales diferentes.',
|
||||
'email_already_confirmed' => 'El email ya ha sido confirmado, Intente loguearse en la aplicación.',
|
||||
'email_confirmation_invalid' => 'Este token de confirmación no e válido o ya ha sido usado,Intente registrar uno nuevamente.',
|
||||
'email_confirmation_expired' => 'El token de confirmación ha expirado, Un nuevo email de confirmacón ha sido enviado.',
|
||||
'ldap_fail_anonymous' => 'El acceso con LDAP ha fallado usando binding anónimo',
|
||||
'ldap_fail_authed' => 'El acceso LDAP usando el dn & password detallados',
|
||||
'ldap_extension_not_installed' => 'La extensión LDAP PHP no se encuentra instalada',
|
||||
'ldap_cannot_connect' => 'No se puede conectar con el servidor ldap, la conexión inicial ha fallado',
|
||||
'social_no_action_defined' => 'Acción no definida',
|
||||
'social_account_in_use' => 'la cuenta :socialAccount ya se encuentra en uso, intente loguearse a través de la opcón :socialAccount .',
|
||||
'social_account_email_in_use' => 'El email :email ya se encuentra en uso. Si ud. ya dispone de una cuenta puede loguearse a través de su cuenta :socialAccount desde la configuración de perfil.',
|
||||
'social_account_existing' => 'La cuenta :socialAccount ya se encuentra asignada a su perfil.',
|
||||
'social_account_already_used_existing' => 'La cuenta :socialAccount ya se encuentra usada por otro usuario.',
|
||||
'social_account_not_used' => 'La cuenta :socialAccount no está asociada a ningún usuario. Por favor adjuntela a su configuración de perfil. ',
|
||||
'social_account_register_instructions' => 'Si no dispone de una cuenta, puede registrar una cuenta usando la opción de :socialAccount .',
|
||||
'social_driver_not_found' => 'Driver social no encontrado',
|
||||
'social_driver_not_configured' => 'Su configuración :socialAccount no es correcta.',
|
||||
|
||||
// System
|
||||
'path_not_writable' => 'La ruta :filePath no pudo ser cargada. Asegurese de que es escribible por el servidor.',
|
||||
'cannot_get_image_from_url' => 'No se puede obtener la imagen desde :url',
|
||||
'cannot_create_thumbs' => 'El servidor no puede crear la imagen miniatura. Por favor chequee que tiene la extensión GD instalada.',
|
||||
'server_upload_limit' => 'El servidor no permite la subida de ficheros de este tamañ. Por favor intente con un fichero de menor tamañ.',
|
||||
'image_upload_error' => 'Ha ocurrido un error al subir la imagen',
|
||||
|
||||
// Attachments
|
||||
'attachment_page_mismatch' => 'Página no coincidente durante la subida del adjunto ',
|
||||
|
||||
// Pages
|
||||
'page_draft_autosave_fail' => 'Fallo al guardar borrador. Asegurese de que tiene conexión a Internet antes de guardar este borrador',
|
||||
|
||||
// Entities
|
||||
'entity_not_found' => 'Entidad no encontrada',
|
||||
'book_not_found' => 'Libro no encontrado',
|
||||
'page_not_found' => 'Página no encontrada',
|
||||
'chapter_not_found' => 'Capítulo no encontrado',
|
||||
'selected_book_not_found' => 'El libro seleccionado no fue encontrado',
|
||||
'selected_book_chapter_not_found' => 'El libro o capítulo seleccionado no fue encontrado',
|
||||
'guests_cannot_save_drafts' => 'Los invitados no pueden guardar los borradores',
|
||||
|
||||
// Users
|
||||
'users_cannot_delete_only_admin' => 'No se puede borrar el único administrador',
|
||||
'users_cannot_delete_guest' => 'No se puede borrar el usuario invitado',
|
||||
|
||||
// Roles
|
||||
'role_cannot_be_edited' => 'Este rol no puede ser editado',
|
||||
'role_system_cannot_be_deleted' => 'Este rol es un rol de sistema y no puede ser borrado',
|
||||
'role_registration_default_cannot_delete' => 'Este rol no puede ser borrado mientras sea el rol por defecto de registro',
|
||||
|
||||
// Error pages
|
||||
'404_page_not_found' => 'Página no encontrada',
|
||||
'sorry_page_not_found' => 'Lo sentimos, la página que intenta acceder no pudo ser encontrada.',
|
||||
'return_home' => 'Volver al home',
|
||||
'error_occurred' => 'Ha ocurrido un error',
|
||||
'app_down' => 'La aplicación :appName se encuentra caída en este momento',
|
||||
'back_soon' => 'Volverá a estar operativa en corto tiempo.',
|
||||
];
|
||||
19
resources/lang/es/pagination.php
Normal file
19
resources/lang/es/pagination.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Pagination Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are used by the paginator library to build
|
||||
| the simple pagination links. You are free to change them to anything
|
||||
| you want to customize your views to better match your application.
|
||||
|
|
||||
*/
|
||||
|
||||
'previous' => '« Anterior',
|
||||
'next' => 'Siguiente »',
|
||||
|
||||
];
|
||||
22
resources/lang/es/passwords.php
Normal file
22
resources/lang/es/passwords.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Password Reminder Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are the default lines which match reasons
|
||||
| that are given by the password broker for a password update attempt
|
||||
| has failed, such as for an invalid token or invalid new password.
|
||||
|
|
||||
*/
|
||||
|
||||
'password' => 'El Password debe ser como mínimo de seis caracteres y coincidir con la confirmación.',
|
||||
'user' => "No podemos encontrar un usuario con esta dirección de e-mail.",
|
||||
'token' => 'El token de reset del password es inválido.',
|
||||
'sent' => 'Hemos enviado a su cuenta de e-mail un link para restaurar su password!',
|
||||
'reset' => 'Su password ha sido restaurado!',
|
||||
|
||||
];
|
||||
112
resources/lang/es/settings.php
Normal file
112
resources/lang/es/settings.php
Normal file
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/**
|
||||
* Settings text strings
|
||||
* Contains all text strings used in the general settings sections of BookStack
|
||||
* including users and roles.
|
||||
*/
|
||||
|
||||
'settings' => 'Ajustes',
|
||||
'settings_save' => 'Guardar ajustes',
|
||||
'settings_save_success' => 'Ajustes guardados',
|
||||
|
||||
/**
|
||||
* App settings
|
||||
*/
|
||||
|
||||
'app_settings' => 'Ajustes de App',
|
||||
'app_name' => 'Nombre de aplicación',
|
||||
'app_name_desc' => 'Este nombre es mostrado en la cabecera y en cualquier email de la aplicación',
|
||||
'app_name_header' => 'Mostrar el nombre de la aplicación en la cabecera?',
|
||||
'app_public_viewing' => 'Permitir vista pública?',
|
||||
'app_secure_images' => 'Habilitar mayor seguridad para subir imágenes?',
|
||||
'app_secure_images_desc' => 'Por razones de performance, todas las imágenes son púicas. Esta opción agrega una cadena larga difícil de adivinar, asegúrese que los indices de directorios no esán habilitados para prevenir el acceso fácil a las imágenes.',
|
||||
'app_editor' => 'Editor de página',
|
||||
'app_editor_desc' => 'Seleccione cuál editor ser usado por todos los usuarios para editar páginas.',
|
||||
'app_custom_html' => 'Contenido de cabecera HTML customizable',
|
||||
'app_custom_html_desc' => 'Cualquier contenido agregado aquíseráinsertado al final de la secón <head> de cada ágina. Esto esútil para sobreescribir estilo o agregar código para anaíticas.',
|
||||
'app_logo' => 'Logo de la aplicación',
|
||||
'app_logo_desc' => 'Esta imagen debería de ser 43px en altura. <br>Iágenes grandes seán escaladas.',
|
||||
'app_primary_color' => 'Color primario de la aplicación',
|
||||
'app_primary_color_desc' => 'Esto debería ser un valor hexadecimal. <br>Deje el valor vaío para reiniciar al valor por defecto.',
|
||||
|
||||
/**
|
||||
* Registration settings
|
||||
*/
|
||||
|
||||
'reg_settings' => 'Ajustes de registro',
|
||||
'reg_allow' => 'Permitir registro?',
|
||||
'reg_default_role' => 'Rol de usuario por defecto despúes del registro',
|
||||
'reg_confirm_email' => 'Requerir email de confirmaación?',
|
||||
'reg_confirm_email_desc' => 'Si la restricción por dominio es usada, entonces la confirmaciónpor email serárequerida y el valor a continuón será ignorado.',
|
||||
'reg_confirm_restrict_domain' => 'Restringir registro al dominio',
|
||||
'reg_confirm_restrict_domain_desc' => 'Introduzca una lista separada por comasa de los emails del dominio a los que les gustaría restringir el registro por dominio. A los usuarios les seá enviado un emal para confirmar la dirección antes de que se le permita interactuar con la aplicacón. <br> Note que los usuarios se les permitir ácambiar sus direcciones de email luego de un registr éxioso.',
|
||||
'reg_confirm_restrict_domain_placeholder' => 'Ninguna restricción establecida',
|
||||
|
||||
/**
|
||||
* Role settings
|
||||
*/
|
||||
|
||||
'roles' => 'Roles',
|
||||
'role_user_roles' => 'Roles de usuario',
|
||||
'role_create' => 'Crear nuevo rol',
|
||||
'role_create_success' => 'Rol creado satisfactoriamente',
|
||||
'role_delete' => 'Borrar rol',
|
||||
'role_delete_confirm' => 'Se borrará el rol con nombre \':roleName\'.',
|
||||
'role_delete_users_assigned' => 'Este rol tiene :userCount usuarios asignados. Si ud. quisiera migrar los usuarios de este rol, seleccione un nuevo rol a continuación.',
|
||||
'role_delete_no_migration' => "No migrar usuarios",
|
||||
'role_delete_sure' => 'Está seguro que desea borrar este rol?',
|
||||
'role_delete_success' => 'Rol borrado satisfactoriamente',
|
||||
'role_edit' => 'Editar rol',
|
||||
'role_details' => 'Detalles de rol',
|
||||
'role_name' => 'Nombre de rol',
|
||||
'role_desc' => 'Descripción corta de rol',
|
||||
'role_system' => 'Permisos de sistema',
|
||||
'role_manage_users' => 'Gestionar usuarios',
|
||||
'role_manage_roles' => 'Gestionar roles y permisos de roles',
|
||||
'role_manage_entity_permissions' => 'Gestionar todos los permisos de libros, capítulos y áginas',
|
||||
'role_manage_own_entity_permissions' => 'Gestionar permisos en libros propios, capítulos y páginas',
|
||||
'role_manage_settings' => 'Gestionar ajustes de activos',
|
||||
'role_asset' => 'Permisos de activos',
|
||||
'role_asset_desc' => 'Estos permisos controlan el acceso por defecto a los activos del sistema. Permisos a Libros, Capítulos y áginas sobreescribiran estos permisos.',
|
||||
'role_all' => 'Todo',
|
||||
'role_own' => 'Propio',
|
||||
'role_controlled_by_asset' => 'Controlado por el actvo al que ha sido subido',
|
||||
'role_save' => 'Guardar rol',
|
||||
'role_update_success' => 'Rol actualizado éxitosamente',
|
||||
'role_users' => 'Usuarios en este rol',
|
||||
'role_users_none' => 'No hay usuarios asignados a este rol',
|
||||
|
||||
/**
|
||||
* Users
|
||||
*/
|
||||
|
||||
'users' => 'Usuarios',
|
||||
'user_profile' => 'Perfil de usuario',
|
||||
'users_add_new' => 'Agregar nuevo usuario',
|
||||
'users_search' => 'Buscar usuarios',
|
||||
'users_role' => 'Roles de usuario',
|
||||
'users_external_auth_id' => 'ID externo de autenticación',
|
||||
'users_password_warning' => 'Solo rellene a continuación si desea cambiar su password:',
|
||||
'users_system_public' => 'Este usuario representa cualquier usuario invitado que visita la aplicación. No puede utilizarse para hacer login sio que es asignado automáticamente.',
|
||||
'users_delete' => 'Borrar usuario',
|
||||
'users_delete_named' => 'Borrar usuario :userName',
|
||||
'users_delete_warning' => 'Se borrará completamente el usuario con el nombre \':userName\' del sistema.',
|
||||
'users_delete_confirm' => 'Está seguro que desea borrar este usuario?',
|
||||
'users_delete_success' => 'Usuarios removidos éxitosamente',
|
||||
'users_edit' => 'Editar Usuario',
|
||||
'users_edit_profile' => 'Editar perfil',
|
||||
'users_edit_success' => 'Usuario actualizado',
|
||||
'users_avatar' => 'Avatar del usuario',
|
||||
'users_avatar_desc' => 'Esta imagen debe ser aproximadamente 256px por lado.',
|
||||
'users_preferred_language' => 'Lenguaje preferido',
|
||||
'users_social_accounts' => 'Cuentas sociales',
|
||||
'users_social_accounts_info' => 'Aquí puede conectar sus otras cuentas para un ápido y ás ácil login. Desconectando una cuenta aqu íno revca accesos ya autorizados. Revoque el acceso desde se perfil desde los ajustes de perfil en la cuenta social conectada.',
|
||||
'users_social_connect' => 'Conectar cuenta',
|
||||
'users_social_disconnect' => 'Desconectar cuenta',
|
||||
'users_social_connected' => 'La cuenta :socialAccount ha sido éxitosamente añadida a su perfil.',
|
||||
'users_social_disconnected' => 'La cuenta :socialAccount ha sido desconectada éxitosamente de su perfil.',
|
||||
|
||||
];
|
||||
108
resources/lang/es/validation.php
Normal file
108
resources/lang/es/validation.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Validation Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines contain the default error messages used by
|
||||
| the validator class. Some of these rules have multiple versions such
|
||||
| as the size rules. Feel free to tweak each of these messages here.
|
||||
|
|
||||
*/
|
||||
|
||||
'accepted' => 'El :attribute debe ser aceptado.',
|
||||
'active_url' => 'El :attribute no es una URl válida.',
|
||||
'after' => 'El :attribute debe ser una fecha posterior :date.',
|
||||
'alpha' => 'El :attribute solo puede contener letras.',
|
||||
'alpha_dash' => 'El :attribute solo puede contener letras, números y guiones.',
|
||||
'alpha_num' => 'El :attribute solo puede contener letras y número.',
|
||||
'array' => 'El :attribute debe de ser un array.',
|
||||
'before' => 'El :attribute debe ser una fecha anterior a :date.',
|
||||
'between' => [
|
||||
'numeric' => 'El :attribute debe estar entre :min y :max.',
|
||||
'file' => 'El :attribute debe estar entre :min y :max kilobytes.',
|
||||
'string' => 'El :attribute debe estar entre :min y :max carácteres.',
|
||||
'array' => 'El :attribute debe estar entre :min y :max items.',
|
||||
],
|
||||
'boolean' => 'El campo :attribute debe ser true o false.',
|
||||
'confirmed' => 'La confirmación de :attribute no concuerda.',
|
||||
'date' => 'El :attribute no es una fecha válida.',
|
||||
'date_format' => 'El :attribute no coincide con el formato :format.',
|
||||
'different' => ':attribute y :other deben ser diferentes.',
|
||||
'digits' => ':attribute debe ser de :digits dígitos.',
|
||||
'digits_between' => ':attribute debe ser un valor entre :min y :max dígios.',
|
||||
'email' => ':attribute debe ser una dirección álida.',
|
||||
'filled' => 'El campo :attribute es requerido.',
|
||||
'exists' => 'El :attribute seleccionado es inválido.',
|
||||
'image' => 'El :attribute debe ser una imagen.',
|
||||
'in' => 'El selected :attribute es inválio.',
|
||||
'integer' => 'El :attribute debe ser un entero.',
|
||||
'ip' => 'El :attribute debe ser una dirección IP álida.',
|
||||
'max' => [
|
||||
'numeric' => ':attribute no puede ser mayor que :max.',
|
||||
'file' => ':attribute no puede ser mayor que :max kilobytes.',
|
||||
'string' => ':attribute no puede ser mayor que :max carácteres.',
|
||||
'array' => ':attribute no puede contener más de :max items.',
|
||||
],
|
||||
'mimes' => ':attribute debe ser un fichero de tipo: :values.',
|
||||
'min' => [
|
||||
'numeric' => ':attribute debe ser al menos de :min.',
|
||||
'file' => ':attribute debe ser al menos :min kilobytes.',
|
||||
'string' => ':attribute debe ser al menos :min caracteres.',
|
||||
'array' => ':attribute debe tener como mínimo :min items.',
|
||||
],
|
||||
'not_in' => ':attribute seleccionado es inválio.',
|
||||
'numeric' => ':attribute debe ser numérico.',
|
||||
'regex' => ':attribute con formato inválido',
|
||||
'required' => ':attribute es requerido.',
|
||||
'required_if' => ':attribute es requerido cuando :other vale :value.',
|
||||
'required_with' => 'El campo :attribute es requerido cuando se encuentre entre los valores :values.',
|
||||
'required_with_all' => 'El campo :attribute es requerido cuando los valores sean :values.',
|
||||
'required_without' => ':attribute es requerido cuando no se encuentre entre los valores :values.',
|
||||
'required_without_all' => ':attribute es requerido cuando ninguno de los valores :values están presentes.',
|
||||
'same' => ':attribute y :other deben coincidir.',
|
||||
'size' => [
|
||||
'numeric' => ':attribute debe ser :size.',
|
||||
'file' => ':attribute debe ser :size kilobytes.',
|
||||
'string' => ':attribute debe ser :size caracteres.',
|
||||
'array' => ':attribute debe contener :size items.',
|
||||
],
|
||||
'string' => 'El atributo :attribute debe ser una cadena.',
|
||||
'timezone' => 'El atributo :attribute debe ser una zona válida.',
|
||||
'unique' => 'El atributo :attribute ya ha sido tomado.',
|
||||
'url' => 'El atributo :attribute tiene un formato inválid.',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Custom Validation Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify custom validation messages for attributes using the
|
||||
| convention "attribute.rule" to name the lines. This makes it quick to
|
||||
| specify a specific custom language line for a given attribute rule.
|
||||
|
|
||||
*/
|
||||
|
||||
'custom' => [
|
||||
'password-confirm' => [
|
||||
'required_with' => 'Confirmación de Password requerida',
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Custom Validation Attributes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are used to swap attribute place-holders
|
||||
| with something more reader friendly such as E-Mail Address instead
|
||||
| of "email". This simply helps us make messages a little cleaner.
|
||||
|
|
||||
*/
|
||||
|
||||
'attributes' => [],
|
||||
|
||||
];
|
||||
@@ -26,6 +26,10 @@ return [
|
||||
'no_pages_viewed' => 'Vous n\'avez rien visité récemment',
|
||||
'no_pages_recently_created' => 'Aucune page créée récemment',
|
||||
'no_pages_recently_updated' => 'Aucune page mise à jour récemment',
|
||||
'export' => 'Exporter',
|
||||
'export_html' => 'Fichiers web',
|
||||
'export_pdf' => 'Fichier PDF',
|
||||
'export_text' => 'Document texte',
|
||||
|
||||
/**
|
||||
* Permissions and restrictions
|
||||
@@ -39,18 +43,9 @@ return [
|
||||
* Search
|
||||
*/
|
||||
'search_results' => 'Résultats de recherche',
|
||||
'search_results_page' => 'Résultats de recherche des pages',
|
||||
'search_results_chapter' => 'Résultats de recherche des chapitres',
|
||||
'search_results_book' => 'Résultats de recherche des livres',
|
||||
'search_clear' => 'Réinitialiser la recherche',
|
||||
'search_view_pages' => 'Voir toutes les pages correspondantes',
|
||||
'search_view_chapters' => 'Voir tous les chapitres correspondants',
|
||||
'search_view_books' => 'Voir tous les livres correspondants',
|
||||
'search_no_pages' => 'Aucune page correspondant à cette recherche',
|
||||
'search_for_term' => 'recherche pour :term',
|
||||
'search_page_for_term' => 'Recherche de page pour :term',
|
||||
'search_chapter_for_term' => 'Recherche de chapitre pour :term',
|
||||
'search_book_for_term' => 'Recherche de livres pour :term',
|
||||
|
||||
/**
|
||||
* Books
|
||||
@@ -160,10 +155,6 @@ return [
|
||||
'pages_revisions_preview' => 'Prévisualisation',
|
||||
'pages_revisions_restore' => 'Restaurer',
|
||||
'pages_revisions_none' => 'Cette page n\'a aucune révision',
|
||||
'pages_export' => 'Exporter',
|
||||
'pages_export_html' => 'Fichiers web',
|
||||
'pages_export_pdf' => 'Fichier PDF',
|
||||
'pages_export_text' => 'Document texte',
|
||||
'pages_copy_link' => 'Copier le lien',
|
||||
'pages_permissions_active' => 'Permissions de page actives',
|
||||
'pages_initial_revision' => 'Publication initiale',
|
||||
|
||||
40
resources/lang/nl/activities.php
Normal file
40
resources/lang/nl/activities.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/**
|
||||
* Activity text strings.
|
||||
* Is used for all the text within activity logs & notifications.
|
||||
*/
|
||||
|
||||
// Pages
|
||||
'page_create' => 'maakte pagina',
|
||||
'page_create_notification' => 'Pagina Succesvol Aangemaakt',
|
||||
'page_update' => 'veranderde pagina',
|
||||
'page_update_notification' => 'Pagina Succesvol Bijgewerkt',
|
||||
'page_delete' => 'verwijderde pagina',
|
||||
'page_delete_notification' => 'Pagina Succesvol Verwijderd',
|
||||
'page_restore' => 'herstelde pagina',
|
||||
'page_restore_notification' => 'Pagina Succesvol Hersteld',
|
||||
'page_move' => 'verplaatste pagina',
|
||||
|
||||
// Chapters
|
||||
'chapter_create' => 'maakte hoofdstuk',
|
||||
'chapter_create_notification' => 'Hoofdstuk Succesvol Aangemaakt',
|
||||
'chapter_update' => 'veranderde hoofdstuk',
|
||||
'chapter_update_notification' => 'Hoofdstuk Succesvol Bijgewerkt',
|
||||
'chapter_delete' => 'verwijderde hoofdstuk',
|
||||
'chapter_delete_notification' => 'Hoofdstuk Succesvol Verwijderd',
|
||||
'chapter_move' => 'verplaatste hoofdstuk',
|
||||
|
||||
// Books
|
||||
'book_create' => 'maakte boek',
|
||||
'book_create_notification' => 'Boek Succesvol Aangemaakt',
|
||||
'book_update' => 'veranderde boek',
|
||||
'book_update_notification' => 'Boek Succesvol Bijgewerkt',
|
||||
'book_delete' => 'verwijderde boek',
|
||||
'book_delete_notification' => 'Boek Succesvol Verwijderd',
|
||||
'book_sort' => 'sorteerde boek',
|
||||
'book_sort_notification' => 'Boek Succesvol Gesorteerd',
|
||||
|
||||
];
|
||||
76
resources/lang/nl/auth.php
Normal file
76
resources/lang/nl/auth.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
return [
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Authentication Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are used during authentication for various
|
||||
| messages that we need to display to the user. You are free to modify
|
||||
| these language lines according to your application's requirements.
|
||||
|
|
||||
*/
|
||||
'failed' => 'Deze inloggegevens zijn niet bij ons bekend.',
|
||||
'throttle' => 'Te veel loginpogingen! Probeer het opnieuw na :seconds seconden.',
|
||||
|
||||
/**
|
||||
* Login & Register
|
||||
*/
|
||||
'sign_up' => 'Registreren',
|
||||
'log_in' => 'Log in',
|
||||
'log_in_with' => 'Login met :socialDriver',
|
||||
'sign_up_with' => 'Registreer met :socialDriver',
|
||||
'logout' => 'Uitloggen',
|
||||
|
||||
'name' => 'Naam',
|
||||
'username' => 'Gebruikersnaam',
|
||||
'email' => 'Email',
|
||||
'password' => 'Wachtwoord',
|
||||
'password_confirm' => 'Wachtwoord Bevestigen',
|
||||
'password_hint' => 'Minimaal 5 tekens',
|
||||
'forgot_password' => 'Wachtwoord vergeten?',
|
||||
'remember_me' => 'Mij onthouden',
|
||||
'ldap_email_hint' => 'Geef een email op waarmee je dit account wilt gebruiken.',
|
||||
'create_account' => 'Account Aanmaken',
|
||||
'social_login' => 'Social Login',
|
||||
'social_registration' => 'Social Registratie',
|
||||
'social_registration_text' => 'Registreer en log in met een andere dienst.',
|
||||
|
||||
'register_thanks' => 'Bedankt voor het registreren!',
|
||||
'register_confirm' => 'Controleer je e-mail en bevestig je registratie om in te loggen op :appName.',
|
||||
'registrations_disabled' => 'Registratie is momenteel niet mogelijk',
|
||||
'registration_email_domain_invalid' => 'Dit e-maildomein is niet toegestaan',
|
||||
'register_success' => 'Bedankt voor het inloggen. Je bent ook geregistreerd.',
|
||||
|
||||
|
||||
/**
|
||||
* Password Reset
|
||||
*/
|
||||
'reset_password' => 'Wachtwoord Herstellen',
|
||||
'reset_password_send_instructions' => 'Geef je e-mail en we sturen je een link om je wachtwoord te herstellen',
|
||||
'reset_password_send_button' => 'Link Sturen',
|
||||
'reset_password_sent_success' => 'Een link om je wachtwoord te herstellen is verstuurd naar :email.',
|
||||
'reset_password_success' => 'Je wachtwoord is succesvol hersteld.',
|
||||
|
||||
'email_reset_subject' => 'Herstel je wachtwoord van :appName',
|
||||
'email_reset_text' => 'Je ontvangt deze e-mail zodat je je wachtwoord kunt herstellen.',
|
||||
'email_reset_not_requested' => 'Als je jouw wachtwoord niet wilt wijzigen, doe dan niets.',
|
||||
|
||||
|
||||
/**
|
||||
* Email Confirmation
|
||||
*/
|
||||
'email_confirm_subject' => 'Bevestig je e-mailadres op :appName',
|
||||
'email_confirm_greeting' => 'Bedankt voor je aanmelding op :appName!',
|
||||
'email_confirm_text' => 'Bevestig je registratie door op onderstaande knop te drukken:',
|
||||
'email_confirm_action' => 'Bevestig je e-mail',
|
||||
'email_confirm_send_error' => 'E-mail bevestiging is vereisd maar het systeem kon geen mail verzenden. Neem contact op met de beheerder.',
|
||||
'email_confirm_success' => 'Je e-mailadres is bevestigt!',
|
||||
'email_confirm_resent' => 'De bevestigingse-mails is opnieuw verzonden. Controleer je inbox.',
|
||||
|
||||
'email_not_confirmed' => 'E-mail nog niet bevestigd',
|
||||
'email_not_confirmed_text' => 'Je e-mailadres is nog niet bevestigd.',
|
||||
'email_not_confirmed_click_link' => 'Klik op de link in de e-mail die vlak na je registratie is verstuurd.',
|
||||
'email_not_confirmed_resend' => 'Als je deze e-mail niet kunt vinden kun je deze met onderstaande formulier opnieuw verzenden.',
|
||||
'email_not_confirmed_resend_button' => 'Bevestigingsmail Opnieuw Verzenden',
|
||||
];
|
||||
58
resources/lang/nl/common.php
Normal file
58
resources/lang/nl/common.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
return [
|
||||
|
||||
/**
|
||||
* Buttons
|
||||
*/
|
||||
'cancel' => 'Annuleren',
|
||||
'confirm' => 'Bevestigen',
|
||||
'back' => 'Terug',
|
||||
'save' => 'Opslaan',
|
||||
'continue' => 'Doorgaan',
|
||||
'select' => 'Kies',
|
||||
|
||||
/**
|
||||
* Form Labels
|
||||
*/
|
||||
'name' => 'Naam',
|
||||
'description' => 'Beschrijving',
|
||||
'role' => 'Rol',
|
||||
|
||||
/**
|
||||
* Actions
|
||||
*/
|
||||
'actions' => 'Acties',
|
||||
'view' => 'Bekijk',
|
||||
'create' => 'Aanmaken',
|
||||
'update' => 'Update',
|
||||
'edit' => 'Bewerk',
|
||||
'sort' => 'Sorteer',
|
||||
'move' => 'Verplaats',
|
||||
'delete' => 'Verwijder',
|
||||
'search' => 'Zoek',
|
||||
'search_clear' => 'Zoekopdracht wissen',
|
||||
'reset' => 'Reset',
|
||||
'remove' => 'Verwijderen',
|
||||
|
||||
|
||||
/**
|
||||
* Misc
|
||||
*/
|
||||
'deleted_user' => 'Verwijderde gebruiker',
|
||||
'no_activity' => 'Geen activiteiten',
|
||||
'no_items' => 'Geen items beschikbaar',
|
||||
'back_to_top' => 'Terug naar boven',
|
||||
'toggle_details' => 'Details Weergeven',
|
||||
|
||||
/**
|
||||
* Header
|
||||
*/
|
||||
'view_profile' => 'Profiel Weergeven',
|
||||
'edit_profile' => 'Profiel Bewerken',
|
||||
|
||||
/**
|
||||
* Email Content
|
||||
*/
|
||||
'email_action_help' => 'Als je de knop ":actionText" niet werkt, kopieer en plak de onderstaande URL in je web browser:',
|
||||
'email_rights' => 'Alle rechten voorbehouden',
|
||||
];
|
||||
24
resources/lang/nl/components.php
Normal file
24
resources/lang/nl/components.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
return [
|
||||
|
||||
/**
|
||||
* Image Manager
|
||||
*/
|
||||
'image_select' => 'Selecteer Afbeelding',
|
||||
'image_all' => 'Alles',
|
||||
'image_all_title' => 'Alle afbeeldingen weergeven',
|
||||
'image_book_title' => 'Afbeeldingen van dit boek weergeven',
|
||||
'image_page_title' => 'Afbeeldingen van deze pagina weergeven',
|
||||
'image_search_hint' => 'Zoek op afbeeldingsnaam',
|
||||
'image_uploaded' => 'Uploaded :uploadedDate',
|
||||
'image_load_more' => 'Meer Laden',
|
||||
'image_image_name' => 'Afbeeldingsnaam',
|
||||
'image_delete_confirm' => 'Deze afbeeldingen is op onderstaande pagina\'s in gebruik, Klik opnieuw op verwijderen om de afbeelding echt te verwijderen.',
|
||||
'image_select_image' => 'Kies Afbeelding',
|
||||
'image_dropzone' => 'Sleep afbeeldingen hier of klik hier om te uploaden',
|
||||
'images_deleted' => 'Verwijderde Afbeeldingen',
|
||||
'image_preview' => 'Afbeelding Voorbeeld',
|
||||
'image_upload_success' => 'Afbeelding succesvol geüpload',
|
||||
'image_update_success' => 'Afbeeldingsdetails succesvol verwijderd',
|
||||
'image_delete_success' => 'Afbeelding succesvol verwijderd'
|
||||
];
|
||||
217
resources/lang/nl/entities.php
Normal file
217
resources/lang/nl/entities.php
Normal file
@@ -0,0 +1,217 @@
|
||||
<?php
|
||||
return [
|
||||
|
||||
/**
|
||||
* Shared
|
||||
*/
|
||||
'recently_created' => 'Recent Aangemaakt',
|
||||
'recently_created_pages' => 'Recent Aangemaakte Pagina\'s',
|
||||
'recently_updated_pages' => 'Recent Bijgewerkte Pagina\'s',
|
||||
'recently_created_chapters' => 'Recent Aangemaakte Hoofdstukken',
|
||||
'recently_created_books' => 'Recent Aangemaakte Boeken',
|
||||
'recently_update' => 'Recent Bijgewerkt',
|
||||
'recently_viewed' => 'Recent Bekeken',
|
||||
'recent_activity' => 'Recente Activiteit',
|
||||
'create_now' => 'Maak er zelf één',
|
||||
'revisions' => 'Revisies',
|
||||
'meta_created' => 'Aangemaakt :timeLength',
|
||||
'meta_created_name' => 'Aangemaakt: :timeLength door :user',
|
||||
'meta_updated' => ':timeLength Aangepast',
|
||||
'meta_updated_name' => 'Aangepast: :timeLength door :user',
|
||||
'x_pages' => ':count Pagina\'s',
|
||||
'entity_select' => 'Entiteit Selecteren',
|
||||
'images' => 'Afbeeldingen',
|
||||
'my_recent_drafts' => 'Mijn Concepten',
|
||||
'my_recently_viewed' => 'Mijn Recent Bekeken',
|
||||
'no_pages_viewed' => 'Je hebt nog niets bekeken',
|
||||
'no_pages_recently_created' => 'Er zijn geen recent aangemaakte pagina\'s',
|
||||
'no_pages_recently_updated' => 'Er zijn geen recente wijzigingen',
|
||||
'export' => 'Exporteren',
|
||||
'export_html' => 'Contained Web File',
|
||||
'export_pdf' => 'PDF File',
|
||||
'export_text' => 'Plain Text File',
|
||||
|
||||
/**
|
||||
* Permissions and restrictions
|
||||
*/
|
||||
'permissions' => 'Permissies',
|
||||
'permissions_intro' => 'Als je dit aanzet, dan gelden rol-permissies niet meer voor deze pagina.',
|
||||
'permissions_enable' => 'Custom Permissies Aanzetten',
|
||||
'permissions_save' => 'Permissies Opslaan',
|
||||
|
||||
/**
|
||||
* Search
|
||||
*/
|
||||
'search_results' => 'Zoekresultaten',
|
||||
'search_clear' => 'Zoekopdracht wissen',
|
||||
'search_no_pages' => 'Er zijn geen pagina\'s gevonden',
|
||||
'search_for_term' => 'Zoeken op :term',
|
||||
|
||||
/**
|
||||
* Books
|
||||
*/
|
||||
'book' => 'Boek',
|
||||
'books' => 'Boeken',
|
||||
'books_empty' => 'Er zijn geen boeken aangemaakt',
|
||||
'books_popular' => 'Populaire Boeken',
|
||||
'books_recent' => 'Recente Boeken',
|
||||
'books_popular_empty' => 'De meest populaire boeken worden hier weergegeven.',
|
||||
'books_create' => 'Nieuw Boek Aanmaken',
|
||||
'books_delete' => 'Boek Verwijderen',
|
||||
'books_delete_named' => 'Verwijder Boek :bookName',
|
||||
'books_delete_explain' => 'Deze actie verwijdert het boek \':bookName\', Alle pagina\'s en hoofdstukken worden verwijderd.',
|
||||
'books_delete_confirmation' => 'Weet je zeker dat je dit boek wilt verwijderen?',
|
||||
'books_edit' => 'Boek Bewerken',
|
||||
'books_edit_named' => 'Bewerkt Boek :bookName',
|
||||
'books_form_book_name' => 'Boek Naam',
|
||||
'books_save' => 'Boek Opslaan',
|
||||
'books_permissions' => 'Boek Permissies',
|
||||
'books_permissions_updated' => 'Boek Permissies Opgeslagen',
|
||||
'books_empty_contents' => 'Er zijn nog een hoofdstukken en pagina\'s voor dit boek gemaakt.',
|
||||
'books_empty_create_page' => 'Pagina Toevoegen',
|
||||
'books_empty_or' => 'of',
|
||||
'books_empty_sort_current_book' => 'Boek sorteren',
|
||||
'books_empty_add_chapter' => 'Hoofdstuk Toevoegen',
|
||||
'books_permissions_active' => 'Boek Permissies Actief',
|
||||
'books_search_this' => 'Zoeken in dit boek',
|
||||
'books_navigation' => 'Boek Navigatie',
|
||||
'books_sort' => 'Inhoud van het boek sorteren',
|
||||
'books_sort_named' => 'Sorteer Boek :bookName',
|
||||
'books_sort_show_other' => 'Bekijk Andere Boeken',
|
||||
'books_sort_save' => 'Nieuwe Order Opslaan',
|
||||
|
||||
/**
|
||||
* Chapters
|
||||
*/
|
||||
'chapter' => 'Hoofdstuk',
|
||||
'chapters' => 'Hoofdstukken',
|
||||
'chapters_popular' => 'Populaire Hoofdstukken',
|
||||
'chapters_new' => 'Nieuw Hoofdstuk',
|
||||
'chapters_create' => 'Hoofdstuk Toevoegen',
|
||||
'chapters_delete' => 'Hoofdstuk Verwijderen',
|
||||
'chapters_delete_named' => 'Verwijder Hoofdstuk :chapterName',
|
||||
'chapters_delete_explain' => 'Dit verwijdert het hoofdstuk \':chapterName\', Alle pagina\'s zullen verwijdert worden.
|
||||
en toegevoegd worden aan het bijbehorende boek.',
|
||||
'chapters_delete_confirm' => 'Weet je zeker dat je dit boek wilt verwijderen?',
|
||||
'chapters_edit' => 'Hoofdstuk Aanpassen',
|
||||
'chapters_edit_named' => 'Hoofdstuk :chapterName Aanpassen',
|
||||
'chapters_save' => 'Hoofdstuk Opslaan',
|
||||
'chapters_move' => 'Hoofdstuk Verplaatsen',
|
||||
'chapters_move_named' => 'Verplaatst Hoofdstuk :chapterName',
|
||||
'chapter_move_success' => 'Hoofdstuk Verplaatst Naar :bookName',
|
||||
'chapters_permissions' => 'Hoofdstuk Permissies',
|
||||
'chapters_empty' => 'Er zijn geen pagina\'s in dit hoofdstuk aangemaakt.',
|
||||
'chapters_permissions_active' => 'Hoofdstuk Permissies Actief',
|
||||
'chapters_permissions_success' => 'Hoofdstuk Permissies Bijgewerkt',
|
||||
|
||||
/**
|
||||
* Pages
|
||||
*/
|
||||
'page' => 'Pagina',
|
||||
'pages' => 'Pagina\'s',
|
||||
'pages_popular' => 'Populaire Pagina\'s',
|
||||
'pages_new' => 'Nieuwe Pagina',
|
||||
'pages_attachments' => 'Bijlages',
|
||||
'pages_navigation' => 'Pagina Navigatie',
|
||||
'pages_delete' => 'Pagina Verwijderen',
|
||||
'pages_delete_named' => 'Verwijderde Pagina :pageName',
|
||||
'pages_delete_draft_named' => 'Verwijderde Conceptpagina :pageName',
|
||||
'pages_delete_draft' => 'Verwijder Conceptpagina',
|
||||
'pages_delete_success' => 'Pagina verwijderd',
|
||||
'pages_delete_draft_success' => 'Concept verwijderd',
|
||||
'pages_delete_confirm' => 'Weet je zeker dat je deze pagina wilt verwijderen?',
|
||||
'pages_delete_draft_confirm' => 'Weet je zeker dat je dit concept wilt verwijderen?',
|
||||
'pages_editing_named' => 'Pagina :pageName Bewerken',
|
||||
'pages_edit_toggle_header' => 'Toggle header',
|
||||
'pages_edit_save_draft' => 'Concept opslaan',
|
||||
'pages_edit_draft' => 'Paginaconcept Bewerken',
|
||||
'pages_editing_draft' => 'Concept Bewerken',
|
||||
'pages_editing_page' => 'Concept Bewerken',
|
||||
'pages_edit_draft_save_at' => 'Concept opgeslagen op ',
|
||||
'pages_edit_delete_draft' => 'Concept Verwijderen',
|
||||
'pages_edit_discard_draft' => 'Concept Verwijderen',
|
||||
'pages_edit_set_changelog' => 'Changelog',
|
||||
'pages_edit_enter_changelog_desc' => 'Geef een korte omschrijving van de wijzingen die je gemaakt hebt.',
|
||||
'pages_edit_enter_changelog' => 'Enter Changelog',
|
||||
'pages_save' => 'Pagina Opslaan',
|
||||
'pages_title' => 'Pagina Titel',
|
||||
'pages_name' => 'Pagina Naam',
|
||||
'pages_md_editor' => 'Bewerker',
|
||||
'pages_md_preview' => 'Preview',
|
||||
'pages_md_insert_image' => 'Afbeelding Invoegen',
|
||||
'pages_md_insert_link' => 'Entity Link Invoegen',
|
||||
'pages_not_in_chapter' => 'Deze pagina staat niet in een hoofdstuk',
|
||||
'pages_move' => 'Pagina Verplaatsten',
|
||||
'pages_move_success' => 'Pagina verplaatst naar ":parentName"',
|
||||
'pages_permissions' => 'Pagina Permissies',
|
||||
'pages_permissions_success' => 'Pagina Permissies bijgwerkt',
|
||||
'pages_revisions' => 'Pagina Revisies',
|
||||
'pages_revisions_named' => 'Pagina Revisies voor :pageName',
|
||||
'pages_revision_named' => 'Pagina Revisie voor :pageName',
|
||||
'pages_revisions_created_by' => 'Aangemaakt door',
|
||||
'pages_revisions_date' => 'Revisiedatum',
|
||||
'pages_revisions_changelog' => 'Changelog',
|
||||
'pages_revisions_changes' => 'Wijzigingen',
|
||||
'pages_revisions_current' => 'Huidige Versie',
|
||||
'pages_revisions_preview' => 'Preview',
|
||||
'pages_revisions_restore' => 'Herstellen',
|
||||
'pages_revisions_none' => 'Deze pagina heeft geen revisies',
|
||||
'pages_copy_link' => 'Link Kopiëren',
|
||||
'pages_permissions_active' => 'Pagina Permissies Actief',
|
||||
'pages_initial_revision' => 'Eerste publicatie',
|
||||
'pages_initial_name' => 'Nieuwe Pagina',
|
||||
'pages_editing_draft_notification' => 'You are currently editing a draft that was last saved :timeDiff.',
|
||||
'pages_draft_edited_notification' => 'This page has been updated by since that time. It is recommended that you discard this draft.',
|
||||
'pages_draft_edit_active' => [
|
||||
'start_a' => ':count users have started editing this page',
|
||||
'start_b' => ':userName has started editing this page',
|
||||
'time_a' => 'since the pages was last updated',
|
||||
'time_b' => 'in the last :minCount minutes',
|
||||
'message' => ':start :time. Take care not to overwrite each other\'s updates!',
|
||||
],
|
||||
'pages_draft_discarded' => 'Draft discarded, The editor has been updated with the current page content',
|
||||
|
||||
/**
|
||||
* Editor sidebar
|
||||
*/
|
||||
'page_tags' => 'Pagina Labels',
|
||||
'tag' => 'Label',
|
||||
'tags' => '',
|
||||
'tag_value' => 'Label Waarde (Optioneel)',
|
||||
'tags_explain' => "Voeg labels toe om de inhoud te categoriseren. \n Je kunt meerdere labels toevoegen.",
|
||||
'tags_add' => 'Voeg een extra label toe',
|
||||
'attachments' => 'Bijlages',
|
||||
'attachments_explain' => 'Upload bijlages of voeg een link toe. Deze worden zichtbaar in het navigatiepaneel.',
|
||||
'attachments_explain_instant_save' => 'Wijzigingen worden meteen opgeslagen.',
|
||||
'attachments_items' => 'Bijlages',
|
||||
'attachments_upload' => 'Bestand Uploaden',
|
||||
'attachments_link' => 'Link Toevoegen',
|
||||
'attachments_set_link' => 'Zet Link',
|
||||
'attachments_delete_confirm' => 'Klik opnieuw op \'verwijderen\' om de bijlage definitief te verwijderen.',
|
||||
'attachments_dropzone' => 'Sleep hier een bestand of klik hier om een bestand toe te voegen',
|
||||
'attachments_no_files' => 'Er zijn geen bestanden geüpload',
|
||||
'attachments_explain_link' => 'Je kunt een link toevoegen als je geen bestanden wilt uploaden. Dit kan een link naar een andere pagina op deze website zijn, maar ook een link naar een andere website.',
|
||||
'attachments_link_name' => 'Link Naam',
|
||||
'attachment_link' => 'Bijlage link',
|
||||
'attachments_link_url' => 'Link naar bestand',
|
||||
'attachments_link_url_hint' => 'Url, site of bestand',
|
||||
'attach' => 'Koppelen',
|
||||
'attachments_edit_file' => 'Bestand Bewerken',
|
||||
'attachments_edit_file_name' => 'Bestandsnaam',
|
||||
'attachments_edit_drop_upload' => 'Sleep een bestand of klik hier om te uploaden en te overschrijven',
|
||||
'attachments_order_updated' => 'De volgorde van de bijlages is bijgewerkt',
|
||||
'attachments_updated_success' => 'Bijlage details bijgewerkt',
|
||||
'attachments_deleted' => 'Bijlage verwijderd',
|
||||
'attachments_file_uploaded' => 'Bestand succesvol geüpload',
|
||||
'attachments_file_updated' => 'Bestand succesvol bijgewerkt',
|
||||
'attachments_link_attached' => 'Link successfully gekoppeld aan de pagina',
|
||||
|
||||
/**
|
||||
* Profile View
|
||||
*/
|
||||
'profile_user_for_x' => 'Lid sinds :time',
|
||||
'profile_created_content' => 'Aangemaakte Inhoud',
|
||||
'profile_not_created_pages' => ':userName heeft geen pagina\'s gemaakt',
|
||||
'profile_not_created_chapters' => ':userName heeft geen hoofdstukken gemaakt',
|
||||
'profile_not_created_books' => ':userName heeft geen boeken gemaakt',
|
||||
];
|
||||
70
resources/lang/nl/errors.php
Normal file
70
resources/lang/nl/errors.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/**
|
||||
* Error text strings.
|
||||
*/
|
||||
|
||||
// Permissions
|
||||
'permission' => 'Je hebt onvoldoende rechten om deze pagina te zien.',
|
||||
'permissionJson' => 'Je hebt onvoldoende rechten voor deze actie.',
|
||||
|
||||
// Auth
|
||||
'error_user_exists_different_creds' => 'Een gebruiker met het e-mailadres :email bestaat al.',
|
||||
'email_already_confirmed' => 'Het e-mailadres is al bevestigd. Probeer in te loggen.',
|
||||
'email_confirmation_invalid' => 'Deze bevestigingstoken is ongeldig, Probeer opnieuw te registreren.',
|
||||
'email_confirmation_expired' => 'De bevestigingstoken is verlopen, Een nieuwe bevestigingsmail is verzonden.',
|
||||
'ldap_fail_anonymous' => 'LDAP toegang kon geen \'anonymous bind\' uitvoeren',
|
||||
'ldap_fail_authed' => 'LDAP toegang was niet mogelijk met de opgegeven dn & wachtwoord',
|
||||
'ldap_extension_not_installed' => 'LDAP PHP extension not installed',
|
||||
'ldap_cannot_connect' => 'Kon niet met de LDAP server verbinden',
|
||||
'social_no_action_defined' => 'Geen actie gedefineerd',
|
||||
'social_account_in_use' => 'Dit :socialAccount account is al in gebruik, Probeer in te loggen met de :socialAccount optie.',
|
||||
'social_account_email_in_use' => 'Het e-mailadres :email is al in gebruik. Als je al een account hebt kun je een :socialAccount account verbinden met je profielinstellingen.',
|
||||
'social_account_existing' => 'Dit :socialAccount is al gekoppeld aan een profiel.',
|
||||
'social_account_already_used_existing' => 'Dit :socialAccount account is ingebruik door een andere gebruiker.',
|
||||
'social_account_not_used' => 'Dit :socialAccount account is niet gekopeld aan een gebruiker. Koppel het via je profielinstellingen. ',
|
||||
'social_account_register_instructions' => 'Als je nog geen account hebt kun je je registreren met de :socialAccount optie.',
|
||||
'social_driver_not_found' => 'Social driver niet gevonden',
|
||||
'social_driver_not_configured' => 'Je :socialAccount instellingen zijn correct geconfigureerd.',
|
||||
|
||||
// System
|
||||
'path_not_writable' => 'Bestand :filePath kon niet geupload worden. Zorg dat je schrijfrechten op de server hebt.',
|
||||
'cannot_get_image_from_url' => 'Kon geen afbeelding genereren van :url',
|
||||
'cannot_create_thumbs' => 'De server kon geen thumbnails maken. Controleer of je de GD PHP extensie geïnstalleerd hebt.',
|
||||
'server_upload_limit' => 'Het afbeeldingsformaat is te groot. Probeer een kleinere bestandsgrootte.',
|
||||
'image_upload_error' => 'Er ging iets fout bij het uploaden van de afbeelding',
|
||||
|
||||
// Attachments
|
||||
'attachment_page_mismatch' => 'Bij het bijwerken van de bijlage bleek de pagina onjuist',
|
||||
|
||||
// Pages
|
||||
'page_draft_autosave_fail' => 'Kon het concept niet opslaan. Zorg ervoor dat je een werkende internetverbinding hebt.',
|
||||
|
||||
// Entities
|
||||
'entity_not_found' => 'Entiteit niet gevonden',
|
||||
'book_not_found' => 'Boek niet gevonden',
|
||||
'page_not_found' => 'Pagina niet gevonden',
|
||||
'chapter_not_found' => 'Hoofdstuk niet gevonden',
|
||||
'selected_book_not_found' => 'Het geselecteerde boek is niet gevonden',
|
||||
'selected_book_chapter_not_found' => 'Het geselecteerde boek of hoofdstuk is niet gevonden',
|
||||
'guests_cannot_save_drafts' => 'Gasten kunnen geen concepten opslaan',
|
||||
|
||||
// Users
|
||||
'users_cannot_delete_only_admin' => 'Je kunt niet het enige admin account verwijderen',
|
||||
'users_cannot_delete_guest' => 'Je kunt het gastaccount niet verwijderen',
|
||||
|
||||
// Roles
|
||||
'role_cannot_be_edited' => 'Deze rol kan niet bewerkt worden',
|
||||
'role_system_cannot_be_deleted' => 'Dit is een systeemrol en kan niet verwijderd worden',
|
||||
'role_registration_default_cannot_delete' => 'Deze rol kan niet verwijerd worden zolang dit de standaardrol na registratie is.',
|
||||
|
||||
// Error pages
|
||||
'404_page_not_found' => 'Pagina Niet Gevonden',
|
||||
'sorry_page_not_found' => 'Sorry, de pagina die je zocht is niet beschikbaar.',
|
||||
'return_home' => 'Terug naar home',
|
||||
'error_occurred' => 'Er Ging Iets Fout',
|
||||
'app_down' => ':appName is nu niet beschikbaar',
|
||||
'back_soon' => 'Komt snel weer online.',
|
||||
];
|
||||
19
resources/lang/nl/pagination.php
Normal file
19
resources/lang/nl/pagination.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Pagination Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are used by the paginator library to build
|
||||
| the simple pagination links. You are free to change them to anything
|
||||
| you want to customize your views to better match your application.
|
||||
|
|
||||
*/
|
||||
|
||||
'previous' => '« Vorige',
|
||||
'next' => 'Volgende »',
|
||||
|
||||
];
|
||||
22
resources/lang/nl/passwords.php
Normal file
22
resources/lang/nl/passwords.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Password Reminder Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are the default lines which match reasons
|
||||
| that are given by the password broker for a password update attempt
|
||||
| has failed, such as for an invalid token or invalid new password.
|
||||
|
|
||||
*/
|
||||
|
||||
'password' => 'Wachtwoorden moeten overeenkomen en minimaal zes tekens lang zijn.',
|
||||
'user' => "We kunnen niemand vinden met dat e-mailadres.",
|
||||
'token' => 'De token om het wachtwoord te herstellen is ongeldig.',
|
||||
'sent' => 'We hebben je een link gestuurd om je wachtwoord te herstellen!',
|
||||
'reset' => 'Je wachtwoord is hersteld!',
|
||||
|
||||
];
|
||||
111
resources/lang/nl/settings.php
Normal file
111
resources/lang/nl/settings.php
Normal file
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/**
|
||||
* Settings text strings
|
||||
* Contains all text strings used in the general settings sections of BookStack
|
||||
* including users and roles.
|
||||
*/
|
||||
|
||||
'settings' => 'Instellingen',
|
||||
'settings_save' => 'Instellingen Opslaan',
|
||||
'settings_save_success' => 'Instellingen Opgeslagen',
|
||||
|
||||
/**
|
||||
* App settings
|
||||
*/
|
||||
|
||||
'app_settings' => 'App Instellingen',
|
||||
'app_name' => 'Applicatienaam',
|
||||
'app_name_desc' => 'De applicatienaam wordt in e-mails in in de header weergegeven.',
|
||||
'app_name_header' => 'Applicatienaam in de header weergeven?',
|
||||
'app_public_viewing' => 'Publieke bewerkingen toestaan?',
|
||||
'app_secure_images' => 'Beter beveiligide afbeeldingen gebruiken?',
|
||||
'app_secure_images_desc' => 'Omwille van de performance zijn alle afbeeldingen publiek toegankelijk. Zorg ervoor dat je de \'directory index\' niet hebt ingeschakeld.',
|
||||
'app_editor' => 'Pagina Bewerken',
|
||||
'app_editor_desc' => 'Selecteer welke tekstverwerker je wilt gebruiken.',
|
||||
'app_custom_html' => 'Speciale HTML toevoegen',
|
||||
'app_custom_html_desc' => 'Alles wat je hier toevoegd wordt in de <head> sectie van elke pagina meengenomen. Dit kun je bijvoorbeeld voor analytics gebruiken.',
|
||||
'app_logo' => 'Applicatielogo',
|
||||
'app_logo_desc' => 'De afbeelding moet 43px hoog zijn. <br>Grotere afbeeldingen worden geschaald.',
|
||||
'app_primary_color' => 'Applicatie hoofdkleur',
|
||||
'app_primary_color_desc' => 'Geef een hexadecimale waarde. <br>Als je niks invult wordt de standaardkleur gebruikt.',
|
||||
|
||||
/**
|
||||
* Registration settings
|
||||
*/
|
||||
|
||||
'reg_settings' => 'Registratieinstellingen',
|
||||
'reg_allow' => 'Registratie toestaan?',
|
||||
'reg_default_role' => 'Standaard rol na registratie',
|
||||
'reg_confirm_email' => 'E-mailbevesting vereist?',
|
||||
'reg_confirm_email_desc' => 'Als domeinrestricties aan staan dan is altijd e-maibevestiging nodig. Onderstaande instelling wordt dan genegeerd.',
|
||||
'reg_confirm_restrict_domain' => 'Beperk registratie tot een maildomein',
|
||||
'reg_confirm_restrict_domain_desc' => 'Geen een komma-gescheiden lijst van domeinnamen die gebruikt mogen worden bij registratie. <br> Let op: na registratie kunnen gebruikers hun e-mailadres nog steeds wijzigen.',
|
||||
'reg_confirm_restrict_domain_placeholder' => 'Geen beperkingen ingesteld',
|
||||
|
||||
/**
|
||||
* Role settings
|
||||
*/
|
||||
|
||||
'roles' => 'Rollen',
|
||||
'role_user_roles' => 'Gebruikrollen',
|
||||
'role_create' => 'Nieuwe Rol Maken',
|
||||
'role_create_success' => 'Rol succesvol aangemaakt',
|
||||
'role_delete' => 'Rol Verwijderen',
|
||||
'role_delete_confirm' => 'Dit verwijdert de rol \':roleName\'.',
|
||||
'role_delete_users_assigned' => 'Er zijn :userCount gebruikers met deze rol. Selecteer hieronder een nieuwe rol als je deze gebruikers een andere rol wilt geven.',
|
||||
'role_delete_no_migration' => "Geen gebruikers migreren",
|
||||
'role_delete_sure' => 'Weet je zeker dat je deze rol wilt verwijderen?',
|
||||
'role_delete_success' => 'Rol succesvol verwijderd',
|
||||
'role_edit' => 'Rol Bewerken',
|
||||
'role_details' => 'Rol Details',
|
||||
'role_name' => 'Rolnaam',
|
||||
'role_desc' => 'Korte beschrijving van de rol',
|
||||
'role_system' => 'Systeem Permissies',
|
||||
'role_manage_users' => 'Gebruikers beheren',
|
||||
'role_manage_roles' => 'Rollen en rechten beheren',
|
||||
'role_manage_entity_permissions' => 'Beheer alle boeken-, hoofdstukken- en paginaresitrcties',
|
||||
'role_manage_own_entity_permissions' => 'Beheer restricties van je eigen boeken, hoofdstukken en pagina\'s',
|
||||
'role_manage_settings' => 'Beheer app instellingen',
|
||||
'role_asset' => 'Asset Permissies',
|
||||
'role_asset_desc' => 'Deze permissies bepalen de standaardtoegangsrechten. Permissies op boeken, hoofdstukken en pagina\'s overschrijven deze instelling.',
|
||||
'role_all' => 'Alles',
|
||||
'role_own' => 'Eigen',
|
||||
'role_controlled_by_asset' => 'Gecontroleerd door de asset waar deze is geüpload',
|
||||
'role_save' => 'Rol Opslaan',
|
||||
'role_update_success' => 'Rol succesvol bijgewerkt',
|
||||
'role_users' => 'Gebruikers in deze rol',
|
||||
'role_users_none' => 'Geen enkele gebruiker heeft deze rol',
|
||||
|
||||
/**
|
||||
* Users
|
||||
*/
|
||||
|
||||
'users' => 'Gebruikers',
|
||||
'user_profile' => 'Gebruikersprofiel',
|
||||
'users_add_new' => 'Gebruiker toevoegen',
|
||||
'users_search' => 'Gebruiker zoeken',
|
||||
'users_role' => 'Gebruikersrollen',
|
||||
'users_external_auth_id' => 'External Authentication ID',
|
||||
'users_password_warning' => 'Vul onderstaande formulier alleen in als je het wachtwoord wilt aanpassen:',
|
||||
'users_system_public' => 'De eigenschappen van deze gebruiker worden voor elke gastbezoeker gebruikt. Er kan niet mee ingelogd worden en wordt automatisch toegewezen.',
|
||||
'users_delete' => 'Verwijder gebruiker',
|
||||
'users_delete_named' => 'Verwijder gebruiker :userName',
|
||||
'users_delete_warning' => 'Dit zal de gebruiker \':userName\' volledig uit het systeem verwijderen.',
|
||||
'users_delete_confirm' => 'Weet je zeker dat je deze gebruiker wilt verwijderen?',
|
||||
'users_delete_success' => 'Gebruiker succesvol verwijderd',
|
||||
'users_edit' => 'Bewerk Gebruiker',
|
||||
'users_edit_profile' => 'Bewerk Profiel',
|
||||
'users_edit_success' => 'Gebruiker succesvol bijgewerkt',
|
||||
'users_avatar' => 'Avatar',
|
||||
'users_avatar_desc' => 'De afbeelding moet vierkant zijn en ongeveer 256px breed.',
|
||||
'users_preferred_language' => 'Voorkeurstaal',
|
||||
'users_social_accounts' => 'Social Accounts',
|
||||
'users_social_accounts_info' => 'Hier kun je accounts verbinden om makkelijker in te loggen. Via je profiel kun je ook weer rechten intrekken die bij deze social accountsh horen.',
|
||||
'users_social_connect' => 'Account Verbinden',
|
||||
'users_social_disconnect' => 'Account Ontkoppelen',
|
||||
'users_social_connected' => ':socialAccount account is succesvol aan je profiel gekoppeld.',
|
||||
'users_social_disconnected' => ':socialAccount account is succesvol ontkoppeld van je profiel.',
|
||||
];
|
||||
108
resources/lang/nl/validation.php
Normal file
108
resources/lang/nl/validation.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Validation Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines contain the default error messages used by
|
||||
| the validator class. Some of these rules have multiple versions such
|
||||
| as the size rules. Feel free to tweak each of these messages here.
|
||||
|
|
||||
*/
|
||||
|
||||
'accepted' => 'The :attribute must be accepted.',
|
||||
'active_url' => 'The :attribute is not a valid URL.',
|
||||
'after' => 'The :attribute must be a date after :date.',
|
||||
'alpha' => 'The :attribute may only contain letters.',
|
||||
'alpha_dash' => 'The :attribute may only contain letters, numbers, and dashes.',
|
||||
'alpha_num' => 'The :attribute may only contain letters and numbers.',
|
||||
'array' => 'The :attribute must be an array.',
|
||||
'before' => 'The :attribute must be a date before :date.',
|
||||
'between' => [
|
||||
'numeric' => 'The :attribute must be between :min and :max.',
|
||||
'file' => 'The :attribute must be between :min and :max kilobytes.',
|
||||
'string' => 'The :attribute must be between :min and :max characters.',
|
||||
'array' => 'The :attribute must have between :min and :max items.',
|
||||
],
|
||||
'boolean' => 'The :attribute field must be true or false.',
|
||||
'confirmed' => 'The :attribute confirmation does not match.',
|
||||
'date' => 'The :attribute is not a valid date.',
|
||||
'date_format' => 'The :attribute does not match the format :format.',
|
||||
'different' => 'The :attribute and :other must be different.',
|
||||
'digits' => 'The :attribute must be :digits digits.',
|
||||
'digits_between' => 'The :attribute must be between :min and :max digits.',
|
||||
'email' => 'The :attribute must be a valid email address.',
|
||||
'filled' => 'The :attribute field is required.',
|
||||
'exists' => 'The selected :attribute is invalid.',
|
||||
'image' => 'The :attribute must be an image.',
|
||||
'in' => 'The selected :attribute is invalid.',
|
||||
'integer' => 'The :attribute must be an integer.',
|
||||
'ip' => 'The :attribute must be a valid IP address.',
|
||||
'max' => [
|
||||
'numeric' => 'The :attribute may not be greater than :max.',
|
||||
'file' => 'The :attribute may not be greater than :max kilobytes.',
|
||||
'string' => 'The :attribute may not be greater than :max characters.',
|
||||
'array' => 'The :attribute may not have more than :max items.',
|
||||
],
|
||||
'mimes' => 'The :attribute must be a file of type: :values.',
|
||||
'min' => [
|
||||
'numeric' => 'The :attribute must be at least :min.',
|
||||
'file' => 'The :attribute must be at least :min kilobytes.',
|
||||
'string' => 'The :attribute must be at least :min characters.',
|
||||
'array' => 'The :attribute must have at least :min items.',
|
||||
],
|
||||
'not_in' => 'The selected :attribute is invalid.',
|
||||
'numeric' => 'The :attribute must be a number.',
|
||||
'regex' => 'The :attribute format is invalid.',
|
||||
'required' => 'The :attribute field is required.',
|
||||
'required_if' => 'The :attribute field is required when :other is :value.',
|
||||
'required_with' => 'The :attribute field is required when :values is present.',
|
||||
'required_with_all' => 'The :attribute field is required when :values is present.',
|
||||
'required_without' => 'The :attribute field is required when :values is not present.',
|
||||
'required_without_all' => 'The :attribute field is required when none of :values are present.',
|
||||
'same' => 'The :attribute and :other must match.',
|
||||
'size' => [
|
||||
'numeric' => 'The :attribute must be :size.',
|
||||
'file' => 'The :attribute must be :size kilobytes.',
|
||||
'string' => 'The :attribute must be :size characters.',
|
||||
'array' => 'The :attribute must contain :size items.',
|
||||
],
|
||||
'string' => 'The :attribute must be a string.',
|
||||
'timezone' => 'The :attribute must be a valid zone.',
|
||||
'unique' => 'The :attribute has already been taken.',
|
||||
'url' => 'The :attribute format is invalid.',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Custom Validation Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify custom validation messages for attributes using the
|
||||
| convention "attribute.rule" to name the lines. This makes it quick to
|
||||
| specify a specific custom language line for a given attribute rule.
|
||||
|
|
||||
*/
|
||||
|
||||
'custom' => [
|
||||
'password-confirm' => [
|
||||
'required_with' => 'Password confirmation required',
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Custom Validation Attributes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are used to swap attribute place-holders
|
||||
| with something more reader friendly such as E-Mail Address instead
|
||||
| of "email". This simply helps us make messages a little cleaner.
|
||||
|
|
||||
*/
|
||||
|
||||
'attributes' => [],
|
||||
|
||||
];
|
||||
@@ -26,6 +26,10 @@ return [
|
||||
'no_pages_viewed' => 'Você não visualizou nenhuma página',
|
||||
'no_pages_recently_created' => 'Nenhuma página recentemente criada',
|
||||
'no_pages_recently_updated' => 'Nenhuma página recentemente atualizada',
|
||||
'export' => 'Exportar',
|
||||
'export_html' => 'Arquivo Web Contained',
|
||||
'export_pdf' => 'Arquivo PDF',
|
||||
'export_text' => 'Arquivo Texto',
|
||||
|
||||
/**
|
||||
* Permissions and restrictions
|
||||
@@ -39,18 +43,9 @@ return [
|
||||
* Search
|
||||
*/
|
||||
'search_results' => 'Resultado(s) da Pesquisa',
|
||||
'search_results_page' => 'Resultado(s) de Pesquisa de Página',
|
||||
'search_results_chapter' => 'Resultado(s) de Pesquisa de Capítulo',
|
||||
'search_results_book' => 'Resultado(s) de Pesquisa de Livro',
|
||||
'search_clear' => 'Limpar Pesquisa',
|
||||
'search_view_pages' => 'Visualizar todas as páginas correspondentes',
|
||||
'search_view_chapters' => 'Visualizar todos os capítulos correspondentes',
|
||||
'search_view_books' => 'Visualizar todos os livros correspondentes',
|
||||
'search_no_pages' => 'Nenhuma página corresponde à pesquisa',
|
||||
'search_for_term' => 'Pesquisar por :term',
|
||||
'search_page_for_term' => 'Pesquisar Página por :term',
|
||||
'search_chapter_for_term' => 'Pesquisar Capítulo por :term',
|
||||
'search_book_for_term' => 'Pesquisar Livros por :term',
|
||||
|
||||
/**
|
||||
* Books
|
||||
@@ -161,10 +156,6 @@ return [
|
||||
'pages_revisions_preview' => 'Preview',
|
||||
'pages_revisions_restore' => 'Restaurar',
|
||||
'pages_revisions_none' => 'Essa página não tem revisões',
|
||||
'pages_export' => 'Exportar',
|
||||
'pages_export_html' => 'Arquivo Web Contained',
|
||||
'pages_export_pdf' => 'Arquivo PDF',
|
||||
'pages_export_text' => 'Arquivo Texto',
|
||||
'pages_copy_link' => 'Copia Link',
|
||||
'pages_permissions_active' => 'Permissões de Página Ativas',
|
||||
'pages_initial_revision' => 'Publicação Inicial',
|
||||
|
||||
40
resources/lang/sk/activities.php
Normal file
40
resources/lang/sk/activities.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/**
|
||||
* Activity text strings.
|
||||
* Is used for all the text within activity logs & notifications.
|
||||
*/
|
||||
|
||||
// Pages
|
||||
'page_create' => 'vytvoril stránku',
|
||||
'page_create_notification' => 'Stránka úspešne vytvorená',
|
||||
'page_update' => 'aktualizoval stránku',
|
||||
'page_update_notification' => 'Stránka úspešne aktualizovaná',
|
||||
'page_delete' => 'odstránil stránku',
|
||||
'page_delete_notification' => 'Stránka úspešne odstránená',
|
||||
'page_restore' => 'obnovil stránku',
|
||||
'page_restore_notification' => 'Stránka úspešne obnovená',
|
||||
'page_move' => 'presunul stránku',
|
||||
|
||||
// Chapters
|
||||
'chapter_create' => 'vytvoril kapitolu',
|
||||
'chapter_create_notification' => 'Kapitola úspešne vytvorená',
|
||||
'chapter_update' => 'aktualizoval kapitolu',
|
||||
'chapter_update_notification' => 'Kapitola úspešne aktualizovaná',
|
||||
'chapter_delete' => 'odstránil kapitolu',
|
||||
'chapter_delete_notification' => 'Kapitola úspešne odstránená',
|
||||
'chapter_move' => 'presunul kapitolu',
|
||||
|
||||
// Books
|
||||
'book_create' => 'vytvoril knihu',
|
||||
'book_create_notification' => 'Kniha úspešne vytvorená',
|
||||
'book_update' => 'aktualizoval knihu',
|
||||
'book_update_notification' => 'Kniha úspešne aktualizovaná',
|
||||
'book_delete' => 'odstránil knihu',
|
||||
'book_delete_notification' => 'Kniha úspešne odstránená',
|
||||
'book_sort' => 'zoradil knihu',
|
||||
'book_sort_notification' => 'Kniha úspešne znovu zoradená',
|
||||
|
||||
];
|
||||
76
resources/lang/sk/auth.php
Normal file
76
resources/lang/sk/auth.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
return [
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Authentication Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are used during authentication for various
|
||||
| messages that we need to display to the user. You are free to modify
|
||||
| these language lines according to your application's requirements.
|
||||
|
|
||||
*/
|
||||
'failed' => 'Tieto údaje nesedia s našimi záznamami.',
|
||||
'throttle' => 'Priveľa pokusov o prihlásenie. Skúste znova o :seconds sekúnd.',
|
||||
|
||||
/**
|
||||
* Login & Register
|
||||
*/
|
||||
'sign_up' => 'Registrácia',
|
||||
'log_in' => 'Prihlásenie',
|
||||
'log_in_with' => 'Prihlásiť sa cez :socialDriver',
|
||||
'sign_up_with' => 'Registrovať sa cez :socialDriver',
|
||||
'logout' => 'Odhlásenie',
|
||||
|
||||
'name' => 'Meno',
|
||||
'username' => 'Používateľské meno',
|
||||
'email' => 'Email',
|
||||
'password' => 'Heslo',
|
||||
'password_confirm' => 'Potvrdiť heslo',
|
||||
'password_hint' => 'Musí mať viac ako 5 znakov',
|
||||
'forgot_password' => 'Zabudli ste heslo?',
|
||||
'remember_me' => 'Zapamätať si ma',
|
||||
'ldap_email_hint' => 'Zadajte prosím email, ktorý sa má použiť pre tento účet.',
|
||||
'create_account' => 'Vytvoriť účet',
|
||||
'social_login' => 'Sociálne prihlásenie',
|
||||
'social_registration' => 'Sociálna registrácia',
|
||||
'social_registration_text' => 'Registrovať sa a prihlásiť sa použitím inej služby.',
|
||||
|
||||
'register_thanks' => 'Ďakujeme zaregistráciu!',
|
||||
'register_confirm' => 'Skontrolujte prosím svoj email a kliknite na potvrdzujúce tlačidlo pre prístup k :appName.',
|
||||
'registrations_disabled' => 'Registrácie sú momentálne zablokované',
|
||||
'registration_email_domain_invalid' => 'Táto emailová doména nemá prístup k tejto aplikácii',
|
||||
'register_success' => 'Ďakujeme za registráciu! Teraz ste registrovaný a prihlásený.',
|
||||
|
||||
|
||||
/**
|
||||
* Password Reset
|
||||
*/
|
||||
'reset_password' => 'Reset hesla',
|
||||
'reset_password_send_instructions' => 'Zadajte svoj email nižšie a bude Vám odoslaný email s odkazom pre reset hesla.',
|
||||
'reset_password_send_button' => 'Poslať odkaz na reset hesla',
|
||||
'reset_password_sent_success' => 'Odkaz na reset hesla bol poslaný na :email.',
|
||||
'reset_password_success' => 'Vaše heslo bolo úspešne resetované.',
|
||||
|
||||
'email_reset_subject' => 'Reset Vášho :appName hesla',
|
||||
'email_reset_text' => 'Tento email Ste dostali pretože sme dostali požiadavku na reset hesla pre Váš účet.',
|
||||
'email_reset_not_requested' => 'Ak ste nepožiadali o reset hesla, nemusíte nič robiť.',
|
||||
|
||||
|
||||
/**
|
||||
* Email Confirmation
|
||||
*/
|
||||
'email_confirm_subject' => 'Potvrdiť email na :appName',
|
||||
'email_confirm_greeting' => 'Ďakujeme za pridanie sa k :appName!',
|
||||
'email_confirm_text' => 'Prosím potvrďte Vašu emailovú adresu kliknutím na tlačidlo nižšie:',
|
||||
'email_confirm_action' => 'Potvrdiť email',
|
||||
'email_confirm_send_error' => 'Je požadované overenie emailu, ale systém nemohol odoslať email. Kontaktujte administrátora by ste sa uistili, že email je nastavený správne.',
|
||||
'email_confirm_success' => 'Váš email bol overený!',
|
||||
'email_confirm_resent' => 'Potvrdzujúci email bol poslaný znovu, skontrolujte prosím svoju emailovú schránku.',
|
||||
|
||||
'email_not_confirmed' => 'Emailová adresa nebola overená',
|
||||
'email_not_confirmed_text' => 'Vaša emailová adresa nebola zatiaľ overená.',
|
||||
'email_not_confirmed_click_link' => 'Prosím, kliknite na odkaz v emaili, ktorý bol poslaný krátko po Vašej registrácii.',
|
||||
'email_not_confirmed_resend' => 'Ak nemôžete násť email, môžete znova odoslať overovací email odoslaním doleuvedeného formulára.',
|
||||
'email_not_confirmed_resend_button' => 'Znova odoslať overovací email',
|
||||
];
|
||||
58
resources/lang/sk/common.php
Normal file
58
resources/lang/sk/common.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
return [
|
||||
|
||||
/**
|
||||
* Buttons
|
||||
*/
|
||||
'cancel' => 'Zrušiť',
|
||||
'confirm' => 'Potvrdiť',
|
||||
'back' => 'Späť',
|
||||
'save' => 'Uložiť',
|
||||
'continue' => 'Pokračovať',
|
||||
'select' => 'Vybrať',
|
||||
|
||||
/**
|
||||
* Form Labels
|
||||
*/
|
||||
'name' => 'Meno',
|
||||
'description' => 'Popis',
|
||||
'role' => 'Rola',
|
||||
|
||||
/**
|
||||
* Actions
|
||||
*/
|
||||
'actions' => 'Akcie',
|
||||
'view' => 'Zobraziť',
|
||||
'create' => 'Vytvoriť',
|
||||
'update' => 'Aktualizovať',
|
||||
'edit' => 'Editovať',
|
||||
'sort' => 'Zoradiť',
|
||||
'move' => 'Presunúť',
|
||||
'delete' => 'Zmazať',
|
||||
'search' => 'Hľadť',
|
||||
'search_clear' => 'Vyčistiť hľadanie',
|
||||
'reset' => 'Reset',
|
||||
'remove' => 'Odstrániť',
|
||||
|
||||
|
||||
/**
|
||||
* Misc
|
||||
*/
|
||||
'deleted_user' => 'Odstránený používateľ',
|
||||
'no_activity' => 'Žiadna aktivita na zobrazenie',
|
||||
'no_items' => 'Žiadne položky nie sú dostupné',
|
||||
'back_to_top' => 'Späť nahor',
|
||||
'toggle_details' => 'Prepnúť detaily',
|
||||
|
||||
/**
|
||||
* Header
|
||||
*/
|
||||
'view_profile' => 'Zobraziť profil',
|
||||
'edit_profile' => 'Upraviť profil',
|
||||
|
||||
/**
|
||||
* Email Content
|
||||
*/
|
||||
'email_action_help' => 'Ak máte problém klinkúť na tlačidlo ":actionText", skopírujte a vložte URL uvedenú nižšie do Vášho prehliadača:',
|
||||
'email_rights' => 'Všetky práva vyhradené',
|
||||
];
|
||||
24
resources/lang/sk/components.php
Normal file
24
resources/lang/sk/components.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
return [
|
||||
|
||||
/**
|
||||
* Image Manager
|
||||
*/
|
||||
'image_select' => 'Vybrať obrázok',
|
||||
'image_all' => 'Všetko',
|
||||
'image_all_title' => 'Zobraziť všetky obrázky',
|
||||
'image_book_title' => 'Zobraziť obrázky nahrané do tejto knihy',
|
||||
'image_page_title' => 'Zobraziť obrázky nahrané do tejto stránky',
|
||||
'image_search_hint' => 'Hľadať obrázok podľa názvu',
|
||||
'image_uploaded' => 'Nahrané :uploadedDate',
|
||||
'image_load_more' => 'Načítať viac',
|
||||
'image_image_name' => 'Názov obrázka',
|
||||
'image_delete_confirm' => 'Tento obrázok je použitý na stránkach uvedených nižšie, kliknite znova na zmazať pre potvrdenie zmazania tohto obrázka.',
|
||||
'image_select_image' => 'Vybrať obrázok',
|
||||
'image_dropzone' => 'Presuňte obrázky sem alebo kliknite sem pre nahranie',
|
||||
'images_deleted' => 'Obrázky zmazané',
|
||||
'image_preview' => 'Náhľad obrázka',
|
||||
'image_upload_success' => 'Obrázok úspešne nahraný',
|
||||
'image_update_success' => 'Detaily obrázka úspešne aktualizované',
|
||||
'image_delete_success' => 'Obrázok úspešne zmazaný'
|
||||
];
|
||||
226
resources/lang/sk/entities.php
Normal file
226
resources/lang/sk/entities.php
Normal file
@@ -0,0 +1,226 @@
|
||||
<?php
|
||||
return [
|
||||
|
||||
/**
|
||||
* Shared
|
||||
*/
|
||||
'recently_created' => 'Nedávno vytvorené',
|
||||
'recently_created_pages' => 'Nedávno vytvorené stránky',
|
||||
'recently_updated_pages' => 'Nedávno aktualizované stránky',
|
||||
'recently_created_chapters' => 'Nedávno vytvorené kapitoly',
|
||||
'recently_created_books' => 'Nedávno vytvorené knihy',
|
||||
'recently_update' => 'Nedávno aktualizované',
|
||||
'recently_viewed' => 'Nedávno zobrazené',
|
||||
'recent_activity' => 'Nedávna aktivita',
|
||||
'create_now' => 'Vytvoriť teraz',
|
||||
'revisions' => 'Revízie',
|
||||
'meta_created' => 'Vytvorené :timeLength',
|
||||
'meta_created_name' => 'Vytvorené :timeLength používateľom :user',
|
||||
'meta_updated' => 'Aktualizované :timeLength',
|
||||
'meta_updated_name' => 'Aktualizované :timeLength používateľom :user',
|
||||
'x_pages' => ':count stránok',
|
||||
'entity_select' => 'Entita vybraná',
|
||||
'images' => 'Obrázky',
|
||||
'my_recent_drafts' => 'Moje nedávne koncepty',
|
||||
'my_recently_viewed' => 'Nedávno mnou zobrazené',
|
||||
'no_pages_viewed' => 'Nepozreli ste si žiadne stránky',
|
||||
'no_pages_recently_created' => 'Žiadne stránky neboli nedávno vytvorené',
|
||||
'no_pages_recently_updated' => 'Žiadne stránky neboli nedávno aktualizované',
|
||||
'export' => 'Export',
|
||||
'export_html' => 'Contained Web File',
|
||||
'export_pdf' => 'PDF súbor',
|
||||
'export_text' => 'Súbor s čistým textom',
|
||||
|
||||
/**
|
||||
* Permissions and restrictions
|
||||
*/
|
||||
'permissions' => 'Oprávnenia',
|
||||
'permissions_intro' => 'Ak budú tieto oprávnenia povolené, budú mať prioritu pred oprávneniami roly.',
|
||||
'permissions_enable' => 'Povoliť vlastné oprávnenia',
|
||||
'permissions_save' => 'Uložiť oprávnenia',
|
||||
|
||||
/**
|
||||
* Search
|
||||
*/
|
||||
'search_results' => 'Výsledky hľadania',
|
||||
'search_results_page' => 'Výsledky hľadania stránky',
|
||||
'search_results_chapter' => 'Výsledky hľadania kapitoly',
|
||||
'search_results_book' => 'Výsledky hľadania knihy',
|
||||
'search_clear' => 'Vyčistiť hľadanie',
|
||||
'search_view_pages' => 'Zobraziť všetky vyhovujúce stránky',
|
||||
'search_view_chapters' => 'Zobraziť všetky vyhovujúce kapitoly',
|
||||
'search_view_books' => 'Zobraziť všetky vyhovujúce knihy',
|
||||
'search_no_pages' => 'Žiadne stránky nevyhovujú tomuto hľadaniu',
|
||||
'search_for_term' => 'Hľadať :term',
|
||||
'search_page_for_term' => 'Hľadať :term medzi stránkami',
|
||||
'search_chapter_for_term' => 'Hľadať :term medzi kapitolami',
|
||||
'search_book_for_term' => 'Hľadať :term medzi knihami',
|
||||
|
||||
/**
|
||||
* Books
|
||||
*/
|
||||
'book' => 'Kniha',
|
||||
'books' => 'Knihy',
|
||||
'books_empty' => 'Žiadne knihy neboli vytvorené',
|
||||
'books_popular' => 'Populárne knihy',
|
||||
'books_recent' => 'Nedávne knihy',
|
||||
'books_popular_empty' => 'Najpopulárnejšie knihy sa objavia tu.',
|
||||
'books_create' => 'Vytvoriť novú knihu',
|
||||
'books_delete' => 'Zmazať knihu',
|
||||
'books_delete_named' => 'Zmazať knihu :bookName',
|
||||
'books_delete_explain' => 'Toto zmaže knihu s názvom \':bookName\', všetky stránky a kapitoly budú odstránené.',
|
||||
'books_delete_confirmation' => 'Ste si istý, že chcete zmazať túto knihu?',
|
||||
'books_edit' => 'Upraviť knihu',
|
||||
'books_edit_named' => 'Upraviť knihu :bookName',
|
||||
'books_form_book_name' => 'Názov knihy',
|
||||
'books_save' => 'Uložiť knihu',
|
||||
'books_permissions' => 'Oprávnenia knihy',
|
||||
'books_permissions_updated' => 'Oprávnenia knihy aktualizované',
|
||||
'books_empty_contents' => 'Pre túto knihu neboli vytvorené žiadne stránky alebo kapitoly.',
|
||||
'books_empty_create_page' => 'Vytvoriť novú stránku',
|
||||
'books_empty_or' => 'alebo',
|
||||
'books_empty_sort_current_book' => 'Zoradiť aktuálnu knihu',
|
||||
'books_empty_add_chapter' => 'Pridať kapitolu',
|
||||
'books_permissions_active' => 'Oprávnenia knihy aktívne',
|
||||
'books_search_this' => 'Hľadať v tejto knihe',
|
||||
'books_navigation' => 'Navigácia knihy',
|
||||
'books_sort' => 'Zoradiť obsah knihy',
|
||||
'books_sort_named' => 'Zoradiť knihu :bookName',
|
||||
'books_sort_show_other' => 'Zobraziť ostatné knihy',
|
||||
'books_sort_save' => 'Uložiť nové zoradenie',
|
||||
|
||||
/**
|
||||
* Chapters
|
||||
*/
|
||||
'chapter' => 'Kapitola',
|
||||
'chapters' => 'Kapitoly',
|
||||
'chapters_popular' => 'Populárne kapitoly',
|
||||
'chapters_new' => 'Nová kapitola',
|
||||
'chapters_create' => 'Vytvoriť novú kapitolu',
|
||||
'chapters_delete' => 'Zmazať kapitolu',
|
||||
'chapters_delete_named' => 'Zmazať kapitolu :chapterName',
|
||||
'chapters_delete_explain' => 'Toto zmaže kapitolu menom \':chapterName\', všetky stránky budú ostránené
|
||||
a pridané priamo do rodičovskej knihy.',
|
||||
'chapters_delete_confirm' => 'Ste si istý, že chcete zmazať túto kapitolu?',
|
||||
'chapters_edit' => 'Upraviť kapitolu',
|
||||
'chapters_edit_named' => 'Upraviť kapitolu :chapterName',
|
||||
'chapters_save' => 'Uložiť kapitolu',
|
||||
'chapters_move' => 'Presunúť kapitolu',
|
||||
'chapters_move_named' => 'Presunúť kapitolu :chapterName',
|
||||
'chapter_move_success' => 'Kapitola presunutá do :bookName',
|
||||
'chapters_permissions' => 'Oprávnenia kapitoly',
|
||||
'chapters_empty' => 'V tejto kapitole nie sú teraz žiadne stránky.',
|
||||
'chapters_permissions_active' => 'Oprávnenia kapitoly aktívne',
|
||||
'chapters_permissions_success' => 'Oprávnenia kapitoly aktualizované',
|
||||
|
||||
/**
|
||||
* Pages
|
||||
*/
|
||||
'page' => 'Stránka',
|
||||
'pages' => 'Stránky',
|
||||
'pages_popular' => 'Populárne stránky',
|
||||
'pages_new' => 'Nová stránka',
|
||||
'pages_attachments' => 'Prílohy',
|
||||
'pages_navigation' => 'Navigácia',
|
||||
'pages_delete' => 'Zmazať stránku',
|
||||
'pages_delete_named' => 'Zmazať stránku :pageName',
|
||||
'pages_delete_draft_named' => 'Zmazať koncept :pageName',
|
||||
'pages_delete_draft' => 'Zmazať koncept',
|
||||
'pages_delete_success' => 'Stránka zmazaná',
|
||||
'pages_delete_draft_success' => 'Koncept stránky zmazaný',
|
||||
'pages_delete_confirm' => 'Ste si istý, že chcete zmazať túto stránku?',
|
||||
'pages_delete_draft_confirm' => 'Ste si istý, že chcete zmazať tento koncept stránky?',
|
||||
'pages_editing_named' => 'Upraviť stránku :pageName',
|
||||
'pages_edit_toggle_header' => 'Prepnúť hlavičku',
|
||||
'pages_edit_save_draft' => 'Uložiť koncept',
|
||||
'pages_edit_draft' => 'Upraviť koncept stránky',
|
||||
'pages_editing_draft' => 'Upravuje sa koncept',
|
||||
'pages_editing_page' => 'Upravuje sa stránka',
|
||||
'pages_edit_draft_save_at' => 'Koncept uložený pod ',
|
||||
'pages_edit_delete_draft' => 'Uložiť koncept',
|
||||
'pages_edit_discard_draft' => 'Zrušiť koncept',
|
||||
'pages_edit_set_changelog' => 'Nastaviť záznam zmien',
|
||||
'pages_edit_enter_changelog_desc' => 'Zadajte krátky popis zmien, ktoré ste urobili',
|
||||
'pages_edit_enter_changelog' => 'Zadať záznam zmien',
|
||||
'pages_save' => 'Uložiť stránku',
|
||||
'pages_title' => 'Titulok stránky',
|
||||
'pages_name' => 'Názov stránky',
|
||||
'pages_md_editor' => 'Editor',
|
||||
'pages_md_preview' => 'Náhľad',
|
||||
'pages_md_insert_image' => 'Vložiť obrázok',
|
||||
'pages_md_insert_link' => 'Vložiť odkaz na entitu',
|
||||
'pages_not_in_chapter' => 'Stránka nie je v kapitole',
|
||||
'pages_move' => 'Presunúť stránku',
|
||||
'pages_move_success' => 'Stránka presunutá do ":parentName"',
|
||||
'pages_permissions' => 'Oprávnenia stránky',
|
||||
'pages_permissions_success' => 'Oprávnenia stránky aktualizované',
|
||||
'pages_revisions' => 'Revízie stránky',
|
||||
'pages_revisions_named' => 'Revízie stránky :pageName',
|
||||
'pages_revision_named' => 'Revízia stránky :pageName',
|
||||
'pages_revisions_created_by' => 'Vytvoril',
|
||||
'pages_revisions_date' => 'Dátum revízie',
|
||||
'pages_revisions_changelog' => 'Záznam zmien',
|
||||
'pages_revisions_changes' => 'Zmeny',
|
||||
'pages_revisions_current' => 'Aktuálna verzia',
|
||||
'pages_revisions_preview' => 'Náhľad',
|
||||
'pages_revisions_restore' => 'Obnoviť',
|
||||
'pages_revisions_none' => 'Táto stránka nemá žiadne revízie',
|
||||
'pages_copy_link' => 'Kopírovať odkaz',
|
||||
'pages_permissions_active' => 'Oprávnienia stránky aktívne',
|
||||
'pages_initial_revision' => 'Prvé zverejnenie',
|
||||
'pages_initial_name' => 'Nová stránka',
|
||||
'pages_editing_draft_notification' => 'Práve upravujete koncept, ktorý bol naposledy uložený :timeDiff.',
|
||||
'pages_draft_edited_notification' => 'Táto stránka bola odvtedy upravená. Odporúča sa odstrániť tento koncept.',
|
||||
'pages_draft_edit_active' => [
|
||||
'start_a' => ':count používateľov začalo upravovať túto stránku',
|
||||
'start_b' => ':userName začal upravovať túto stránku',
|
||||
'time_a' => 'odkedy boli stránky naposledy aktualizované',
|
||||
'time_b' => 'za posledných :minCount minút',
|
||||
'message' => ':start :time. Dávajte pozor aby ste si navzájom neprepísali zmeny!',
|
||||
],
|
||||
'pages_draft_discarded' => 'Koncept ostránený, aktuálny obsah stránky bol nahraný do editora',
|
||||
|
||||
/**
|
||||
* Editor sidebar
|
||||
*/
|
||||
'page_tags' => 'Štítky stránok',
|
||||
'tag' => 'Štítok',
|
||||
'tags' => 'Štítky',
|
||||
'tag_value' => 'Hodnota štítku (Voliteľné)',
|
||||
'tags_explain' => "Pridajte pár štítkov pre uľahčenie kategorizácie Vášho obsahu. \n Štítku môžete priradiť hodnotu pre ešte lepšiu organizáciu.",
|
||||
'tags_add' => 'Pridať ďalší štítok',
|
||||
'attachments' => 'Prílohy',
|
||||
'attachments_explain' => 'Nahrajte nejaké súbory alebo priložte zopár odkazov pre zobrazenie na Vašej stránke. Budú viditeľné v bočnom paneli.',
|
||||
'attachments_explain_instant_save' => 'Zmeny budú okamžite uložené.',
|
||||
'attachments_items' => 'Priložené položky',
|
||||
'attachments_upload' => 'Nahrať súbor',
|
||||
'attachments_link' => 'Priložiť odkaz',
|
||||
'attachments_set_link' => 'Nastaviť odkaz',
|
||||
'attachments_delete_confirm' => 'Kliknite znova na zmazať pre potvrdenie zmazania prílohy.',
|
||||
'attachments_dropzone' => 'Presuňte súbory alebo klinknite sem pre priloženie súboru',
|
||||
'attachments_no_files' => 'Žiadne súbory neboli nahrané',
|
||||
'attachments_explain_link' => 'Ak nechcete priložiť súbor, môžete priložiť odkaz. Môže to byť odkaz na inú stránku alebo odkaz na súbor v cloude.',
|
||||
'attachments_link_name' => 'Názov odkazu',
|
||||
'attachment_link' => 'Odkaz na prílohu',
|
||||
'attachments_link_url' => 'Odkaz na súbor',
|
||||
'attachments_link_url_hint' => 'Url stránky alebo súboru',
|
||||
'attach' => 'Priložiť',
|
||||
'attachments_edit_file' => 'Upraviť súbor',
|
||||
'attachments_edit_file_name' => 'Názov súboru',
|
||||
'attachments_edit_drop_upload' => 'Presuňte súbory sem alebo klinknite pre nahranie a prepis',
|
||||
'attachments_order_updated' => 'Poradie príloh aktualizované',
|
||||
'attachments_updated_success' => 'Detaily prílohy aktualizované',
|
||||
'attachments_deleted' => 'Príloha zmazaná',
|
||||
'attachments_file_uploaded' => 'Súbor úspešne nahraný',
|
||||
'attachments_file_updated' => 'Súbor úspešne aktualizovaný',
|
||||
'attachments_link_attached' => 'Odkaz úspešne pripojený k stránke',
|
||||
|
||||
/**
|
||||
* Profile View
|
||||
*/
|
||||
'profile_user_for_x' => 'Používateľ už :time',
|
||||
'profile_created_content' => 'Vytvorený obsah',
|
||||
'profile_not_created_pages' => ':userName nevytvoril žiadne stránky',
|
||||
'profile_not_created_chapters' => ':userName nevytvoril žiadne kapitoly',
|
||||
'profile_not_created_books' => ':userName nevytvoril žiadne knihy',
|
||||
];
|
||||
70
resources/lang/sk/errors.php
Normal file
70
resources/lang/sk/errors.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/**
|
||||
* Error text strings.
|
||||
*/
|
||||
|
||||
// Permissions
|
||||
'permission' => 'Nemáte oprávnenie pre prístup k požadovanej stránke.',
|
||||
'permissionJson' => 'Nemáte oprávnenie pre vykonanie požadovaného úkonu.',
|
||||
|
||||
// Auth
|
||||
'error_user_exists_different_creds' => 'Používateľ s emailom :email už existuje, ale s inými údajmi.',
|
||||
'email_already_confirmed' => 'Email bol už overený, skúste sa prihlásiť.',
|
||||
'email_confirmation_invalid' => 'Tento potvrdzujúci token nie je platný alebo už bol použitý, skúste sa prosím registrovať znova.',
|
||||
'email_confirmation_expired' => 'Potvrdzujúci token expiroval, bol odoslaný nový potvrdzujúci email.',
|
||||
'ldap_fail_anonymous' => 'LDAP access failed using anonymous bind',
|
||||
'ldap_fail_authed' => 'LDAP access failed using given dn & password details',
|
||||
'ldap_extension_not_installed' => 'LDAP PHP extension not installed',
|
||||
'ldap_cannot_connect' => 'Cannot connect to ldap server, Initial connection failed',
|
||||
'social_no_action_defined' => 'Nebola definovaná žiadna akcia',
|
||||
'social_account_in_use' => 'Tento :socialAccount účet sa už používa, skúste sa prihlásiť pomocou možnosti :socialAccount.',
|
||||
'social_account_email_in_use' => 'Email :email sa už používa. Ak už máte účet, môžete pripojiť svoj :socialAccount účet v nastaveniach profilu.',
|
||||
'social_account_existing' => 'Tento :socialAccount účet je už spojený s Vaším profilom.',
|
||||
'social_account_already_used_existing' => 'Tento :socialAccount účet už používa iný používateľ.',
|
||||
'social_account_not_used' => 'Tento :socialAccount účet nie je spojený so žiadnym používateľom. Pripojte ho prosím v nastaveniach Vášho profilu. ',
|
||||
'social_account_register_instructions' => 'Ak zatiaľ nemáte účet, môžete sa registrovať pomocou možnosti :socialAccount.',
|
||||
'social_driver_not_found' => 'Ovládač socialnych sietí nebol nájdený',
|
||||
'social_driver_not_configured' => 'Nastavenia Vášho :socialAccount účtu nie sú správne.',
|
||||
|
||||
// System
|
||||
'path_not_writable' => 'Do cesty :filePath sa nedá nahrávať. Uistite sa, že je zapisovateľná serverom.',
|
||||
'cannot_get_image_from_url' => 'Nedá sa získať obrázok z :url',
|
||||
'cannot_create_thumbs' => 'Server nedokáže vytvoriť náhľady. Skontrolujte prosím, či máte nainštalované GD rozšírenie PHP.',
|
||||
'server_upload_limit' => 'Server nedovoľuje nahrávanie súborov s takouto veľkosťou. Skúste prosím menší súbor.',
|
||||
'image_upload_error' => 'Pri nahrávaní obrázka nastala chyba',
|
||||
|
||||
// Attachments
|
||||
'attachment_page_mismatch' => 'Page mismatch during attachment update',
|
||||
|
||||
// Pages
|
||||
'page_draft_autosave_fail' => 'Koncept nemohol byť uložený. Uistite sa, že máte pripojenie k internetu pre uložením tejto stránky',
|
||||
|
||||
// Entities
|
||||
'entity_not_found' => 'Entita nenájdená',
|
||||
'book_not_found' => 'Kniha nenájdená',
|
||||
'page_not_found' => 'Stránka nenájdená',
|
||||
'chapter_not_found' => 'Kapitola nenájdená',
|
||||
'selected_book_not_found' => 'Vybraná kniha nebola nájdená',
|
||||
'selected_book_chapter_not_found' => 'Vybraná kniha alebo kapitola nebola nájdená',
|
||||
'guests_cannot_save_drafts' => 'Hosť nemôže ukladať koncepty',
|
||||
|
||||
// Users
|
||||
'users_cannot_delete_only_admin' => 'Nemôžete zmazať posledného správcu',
|
||||
'users_cannot_delete_guest' => 'Nemôžete zmazať hosťa',
|
||||
|
||||
// Roles
|
||||
'role_cannot_be_edited' => 'Táto rola nemôže byť upravovaná',
|
||||
'role_system_cannot_be_deleted' => 'Táto rola je systémová rola a nemôže byť zmazaná',
|
||||
'role_registration_default_cannot_delete' => 'Táto rola nemôže byť zmazaná, pretože je nastavená ako prednastavená rola pri registrácii',
|
||||
|
||||
// Error pages
|
||||
'404_page_not_found' => 'Stránka nenájdená',
|
||||
'sorry_page_not_found' => 'Prepáčte, stránka ktorú hľadáte nebola nájdená.',
|
||||
'return_home' => 'Vrátiť sa domov',
|
||||
'error_occurred' => 'Nastala chyba',
|
||||
'app_down' => ':appName je momentálne nedostupná',
|
||||
'back_soon' => 'Čoskoro bude opäť dostupná.',
|
||||
];
|
||||
19
resources/lang/sk/pagination.php
Normal file
19
resources/lang/sk/pagination.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Pagination Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are used by the paginator library to build
|
||||
| the simple pagination links. You are free to change them to anything
|
||||
| you want to customize your views to better match your application.
|
||||
|
|
||||
*/
|
||||
|
||||
'previous' => '« Predchádzajúca',
|
||||
'next' => 'Ďalšia »',
|
||||
|
||||
];
|
||||
22
resources/lang/sk/passwords.php
Normal file
22
resources/lang/sk/passwords.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Password Reminder Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are the default lines which match reasons
|
||||
| that are given by the password broker for a password update attempt
|
||||
| has failed, such as for an invalid token or invalid new password.
|
||||
|
|
||||
*/
|
||||
|
||||
'password' => 'Heslo musí obsahovať aspoň šesť znakov a musí byť rovnaké ako potvrdzujúce.',
|
||||
'user' => "Nenašli sme používateľa s takou emailovou adresou.",
|
||||
'token' => 'Tento token pre reset hesla je neplatný.',
|
||||
'sent' => 'Poslali sme Vám email s odkazom na reset hesla!',
|
||||
'reset' => 'Vaše heslo bolo resetované!',
|
||||
|
||||
];
|
||||
111
resources/lang/sk/settings.php
Normal file
111
resources/lang/sk/settings.php
Normal file
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/**
|
||||
* Settings text strings
|
||||
* Contains all text strings used in the general settings sections of BookStack
|
||||
* including users and roles.
|
||||
*/
|
||||
|
||||
'settings' => 'Nastavenia',
|
||||
'settings_save' => 'Uložiť nastavenia',
|
||||
'settings_save_success' => 'Nastavenia uložené',
|
||||
|
||||
/**
|
||||
* App settings
|
||||
*/
|
||||
|
||||
'app_settings' => 'Nastavenia aplikácie',
|
||||
'app_name' => 'Názov aplikácia',
|
||||
'app_name_desc' => 'Tento názov sa zobrazuje v hlavičke a v emailoch.',
|
||||
'app_name_header' => 'Zobraziť názov aplikácie v hlavičke?',
|
||||
'app_public_viewing' => 'Povoliť verejné zobrazenie?',
|
||||
'app_secure_images' => 'Povoliť nahrávanie súborov so zvýšeným zabezpečením?',
|
||||
'app_secure_images_desc' => 'Kvôli výkonu sú všetky obrázky verejné. Táto možnosť pridá pred URL obrázka náhodný, ťažko uhádnuteľný reťazec. Aby ste zabránili jednoduchému prístupu, uistite sa, že indexy priečinkov nie sú povolené.',
|
||||
'app_editor' => 'Editor stránky',
|
||||
'app_editor_desc' => 'Vyberte editor, ktorý bude používaný všetkými používateľmi na editáciu stránok.',
|
||||
'app_custom_html' => 'Vlastný HTML obsah hlavičky',
|
||||
'app_custom_html_desc' => 'Všetok text pridaný sem bude vložený naspodok <head> sekcie na každej stránke. Môže sa to zísť pri zmene štýlu alebo pre pridanie analytického kódu.',
|
||||
'app_logo' => 'Logo aplikácie',
|
||||
'app_logo_desc' => 'Tento obrázok by mal mať 43px na výšku. <br>Veľké obrázky budú preškálované na menší rozmer.',
|
||||
'app_primary_color' => 'Primárna farba pre aplikáciu',
|
||||
'app_primary_color_desc' => 'Toto by mala byť hodnota v hex tvare. <br>Nechajte prázdne ak chcete použiť prednastavenú farbu.',
|
||||
|
||||
/**
|
||||
* Registration settings
|
||||
*/
|
||||
|
||||
'reg_settings' => 'Nastavenia registrácie',
|
||||
'reg_allow' => 'Povoliť registráciu?',
|
||||
'reg_default_role' => 'Prednastavená používateľská rola po registrácii',
|
||||
'reg_confirm_email' => 'Vyžadovať overenie emailu?',
|
||||
'reg_confirm_email_desc' => 'Ak je použité obmedzenie domény, potom bude vyžadované overenie emailu a hodnota nižšie bude ignorovaná.',
|
||||
'reg_confirm_restrict_domain' => 'Obmedziť registráciu na doménu',
|
||||
'reg_confirm_restrict_domain_desc' => 'Zadajte zoznam domén, pre ktoré chcete povoliť registráciu oddelených čiarkou. Používatelia dostanú email kvôli overeniu adresy predtým ako im bude dovolené používať aplikáciu. <br> Používatelia si budú môcť po úspešnej registrácii zmeniť svoju emailovú adresu.',
|
||||
'reg_confirm_restrict_domain_placeholder' => 'Nie sú nastavené žiadne obmedzenia',
|
||||
|
||||
/**
|
||||
* Role settings
|
||||
*/
|
||||
|
||||
'roles' => 'Roly',
|
||||
'role_user_roles' => 'Používateľské roly',
|
||||
'role_create' => 'Vytvoriť novú rolu',
|
||||
'role_create_success' => 'Rola úspešne vytvorená',
|
||||
'role_delete' => 'Zmazať rolu',
|
||||
'role_delete_confirm' => 'Toto zmaže rolu menom \':roleName\'.',
|
||||
'role_delete_users_assigned' => 'Túto rolu má priradenú :userCount používateľov. Ak chcete premigrovať používateľov z tejto roly, vyberte novú rolu nižšie.',
|
||||
'role_delete_no_migration' => "Nemigrovať používateľov",
|
||||
'role_delete_sure' => 'Ste si istý, že chcete zmazať túto rolu?',
|
||||
'role_delete_success' => 'Rola úspešne zmazaná',
|
||||
'role_edit' => 'Upraviť rolu',
|
||||
'role_details' => 'Detaily roly',
|
||||
'role_name' => 'Názov roly',
|
||||
'role_desc' => 'Krátky popis roly',
|
||||
'role_system' => 'Systémové oprávnenia',
|
||||
'role_manage_users' => 'Spravovať používateľov',
|
||||
'role_manage_roles' => 'Spravovať role a oprávnenia rolí',
|
||||
'role_manage_entity_permissions' => 'Spravovať všetky oprávnenia kníh, kapitol a stránok',
|
||||
'role_manage_own_entity_permissions' => 'Spravovať oprávnenia vlastných kníh, kapitol a stránok',
|
||||
'role_manage_settings' => 'Spravovať nastavenia aplikácie',
|
||||
'role_asset' => 'Oprávnenia majetku',
|
||||
'role_asset_desc' => 'Tieto oprávnenia regulujú prednastavený prístup k zdroju v systéme. Oprávnenia pre knihy, kapitoly a stránky majú vyššiu prioritu.',
|
||||
'role_all' => 'Všetko',
|
||||
'role_own' => 'Vlastné',
|
||||
'role_controlled_by_asset' => 'Regulované zdrojom, do ktorého sú nahrané',
|
||||
'role_save' => 'Uložiť rolu',
|
||||
'role_update_success' => 'Roly úspešne aktualizované',
|
||||
'role_users' => 'Používatelia s touto rolou',
|
||||
'role_users_none' => 'Žiadni používatelia nemajú priradenú túto rolu',
|
||||
|
||||
/**
|
||||
* Users
|
||||
*/
|
||||
|
||||
'users' => 'Používatelia',
|
||||
'user_profile' => 'Profil používateľa',
|
||||
'users_add_new' => 'Pridať nového používateľa',
|
||||
'users_search' => 'Hľadať medzi používateľmi',
|
||||
'users_role' => 'Používateľské roly',
|
||||
'users_external_auth_id' => 'Externé autentifikačné ID',
|
||||
'users_password_warning' => 'Pole nižšie vyplňte iba ak chcete zmeniť heslo:',
|
||||
'users_system_public' => 'Tento účet reprezentuje každého hosťovského používateľa, ktorý navštívi Vašu inštanciu. Nedá sa pomocou neho prihlásiť a je priradený automaticky.',
|
||||
'users_delete' => 'Zmazať používateľa',
|
||||
'users_delete_named' => 'Zmazať používateľa :userName',
|
||||
'users_delete_warning' => ' Toto úplne odstráni používateľa menom \':userName\' zo systému.',
|
||||
'users_delete_confirm' => 'Ste si istý, že chcete zmazať tohoto používateľa?',
|
||||
'users_delete_success' => 'Používateľ úspešne zmazaný',
|
||||
'users_edit' => 'Upraviť používateľa',
|
||||
'users_edit_profile' => 'Upraviť profil',
|
||||
'users_edit_success' => 'Používateľ úspešne upravený',
|
||||
'users_avatar' => 'Avatar používateľa',
|
||||
'users_avatar_desc' => 'Tento obrázok by mal byť štvorec s rozmerom približne 256px.',
|
||||
'users_preferred_language' => 'Preferovaný jazyk',
|
||||
'users_social_accounts' => 'Sociálne účty',
|
||||
'users_social_accounts_info' => 'Tu si môžete pripojiť iné účty pre rýchlejšie a jednoduchšie prihlásenie. Disconnecting an account here does not previously authorized access. Revoke access from your profile settings on the connected social account.',
|
||||
'users_social_connect' => 'Pripojiť účet',
|
||||
'users_social_disconnect' => 'Odpojiť účet',
|
||||
'users_social_connected' => ':socialAccount účet bol úspešne pripojený k Vášmu profilu.',
|
||||
'users_social_disconnected' => ':socialAccount účet bol úspešne odpojený od Vášho profilu.',
|
||||
];
|
||||
108
resources/lang/sk/validation.php
Normal file
108
resources/lang/sk/validation.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Validation Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines contain the default error messages used by
|
||||
| the validator class. Some of these rules have multiple versions such
|
||||
| as the size rules. Feel free to tweak each of these messages here.
|
||||
|
|
||||
*/
|
||||
|
||||
'accepted' => ':attribute musí byť akceptovaný.',
|
||||
'active_url' => ':attribute nie je platná URL.',
|
||||
'after' => ':attribute musí byť dátum po :date.',
|
||||
'alpha' => ':attribute môže obsahovať iba písmená.',
|
||||
'alpha_dash' => ':attribute môže obsahovať iba písmená, čísla a pomlčky.',
|
||||
'alpha_num' => ':attribute môže obsahovať iba písmená a čísla.',
|
||||
'array' => ':attribute musí byť pole.',
|
||||
'before' => ':attribute musí byť dátum pred :date.',
|
||||
'between' => [
|
||||
'numeric' => ':attribute musí byť medzi :min a :max.',
|
||||
'file' => ':attribute musí byť medzi :min a :max kilobajtmi.',
|
||||
'string' => ':attribute musí byť medzi :min a :max znakmi.',
|
||||
'array' => ':attribute musí byť medzi :min a :max položkami.',
|
||||
],
|
||||
'boolean' => ':attribute pole musí byť true alebo false.',
|
||||
'confirmed' => ':attribute potvrdenie nesedí.',
|
||||
'date' => ':attribute nie je platný dátum.',
|
||||
'date_format' => ':attribute nesedí s formátom :format.',
|
||||
'different' => ':attribute a :other musia byť rozdielne.',
|
||||
'digits' => ':attribute musí mať :digits číslic.',
|
||||
'digits_between' => ':attribute musí mať medzi :min a :max číslicami.',
|
||||
'email' => ':attribute musí byť platná emailová adresa.',
|
||||
'filled' => 'Políčko :attribute je povinné.',
|
||||
'exists' => 'Vybraný :attribute nie je platný.',
|
||||
'image' => ':attribute musí byť obrázok.',
|
||||
'in' => 'Vybraný :attribute je neplatný.',
|
||||
'integer' => ':attribute musí byť celé číslo.',
|
||||
'ip' => ':attribute musí byť platná IP adresa.',
|
||||
'max' => [
|
||||
'numeric' => ':attribute nesmie byť väčší ako :max.',
|
||||
'file' => ':attribute nesmie byť väčší ako :max kilobajtov.',
|
||||
'string' => ':attribute nesmie byť dlhší ako :max znakov.',
|
||||
'array' => ':attribute nesmie mať viac ako :max položiek.',
|
||||
],
|
||||
'mimes' => ':attribute musí byť súbor typu: :values.',
|
||||
'min' => [
|
||||
'numeric' => ':attribute musí byť aspoň :min.',
|
||||
'file' => ':attribute musí mať aspoň :min kilobajtov.',
|
||||
'string' => ':attribute musí mať aspoň :min znakov.',
|
||||
'array' => ':attribute musí mať aspoň :min položiek.',
|
||||
],
|
||||
'not_in' => 'Vybraný :attribute je neplatný.',
|
||||
'numeric' => ':attribute musí byť číslo.',
|
||||
'regex' => ':attribute formát je neplatný.',
|
||||
'required' => 'Políčko :attribute je povinné.',
|
||||
'required_if' => 'Políčko :attribute je povinné ak :other je :value.',
|
||||
'required_with' => 'Políčko :attribute je povinné ak :values existuje.',
|
||||
'required_with_all' => 'Políčko :attribute je povinné ak :values existuje.',
|
||||
'required_without' => 'Políčko :attribute je povinné aj :values neexistuje.',
|
||||
'required_without_all' => 'Políčko :attribute je povinné ak ani jedno z :values neexistuje.',
|
||||
'same' => ':attribute a :other musia byť rovnaké.',
|
||||
'size' => [
|
||||
'numeric' => ':attribute musí byť :size.',
|
||||
'file' => ':attribute musí mať :size kilobajtov.',
|
||||
'string' => ':attribute musí mať :size znakov.',
|
||||
'array' => ':attribute musí obsahovať :size položiek.',
|
||||
],
|
||||
'string' => ':attribute musí byť reťazec.',
|
||||
'timezone' => ':attribute musí byť plantá časová zóna.',
|
||||
'unique' => ':attribute je už použité.',
|
||||
'url' => ':attribute formát je neplatný.',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Custom Validation Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify custom validation messages for attributes using the
|
||||
| convention "attribute.rule" to name the lines. This makes it quick to
|
||||
| specify a specific custom language line for a given attribute rule.
|
||||
|
|
||||
*/
|
||||
|
||||
'custom' => [
|
||||
'password-confirm' => [
|
||||
'required_with' => 'Vyžaduje sa potvrdenie hesla',
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Custom Validation Attributes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are used to swap attribute place-holders
|
||||
| with something more reader friendly such as E-Mail Address instead
|
||||
| of "email". This simply helps us make messages a little cleaner.
|
||||
|
|
||||
*/
|
||||
|
||||
'attributes' => [],
|
||||
|
||||
];
|
||||
@@ -17,7 +17,7 @@
|
||||
<!-- Scripts -->
|
||||
<script src="{{ baseUrl('/libs/jquery/jquery.min.js?version=2.1.4') }}"></script>
|
||||
<script src="{{ baseUrl('/libs/jquery/jquery-ui.min.js?version=1.11.4') }}"></script>
|
||||
<script src="{{ baseUrl('/translations.js') }}"></script>
|
||||
<script src="{{ baseUrl('/translations') }}"></script>
|
||||
|
||||
@yield('head')
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-lg-4 col-sm-3 text-center">
|
||||
<form action="{{ baseUrl('/search/all') }}" method="GET" class="search-box">
|
||||
<form action="{{ baseUrl('/search') }}" method="GET" class="search-box">
|
||||
<input id="header-search-box-input" type="text" name="term" tabindex="2" value="{{ isset($searchTerm) ? $searchTerm : '' }}">
|
||||
<button id="header-search-box-button" type="submit" class="text-button"><i class="zmdi zmdi-search"></i></button>
|
||||
</form>
|
||||
|
||||
@@ -11,6 +11,6 @@
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<a href="{{ back()->getTargetUrl() }}" class="button muted">{{ trans('common.cancel') }}</a>
|
||||
<a href="{{ isset($book) ? $book->getUrl() : baseUrl('/books') }}" class="button muted">{{ trans('common.cancel') }}</a>
|
||||
<button type="submit" class="button pos">{{ trans('entities.books_save') }}</button>
|
||||
</div>
|
||||
@@ -11,11 +11,11 @@
|
||||
<div class="col-sm-6">
|
||||
<div class="action-buttons faded">
|
||||
<span dropdown class="dropdown-container">
|
||||
<div dropdown-toggle class="text-button text-primary"><i class="zmdi zmdi-open-in-new"></i>{{ trans('entities.pages_export') }}</div>
|
||||
<div dropdown-toggle class="text-button text-primary"><i class="zmdi zmdi-open-in-new"></i>{{ trans('entities.export') }}</div>
|
||||
<ul class="wide">
|
||||
<li><a href="{{ $book->getUrl('/export/html') }}" target="_blank">{{ trans('entities.pages_export_html') }} <span class="text-muted float right">.html</span></a></li>
|
||||
<li><a href="{{ $book->getUrl('/export/pdf') }}" target="_blank">{{ trans('entities.pages_export_pdf') }} <span class="text-muted float right">.pdf</span></a></li>
|
||||
<li><a href="{{ $book->getUrl('/export/plaintext') }}" target="_blank">{{ trans('entities.pages_export_text') }} <span class="text-muted float right">.txt</span></a></li>
|
||||
<li><a href="{{ $book->getUrl('/export/html') }}" target="_blank">{{ trans('entities.export_html') }} <span class="text-muted float right">.html</span></a></li>
|
||||
<li><a href="{{ $book->getUrl('/export/pdf') }}" target="_blank">{{ trans('entities.export_pdf') }} <span class="text-muted float right">.pdf</span></a></li>
|
||||
<li><a href="{{ $book->getUrl('/export/plaintext') }}" target="_blank">{{ trans('entities.export_text') }} <span class="text-muted float right">.txt</span></a></li>
|
||||
</ul>
|
||||
</span>
|
||||
@if(userCan('page-create', $book))
|
||||
@@ -50,15 +50,15 @@
|
||||
</div>
|
||||
|
||||
|
||||
<div class="container" id="book-dashboard" ng-controller="BookShowController" book-id="{{ $book->id }}">
|
||||
<div class="container" id="entity-dashboard" entity-id="{{ $book->id }}" entity-type="book">
|
||||
<div class="row">
|
||||
<div class="col-md-7">
|
||||
|
||||
<h1>{{$book->name}}</h1>
|
||||
<div class="book-content" ng-show="!searching">
|
||||
<p class="text-muted" ng-non-bindable>{{$book->description}}</p>
|
||||
<div class="book-content" v-if="!searching">
|
||||
<p class="text-muted" v-pre>{{$book->description}}</p>
|
||||
|
||||
<div class="page-list" ng-non-bindable>
|
||||
<div class="page-list" v-pre>
|
||||
<hr>
|
||||
@if(count($bookChildren) > 0)
|
||||
@foreach($bookChildren as $childElement)
|
||||
@@ -81,12 +81,12 @@
|
||||
@include('partials.entity-meta', ['entity' => $book])
|
||||
</div>
|
||||
</div>
|
||||
<div class="search-results" ng-cloak ng-show="searching">
|
||||
<h3 class="text-muted">{{ trans('entities.search_results') }} <a ng-if="searching" ng-click="clearSearch()" class="text-small"><i class="zmdi zmdi-close"></i>{{ trans('entities.search_clear') }}</a></h3>
|
||||
<div ng-if="!searchResults">
|
||||
<div class="search-results" v-cloak v-if="searching">
|
||||
<h3 class="text-muted">{{ trans('entities.search_results') }} <a v-if="searching" v-on:click="clearSearch()" class="text-small"><i class="zmdi zmdi-close"></i>{{ trans('entities.search_clear') }}</a></h3>
|
||||
<div v-if="!searchResults">
|
||||
@include('partials/loading-icon')
|
||||
</div>
|
||||
<div ng-bind-html="searchResults"></div>
|
||||
<div v-html="searchResults"></div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -94,6 +94,7 @@
|
||||
|
||||
<div class="col-md-4 col-md-offset-1">
|
||||
<div class="margin-top large"></div>
|
||||
|
||||
@if($book->restricted)
|
||||
<p class="text-muted">
|
||||
@if(userCan('restrictions-manage', $book))
|
||||
@@ -103,14 +104,16 @@
|
||||
@endif
|
||||
</p>
|
||||
@endif
|
||||
|
||||
<div class="search-box">
|
||||
<form ng-submit="searchBook($event)">
|
||||
<input ng-model="searchTerm" ng-change="checkSearchForm()" type="text" name="term" placeholder="{{ trans('entities.books_search_this') }}">
|
||||
<form v-on:submit="searchBook">
|
||||
<input v-model="searchTerm" v-on:change="checkSearchForm()" type="text" name="term" placeholder="{{ trans('entities.books_search_this') }}">
|
||||
<button type="submit"><i class="zmdi zmdi-search"></i></button>
|
||||
<button ng-if="searching" ng-click="clearSearch()" type="button"><i class="zmdi zmdi-close"></i></button>
|
||||
<button v-if="searching" v-cloak class="text-neg" v-on:click="clearSearch()" type="button"><i class="zmdi zmdi-close"></i></button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="activity anim fadeIn">
|
||||
|
||||
<div class="activity">
|
||||
<h3>{{ trans('entities.recent_activity') }}</h3>
|
||||
@include('partials/activity-list', ['activity' => Activity::entityActivity($book, 20, 0)])
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<div class="breadcrumbs">
|
||||
@if (userCan('view', $chapter->book))
|
||||
<a href="{{ $chapter->book->getUrl() }}" class="text-book text-button"><i class="zmdi zmdi-book"></i>{{ $chapter->book->getShortName() }}</a>
|
||||
<span class="sep">»</span>
|
||||
@endif
|
||||
<a href="{{ $chapter->getUrl() }}" class="text-chapter text-button"><i class="zmdi zmdi-collection-bookmark"></i>{{$chapter->getShortName()}}</a>
|
||||
</div>
|
||||
@@ -11,11 +11,11 @@
|
||||
<div class="col-sm-4 faded">
|
||||
<div class="action-buttons">
|
||||
<span dropdown class="dropdown-container">
|
||||
<div dropdown-toggle class="text-button text-primary"><i class="zmdi zmdi-open-in-new"></i>{{ trans('entities.pages_export') }}</div>
|
||||
<div dropdown-toggle class="text-button text-primary"><i class="zmdi zmdi-open-in-new"></i>{{ trans('entities.export') }}</div>
|
||||
<ul class="wide">
|
||||
<li><a href="{{ $chapter->getUrl('/export/html') }}" target="_blank">{{ trans('entities.pages_export_html') }} <span class="text-muted float right">.html</span></a></li>
|
||||
<li><a href="{{ $chapter->getUrl('/export/pdf') }}" target="_blank">{{ trans('entities.pages_export_pdf') }} <span class="text-muted float right">.pdf</span></a></li>
|
||||
<li><a href="{{ $chapter->getUrl('/export/plaintext') }}" target="_blank">{{ trans('entities.pages_export_text') }} <span class="text-muted float right">.txt</span></a></li>
|
||||
<li><a href="{{ $chapter->getUrl('/export/html') }}" target="_blank">{{ trans('entities.export_html') }} <span class="text-muted float right">.html</span></a></li>
|
||||
<li><a href="{{ $chapter->getUrl('/export/pdf') }}" target="_blank">{{ trans('entities.export_pdf') }} <span class="text-muted float right">.pdf</span></a></li>
|
||||
<li><a href="{{ $chapter->getUrl('/export/plaintext') }}" target="_blank">{{ trans('entities.export_text') }} <span class="text-muted float right">.txt</span></a></li>
|
||||
</ul>
|
||||
</span>
|
||||
@if(userCan('page-create', $chapter))
|
||||
@@ -47,40 +47,50 @@
|
||||
</div>
|
||||
|
||||
|
||||
<div class="container" ng-non-bindable>
|
||||
<div class="container" id="entity-dashboard" entity-id="{{ $chapter->id }}" entity-type="chapter">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="col-md-7">
|
||||
<h1>{{ $chapter->name }}</h1>
|
||||
<p class="text-muted">{{ $chapter->description }}</p>
|
||||
<div class="chapter-content" v-if="!searching">
|
||||
<p class="text-muted">{{ $chapter->description }}</p>
|
||||
|
||||
@if(count($pages) > 0)
|
||||
<div class="page-list">
|
||||
<hr>
|
||||
@foreach($pages as $page)
|
||||
@include('pages/list-item', ['page' => $page])
|
||||
@if(count($pages) > 0)
|
||||
<div class="page-list">
|
||||
<hr>
|
||||
@endforeach
|
||||
</div>
|
||||
@else
|
||||
<hr>
|
||||
<p class="text-muted">{{ trans('entities.chapters_empty') }}</p>
|
||||
<p>
|
||||
@if(userCan('page-create', $chapter))
|
||||
<a href="{{ $chapter->getUrl('/create-page') }}" class="text-page"><i class="zmdi zmdi-file-text"></i>{{ trans('entities.books_empty_create_page') }}</a>
|
||||
@endif
|
||||
@if(userCan('page-create', $chapter) && userCan('book-update', $book))
|
||||
<em class="text-muted">-{{ trans('entities.books_empty_or') }}-</em>
|
||||
@endif
|
||||
@if(userCan('book-update', $book))
|
||||
<a href="{{ $book->getUrl('/sort') }}" class="text-book"><i class="zmdi zmdi-book"></i>{{ trans('entities.books_empty_sort_current_book') }}</a>
|
||||
@endif
|
||||
</p>
|
||||
<hr>
|
||||
@endif
|
||||
@foreach($pages as $page)
|
||||
@include('pages/list-item', ['page' => $page])
|
||||
<hr>
|
||||
@endforeach
|
||||
</div>
|
||||
@else
|
||||
<hr>
|
||||
<p class="text-muted">{{ trans('entities.chapters_empty') }}</p>
|
||||
<p>
|
||||
@if(userCan('page-create', $chapter))
|
||||
<a href="{{ $chapter->getUrl('/create-page') }}" class="text-page"><i class="zmdi zmdi-file-text"></i>{{ trans('entities.books_empty_create_page') }}</a>
|
||||
@endif
|
||||
@if(userCan('page-create', $chapter) && userCan('book-update', $book))
|
||||
<em class="text-muted">-{{ trans('entities.books_empty_or') }}-</em>
|
||||
@endif
|
||||
@if(userCan('book-update', $book))
|
||||
<a href="{{ $book->getUrl('/sort') }}" class="text-book"><i class="zmdi zmdi-book"></i>{{ trans('entities.books_empty_sort_current_book') }}</a>
|
||||
@endif
|
||||
</p>
|
||||
<hr>
|
||||
@endif
|
||||
|
||||
@include('partials.entity-meta', ['entity' => $chapter])
|
||||
@include('partials.entity-meta', ['entity' => $chapter])
|
||||
</div>
|
||||
|
||||
<div class="search-results" v-cloak v-if="searching">
|
||||
<h3 class="text-muted">{{ trans('entities.search_results') }} <a v-if="searching" v-on:click="clearSearch()" class="text-small"><i class="zmdi zmdi-close"></i>{{ trans('entities.search_clear') }}</a></h3>
|
||||
<div v-if="!searchResults">
|
||||
@include('partials/loading-icon')
|
||||
</div>
|
||||
<div v-html="searchResults"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 col-md-offset-1">
|
||||
<div class="col-md-4 col-md-offset-1">
|
||||
<div class="margin-top large"></div>
|
||||
@if($book->restricted || $chapter->restricted)
|
||||
<div class="text-muted">
|
||||
@@ -105,7 +115,16 @@
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="search-box">
|
||||
<form v-on:submit="searchBook">
|
||||
<input v-model="searchTerm" v-on:change="checkSearchForm()" type="text" name="term" placeholder="{{ trans('entities.chapters_search_this') }}">
|
||||
<button type="submit"><i class="zmdi zmdi-search"></i></button>
|
||||
<button v-if="searching" v-cloak class="text-neg" v-on:click="clearSearch()" type="button"><i class="zmdi zmdi-close"></i></button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@include('pages/sidebar-tree-list', ['book' => $book, 'sidebarTree' => $sidebarTree])
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
<div class="breadcrumbs">
|
||||
<a href="{{ $page->book->getUrl() }}" class="text-book text-button"><i class="zmdi zmdi-book"></i>{{ $page->book->getShortName() }}</a>
|
||||
@if($page->hasChapter())
|
||||
@if (userCan('view', $page->book))
|
||||
<a href="{{ $page->book->getUrl() }}" class="text-book text-button"><i class="zmdi zmdi-book"></i>{{ $page->book->getShortName() }}</a>
|
||||
<span class="sep">»</span>
|
||||
@endif
|
||||
@if($page->hasChapter() && userCan('view', $page->chapter))
|
||||
<a href="{{ $page->chapter->getUrl() }}" class="text-chapter text-button">
|
||||
<i class="zmdi zmdi-collection-bookmark"></i>
|
||||
{{ $page->chapter->getShortName() }}
|
||||
</a>
|
||||
<span class="sep">»</span>
|
||||
@endif
|
||||
<span class="sep">»</span>
|
||||
<a href="{{ $page->getUrl() }}" class="text-page text-button"><i class="zmdi zmdi-file"></i>{{ $page->getShortName() }}</a>
|
||||
</div>
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th width="3%">{{ trans('entities.pages_revisions_number') }}</th>
|
||||
<th width="23%">{{ trans('entities.pages_name') }}</th>
|
||||
<th colspan="2" width="8%">{{ trans('entities.pages_revisions_created_by') }}</th>
|
||||
<th width="15%">{{ trans('entities.pages_revisions_date') }}</th>
|
||||
@@ -27,6 +28,7 @@
|
||||
</tr>
|
||||
@foreach($page->revisions as $index => $revision)
|
||||
<tr>
|
||||
<td>{{ $revision->revision_number == 0 ? '' : $revision->revision_number }}</td>
|
||||
<td>{{ $revision->name }}</td>
|
||||
<td style="line-height: 0;">
|
||||
@if($revision->createdBy)
|
||||
|
||||
@@ -11,11 +11,11 @@
|
||||
<div class="col-sm-6 faded">
|
||||
<div class="action-buttons">
|
||||
<span dropdown class="dropdown-container">
|
||||
<div dropdown-toggle class="text-button text-primary"><i class="zmdi zmdi-open-in-new"></i>{{ trans('entities.pages_export') }}</div>
|
||||
<div dropdown-toggle class="text-button text-primary"><i class="zmdi zmdi-open-in-new"></i>{{ trans('entities.export') }}</div>
|
||||
<ul class="wide">
|
||||
<li><a href="{{ $page->getUrl('/export/html') }}" target="_blank">{{ trans('entities.pages_export_html') }} <span class="text-muted float right">.html</span></a></li>
|
||||
<li><a href="{{ $page->getUrl('/export/pdf') }}" target="_blank">{{ trans('entities.pages_export_pdf') }} <span class="text-muted float right">.pdf</span></a></li>
|
||||
<li><a href="{{ $page->getUrl('/export/plaintext') }}" target="_blank">{{ trans('entities.pages_export_text') }} <span class="text-muted float right">.txt</span></a></li>
|
||||
<li><a href="{{ $page->getUrl('/export/html') }}" target="_blank">{{ trans('entities.export_html') }} <span class="text-muted float right">.html</span></a></li>
|
||||
<li><a href="{{ $page->getUrl('/export/pdf') }}" target="_blank">{{ trans('entities.export_pdf') }} <span class="text-muted float right">.pdf</span></a></li>
|
||||
<li><a href="{{ $page->getUrl('/export/plaintext') }}" target="_blank">{{ trans('entities.export_text') }} <span class="text-muted float right">.txt</span></a></li>
|
||||
</ul>
|
||||
</span>
|
||||
@if(userCan('page-update', $page))
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
|
||||
@if(isset($page) && $page->tags->count() > 0)
|
||||
<div class="tag-display">
|
||||
<h6 class="text-muted">Page Tags</h6>
|
||||
<h6 class="text-muted">{{ trans('entities.page_tags') }}</h6>
|
||||
<table>
|
||||
<tbody>
|
||||
@foreach($page->tags as $tag)
|
||||
<tr class="tag">
|
||||
<td @if(!$tag->value) colspan="2" @endif><a href="{{ baseUrl('/search/all?term=%5B' . urlencode($tag->name) .'%5D') }}">{{ $tag->name }}</a></td>
|
||||
@if($tag->value) <td class="tag-value"><a href="{{ baseUrl('/search/all?term=%5B' . urlencode($tag->name) .'%3D' . urlencode($tag->value) . '%5D') }}">{{$tag->value}}</a></td> @endif
|
||||
<td @if(!$tag->value) colspan="2" @endif><a href="{{ baseUrl('/search?term=%5B' . urlencode($tag->name) .'%5D') }}">{{ $tag->name }}</a></td>
|
||||
@if($tag->value) <td class="tag-value"><a href="{{ baseUrl('/search?term=%5B' . urlencode($tag->name) .'%3D' . urlencode($tag->value) . '%5D') }}">{{$tag->value}}</a></td> @endif
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
@@ -39,8 +39,10 @@
|
||||
|
||||
<h6 class="text-muted">{{ trans('entities.books_navigation') }}</h6>
|
||||
<ul class="sidebar-page-list menu">
|
||||
<li class="book-header"><a href="{{ $book->getUrl() }}" class="book {{ $current->matches($book)? 'selected' : '' }}"><i class="zmdi zmdi-book"></i>{{$book->name}}</a></li>
|
||||
|
||||
@if (userCan('view', $book))
|
||||
<li class="book-header"><a href="{{ $book->getUrl() }}" class="book {{ $current->matches($book)? 'selected' : '' }}"><i class="zmdi zmdi-book"></i>{{$book->name}}</a></li>
|
||||
@endif
|
||||
|
||||
@foreach($sidebarTree as $bookChild)
|
||||
<li class="list-item-{{ $bookChild->getClassName() }} {{ $bookChild->getClassName() }} {{ $bookChild->isA('page') && $bookChild->draft ? 'draft' : '' }}">
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
<p class="text-muted small">
|
||||
@if ($entity->isA('page')) {{ trans('entities.meta_revision', ['revisionCount' => $entity->revision_count]) }} <br> @endif
|
||||
@if ($entity->createdBy)
|
||||
{!! trans('entities.meta_created_name', ['timeLength' => $entity->created_at->diffForHumans(), 'user' => "<a href='{$entity->createdBy->getProfileUrl()}'>".htmlentities($entity->createdBy->name). "</a>"]) !!}
|
||||
{!! trans('entities.meta_created_name', [
|
||||
'timeLength' => '<span title="'.$entity->created_at->toDayDateTimeString().'">'.$entity->created_at->diffForHumans() . '</span>',
|
||||
'user' => "<a href='{$entity->createdBy->getProfileUrl()}'>".htmlentities($entity->createdBy->name). "</a>"
|
||||
]) !!}
|
||||
@else
|
||||
{{ trans('entities.meta_created', ['timeLength' => $entity->created_at->diffForHumans()]) }}
|
||||
<span title="{{$entity->created_at->toDayDateTimeString()}}">{{ trans('entities.meta_created', ['timeLength' => $entity->created_at->diffForHumans()]) }}</span>
|
||||
@endif
|
||||
<br>
|
||||
@if ($entity->updatedBy)
|
||||
{!! trans('entities.meta_updated_name', ['timeLength' => $entity->updated_at->diffForHumans(), 'user' => "<a href='{$entity->updatedBy->getProfileUrl()}'>".htmlentities($entity->updatedBy->name). "</a>"]) !!}
|
||||
{!! trans('entities.meta_updated_name', [
|
||||
'timeLength' => '<span title="' . $entity->updated_at->toDayDateTimeString() .'">' . $entity->updated_at->diffForHumans() .'</span>',
|
||||
'user' => "<a href='{$entity->updatedBy->getProfileUrl()}'>".htmlentities($entity->updatedBy->name). "</a>"
|
||||
]) !!}
|
||||
@else
|
||||
{{ trans('entities.meta_updated', ['timeLength' => $entity->updated_at->diffForHumans()]) }}
|
||||
<span title="{{ $entity->updated_at->toDayDateTimeString() }}">{{ trans('entities.meta_updated', ['timeLength' => $entity->updated_at->diffForHumans()]) }}</span>
|
||||
@endif
|
||||
</p>
|
||||
@@ -2,59 +2,212 @@
|
||||
|
||||
@section('content')
|
||||
|
||||
<input type="hidden" name="searchTerm" value="{{$searchTerm}}">
|
||||
|
||||
<div id="search-system">
|
||||
|
||||
<div class="faded-small toolbar">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 faded">
|
||||
<div class="breadcrumbs">
|
||||
<a href="{{ baseUrl("/search/all?term={$searchTerm}") }}" class="text-button"><i class="zmdi zmdi-search"></i>{{ $searchTerm }}</a>
|
||||
<a href="{{ baseUrl("/search?term=" . urlencode($searchTerm)) }}" class="text-button"><i class="zmdi zmdi-search"></i>{{ trans('entities.search_for_term', ['term' => $searchTerm]) }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="container" ng-non-bindable>
|
||||
|
||||
<h1>{{ trans('entities.search_results') }}</h1>
|
||||
|
||||
<p>
|
||||
@if(count($pages) > 0)
|
||||
<a href="{{ baseUrl("/search/pages?term={$searchTerm}") }}" class="text-page"><i class="zmdi zmdi-file-text"></i>{{ trans('entities.search_view_pages') }}</a>
|
||||
@endif
|
||||
|
||||
@if(count($chapters) > 0)
|
||||
|
||||
<a href="{{ baseUrl("/search/chapters?term={$searchTerm}") }}" class="text-chapter"><i class="zmdi zmdi-collection-bookmark"></i>{{ trans('entities.search_view_chapters') }}</a>
|
||||
@endif
|
||||
|
||||
@if(count($books) > 0)
|
||||
|
||||
<a href="{{ baseUrl("/search/books?term={$searchTerm}") }}" class="text-book"><i class="zmdi zmdi-book"></i>{{ trans('entities.search_view_books') }}</a>
|
||||
@endif
|
||||
</p>
|
||||
<div class="container" ng-non-bindable id="searchSystem">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h3><a href="{{ baseUrl("/search/pages?term={$searchTerm}") }}" class="no-color">{{ trans('entities.pages') }}</a></h3>
|
||||
@include('partials/entity-list', ['entities' => $pages, 'style' => 'detailed'])
|
||||
</div>
|
||||
<div class="col-md-5 col-md-offset-1">
|
||||
@if(count($books) > 0)
|
||||
<h3><a href="{{ baseUrl("/search/books?term={$searchTerm}") }}" class="no-color">{{ trans('entities.books') }}</a></h3>
|
||||
@include('partials/entity-list', ['entities' => $books])
|
||||
@endif
|
||||
|
||||
@if(count($chapters) > 0)
|
||||
<h3><a href="{{ baseUrl("/search/chapters?term={$searchTerm}") }}" class="no-color">{{ trans('entities.chapters') }}</a></h3>
|
||||
@include('partials/entity-list', ['entities' => $chapters])
|
||||
<div class="col-md-6">
|
||||
<h1>{{ trans('entities.search_results') }}</h1>
|
||||
<h6 class="text-muted">{{ trans_choice('entities.search_total_results_found', $totalResults, ['count' => $totalResults]) }}</h6>
|
||||
@include('partials/entity-list', ['entities' => $entities])
|
||||
@if ($hasNextPage)
|
||||
<a href="{{ $nextPageLink }}" class="button">{{ trans('entities.search_more') }}</a>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="col-md-5 col-md-offset-1">
|
||||
<h3>{{ trans('entities.search_filters') }}</h3>
|
||||
|
||||
<form v-on:submit="updateSearch" v-cloak class="v-cloak anim fadeIn">
|
||||
<h6 class="text-muted">{{ trans('entities.search_content_type') }}</h6>
|
||||
<div class="form-group">
|
||||
<label class="inline checkbox text-page"><input type="checkbox" v-on:change="typeChange" v-model="search.type.page" value="page">{{ trans('entities.page') }}</label>
|
||||
<label class="inline checkbox text-chapter"><input type="checkbox" v-on:change="typeChange" v-model="search.type.chapter" value="chapter">{{ trans('entities.chapter') }}</label>
|
||||
<label class="inline checkbox text-book"><input type="checkbox" v-on:change="typeChange" v-model="search.type.book" value="book">{{ trans('entities.book') }}</label>
|
||||
</div>
|
||||
|
||||
<h6 class="text-muted">{{ trans('entities.search_exact_matches') }}</h6>
|
||||
<table cellpadding="0" cellspacing="0" border="0" class="no-style">
|
||||
<tr v-for="(term, i) in search.exactTerms">
|
||||
<td style="padding: 0 12px 6px 0;">
|
||||
<input class="exact-input outline" v-on:input="exactChange" type="text" v-model="search.exactTerms[i]"></td>
|
||||
<td>
|
||||
<button type="button" class="text-neg text-button" v-on:click="removeExact(i)">
|
||||
<i class="zmdi zmdi-close"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<button type="button" class="text-button" v-on:click="addExact">
|
||||
<i class="zmdi zmdi-plus-circle-o"></i>{{ trans('common.add') }}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h6 class="text-muted">{{ trans('entities.search_tags') }}</h6>
|
||||
<table cellpadding="0" cellspacing="0" border="0" class="no-style">
|
||||
<tr v-for="(term, i) in search.tagTerms">
|
||||
<td style="padding: 0 12px 6px 0;">
|
||||
<input class="tag-input outline" v-on:input="tagChange" type="text" v-model="search.tagTerms[i]"></td>
|
||||
<td>
|
||||
<button type="button" class="text-neg text-button" v-on:click="removeTag(i)">
|
||||
<i class="zmdi zmdi-close"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<button type="button" class="text-button" v-on:click="addTag">
|
||||
<i class="zmdi zmdi-plus-circle-o"></i>{{ trans('common.add') }}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h6 class="text-muted">Options</h6>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" v-on:change="optionChange('viewed_by_me')"
|
||||
v-model="search.option.viewed_by_me" value="page">
|
||||
{{ trans('entities.search_viewed_by_me') }}
|
||||
</label>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" v-on:change="optionChange('not_viewed_by_me')"
|
||||
v-model="search.option.not_viewed_by_me" value="page">
|
||||
{{ trans('entities.search_not_viewed_by_me') }}
|
||||
</label>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" v-on:change="optionChange('is_restricted')"
|
||||
v-model="search.option.is_restricted" value="page">
|
||||
{{ trans('entities.search_permissions_set') }}
|
||||
</label>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" v-on:change="optionChange('created_by:me')"
|
||||
v-model="search.option['created_by:me']" value="page">
|
||||
{{ trans('entities.search_created_by_me') }}
|
||||
</label>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" v-on:change="optionChange('updated_by:me')"
|
||||
v-model="search.option['updated_by:me']" value="page">
|
||||
{{ trans('entities.search_updated_by_me') }}
|
||||
</label>
|
||||
|
||||
<h6 class="text-muted">Date Options</h6>
|
||||
<table cellpadding="0" cellspacing="0" border="0" class="no-style form-table">
|
||||
<tr>
|
||||
<td width="200">{{ trans('entities.search_updated_after') }}</td>
|
||||
<td width="80">
|
||||
<button type="button" class="text-button" v-if="!search.dates.updated_after"
|
||||
v-on:click="enableDate('updated_after')">{{ trans('entities.search_set_date') }}</button>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="search.dates.updated_after">
|
||||
<td>
|
||||
<input v-if="search.dates.updated_after" class="tag-input"
|
||||
v-on:input="dateChange('updated_after')" type="date" v-model="search.dates.updated_after"
|
||||
pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}">
|
||||
</td>
|
||||
<td>
|
||||
<button v-if="search.dates.updated_after" type="button" class="text-neg text-button"
|
||||
v-on:click="dateRemove('updated_after')">
|
||||
<i class="zmdi zmdi-close"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ trans('entities.search_updated_before') }}</td>
|
||||
<td>
|
||||
<button type="button" class="text-button" v-if="!search.dates.updated_before"
|
||||
v-on:click="enableDate('updated_before')">{{ trans('entities.search_set_date') }}</button>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="search.dates.updated_before">
|
||||
<td>
|
||||
<input v-if="search.dates.updated_before" class="tag-input"
|
||||
v-on:input="dateChange('updated_before')" type="date" v-model="search.dates.updated_before"
|
||||
pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}">
|
||||
</td>
|
||||
<td>
|
||||
<button v-if="search.dates.updated_before" type="button" class="text-neg text-button"
|
||||
v-on:click="dateRemove('updated_before')">
|
||||
<i class="zmdi zmdi-close"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ trans('entities.search_created_after') }}</td>
|
||||
<td>
|
||||
<button type="button" class="text-button" v-if="!search.dates.created_after"
|
||||
v-on:click="enableDate('created_after')">{{ trans('entities.search_set_date') }}</button>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="search.dates.created_after">
|
||||
<td>
|
||||
<input v-if="search.dates.created_after" class="tag-input"
|
||||
v-on:input="dateChange('created_after')" type="date" v-model="search.dates.created_after"
|
||||
pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}">
|
||||
</td>
|
||||
<td>
|
||||
<button v-if="search.dates.created_after" type="button" class="text-neg text-button"
|
||||
v-on:click="dateRemove('created_after')">
|
||||
<i class="zmdi zmdi-close"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ trans('entities.search_created_before') }}</td>
|
||||
<td>
|
||||
<button type="button" class="text-button" v-if="!search.dates.created_before"
|
||||
v-on:click="enableDate('created_before')">{{ trans('entities.search_set_date') }}</button>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="search.dates.created_before">
|
||||
<td>
|
||||
<input v-if="search.dates.created_before" class="tag-input"
|
||||
v-on:input="dateChange('created_before')" type="date" v-model="search.dates.created_before"
|
||||
pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}">
|
||||
</td>
|
||||
<td>
|
||||
<button v-if="search.dates.created_before" type="button" class="text-neg text-button"
|
||||
v-on:click="dateRemove('created_before')">
|
||||
<i class="zmdi zmdi-close"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
<button type="submit" class="button primary">{{ trans('entities.search_update') }}</button>
|
||||
</form>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@stop
|
||||
@@ -21,6 +21,10 @@
|
||||
<form action="{{ baseUrl("/settings/users/create") }}" method="post">
|
||||
{!! csrf_field() !!}
|
||||
@include('users/forms/' . $authMethod)
|
||||
<div class="form-group">
|
||||
<a href="{{ baseUrl($currentUser->can('users-manage') ? "/settings/users" : "/") }}" class="button muted">{{ trans('common.cancel') }}</a>
|
||||
<button class="button pos" type="submit">{{ trans('common.save') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -19,38 +19,42 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6" ng-non-bindable>
|
||||
{!! csrf_field() !!}
|
||||
<input type="hidden" name="_method" value="put">
|
||||
@include('users.forms.' . $authMethod, ['model' => $user])
|
||||
<div class="col-sm-6" ng-non-bindable>
|
||||
{!! csrf_field() !!}
|
||||
<input type="hidden" name="_method" value="put">
|
||||
@include('users.forms.' . $authMethod, ['model' => $user])
|
||||
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group" id="logo-control">
|
||||
<label for="user-avatar">{{ trans('settings.users_avatar') }}</label>
|
||||
<p class="small">{{ trans('settings.users_avatar_desc') }}</p>
|
||||
|
||||
@include('components.image-picker', [
|
||||
'resizeHeight' => '512',
|
||||
'resizeWidth' => '512',
|
||||
'showRemove' => false,
|
||||
'defaultImage' => baseUrl('/user_avatar.png'),
|
||||
'currentImage' => $user->getAvatar(80),
|
||||
'currentId' => $user->image_id,
|
||||
'name' => 'image_id',
|
||||
'imageClass' => 'avatar large'
|
||||
])
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="user-language">{{ trans('settings.users_preferred_language') }}</label>
|
||||
<select name="setting[language]" id="user-language">
|
||||
@foreach(trans('settings.language_select') as $lang => $label)
|
||||
<option @if(setting()->getUser($user, 'language') === $lang) selected @endif value="{{ $lang }}">{{ $label }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group" id="logo-control">
|
||||
<label for="user-avatar">{{ trans('settings.users_avatar') }}</label>
|
||||
<p class="small">{{ trans('settings.users_avatar_desc') }}</p>
|
||||
|
||||
@include('components.image-picker', [
|
||||
'resizeHeight' => '512',
|
||||
'resizeWidth' => '512',
|
||||
'showRemove' => false,
|
||||
'defaultImage' => baseUrl('/user_avatar.png'),
|
||||
'currentImage' => $user->getAvatar(80),
|
||||
'currentId' => $user->image_id,
|
||||
'name' => 'image_id',
|
||||
'imageClass' => 'avatar large'
|
||||
])
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="user-language">{{ trans('settings.users_preferred_language') }}</label>
|
||||
<select name="setting[language]" id="user-language">
|
||||
@foreach(trans('settings.language_select') as $lang => $label)
|
||||
<option @if(setting()->getUser($user, 'language') === $lang) selected @endif value="{{ $lang }}">{{ $label }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<a href="{{ baseUrl($currentUser->can('users-manage') ? "/settings/users" : "/") }}" class="button muted">{{ trans('common.cancel') }}</a>
|
||||
<button class="button pos" type="submit">{{ trans('common.save') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<hr class="margin-top large">
|
||||
@@ -60,7 +64,7 @@
|
||||
<p class="text-muted">{{ trans('settings.users_social_accounts_info') }}</p>
|
||||
<div class="row">
|
||||
@foreach($activeSocialDrivers as $driver => $enabled)
|
||||
<div class="col-md-3 text-center">
|
||||
<div class="col-sm-3 col-xs-6 text-center">
|
||||
<div>@icon($driver, ['width' => 56])</div>
|
||||
<div>
|
||||
@if($user->hasSocialAccount($driver))
|
||||
|
||||
@@ -22,9 +22,4 @@
|
||||
<label for="external_auth_id">{{ trans('settings.users_external_auth_id') }}</label>
|
||||
@include('form.text', ['name' => 'external_auth_id'])
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="form-group">
|
||||
<a href="{{ baseUrl("/settings/users") }}" class="button muted">{{ trans('common.cancel') }}</a>
|
||||
<button class="button pos" type="submit">{{ trans('common.save') }}</button>
|
||||
</div>
|
||||
@endif
|
||||
@@ -31,10 +31,4 @@
|
||||
<div class="form-group">
|
||||
<label for="password-confirm">{{ trans('auth.password_confirm') }}</label>
|
||||
@include('form.password', ['name' => 'password-confirm'])
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<a href="{{ baseUrl("/settings/users") }}" class="button muted">{{ trans('common.cancel') }}</a>
|
||||
<button class="button pos" type="submit">{{ trans('common.save') }}</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -19,8 +19,3 @@
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="form-group">
|
||||
<a href="{{ baseUrl("/settings/users") }}" class="button muted">{{ trans('common.cancel') }}</a>
|
||||
<button class="button pos" type="submit">{{ trans('common.save') }}</button>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
Route::get('/translations.js', 'HomeController@getTranslations');
|
||||
Route::get('/translations', 'HomeController@getTranslations');
|
||||
|
||||
// Authenticated routes...
|
||||
Route::group(['middleware' => 'auth'], function () {
|
||||
@@ -123,11 +123,9 @@ Route::group(['middleware' => 'auth'], function () {
|
||||
Route::get('/link/{id}', 'PageController@redirectFromLink');
|
||||
|
||||
// Search
|
||||
Route::get('/search/all', 'SearchController@searchAll');
|
||||
Route::get('/search/pages', 'SearchController@searchPages');
|
||||
Route::get('/search/books', 'SearchController@searchBooks');
|
||||
Route::get('/search/chapters', 'SearchController@searchChapters');
|
||||
Route::get('/search', 'SearchController@search');
|
||||
Route::get('/search/book/{bookId}', 'SearchController@searchBook');
|
||||
Route::get('/search/chapter/{bookId}', 'SearchController@searchChapter');
|
||||
|
||||
// Other Pages
|
||||
Route::get('/', 'HomeController@index');
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php namespace Tests;
|
||||
|
||||
use BookStack\Role;
|
||||
use BookStack\Services\PermissionService;
|
||||
use Illuminate\Contracts\Console\Kernel;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use Laravel\BrowserKitTesting\TestCase;
|
||||
@@ -22,6 +23,12 @@ abstract class BrowserKitTest extends TestCase
|
||||
private $admin;
|
||||
private $editor;
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
\DB::disconnect();
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the application.
|
||||
*
|
||||
@@ -99,11 +106,9 @@ abstract class BrowserKitTest extends TestCase
|
||||
{
|
||||
if ($updaterUser === false) $updaterUser = $creatorUser;
|
||||
$book = factory(\BookStack\Book::class)->create(['created_by' => $creatorUser->id, 'updated_by' => $updaterUser->id]);
|
||||
$chapter = factory(\BookStack\Chapter::class)->create(['created_by' => $creatorUser->id, 'updated_by' => $updaterUser->id]);
|
||||
$page = factory(\BookStack\Page::class)->create(['created_by' => $creatorUser->id, 'updated_by' => $updaterUser->id, 'book_id' => $book->id]);
|
||||
$book->chapters()->saveMany([$chapter]);
|
||||
$chapter->pages()->saveMany([$page]);
|
||||
$restrictionService = $this->app[\BookStack\Services\PermissionService::class];
|
||||
$chapter = factory(\BookStack\Chapter::class)->create(['created_by' => $creatorUser->id, 'updated_by' => $updaterUser->id, 'book_id' => $book->id]);
|
||||
$page = factory(\BookStack\Page::class)->create(['created_by' => $creatorUser->id, 'updated_by' => $updaterUser->id, 'book_id' => $book->id, 'chapter_id' => $chapter->id]);
|
||||
$restrictionService = $this->app[PermissionService::class];
|
||||
$restrictionService->buildJointPermissionsForEntity($book);
|
||||
return [
|
||||
'book' => $book,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user