diff --git a/app/Actions/ActivityService.php b/app/Actions/ActivityService.php index 37cd0a6a4..11f8b8732 100644 --- a/app/Actions/ActivityService.php +++ b/app/Actions/ActivityService.php @@ -103,7 +103,7 @@ class ActivityService * @param int $page * @return array */ - public function entityActivity($entity, $count = 20, $page = 0) + public function entityActivity($entity, $count = 20, $page = 1) { if ($entity->isA('book')) { $query = $this->activity->where('book_id', '=', $entity->id); @@ -114,7 +114,7 @@ class ActivityService $activity = $this->permissionService ->filterRestrictedEntityRelations($query, 'activities', 'entity_id', 'entity_type') - ->orderBy('created_at', 'desc')->with(['entity', 'user.avatar'])->skip($count * $page)->take($count)->get(); + ->orderBy('created_at', 'desc')->with(['entity', 'user.avatar'])->skip($count * ($page - 1))->take($count)->get(); return $this->filterSimilar($activity); } diff --git a/app/Actions/ViewService.php b/app/Actions/ViewService.php index d5f8002fc..532f31c42 100644 --- a/app/Actions/ViewService.php +++ b/app/Actions/ViewService.php @@ -2,21 +2,26 @@ use BookStack\Auth\Permissions\PermissionService; use BookStack\Entities\Entity; +use BookStack\Entities\EntityProvider; +use Illuminate\Support\Collection; class ViewService { protected $view; protected $permissionService; + protected $entityProvider; /** * ViewService constructor. * @param \BookStack\Actions\View $view * @param \BookStack\Auth\Permissions\PermissionService $permissionService + * @param EntityProvider $entityProvider */ - public function __construct(View $view, PermissionService $permissionService) + public function __construct(View $view, PermissionService $permissionService, EntityProvider $entityProvider) { $this->view = $view; $this->permissionService = $permissionService; + $this->entityProvider = $entityProvider; } /** @@ -50,23 +55,21 @@ class ViewService * Get the entities with the most views. * @param int $count * @param int $page - * @param Entity|false|array $filterModel + * @param string|array $filterModels * @param string $action - used for permission checking - * @return + * @return Collection */ - public function getPopular($count = 10, $page = 0, $filterModel = false, $action = 'view') + public function getPopular(int $count = 10, int $page = 0, $filterModels = null, string $action = 'view') { - // TODO - Standardise input filter $skipCount = $count * $page; - $query = $this->permissionService->filterRestrictedEntityRelations($this->view, 'views', 'viewable_id', 'viewable_type', $action) + $query = $this->permissionService + ->filterRestrictedEntityRelations($this->view, 'views', 'viewable_id', 'viewable_type', $action) ->select('*', 'viewable_id', 'viewable_type', \DB::raw('SUM(views) as view_count')) ->groupBy('viewable_id', 'viewable_type') ->orderBy('view_count', 'desc'); - if ($filterModel && is_array($filterModel)) { - $query->whereIn('viewable_type', $filterModel); - } else if ($filterModel) { - $query->where('viewable_type', '=', $filterModel->getMorphClass()); + if ($filterModels) { + $query->whereIn('viewable_type', $this->entityProvider->getMorphClasses($filterModels)); } return $query->with('viewable')->skip($skipCount)->take($count)->get()->pluck('viewable'); diff --git a/app/Auth/Permissions/PermissionService.php b/app/Auth/Permissions/PermissionService.php index 8fc70e916..1e1ee3946 100644 --- a/app/Auth/Permissions/PermissionService.php +++ b/app/Auth/Permissions/PermissionService.php @@ -704,7 +704,7 @@ class PermissionService * @param string $entityIdColumn * @param string $entityTypeColumn * @param string $action - * @return mixed + * @return QueryBuilder */ public function filterRestrictedEntityRelations($query, $tableName, $entityIdColumn, $entityTypeColumn, $action = 'view') { diff --git a/app/Auth/Role.php b/app/Auth/Role.php index c8bb47e45..917d8aa26 100644 --- a/app/Auth/Role.php +++ b/app/Auth/Role.php @@ -1,6 +1,7 @@ belongsToMany(User::class); + return $this->belongsToMany(User::class)->orderBy('name', 'asc'); } /** @@ -30,7 +31,7 @@ class Role extends Model */ public function permissions() { - return $this->belongsToMany(Permissions\RolePermission::class, 'permission_role', 'role_id', 'permission_id'); + return $this->belongsToMany(RolePermission::class, 'permission_role', 'role_id', 'permission_id'); } /** @@ -51,18 +52,18 @@ class Role extends Model /** * Add a permission to this role. - * @param \BookStack\Auth\Permissions\RolePermission $permission + * @param RolePermission $permission */ - public function attachPermission(Permissions\RolePermission $permission) + public function attachPermission(RolePermission $permission) { $this->permissions()->attach($permission->id); } /** * Detach a single permission from this role. - * @param \BookStack\Auth\Permissions\RolePermission $permission + * @param RolePermission $permission */ - public function detachPermission(Permissions\RolePermission $permission) + public function detachPermission(RolePermission $permission) { $this->permissions()->detach($permission->id); } diff --git a/app/Auth/UserRepo.php b/app/Auth/UserRepo.php index 31b91108d..1a73d0072 100644 --- a/app/Auth/UserRepo.php +++ b/app/Auth/UserRepo.php @@ -6,6 +6,7 @@ use BookStack\Exceptions\NotFoundException; use BookStack\Exceptions\UserUpdateException; use BookStack\Uploads\Image; use Exception; +use Illuminate\Database\Eloquent\Builder; use Images; class UserRepo @@ -48,7 +49,7 @@ class UserRepo /** * Get all the users with their permissions. - * @return \Illuminate\Database\Eloquent\Builder|static + * @return Builder|static */ public function getAllUsers() { @@ -59,7 +60,7 @@ class UserRepo * Get all the users with their permissions in a paginated format. * @param int $count * @param $sortData - * @return \Illuminate\Database\Eloquent\Builder|static + * @return Builder|static */ public function getAllUsersPaginatedAndSorted($count, $sortData) { @@ -223,16 +224,15 @@ class UserRepo */ public function getRecentlyCreated(User $user, $count = 20) { + $createdByUserQuery = function(Builder $query) use ($user) { + $query->where('created_by', '=', $user->id); + }; + return [ - 'pages' => $this->entityRepo->getRecentlyCreated('page', $count, 0, function ($query) use ($user) { - $query->where('created_by', '=', $user->id); - }), - 'chapters' => $this->entityRepo->getRecentlyCreated('chapter', $count, 0, function ($query) use ($user) { - $query->where('created_by', '=', $user->id); - }), - 'books' => $this->entityRepo->getRecentlyCreated('book', $count, 0, function ($query) use ($user) { - $query->where('created_by', '=', $user->id); - }) + 'pages' => $this->entityRepo->getRecentlyCreated('page', $count, 0, $createdByUserQuery), + 'chapters' => $this->entityRepo->getRecentlyCreated('chapter', $count, 0, $createdByUserQuery), + 'books' => $this->entityRepo->getRecentlyCreated('book', $count, 0, $createdByUserQuery), + 'shelves' => $this->entityRepo->getRecentlyCreated('bookshelf', $count, 0, $createdByUserQuery) ]; } @@ -247,6 +247,7 @@ class UserRepo 'pages' => $this->entityRepo->getUserTotalCreated('page', $user), 'chapters' => $this->entityRepo->getUserTotalCreated('chapter', $user), 'books' => $this->entityRepo->getUserTotalCreated('book', $user), + 'shelves' => $this->entityRepo->getUserTotalCreated('bookshelf', $user), ]; } @@ -256,7 +257,7 @@ class UserRepo */ public function getAllRoles() { - return $this->role->all(); + return $this->role->newQuery()->orderBy('name', 'asc')->get(); } /** diff --git a/app/Entities/Book.php b/app/Entities/Book.php index 5ab5142c9..77cacf632 100644 --- a/app/Entities/Book.php +++ b/app/Entities/Book.php @@ -38,7 +38,7 @@ class Book extends Entity */ public function getBookCover($width = 440, $height = 250) { - $default = baseUrl('/book_default_cover.png'); + $default = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='; if (!$this->image_id) { return $default; } @@ -69,6 +69,15 @@ class Book extends Entity return $this->hasMany(Page::class); } + /** + * Get the direct child pages of this book. + * @return \Illuminate\Database\Eloquent\Relations\HasMany + */ + public function directPages() + { + return $this->pages()->where('chapter_id', '=', '0'); + } + /** * Get all chapters within this book. * @return \Illuminate\Database\Eloquent\Relations\HasMany @@ -92,7 +101,7 @@ class Book extends Entity * @param int $length * @return string */ - public function getExcerpt($length = 100) + public function getExcerpt(int $length = 100) { $description = $this->description; return strlen($description) > $length ? substr($description, 0, $length-3) . '...' : $description; diff --git a/app/Entities/Bookshelf.php b/app/Entities/Bookshelf.php index c37e36b59..08ce8d8cb 100644 --- a/app/Entities/Bookshelf.php +++ b/app/Entities/Bookshelf.php @@ -50,7 +50,8 @@ class Bookshelf extends Entity */ public function getBookCover($width = 440, $height = 250) { - $default = baseUrl('/book_default_cover.png'); + // TODO - Make generic, focused on books right now, Perhaps set-up a better image + $default = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='; if (!$this->image_id) { return $default; } @@ -64,7 +65,7 @@ class Bookshelf extends Entity } /** - * Get the cover image of the book + * Get the cover image of the shelf * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function cover() @@ -77,7 +78,7 @@ class Bookshelf extends Entity * @param int $length * @return string */ - public function getExcerpt($length = 100) + public function getExcerpt(int $length = 100) { $description = $this->description; return strlen($description) > $length ? substr($description, 0, $length-3) . '...' : $description; @@ -91,4 +92,14 @@ class Bookshelf extends Entity { return "'BookStack\\\\BookShelf' 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"; } + + /** + * Check if this shelf contains the given book. + * @param Book $book + * @return bool + */ + public function contains(Book $book) + { + return $this->books()->where('id', '=', $book->id)->count() > 0; + } } diff --git a/app/Entities/BreadcrumbsViewComposer.php b/app/Entities/BreadcrumbsViewComposer.php new file mode 100644 index 000000000..7745d9aee --- /dev/null +++ b/app/Entities/BreadcrumbsViewComposer.php @@ -0,0 +1,34 @@ +entityContextManager = $entityContextManager; + } + + /** + * Modify data when the view is composed. + * @param View $view + */ + public function compose(View $view) + { + $crumbs = $view->getData()['crumbs']; + if (array_first($crumbs) instanceof Book) { + $shelf = $this->entityContextManager->getContextualShelfForBook(array_first($crumbs)); + if ($shelf) { + array_unshift($crumbs, $shelf); + $view->with('crumbs', $crumbs); + } + } + } +} \ No newline at end of file diff --git a/app/Entities/Chapter.php b/app/Entities/Chapter.php index 079105ba9..bdacb7c9d 100644 --- a/app/Entities/Chapter.php +++ b/app/Entities/Chapter.php @@ -53,9 +53,9 @@ class Chapter extends Entity * @param int $length * @return string */ - public function getExcerpt($length = 100) + public function getExcerpt(int $length = 100) { - $description = $this->description; + $description = $this->text ?? $this->description; return strlen($description) > $length ? substr($description, 0, $length-3) . '...' : $description; } @@ -67,4 +67,13 @@ class Chapter extends Entity { 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"; } + + /** + * Check if this chapter has any child pages. + * @return bool + */ + public function hasChildren() + { + return count($this->pages) > 0; + } } diff --git a/app/Entities/Entity.php b/app/Entities/Entity.php index 21d172e70..482d21766 100644 --- a/app/Entities/Entity.php +++ b/app/Entities/Entity.php @@ -102,6 +102,11 @@ class Entity extends Ownable return $this->morphMany(View::class, 'viewable'); } + public function viewCountQuery() + { + return $this->views()->selectRaw('viewable_id, sum(views) as view_count')->groupBy('viewable_id'); + } + /** * Get the Tag models that have been user assigned to this entity. * @return \Illuminate\Database\Eloquent\Relations\MorphMany @@ -218,6 +223,20 @@ class Entity extends Ownable return $this->{$this->textField}; } + /** + * Get an excerpt of this entity's descriptive content to the specified length. + * @param int $length + * @return mixed + */ + public function getExcerpt(int $length = 100) + { + $text = $this->getText(); + if (mb_strlen($text) > $length) { + $text = mb_substr($text, 0, $length-3) . '...'; + } + return trim($text); + } + /** * Return a generalised, common raw query that can be 'unioned' across entities. * @return string diff --git a/app/Entities/EntityContextManager.php b/app/Entities/EntityContextManager.php new file mode 100644 index 000000000..23ffed0d2 --- /dev/null +++ b/app/Entities/EntityContextManager.php @@ -0,0 +1,62 @@ +session = $session; + $this->entityRepo = $entityRepo; + } + + /** + * Get the current bookshelf context for the given book. + * @param Book $book + * @return Bookshelf|null + */ + public function getContextualShelfForBook(Book $book) + { + $contextBookshelfId = $this->session->get($this->KEY_SHELF_CONTEXT_ID, null); + if (is_int($contextBookshelfId)) { + + /** @var Bookshelf $shelf */ + $shelf = $this->entityRepo->getById('bookshelf', $contextBookshelfId); + + if ($shelf && $shelf->contains($book)) { + return $shelf; + } + + } + return null; + } + + /** + * Store the current contextual shelf ID. + * @param int $shelfId + */ + public function setShelfContext(int $shelfId) + { + $this->session->put($this->KEY_SHELF_CONTEXT_ID, $shelfId); + } + + /** + * Clear the session stored shelf context id. + */ + public function clearShelfContext() + { + $this->session->forget($this->KEY_SHELF_CONTEXT_ID); + } + +} \ No newline at end of file diff --git a/app/Entities/EntityProvider.php b/app/Entities/EntityProvider.php index 04939a14a..d0d4a7ad6 100644 --- a/app/Entities/EntityProvider.php +++ b/app/Entities/EntityProvider.php @@ -84,4 +84,23 @@ class EntityProvider $type = strtolower($type); return $this->all()[$type]; } + + /** + * Get the morph classes, as an array, for a single or multiple types. + * @param string|array $types + * @return array + */ + public function getMorphClasses($types) + { + if (is_string($types)) { + $types = [$types]; + } + + $morphClasses = []; + foreach ($types as $type) { + $model = $this->get($type); + $morphClasses[] = $model->getMorphClass(); + } + return $morphClasses; + } } diff --git a/app/Entities/Page.php b/app/Entities/Page.php index ea7df16f4..1c2cc5cff 100644 --- a/app/Entities/Page.php +++ b/app/Entities/Page.php @@ -102,17 +102,6 @@ class Page extends Entity return baseUrl('/books/' . urlencode($bookSlug) . $midText . $idComponent); } - /** - * Get an excerpt of this page's content to the specified length. - * @param int $length - * @return mixed - */ - public function getExcerpt($length = 100) - { - $text = strlen($this->text) > $length ? substr($this->text, 0, $length-3) . '...' : $this->text; - return mb_convert_encoding($text, 'UTF-8'); - } - /** * Return a generalised, common raw query that can be 'unioned' across entities. * @param bool $withContent diff --git a/app/Entities/PageRevision.php b/app/Entities/PageRevision.php index d30147bfc..acdec2802 100644 --- a/app/Entities/PageRevision.php +++ b/app/Entities/PageRevision.php @@ -62,4 +62,5 @@ class PageRevision extends Model { return $type === 'revision'; } + } diff --git a/app/Entities/Repos/EntityRepo.php b/app/Entities/Repos/EntityRepo.php index 576ed70f0..6fc2689a5 100644 --- a/app/Entities/Repos/EntityRepo.php +++ b/app/Entities/Repos/EntityRepo.php @@ -15,6 +15,7 @@ use BookStack\Exceptions\NotFoundException; use BookStack\Exceptions\NotifyException; use BookStack\Uploads\AttachmentService; use DOMDocument; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Http\Request; use Illuminate\Support\Collection; @@ -179,11 +180,38 @@ class EntityRepo * Get all entities in a paginated format * @param $type * @param int $count + * @param string $sort + * @param string $order + * @param null|callable $queryAddition * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator */ - public function getAllPaginated($type, $count = 10) + public function getAllPaginated($type, int $count = 10, string $sort = 'name', string $order = 'asc', $queryAddition = null) { - return $this->entityQuery($type)->orderBy('name', 'asc')->paginate($count); + $query = $this->entityQuery($type); + $query = $this->addSortToQuery($query, $sort, $order); + if ($queryAddition) { + $queryAddition($query); + } + return $query->paginate($count); + } + + /** + * Add sorting operations to an entity query. + * @param Builder $query + * @param string $sort + * @param string $order + * @return Builder + */ + protected function addSortToQuery(Builder $query, string $sort = 'name', string $order = 'asc') + { + $order = ($order === 'asc') ? 'asc' : 'desc'; + $propertySorts = ['name', 'created_at', 'updated_at']; + + if (in_array($sort, $propertySorts)) { + return $query->orderBy($sort, $order); + } + + return $query; } /** @@ -265,15 +293,14 @@ class EntityRepo /** * Get the most popular entities base on all views. - * @param string|bool $type + * @param string $type * @param int $count * @param int $page * @return mixed */ - public function getPopular($type, $count = 10, $page = 0) + public function getPopular(string $type, int $count = 10, int $page = 0) { - $filter = is_bool($type) ? false : $this->entityProvider->get($type); - return $this->viewService->getPopular($count, $page, $filter); + return $this->viewService->getPopular($count, $page, $type); } /** @@ -313,6 +340,18 @@ class EntityRepo return $this->permissionService->enforceEntityRestrictions('book', $bookshelf->books())->get(); } + /** + * Get the direct children of a book. + * @param Book $book + * @return \Illuminate\Database\Eloquent\Collection + */ + public function getBookDirectChildren(Book $book) + { + $pages = $this->permissionService->enforceEntityRestrictions('page', $book->directPages())->get(); + $chapters = $this->permissionService->enforceEntityRestrictions('chapters', $book->chapters())->get(); + return collect()->concat($pages)->concat($chapters)->sortBy('priority')->sortByDesc('draft'); + } + /** * Get all child objects of a book. * Returns a sorted collection of Pages and Chapters. diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index e820154e7..78a8d33c0 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -128,7 +128,7 @@ class LoginController extends Controller ]); } - return view('auth/login', ['socialDrivers' => $socialDrivers, 'authMethod' => $authMethod]); + return view('auth.login', ['socialDrivers' => $socialDrivers, 'authMethod' => $authMethod]); } /** diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php index cdcca116c..da4f42bb1 100644 --- a/app/Http/Controllers/Auth/RegisterController.php +++ b/app/Http/Controllers/Auth/RegisterController.php @@ -176,7 +176,7 @@ class RegisterController extends Controller */ public function getRegisterConfirmation() { - return view('auth/register-confirm'); + return view('auth.register-confirm'); } /** @@ -204,7 +204,7 @@ class RegisterController extends Controller */ public function showAwaitingConfirmation() { - return view('auth/user-unconfirmed'); + return view('auth.user-unconfirmed'); } /** diff --git a/app/Http/Controllers/BookController.php b/app/Http/Controllers/BookController.php index 44368a9c4..9eb19ce65 100644 --- a/app/Http/Controllers/BookController.php +++ b/app/Http/Controllers/BookController.php @@ -3,6 +3,7 @@ use Activity; use BookStack\Auth\UserRepo; use BookStack\Entities\Book; +use BookStack\Entities\EntityContextManager; use BookStack\Entities\Repos\EntityRepo; use BookStack\Entities\ExportService; use Illuminate\Http\Request; @@ -15,18 +16,25 @@ class BookController extends Controller protected $entityRepo; protected $userRepo; protected $exportService; + protected $entityContextManager; /** * BookController constructor. * @param EntityRepo $entityRepo - * @param \BookStack\Auth\UserRepo $userRepo - * @param \BookStack\Entities\ExportService $exportService + * @param UserRepo $userRepo + * @param ExportService $exportService + * @param EntityContextManager $entityContextManager */ - public function __construct(EntityRepo $entityRepo, UserRepo $userRepo, ExportService $exportService) - { + public function __construct( + EntityRepo $entityRepo, + UserRepo $userRepo, + ExportService $exportService, + EntityContextManager $entityContextManager + ) { $this->entityRepo = $entityRepo; $this->userRepo = $userRepo; $this->exportService = $exportService; + $this->entityContextManager = $entityContextManager; parent::__construct(); } @@ -36,18 +44,32 @@ class BookController extends Controller */ public function index() { - $books = $this->entityRepo->getAllPaginated('book', 18); + $view = setting()->getUser($this->currentUser, 'books_view_type', config('app.views.books')); + $sort = setting()->getUser($this->currentUser, 'books_sort', 'name'); + $order = setting()->getUser($this->currentUser, 'books_sort_order', 'asc'); + $sortOptions = [ + 'name' => trans('common.sort_name'), + 'created_at' => trans('common.sort_created_at'), + 'updated_at' => trans('common.sort_updated_at'), + ]; + + $books = $this->entityRepo->getAllPaginated('book', 18, $sort, $order); $recents = $this->signedIn ? $this->entityRepo->getRecentlyViewed('book', 4, 0) : false; $popular = $this->entityRepo->getPopular('book', 4, 0); $new = $this->entityRepo->getRecentlyCreated('book', 4, 0); - $booksViewType = setting()->getUser($this->currentUser, 'books_view_type', config('app.views.books', 'list')); + + $this->entityContextManager->clearShelfContext(); + $this->setPageTitle(trans('entities.books')); - return view('books/index', [ + return view('books.index', [ 'books' => $books, 'recents' => $recents, 'popular' => $popular, 'new' => $new, - 'booksViewType' => $booksViewType + 'view' => $view, + 'sort' => $sort, + 'order' => $order, + 'sortOptions' => $sortOptions, ]); } @@ -59,7 +81,7 @@ class BookController extends Controller { $this->checkPermission('book-create-all'); $this->setPageTitle(trans('entities.books_create')); - return view('books/create'); + return view('books.create'); } /** @@ -83,20 +105,28 @@ class BookController extends Controller /** * Display the specified book. * @param $slug + * @param Request $request * @return Response + * @throws \BookStack\Exceptions\NotFoundException */ - public function show($slug) + public function show($slug, Request $request) { $book = $this->entityRepo->getBySlug('book', $slug); $this->checkOwnablePermission('book-view', $book); + $bookChildren = $this->entityRepo->getBookChildren($book); + Views::add($book); + if ($request->has('shelf')) { + $this->entityContextManager->setShelfContext(intval($request->get('shelf'))); + } + $this->setPageTitle($book->getShortName()); - return view('books/show', [ + return view('books.show', [ 'book' => $book, 'current' => $book, 'bookChildren' => $bookChildren, - 'activity' => Activity::entityActivity($book, 20, 0) + 'activity' => Activity::entityActivity($book, 20, 1) ]); } @@ -110,7 +140,7 @@ class BookController extends Controller $book = $this->entityRepo->getBySlug('book', $slug); $this->checkOwnablePermission('book-update', $book); $this->setPageTitle(trans('entities.books_edit_named', ['bookName'=>$book->getShortName()])); - return view('books/edit', ['book' => $book, 'current' => $book]); + return view('books.edit', ['book' => $book, 'current' => $book]); } /** @@ -142,22 +172,24 @@ class BookController extends Controller $book = $this->entityRepo->getBySlug('book', $bookSlug); $this->checkOwnablePermission('book-delete', $book); $this->setPageTitle(trans('entities.books_delete_named', ['bookName'=>$book->getShortName()])); - return view('books/delete', ['book' => $book, 'current' => $book]); + return view('books.delete', ['book' => $book, 'current' => $book]); } /** * Shows the view which allows pages to be re-ordered and sorted. * @param string $bookSlug * @return \Illuminate\View\View + * @throws \BookStack\Exceptions\NotFoundException */ public function sort($bookSlug) { $book = $this->entityRepo->getBySlug('book', $bookSlug); $this->checkOwnablePermission('book-update', $book); + $bookChildren = $this->entityRepo->getBookChildren($book, true); - $books = $this->entityRepo->getAll('book', false, 'update'); + $this->setPageTitle(trans('entities.books_sort_named', ['bookName'=>$book->getShortName()])); - return view('books/sort', ['book' => $book, 'current' => $book, 'books' => $books, 'bookChildren' => $bookChildren]); + return view('books.sort', ['book' => $book, 'current' => $book, 'bookChildren' => $bookChildren]); } /** @@ -170,7 +202,7 @@ class BookController extends Controller { $book = $this->entityRepo->getBySlug('book', $bookSlug); $bookChildren = $this->entityRepo->getBookChildren($book); - return view('books/sort-box', ['book' => $book, 'bookChildren' => $bookChildren]); + return view('books.sort-box', ['book' => $book, 'bookChildren' => $bookChildren]); } /** @@ -263,12 +295,12 @@ class BookController extends Controller * @param $bookSlug * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ - public function showRestrict($bookSlug) + public function showPermissions($bookSlug) { $book = $this->entityRepo->getBySlug('book', $bookSlug); $this->checkOwnablePermission('restrictions-manage', $book); $roles = $this->userRepo->getRestrictableRoles(); - return view('books/restrictions', [ + return view('books.permissions', [ 'book' => $book, 'roles' => $roles ]); @@ -277,11 +309,12 @@ class BookController extends Controller /** * Set the restrictions for this book. * @param $bookSlug - * @param $bookSlug * @param Request $request * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + * @throws \BookStack\Exceptions\NotFoundException + * @throws \Throwable */ - public function restrict($bookSlug, Request $request) + public function permissions($bookSlug, Request $request) { $book = $this->entityRepo->getBySlug('book', $bookSlug); $this->checkOwnablePermission('restrictions-manage', $book); diff --git a/app/Http/Controllers/BookshelfController.php b/app/Http/Controllers/BookshelfController.php index 5c2898786..b86bc2e38 100644 --- a/app/Http/Controllers/BookshelfController.php +++ b/app/Http/Controllers/BookshelfController.php @@ -3,8 +3,8 @@ use Activity; use BookStack\Auth\UserRepo; use BookStack\Entities\Bookshelf; +use BookStack\Entities\EntityContextManager; use BookStack\Entities\Repos\EntityRepo; -use BookStack\Entities\ExportService; use Illuminate\Http\Request; use Illuminate\Http\Response; use Views; @@ -14,19 +14,19 @@ class BookshelfController extends Controller protected $entityRepo; protected $userRepo; - protected $exportService; + protected $entityContextManager; /** * BookController constructor. - * @param \BookStack\Entities\Repos\EntityRepo $entityRepo + * @param EntityRepo $entityRepo * @param UserRepo $userRepo - * @param \BookStack\Entities\ExportService $exportService + * @param EntityContextManager $entityContextManager */ - public function __construct(EntityRepo $entityRepo, UserRepo $userRepo, ExportService $exportService) + public function __construct(EntityRepo $entityRepo, UserRepo $userRepo, EntityContextManager $entityContextManager) { $this->entityRepo = $entityRepo; $this->userRepo = $userRepo; - $this->exportService = $exportService; + $this->entityContextManager = $entityContextManager; parent::__construct(); } @@ -36,19 +36,35 @@ class BookshelfController extends Controller */ public function index() { - $shelves = $this->entityRepo->getAllPaginated('bookshelf', 18); + $view = setting()->getUser($this->currentUser, 'bookshelves_view_type', config('app.views.bookshelves', 'grid')); + $sort = setting()->getUser($this->currentUser, 'bookshelves_sort', 'name'); + $order = setting()->getUser($this->currentUser, 'bookshelves_sort_order', 'asc'); + $sortOptions = [ + 'name' => trans('common.sort_name'), + 'created_at' => trans('common.sort_created_at'), + 'updated_at' => trans('common.sort_updated_at'), + ]; + + $shelves = $this->entityRepo->getAllPaginated('bookshelf', 18, $sort, $order); + foreach ($shelves as $shelf) { + $shelf->books = $this->entityRepo->getBookshelfChildren($shelf); + } + $recents = $this->signedIn ? $this->entityRepo->getRecentlyViewed('bookshelf', 4, 0) : false; $popular = $this->entityRepo->getPopular('bookshelf', 4, 0); $new = $this->entityRepo->getRecentlyCreated('bookshelf', 4, 0); - $shelvesViewType = setting()->getUser($this->currentUser, 'bookshelves_view_type', config('app.views.bookshelves', 'grid')); + $this->entityContextManager->clearShelfContext(); $this->setPageTitle(trans('entities.shelves')); - return view('shelves/index', [ + return view('shelves.index', [ 'shelves' => $shelves, 'recents' => $recents, 'popular' => $popular, 'new' => $new, - 'shelvesViewType' => $shelvesViewType + 'view' => $view, + 'sort' => $sort, + 'order' => $order, + 'sortOptions' => $sortOptions, ]); } @@ -61,7 +77,7 @@ class BookshelfController extends Controller $this->checkPermission('bookshelf-create-all'); $books = $this->entityRepo->getAll('book', false, 'update'); $this->setPageTitle(trans('entities.shelves_create')); - return view('shelves/create', ['books' => $books]); + return view('shelves.create', ['books' => $books]); } /** @@ -93,17 +109,19 @@ class BookshelfController extends Controller */ public function show(string $slug) { - $bookshelf = $this->entityRepo->getBySlug('bookshelf', $slug); /** @var $bookshelf Bookshelf */ + /** @var Bookshelf $bookshelf */ + $bookshelf = $this->entityRepo->getBySlug('bookshelf', $slug); $this->checkOwnablePermission('book-view', $bookshelf); $books = $this->entityRepo->getBookshelfChildren($bookshelf); Views::add($bookshelf); + $this->entityContextManager->setShelfContext($bookshelf->id); $this->setPageTitle($bookshelf->getShortName()); - return view('shelves/show', [ + return view('shelves.show', [ 'shelf' => $bookshelf, 'books' => $books, - 'activity' => Activity::entityActivity($bookshelf, 20, 0) + 'activity' => Activity::entityActivity($bookshelf, 20, 1) ]); } @@ -126,7 +144,7 @@ class BookshelfController extends Controller }); $this->setPageTitle(trans('entities.shelves_edit_named', ['name' => $bookshelf->getShortName()])); - return view('shelves/edit', [ + return view('shelves.edit', [ 'shelf' => $bookshelf, 'books' => $books, 'shelfBooks' => $shelfBooks, @@ -170,7 +188,7 @@ class BookshelfController extends Controller $this->checkOwnablePermission('bookshelf-delete', $bookshelf); $this->setPageTitle(trans('entities.shelves_delete_named', ['name' => $bookshelf->getShortName()])); - return view('shelves/delete', ['shelf' => $bookshelf]); + return view('shelves.delete', ['shelf' => $bookshelf]); } /** @@ -190,31 +208,32 @@ class BookshelfController extends Controller } /** - * Show the Restrictions view. - * @param $slug + * Show the permissions view. + * @param string $slug * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View * @throws \BookStack\Exceptions\NotFoundException */ - public function showRestrict(string $slug) + public function showPermissions(string $slug) { $bookshelf = $this->entityRepo->getBySlug('bookshelf', $slug); $this->checkOwnablePermission('restrictions-manage', $bookshelf); $roles = $this->userRepo->getRestrictableRoles(); - return view('shelves.restrictions', [ + return view('shelves.permissions', [ 'shelf' => $bookshelf, 'roles' => $roles ]); } /** - * Set the restrictions for this bookshelf. - * @param $slug + * Set the permissions for this bookshelf. + * @param string $slug * @param Request $request * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector * @throws \BookStack\Exceptions\NotFoundException + * @throws \Throwable */ - public function restrict(string $slug, Request $request) + public function permissions(string $slug, Request $request) { $bookshelf = $this->entityRepo->getBySlug('bookshelf', $slug); $this->checkOwnablePermission('restrictions-manage', $bookshelf); diff --git a/app/Http/Controllers/ChapterController.php b/app/Http/Controllers/ChapterController.php index 20ab96133..c19e45694 100644 --- a/app/Http/Controllers/ChapterController.php +++ b/app/Http/Controllers/ChapterController.php @@ -39,7 +39,7 @@ class ChapterController extends Controller $book = $this->entityRepo->getBySlug('book', $bookSlug); $this->checkOwnablePermission('chapter-create', $book); $this->setPageTitle(trans('entities.chapters_create')); - return view('chapters/create', ['book' => $book, 'current' => $book]); + return view('chapters.create', ['book' => $book, 'current' => $book]); } /** @@ -78,7 +78,7 @@ class ChapterController extends Controller Views::add($chapter); $this->setPageTitle($chapter->getShortName()); $pages = $this->entityRepo->getChapterChildren($chapter); - return view('chapters/show', [ + return view('chapters.show', [ 'book' => $chapter->book, 'chapter' => $chapter, 'current' => $chapter, @@ -98,7 +98,7 @@ class ChapterController extends Controller $chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug); $this->checkOwnablePermission('chapter-update', $chapter); $this->setPageTitle(trans('entities.chapters_edit_named', ['chapterName' => $chapter->getShortName()])); - return view('chapters/edit', ['book' => $chapter->book, 'chapter' => $chapter, 'current' => $chapter]); + return view('chapters.edit', ['book' => $chapter->book, 'chapter' => $chapter, 'current' => $chapter]); } /** @@ -130,7 +130,7 @@ class ChapterController extends Controller $chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug); $this->checkOwnablePermission('chapter-delete', $chapter); $this->setPageTitle(trans('entities.chapters_delete_named', ['chapterName' => $chapter->getShortName()])); - return view('chapters/delete', ['book' => $chapter->book, 'chapter' => $chapter, 'current' => $chapter]); + return view('chapters.delete', ['book' => $chapter->book, 'chapter' => $chapter, 'current' => $chapter]); } /** @@ -162,7 +162,7 @@ class ChapterController extends Controller $this->setPageTitle(trans('entities.chapters_move_named', ['chapterName' => $chapter->getShortName()])); $this->checkOwnablePermission('chapter-update', $chapter); $this->checkOwnablePermission('chapter-delete', $chapter); - return view('chapters/move', [ + return view('chapters.move', [ 'chapter' => $chapter, 'book' => $chapter->book ]); @@ -214,13 +214,14 @@ class ChapterController extends Controller * @param $bookSlug * @param $chapterSlug * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + * @throws \BookStack\Exceptions\NotFoundException */ - public function showRestrict($bookSlug, $chapterSlug) + public function showPermissions($bookSlug, $chapterSlug) { $chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug); $this->checkOwnablePermission('restrictions-manage', $chapter); $roles = $this->userRepo->getRestrictableRoles(); - return view('chapters/restrictions', [ + return view('chapters.permissions', [ 'chapter' => $chapter, 'roles' => $roles ]); @@ -232,8 +233,10 @@ class ChapterController extends Controller * @param $chapterSlug * @param Request $request * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + * @throws \BookStack\Exceptions\NotFoundException + * @throws \Throwable */ - public function restrict($bookSlug, $chapterSlug, Request $request) + public function permissions($bookSlug, $chapterSlug, Request $request) { $chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug); $this->checkOwnablePermission('restrictions-manage', $chapter); diff --git a/app/Http/Controllers/CommentController.php b/app/Http/Controllers/CommentController.php index 2039ce7fe..860b50762 100644 --- a/app/Http/Controllers/CommentController.php +++ b/app/Http/Controllers/CommentController.php @@ -54,7 +54,7 @@ class CommentController extends Controller $this->checkPermission('comment-create-all'); $comment = $this->commentRepo->create($page, $request->only(['html', 'text', 'parent_id'])); Activity::add($page, 'commented_on', $page->book->id); - return view('comments/comment', ['comment' => $comment]); + return view('comments.comment', ['comment' => $comment]); } /** @@ -75,7 +75,7 @@ class CommentController extends Controller $this->checkOwnablePermission('comment-update', $comment); $comment = $this->commentRepo->update($comment, $request->only(['html', 'text'])); - return view('comments/comment', ['comment' => $comment]); + return view('comments.comment', ['comment' => $comment]); } /** diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 80f567eaa..fc4f184fc 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -123,6 +123,20 @@ abstract class Controller extends BaseController return true; } + /** + * Check if the current user has a permission or bypass if the provided user + * id matches the current user. + * @param string $permissionName + * @param int $userId + * @return bool + */ + protected function checkPermissionOrCurrentUser(string $permissionName, int $userId) + { + return $this->checkPermissionOr($permissionName, function() use ($userId) { + return $userId === $this->currentUser->id; + }); + } + /** * Send back a json error message. * @param string $messageText diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 5a5f34e4a..c5f3cd02a 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -19,7 +19,6 @@ class HomeController extends Controller parent::__construct(); } - /** * Display the homepage. * @return Response @@ -45,17 +44,36 @@ class HomeController extends Controller 'draftPages' => $draftPages, ]; + // Add required list ordering & sorting for books & shelves views. + if ($homepageOption === 'bookshelves' || $homepageOption === 'books') { + $key = $homepageOption; + $view = setting()->getUser($this->currentUser, $key . '_view_type', config('app.views.' . $key)); + $sort = setting()->getUser($this->currentUser, $key . '_sort', 'name'); + $order = setting()->getUser($this->currentUser, $key . '_sort_order', 'asc'); + + $sortOptions = [ + 'name' => trans('common.sort_name'), + 'created_at' => trans('common.sort_created_at'), + 'updated_at' => trans('common.sort_updated_at'), + ]; + + $commonData = array_merge($commonData, [ + 'view' => $view, + 'sort' => $sort, + 'order' => $order, + 'sortOptions' => $sortOptions, + ]); + } + if ($homepageOption === 'bookshelves') { - $shelves = $this->entityRepo->getAllPaginated('bookshelf', 18); - $shelvesViewType = setting()->getUser($this->currentUser, 'bookshelves_view_type', config('app.views.bookshelves', 'grid')); - $data = array_merge($commonData, ['shelves' => $shelves, 'shelvesViewType' => $shelvesViewType]); + $shelves = $this->entityRepo->getAllPaginated('bookshelf', 18, $commonData['sort'], $commonData['order']); + $data = array_merge($commonData, ['shelves' => $shelves]); return view('common.home-shelves', $data); } if ($homepageOption === 'books') { - $books = $this->entityRepo->getAllPaginated('book', 18); - $booksViewType = setting()->getUser($this->currentUser, 'books_view_type', config('app.views.books', 'list')); - $data = array_merge($commonData, ['books' => $books, 'booksViewType' => $booksViewType]); + $books = $this->entityRepo->getAllPaginated('book', 18, $commonData['sort'], $commonData['order']); + $data = array_merge($commonData, ['books' => $books]); return view('common.home-book', $data); } @@ -105,7 +123,7 @@ class HomeController extends Controller */ public function customHeadContent() { - return view('partials/custom-head-content'); + return view('partials.custom-head-content'); } /** @@ -120,7 +138,7 @@ class HomeController extends Controller $allowRobots = $sitePublic; } return response() - ->view('common/robots', ['allowRobots' => $allowRobots]) + ->view('common.robots', ['allowRobots' => $allowRobots]) ->header('Content-Type', 'text/plain'); } @@ -129,6 +147,6 @@ class HomeController extends Controller */ public function getNotFound() { - return response()->view('errors/404', [], 404); + return response()->view('errors.404', [], 404); } } diff --git a/app/Http/Controllers/PageController.php b/app/Http/Controllers/PageController.php index d95e02470..16a7d5a5e 100644 --- a/app/Http/Controllers/PageController.php +++ b/app/Http/Controllers/PageController.php @@ -61,7 +61,7 @@ class PageController extends Controller // Otherwise show the edit view if they're a guest $this->setPageTitle(trans('entities.pages_new')); - return view('pages/guest-create', ['parent' => $parent]); + return view('pages.guest-create', ['parent' => $parent]); } /** @@ -110,7 +110,7 @@ class PageController extends Controller $this->setPageTitle(trans('entities.pages_edit_draft')); $draftsEnabled = $this->signedIn; - return view('pages/edit', [ + return view('pages.edit', [ 'page' => $draft, 'book' => $draft->book, 'isDraft' => true, @@ -184,7 +184,7 @@ class PageController extends Controller Views::add($page); $this->setPageTitle($page->getShortName()); - return view('pages/show', [ + return view('pages.show', [ 'page' => $page,'book' => $page->book, 'current' => $page, 'sidebarTree' => $sidebarTree, @@ -239,7 +239,7 @@ class PageController extends Controller } $draftsEnabled = $this->signedIn; - return view('pages/edit', [ + return view('pages.edit', [ 'page' => $page, 'book' => $page->book, 'current' => $page, @@ -317,7 +317,7 @@ class PageController extends Controller $page = $this->pageRepo->getPageBySlug($pageSlug, $bookSlug); $this->checkOwnablePermission('page-delete', $page); $this->setPageTitle(trans('entities.pages_delete_named', ['pageName'=>$page->getShortName()])); - return view('pages/delete', ['book' => $page->book, 'page' => $page, 'current' => $page]); + return view('pages.delete', ['book' => $page->book, 'page' => $page, 'current' => $page]); } @@ -333,7 +333,7 @@ class PageController extends Controller $page = $this->pageRepo->getById('page', $pageId, true); $this->checkOwnablePermission('page-update', $page); $this->setPageTitle(trans('entities.pages_delete_draft_named', ['pageName'=>$page->getShortName()])); - return view('pages/delete', ['book' => $page->book, 'page' => $page, 'current' => $page]); + return view('pages.delete', ['book' => $page->book, 'page' => $page, 'current' => $page]); } /** @@ -377,12 +377,13 @@ class PageController extends Controller * @param string $bookSlug * @param string $pageSlug * @return \Illuminate\View\View + * @throws NotFoundException */ public function showRevisions($bookSlug, $pageSlug) { $page = $this->pageRepo->getPageBySlug($pageSlug, $bookSlug); $this->setPageTitle(trans('entities.pages_revisions_named', ['pageName'=>$page->getShortName()])); - return view('pages/revisions', ['page' => $page, 'book' => $page->book, 'current' => $page]); + return view('pages.revisions', ['page' => $page, 'current' => $page]); } /** @@ -403,9 +404,10 @@ class PageController extends Controller $page->fill($revision->toArray()); $this->setPageTitle(trans('entities.pages_revision_named', ['pageName' => $page->getShortName()])); - return view('pages/revision', [ + return view('pages.revision', [ 'page' => $page, 'book' => $page->book, + 'diff' => null, 'revision' => $revision ]); } @@ -432,7 +434,7 @@ class PageController extends Controller $page->fill($revision->toArray()); $this->setPageTitle(trans('entities.pages_revision_named', ['pageName'=>$page->getShortName()])); - return view('pages/revision', [ + return view('pages.revision', [ 'page' => $page, 'book' => $page->book, 'diff' => $diff, @@ -482,12 +484,12 @@ class PageController extends Controller // Check if its the latest revision, cannot delete latest revision. if (intval($currentRevision->id) === intval($revId)) { session()->flash('error', trans('entities.revision_cannot_delete_latest')); - return response()->view('pages/revisions', ['page' => $page, 'book' => $page->book, 'current' => $page], 400); + return response()->view('pages.revisions', ['page' => $page, 'book' => $page->book, 'current' => $page], 400); } $revision->delete(); session()->flash('success', trans('entities.revision_delete_success')); - return view('pages/revisions', ['page' => $page, 'book' => $page->book, 'current' => $page]); + return view('pages.revisions', ['page' => $page, 'book' => $page->book, 'current' => $page]); } /** @@ -532,49 +534,20 @@ class PageController extends Controller return $this->downloadResponse($pageText, $pageSlug . '.txt'); } - /** - * Show a listing of recently created pages - * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View - */ - public function showRecentlyCreated() - { - $pages = $this->pageRepo->getRecentlyCreatedPaginated('page', 20)->setPath(baseUrl('/pages/recently-created')); - return view('pages/detailed-listing', [ - 'title' => trans('entities.recently_created_pages'), - 'pages' => $pages - ]); - } - /** * Show a listing of recently created pages * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function showRecentlyUpdated() { + // TODO - Still exist? $pages = $this->pageRepo->getRecentlyUpdatedPaginated('page', 20)->setPath(baseUrl('/pages/recently-updated')); - return view('pages/detailed-listing', [ + return view('pages.detailed-listing', [ 'title' => trans('entities.recently_updated_pages'), 'pages' => $pages ]); } - /** - * Show the Restrictions view. - * @param string $bookSlug - * @param string $pageSlug - * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View - */ - public function showRestrict($bookSlug, $pageSlug) - { - $page = $this->pageRepo->getPageBySlug($pageSlug, $bookSlug); - $this->checkOwnablePermission('restrictions-manage', $page); - $roles = $this->userRepo->getRestrictableRoles(); - return view('pages/restrictions', [ - 'page' => $page, - 'roles' => $roles - ]); - } - /** * Show the view to choose a new parent to move a page into. * @param string $bookSlug @@ -587,7 +560,7 @@ class PageController extends Controller $page = $this->pageRepo->getPageBySlug($pageSlug, $bookSlug); $this->checkOwnablePermission('page-update', $page); $this->checkOwnablePermission('page-delete', $page); - return view('pages/move', [ + return view('pages.move', [ 'book' => $page->book, 'page' => $page ]); @@ -645,7 +618,7 @@ class PageController extends Controller $page = $this->pageRepo->getPageBySlug($pageSlug, $bookSlug); $this->checkOwnablePermission('page-view', $page); session()->flashInput(['name' => $page->name]); - return view('pages/copy', [ + return view('pages.copy', [ 'book' => $page->book, 'page' => $page ]); @@ -690,6 +663,24 @@ class PageController extends Controller return redirect($pageCopy->getUrl()); } + /** + * Show the Permissions view. + * @param string $bookSlug + * @param string $pageSlug + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + * @throws NotFoundException + */ + public function showPermissions($bookSlug, $pageSlug) + { + $page = $this->pageRepo->getPageBySlug($pageSlug, $bookSlug); + $this->checkOwnablePermission('restrictions-manage', $page); + $roles = $this->userRepo->getRestrictableRoles(); + return view('pages.permissions', [ + 'page' => $page, + 'roles' => $roles + ]); + } + /** * Set the permissions for this page. * @param string $bookSlug @@ -697,8 +688,9 @@ class PageController extends Controller * @param Request $request * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector * @throws NotFoundException + * @throws \Throwable */ - public function restrict($bookSlug, $pageSlug, Request $request) + public function permissions($bookSlug, $pageSlug, Request $request) { $page = $this->pageRepo->getPageBySlug($pageSlug, $bookSlug); $this->checkOwnablePermission('restrictions-manage', $page); diff --git a/app/Http/Controllers/PermissionController.php b/app/Http/Controllers/PermissionController.php index 9be343c9a..9893d5993 100644 --- a/app/Http/Controllers/PermissionController.php +++ b/app/Http/Controllers/PermissionController.php @@ -26,7 +26,7 @@ class PermissionController extends Controller { $this->checkPermission('user-roles-manage'); $roles = $this->permissionsRepo->getAllRoles(); - return view('settings/roles/index', ['roles' => $roles]); + return view('settings.roles.index', ['roles' => $roles]); } /** @@ -36,7 +36,7 @@ class PermissionController extends Controller public function createRole() { $this->checkPermission('user-roles-manage'); - return view('settings/roles/create'); + return view('settings.roles.create'); } /** @@ -70,7 +70,7 @@ class PermissionController extends Controller if ($role->hidden) { throw new PermissionsException(trans('errors.role_cannot_be_edited')); } - return view('settings/roles/edit', ['role' => $role]); + return view('settings.roles.edit', ['role' => $role]); } /** @@ -106,7 +106,7 @@ class PermissionController extends Controller $roles = $this->permissionsRepo->getAllRolesExcept($role); $blankRole = $role->newInstance(['display_name' => trans('settings.role_delete_no_migration')]); $roles->prepend($blankRole); - return view('settings/roles/delete', ['role' => $role, 'roles' => $roles]); + return view('settings.roles.delete', ['role' => $role, 'roles' => $roles]); } /** diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php index d8f2dc4d7..4bcf7b40e 100644 --- a/app/Http/Controllers/SearchController.php +++ b/app/Http/Controllers/SearchController.php @@ -1,34 +1,45 @@ entityRepo = $entityRepo; $this->viewService = $viewService; $this->searchService = $searchService; + $this->entityContextManager = $entityContextManager; parent::__construct(); } /** * Searches all entities. * @param Request $request - * @return \Illuminate\View\View + * @return View * @internal param string $searchTerm */ public function search(Request $request) @@ -41,7 +52,7 @@ class SearchController extends Controller $results = $this->searchService->searchEntities($searchTerm, 'all', $page, 20); - return view('search/all', [ + return view('search.all', [ 'entities' => $results['results'], 'totalResults' => $results['total'], 'searchTerm' => $searchTerm, @@ -55,28 +66,28 @@ class SearchController extends Controller * Searches all entities within a book. * @param Request $request * @param integer $bookId - * @return \Illuminate\View\View + * @return View * @internal param string $searchTerm */ public function searchBook(Request $request, $bookId) { $term = $request->get('term', ''); $results = $this->searchService->searchBook($bookId, $term); - return view('partials/entity-list', ['entities' => $results]); + return view('partials.entity-list', ['entities' => $results]); } /** * Searches all entities within a chapter. * @param Request $request * @param integer $chapterId - * @return \Illuminate\View\View + * @return 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]); + return view('partials.entity-list', ['entities' => $results]); } /** @@ -87,21 +98,64 @@ class SearchController extends Controller */ public function searchEntitiesAjax(Request $request) { - $entityTypes = $request->filled('types') ? collect(explode(',', $request->get('types'))) : collect(['page', 'chapter', 'book']); + $entityTypes = $request->filled('types') ? explode(',', $request->get('types')) : ['page', 'chapter', 'book']; $searchTerm = $request->get('term', false); $permission = $request->get('permission', 'view'); // Search for entities otherwise show most popular if ($searchTerm !== false) { - $searchTerm .= ' {type:'. implode('|', $entityTypes->toArray()) .'}'; + $searchTerm .= ' {type:'. implode('|', $entityTypes) .'}'; $entities = $this->searchService->searchEntities($searchTerm, 'all', 1, 20, $permission)['results']; } else { - $entityNames = $entityTypes->map(function ($type) { - return 'BookStack\\' . ucfirst($type); // TODO - Extract this elsewhere, too specific and stringy - })->toArray(); - $entities = $this->viewService->getPopular(20, 0, $entityNames, $permission); + $entities = $this->viewService->getPopular(20, 0, $entityTypes, $permission); } - return view('search/entity-ajax-list', ['entities' => $entities]); + return view('search.entity-ajax-list', ['entities' => $entities]); + } + + /** + * Search siblings items in the system. + * @param Request $request + * @return Factory|View|mixed + */ + public function searchSiblings(Request $request) + { + $type = $request->get('entity_type', null); + $id = $request->get('entity_id', null); + + $entity = $this->entityRepo->getById($type, $id); + if (!$entity) { + return $this->jsonError(trans('errors.entity_not_found'), 404); + } + + $entities = []; + + // Page in chapter + if ($entity->isA('page') && $entity->chapter) { + $entities = $this->entityRepo->getChapterChildren($entity->chapter); + } + + // Page in book or chapter + if (($entity->isA('page') && !$entity->chapter) || $entity->isA('chapter')) { + $entities = $this->entityRepo->getBookDirectChildren($entity->book); + } + + // Book + // Gets just the books in a shelf if shelf is in context + if ($entity->isA('book')) { + $contextShelf = $this->entityContextManager->getContextualShelfForBook($entity); + if ($contextShelf) { + $entities = $this->entityRepo->getBookshelfChildren($contextShelf); + } else { + $entities = $this->entityRepo->getAll('book'); + } + } + + // Shelve + if ($entity->isA('bookshelf')) { + $entities = $this->entityRepo->getAll('bookshelf'); + } + + return view('partials.entity-list-basic', ['entities' => $entities, 'style' => 'compact']); } } diff --git a/app/Http/Controllers/SettingController.php b/app/Http/Controllers/SettingController.php index 01fb68fe0..159e19a2b 100644 --- a/app/Http/Controllers/SettingController.php +++ b/app/Http/Controllers/SettingController.php @@ -1,5 +1,6 @@ $version]); + return view('settings.index', [ + 'version' => $version, + 'guestUser' => User::getDefault() + ]); } /** @@ -57,7 +61,7 @@ class SettingController extends Controller // Get application version $version = trim(file_get_contents(base_path('version'))); - return view('settings/maintenance', ['version' => $version]); + return view('settings.maintenance', ['version' => $version]); } /** diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index cc5ada3f2..1bb5d46cd 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -41,7 +41,7 @@ class UserController extends Controller $users = $this->userRepo->getAllUsersPaginatedAndSorted(20, $listDetails); $this->setPageTitle(trans('settings.users')); $users->appends($listDetails); - return view('users/index', ['users' => $users, 'listDetails' => $listDetails]); + return view('users.index', ['users' => $users, 'listDetails' => $listDetails]); } /** @@ -53,7 +53,7 @@ class UserController extends Controller $this->checkPermission('users-manage'); $authMethod = config('auth.method'); $roles = $this->userRepo->getAllRoles(); - return view('users/create', ['authMethod' => $authMethod, 'roles' => $roles]); + return view('users.create', ['authMethod' => $authMethod, 'roles' => $roles]); } /** @@ -118,7 +118,7 @@ class UserController extends Controller $activeSocialDrivers = $socialAuthService->getActiveDrivers(); $this->setPageTitle(trans('settings.user_profile')); $roles = $this->userRepo->getAllRoles(); - return view('users/edit', ['user' => $user, 'activeSocialDrivers' => $activeSocialDrivers, 'authMethod' => $authMethod, 'roles' => $roles]); + return view('users.edit', ['user' => $user, 'activeSocialDrivers' => $activeSocialDrivers, 'authMethod' => $authMethod, 'roles' => $roles]); } /** @@ -190,7 +190,7 @@ class UserController extends Controller $user = $this->userRepo->getById($id); $this->setPageTitle(trans('settings.users_delete_named', ['userName' => $user->name])); - return view('users/delete', ['user' => $user]); + return view('users.delete', ['user' => $user]); } /** @@ -232,10 +232,12 @@ class UserController extends Controller public function showProfilePage($id) { $user = $this->userRepo->getById($id); + $userActivity = $this->userRepo->getActivity($user); $recentlyCreated = $this->userRepo->getRecentlyCreated($user, 5, 0); $assetCounts = $this->userRepo->getAssetCounts($user); - return view('users/profile', [ + + return view('users.profile', [ 'user' => $user, 'activity' => $userActivity, 'recentlyCreated' => $recentlyCreated, @@ -251,19 +253,7 @@ class UserController extends Controller */ public function switchBookView($id, Request $request) { - $this->checkPermissionOr('users-manage', function () use ($id) { - return $this->currentUser->id == $id; - }); - - $viewType = $request->get('view_type'); - if (!in_array($viewType, ['grid', 'list'])) { - $viewType = 'list'; - } - - $user = $this->user->findOrFail($id); - setting()->putUser($user, 'books_view_type', $viewType); - - return redirect()->back(302, [], "/settings/users/$id"); + return $this->switchViewType($id, $request, 'books'); } /** @@ -274,18 +264,98 @@ class UserController extends Controller */ public function switchShelfView($id, Request $request) { - $this->checkPermissionOr('users-manage', function () use ($id) { - return $this->currentUser->id == $id; - }); + return $this->switchViewType($id, $request, 'bookshelves'); + } + + /** + * For a type of list, switch with stored view type for a user. + * @param integer $userId + * @param Request $request + * @param string $listName + * @return \Illuminate\Http\RedirectResponse + */ + protected function switchViewType($userId, Request $request, string $listName) + { + $this->checkPermissionOrCurrentUser('users-manage', $userId); $viewType = $request->get('view_type'); if (!in_array($viewType, ['grid', 'list'])) { $viewType = 'list'; } - $user = $this->userRepo->getById($id); - setting()->putUser($user, 'bookshelves_view_type', $viewType); + $user = $this->userRepo->getById($userId); + $key = $listName . '_view_type'; + setting()->putUser($user, $key, $viewType); - return redirect()->back(302, [], "/settings/users/$id"); + return redirect()->back(302, [], "/settings/users/$userId"); } + + /** + * Change the stored sort type for a particular view. + * @param string $id + * @param string $type + * @param Request $request + * @return \Illuminate\Http\RedirectResponse + */ + public function changeSort(string $id, string $type, Request $request) + { + $validSortTypes = ['books', 'bookshelves']; + if (!in_array($type, $validSortTypes)) { + return redirect()->back(500); + } + return $this->changeListSort($id, $request, $type); + } + + /** + * Update the stored section expansion preference for the given user. + * @param string $id + * @param string $key + * @param Request $request + * @return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response + */ + public function updateExpansionPreference(string $id, string $key, Request $request) + { + $this->checkPermissionOrCurrentUser('users-manage', $id); + $keyWhitelist = ['home-details']; + if (!in_array($key, $keyWhitelist)) { + return response("Invalid key", 500); + } + + $newState = $request->get('expand', 'false'); + + $user = $this->user->findOrFail($id); + setting()->putUser($user, 'section_expansion#' . $key, $newState); + return response("", 204); + } + + /** + * Changed the stored preference for a list sort order. + * @param int $userId + * @param Request $request + * @param string $listName + * @return \Illuminate\Http\RedirectResponse + */ + protected function changeListSort(int $userId, Request $request, string $listName) + { + $this->checkPermissionOrCurrentUser('users-manage', $userId); + + $sort = $request->get('sort'); + if (!in_array($sort, ['name', 'created_at', 'updated_at'])) { + $sort = 'name'; + } + + $order = $request->get('order'); + if (!in_array($order, ['asc', 'desc'])) { + $order = 'asc'; + } + + $user = $this->user->findOrFail($userId); + $sortKey = $listName . '_sort'; + $orderKey = $listName . '_sort_order'; + setting()->putUser($user, $sortKey, $sort); + setting()->putUser($user, $orderKey, $order); + + return redirect()->back(302, [], "/settings/users/$userId"); + } + } diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php index c9b2726e8..1a3384367 100644 --- a/app/Http/Middleware/Authenticate.php +++ b/app/Http/Middleware/Authenticate.php @@ -37,7 +37,7 @@ class Authenticate } } - if ($this->auth->guest() && !setting('app-public')) { + if (!hasAppAccess()) { if ($request->ajax()) { return response('Unauthorized.', 401); } else { diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 3ca59dcb3..9b91ba126 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -3,12 +3,14 @@ use Blade; use BookStack\Entities\Book; use BookStack\Entities\Bookshelf; +use BookStack\Entities\BreadcrumbsViewComposer; use BookStack\Entities\Chapter; use BookStack\Entities\Page; use BookStack\Settings\Setting; use BookStack\Settings\SettingService; use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Http\UploadedFile; +use Illuminate\Support\Facades\View; use Illuminate\Support\ServiceProvider; use Schema; use Validator; @@ -33,7 +35,6 @@ class AppServiceProvider extends ServiceProvider return substr_count($uploadName, '.') < 2; }); - // Custom blade view directives Blade::directive('icon', function ($expression) { return ""; @@ -49,6 +50,9 @@ class AppServiceProvider extends ServiceProvider 'BookStack\\Chapter' => Chapter::class, 'BookStack\\Page' => Page::class, ]); + + // View Composers + View::composer('partials.breadcrumbs', BreadcrumbsViewComposer::class); } /** diff --git a/app/Providers/CustomFacadeProvider.php b/app/Providers/CustomFacadeProvider.php index 5508ee9cd..e7bde5290 100644 --- a/app/Providers/CustomFacadeProvider.php +++ b/app/Providers/CustomFacadeProvider.php @@ -2,20 +2,11 @@ namespace BookStack\Providers; -use BookStack\Actions\Activity; use BookStack\Actions\ActivityService; -use BookStack\Actions\View; use BookStack\Actions\ViewService; -use BookStack\Auth\Permissions\PermissionService; -use BookStack\Settings\Setting; use BookStack\Settings\SettingService; -use BookStack\Uploads\HttpFetcher; -use BookStack\Uploads\Image; use BookStack\Uploads\ImageService; -use Illuminate\Contracts\Cache\Repository; -use Illuminate\Contracts\Filesystem\Factory; use Illuminate\Support\ServiceProvider; -use Intervention\Image\ImageManager; class CustomFacadeProvider extends ServiceProvider { @@ -37,34 +28,19 @@ class CustomFacadeProvider extends ServiceProvider public function register() { $this->app->bind('activity', function () { - return new ActivityService( - $this->app->make(Activity::class), - $this->app->make(PermissionService::class) - ); + return $this->app->make(ActivityService::class); }); $this->app->bind('views', function () { - return new ViewService( - $this->app->make(View::class), - $this->app->make(PermissionService::class) - ); + return $this->app->make(ViewService::class); }); $this->app->bind('setting', function () { - return new SettingService( - $this->app->make(Setting::class), - $this->app->make(Repository::class) - ); + return $this->app->make(SettingService::class); }); $this->app->bind('images', function () { - return new ImageService( - $this->app->make(Image::class), - $this->app->make(ImageManager::class), - $this->app->make(Factory::class), - $this->app->make(Repository::class), - $this->app->make(HttpFetcher::class) - ); + return $this->app->make(ImageService::class); }); } } diff --git a/app/Settings/SettingService.php b/app/Settings/SettingService.php index c9491e3ee..489963aad 100644 --- a/app/Settings/SettingService.php +++ b/app/Settings/SettingService.php @@ -61,9 +61,23 @@ class SettingService */ public function getUser($user, $key, $default = false) { + if ($user->isDefault()) { + return session()->get($key, $default); + } return $this->get($this->userKey($user->id, $key), $default); } + /** + * Get a value for the current logged-in user. + * @param $key + * @param bool $default + * @return bool|string + */ + public function getForCurrentUser($key, $default = false) + { + return $this->getUser(user(), $key, $default); + } + /** * Gets a setting value from the cache or database. * Looks at the system defaults if not cached or in database. @@ -180,6 +194,9 @@ class SettingService */ public function putUser($user, $key, $value) { + if ($user->isDefault()) { + return session()->put($key, $value); + } return $this->put($this->userKey($user->id, $key), $value); } diff --git a/app/helpers.php b/app/helpers.php index d9533645d..3f7b5e1b1 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -43,11 +43,19 @@ function user() * Check if current user is a signed in user. * @return bool */ -function signedInUser() +function signedInUser() : bool { return auth()->user() && !auth()->user()->isDefault(); } +/** + * Check if the current user has general access. + * @return bool + */ +function hasAppAccess() : bool { + return !auth()->guest() || setting('app-public'); +} + /** * Check if the current user has a permission. * If an ownable element is passed in the jointPermissions are checked against diff --git a/package-lock.json b/package-lock.json index e1d1ace43..1a5fef175 100644 --- a/package-lock.json +++ b/package-lock.json @@ -981,12 +981,6 @@ "integrity": "sha1-rCsnk5xUPpXSwG5/f1wnvkqlQ74=", "dev": true }, - "alphanum-sort": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", - "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", - "dev": true - }, "amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", @@ -1176,27 +1170,49 @@ "dev": true }, "autoprefixer": { - "version": "8.6.5", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-8.6.5.tgz", - "integrity": "sha512-PLWJN3Xo/rycNkx+mp8iBDMTm3FeWe4VmYaZDSqL5QQB9sLsQkG5k8n+LNDFnhh9kdq2K+egL/icpctOmDHwig==", + "version": "9.4.7", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.4.7.tgz", + "integrity": "sha512-qS5wW6aXHkm53Y4z73tFGsUhmZu4aMPV9iHXYlF0c/wxjknXNHuj/1cIQb+6YH692DbJGGWcckAXX+VxKvahMA==", "dev": true, "requires": { - "browserslist": "^3.2.8", - "caniuse-lite": "^1.0.30000864", + "browserslist": "^4.4.1", + "caniuse-lite": "^1.0.30000932", "normalize-range": "^0.1.2", "num2fraction": "^1.2.2", - "postcss": "^6.0.23", - "postcss-value-parser": "^3.2.3" + "postcss": "^7.0.14", + "postcss-value-parser": "^3.3.1" }, "dependencies": { "browserslist": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", - "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.4.1.tgz", + "integrity": "sha512-pEBxEXg7JwaakBXjATYw/D1YZh4QUSCX/Mnd/wnqSRPPSi1U39iDhDoKGoBUcraKdxDlrYqJxSI5nNvD+dWP2A==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000844", - "electron-to-chromium": "^1.3.47" + "caniuse-lite": "^1.0.30000929", + "electron-to-chromium": "^1.3.103", + "node-releases": "^1.1.3" + } + }, + "caniuse-lite": { + "version": "1.0.30000934", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000934.tgz", + "integrity": "sha512-o7yfZn0R9N+mWAuksDsdLsb1gu9o//XK0QSU0zSSReKNRsXsFc/n/psxi0YSPNiqlKxImp5h4DHnAPdwYJ8nNA==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.112", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.112.tgz", + "integrity": "sha512-FyVLdiRZnLw2WE5ECtveN0JJ7klyiz/HMfKE1/Rjff3l7pe4vfkYtBlcCqTckvR8E7asjJGh0m9gRPR3Anp/UA==", + "dev": true + }, + "node-releases": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.7.tgz", + "integrity": "sha512-bKdrwaqJUPHqlCzDD7so/R+Nk0jGv9a11ZhLrD9f6i947qGLrGAhU3OxRENa19QQmwzGy/g6zCDEuLGDO8HPvA==", + "dev": true, + "requires": { + "semver": "^5.3.0" } } } @@ -1240,50 +1256,6 @@ } } }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, "babel-loader": { "version": "8.0.4", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.4.tgz", @@ -1570,31 +1542,59 @@ "dev": true }, "cacache": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", - "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.2.tgz", + "integrity": "sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==", "dev": true, "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.1", - "mississippi": "^2.0.0", + "bluebird": "^3.5.3", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", "mkdirp": "^0.5.1", "move-concurrently": "^1.0.1", "promise-inflight": "^1.0.1", "rimraf": "^2.6.2", - "ssri": "^5.2.4", - "unique-filename": "^1.1.0", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", "y18n": "^4.0.0" }, "dependencies": { + "bluebird": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", + "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==", + "dev": true + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true + }, + "yallist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "dev": true } } }, @@ -1639,36 +1639,6 @@ "map-obj": "^1.0.0" } }, - "caniuse-api": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.6.1.tgz", - "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=", - "dev": true, - "requires": { - "browserslist": "^1.3.6", - "caniuse-db": "^1.0.30000529", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - }, - "dependencies": { - "browserslist": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", - "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", - "dev": true, - "requires": { - "caniuse-db": "^1.0.30000639", - "electron-to-chromium": "^1.2.7" - } - } - } - }, - "caniuse-db": { - "version": "1.0.30000904", - "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000904.tgz", - "integrity": "sha512-iZ36AxtEx7ZiCBKhF2qFL8ED6u9zJGPU7Aq6HwZQYUbetBgYkGZfoPHq9z38jahV2kr8BgDYfXvftA35Ng2AaA==", - "dev": true - }, "caniuse-lite": { "version": "1.0.30000904", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000904.tgz", @@ -1734,42 +1704,6 @@ "safe-buffer": "^5.0.1" } }, - "clap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", - "integrity": "sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA==", - "dev": true, - "requires": { - "chalk": "^1.1.3" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", @@ -1820,12 +1754,6 @@ "wrap-ansi": "^2.0.0" } }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, "clone-deep": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-2.0.2.tgz", @@ -1861,15 +1789,6 @@ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", "dev": true }, - "coa": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz", - "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=", - "dev": true, - "requires": { - "q": "^1.1.2" - } - }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -1891,17 +1810,6 @@ "object-visit": "^1.0.0" } }, - "color": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", - "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", - "dev": true, - "requires": { - "clone": "^1.0.2", - "color-convert": "^1.3.0", - "color-string": "^0.3.0" - } - }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -1917,32 +1825,6 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "color-string": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", - "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", - "dev": true, - "requires": { - "color-name": "^1.0.0" - } - }, - "colormin": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz", - "integrity": "sha1-6i90IKcrlogaOKrlnsEkpvcpgTM=", - "dev": true, - "requires": { - "color": "^0.11.0", - "css-color-names": "0.0.4", - "has": "^1.0.1" - } - }, - "colors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", - "dev": true - }, "combined-stream": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", @@ -1953,9 +1835,9 @@ } }, "commander": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", - "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", "dev": true }, "commondir": { @@ -2062,22 +1944,6 @@ "require-from-string": "^2.0.1" }, "dependencies": { - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "js-yaml": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -2156,92 +2022,95 @@ "randomfill": "^1.0.3" } }, - "css-color-names": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", - "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", - "dev": true - }, "css-loader": { - "version": "0.28.11", - "resolved": "http://registry.npmjs.org/css-loader/-/css-loader-0.28.11.tgz", - "integrity": "sha512-wovHgjAx8ZIMGSL8pTys7edA1ClmzxHeY6n/d97gg5odgsxEgKjULPR0viqyC+FWMCL9sfqoC/QCUBo62tLvPg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-2.1.0.tgz", + "integrity": "sha512-MoOu+CStsGrSt5K2OeZ89q3Snf+IkxRfAIt9aAKg4piioTrhtP1iEFPu+OVn3Ohz24FO6L+rw9UJxBILiSBw5Q==", "dev": true, "requires": { - "babel-code-frame": "^6.26.0", - "css-selector-tokenizer": "^0.7.0", - "cssnano": "^3.10.0", - "icss-utils": "^2.1.0", - "loader-utils": "^1.0.2", - "lodash.camelcase": "^4.3.0", - "object-assign": "^4.1.1", - "postcss": "^5.0.6", - "postcss-modules-extract-imports": "^1.2.0", - "postcss-modules-local-by-default": "^1.2.0", - "postcss-modules-scope": "^1.1.0", - "postcss-modules-values": "^1.3.0", + "icss-utils": "^4.0.0", + "loader-utils": "^1.2.1", + "lodash": "^4.17.11", + "postcss": "^7.0.6", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^2.0.3", + "postcss-modules-scope": "^2.0.0", + "postcss-modules-values": "^2.0.0", "postcss-value-parser": "^3.3.0", - "source-list-map": "^2.0.0" + "schema-utils": "^1.0.0" }, "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "ajv": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.8.1.tgz", + "integrity": "sha512-eqxCp82P+JfqL683wwsL73XmFs1eG6qjw+RD3YHx+Jll1r0jNd4dh8QG9NYAeNGA/hnZjeEDgtTskgJULbxpWQ==", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "has-flag": { + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", + "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "schema-utils": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" } } } @@ -2276,7 +2145,7 @@ }, "regjsgen": { "version": "0.2.0", - "resolved": "http://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", "dev": true }, @@ -2297,150 +2166,6 @@ "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=", "dev": true }, - "cssnano": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz", - "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=", - "dev": true, - "requires": { - "autoprefixer": "^6.3.1", - "decamelize": "^1.1.2", - "defined": "^1.0.0", - "has": "^1.0.1", - "object-assign": "^4.0.1", - "postcss": "^5.0.14", - "postcss-calc": "^5.2.0", - "postcss-colormin": "^2.1.8", - "postcss-convert-values": "^2.3.4", - "postcss-discard-comments": "^2.0.4", - "postcss-discard-duplicates": "^2.0.1", - "postcss-discard-empty": "^2.0.1", - "postcss-discard-overridden": "^0.1.1", - "postcss-discard-unused": "^2.2.1", - "postcss-filter-plugins": "^2.0.0", - "postcss-merge-idents": "^2.1.5", - "postcss-merge-longhand": "^2.0.1", - "postcss-merge-rules": "^2.0.3", - "postcss-minify-font-values": "^1.0.2", - "postcss-minify-gradients": "^1.0.1", - "postcss-minify-params": "^1.0.4", - "postcss-minify-selectors": "^2.0.4", - "postcss-normalize-charset": "^1.1.0", - "postcss-normalize-url": "^3.0.7", - "postcss-ordered-values": "^2.1.0", - "postcss-reduce-idents": "^2.2.2", - "postcss-reduce-initial": "^1.0.0", - "postcss-reduce-transforms": "^1.0.3", - "postcss-svgo": "^2.1.1", - "postcss-unique-selectors": "^2.0.2", - "postcss-value-parser": "^3.2.3", - "postcss-zindex": "^2.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "autoprefixer": { - "version": "6.7.7", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", - "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", - "dev": true, - "requires": { - "browserslist": "^1.7.6", - "caniuse-db": "^1.0.30000634", - "normalize-range": "^0.1.2", - "num2fraction": "^1.2.2", - "postcss": "^5.2.16", - "postcss-value-parser": "^3.2.3" - } - }, - "browserslist": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", - "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", - "dev": true, - "requires": { - "caniuse-db": "^1.0.30000639", - "electron-to-chromium": "^1.2.7" - } - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "csso": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/csso/-/csso-2.3.2.tgz", - "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=", - "dev": true, - "requires": { - "clap": "^1.0.9", - "source-map": "^0.5.3" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -2562,12 +2287,6 @@ } } }, - "defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true - }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -2750,9 +2469,9 @@ } }, "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, "esrecurse": { @@ -2876,29 +2595,6 @@ "is-extglob": "^1.0.0" } }, - "extract-text-webpack-plugin": { - "version": "4.0.0-beta.0", - "resolved": "https://registry.npmjs.org/extract-text-webpack-plugin/-/extract-text-webpack-plugin-4.0.0-beta.0.tgz", - "integrity": "sha512-Hypkn9jUTnFr0DpekNam53X47tXn3ucY08BQumv7kdGgeVUBLq3DJHJTi6HNxv4jl9W+Skxjz9+RnK0sJyqqjA==", - "dev": true, - "requires": { - "async": "^2.4.1", - "loader-utils": "^1.1.0", - "schema-utils": "^0.4.5", - "webpack-sources": "^1.1.0" - }, - "dependencies": { - "async": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", - "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", - "dev": true, - "requires": { - "lodash": "^4.14.0" - } - } - } - }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -2995,12 +2691,6 @@ "locate-path": "^2.0.0" } }, - "flatten": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", - "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=", - "dev": true - }, "flush-write-stream": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", @@ -3143,7 +2833,8 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", @@ -3154,7 +2845,8 @@ "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -3271,7 +2963,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -3283,6 +2976,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -3416,7 +3110,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -3428,6 +3123,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -3549,6 +3245,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3915,12 +3612,6 @@ "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", "dev": true }, - "html-comment-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", - "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==", - "dev": true - }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -3945,12 +3636,12 @@ "dev": true }, "icss-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz", - "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.0.0.tgz", + "integrity": "sha512-bA/xGiwWM17qjllIs9X/y0EjsB7e0AV08F3OL8UPsoNkNRibIuu8f1eKTnQ8QO1DteKKTxTUAn+IEWUToIwGOA==", "dev": true, "requires": { - "postcss": "^6.0.1" + "postcss": "^7.0.5" } }, "ieee754": { @@ -4068,12 +3759,6 @@ "repeating": "^2.0.0" } }, - "indexes-of": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", - "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", - "dev": true - }, "indexof": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", @@ -4117,12 +3802,6 @@ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, - "is-absolute-url": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", - "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", - "dev": true - }, "is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", @@ -4270,12 +3949,6 @@ "kind-of": "^3.0.2" } }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true - }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -4320,15 +3993,6 @@ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, - "is-svg": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz", - "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=", - "dev": true, - "requires": { - "html-comment-regex": "^1.1.0" - } - }, "is-symbol": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", @@ -4422,13 +4086,13 @@ "dev": true }, "js-yaml": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz", - "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz", + "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==", "dev": true, "requires": { "argparse": "^1.0.7", - "esprima": "^2.6.0" + "esprima": "^4.0.0" } }, "jsbn": { @@ -4588,12 +4252,6 @@ "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", "dev": true }, - "lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", - "dev": true - }, "lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", @@ -4606,12 +4264,6 @@ "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", "dev": true }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true - }, "lodash.mergewith": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", @@ -4624,12 +4276,6 @@ "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=", "dev": true }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", - "dev": true - }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -4715,12 +4361,6 @@ "resolved": "https://registry.npmjs.org/markdown-it-task-lists/-/markdown-it-task-lists-2.1.1.tgz", "integrity": "sha512-TxFAc76Jnhb2OUu+n3yz9RMu4CwGfaT788br6HhEDlvWfdeJcLUsxk1Hgw2yJio0OXsxv7pyIPmvECY7bMbluA==" }, - "math-expression-evaluator": { - "version": "1.2.17", - "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz", - "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=", - "dev": true - }, "math-random": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", @@ -4856,6 +4496,54 @@ "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true }, + "mini-css-extract-plugin": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.5.0.tgz", + "integrity": "sha512-IuaLjruM0vMKhUUT51fQdQzBYTX49dLj8w68ALEAe2A4iYNpIC4eMac67mt3NzycvjOlf07/kYxJDc0RTl1Wqw==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "schema-utils": "^1.0.0", + "webpack-sources": "^1.1.0" + }, + "dependencies": { + "ajv": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.8.1.tgz", + "integrity": "sha512-eqxCp82P+JfqL683wwsL73XmFs1eG6qjw+RD3YHx+Jll1r0jNd4dh8QG9NYAeNGA/hnZjeEDgtTskgJULbxpWQ==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, "minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -4884,9 +4572,9 @@ "dev": true }, "mississippi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz", - "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", "dev": true, "requires": { "concat-stream": "^1.5.0", @@ -4895,10 +4583,22 @@ "flush-write-stream": "^1.0.0", "from2": "^2.1.0", "parallel-transform": "^1.1.0", - "pump": "^2.0.1", + "pump": "^3.0.0", "pumpify": "^1.3.3", "stream-each": "^1.1.0", "through2": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } } }, "mixin-deep": { @@ -5183,18 +4883,6 @@ "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", "dev": true }, - "normalize-url": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", - "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", - "dev": true, - "requires": { - "object-assign": "^4.0.1", - "prepend-http": "^1.0.0", - "query-string": "^4.1.0", - "sort-keys": "^1.0.0" - } - }, "npm-run-all": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", @@ -5676,657 +5364,45 @@ "dev": true }, "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "postcss-calc": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz", - "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", - "dev": true, - "requires": { - "postcss": "^5.0.2", - "postcss-message-helpers": "^2.0.0", - "reduce-css-calc": "^1.2.6" + "supports-color": "^6.1.0" }, "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "dependencies": { "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-colormin": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-2.2.2.tgz", - "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=", - "dev": true, - "requires": { - "colormin": "^1.0.5", - "postcss": "^5.0.13", - "postcss-value-parser": "^3.2.3" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-convert-values": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz", - "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=", - "dev": true, - "requires": { - "postcss": "^5.0.11", - "postcss-value-parser": "^3.1.2" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-discard-comments": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz", - "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", - "dev": true, - "requires": { - "postcss": "^5.0.14" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-discard-duplicates": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz", - "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=", - "dev": true, - "requires": { - "postcss": "^5.0.4" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-discard-empty": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz", - "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", - "dev": true, - "requires": { - "postcss": "^5.0.14" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-discard-overridden": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz", - "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", - "dev": true, - "requires": { - "postcss": "^5.0.16" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-discard-unused": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz", - "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", - "dev": true, - "requires": { - "postcss": "^5.0.14", - "uniqs": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-filter-plugins": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.3.tgz", - "integrity": "sha512-T53GVFsdinJhgwm7rg1BzbeBRomOg9y5MBVhGcsV0CxurUdVj1UlPdKtn7aqYA/c/QVkzKMjq2bSV5dKG5+AwQ==", - "dev": true, - "requires": { - "postcss": "^5.0.4" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" + "has-flag": "^3.0.0" } } } @@ -6342,1173 +5418,92 @@ } }, "postcss-loader": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-2.1.6.tgz", - "integrity": "sha512-hgiWSc13xVQAq25cVw80CH0l49ZKlAnU1hKPOdRrNj89bokRr/bZF2nT+hebPPF9c9xs8c3gw3Fr2nxtmXYnNg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz", + "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==", "dev": true, "requires": { "loader-utils": "^1.1.0", - "postcss": "^6.0.0", + "postcss": "^7.0.0", "postcss-load-config": "^2.0.0", - "schema-utils": "^0.4.0" - } - }, - "postcss-merge-idents": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz", - "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", - "dev": true, - "requires": { - "has": "^1.0.1", - "postcss": "^5.0.10", - "postcss-value-parser": "^3.1.1" + "schema-utils": "^1.0.0" }, "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "ajv": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.8.1.tgz", + "integrity": "sha512-eqxCp82P+JfqL683wwsL73XmFs1eG6qjw+RD3YHx+Jll1r0jNd4dh8QG9NYAeNGA/hnZjeEDgtTskgJULbxpWQ==", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "has-flag": { + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "schema-utils": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-merge-longhand": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz", - "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=", - "dev": true, - "requires": { - "postcss": "^5.0.4" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-merge-rules": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz", - "integrity": "sha1-0d9d+qexrMO+VT8OnhDofGG19yE=", - "dev": true, - "requires": { - "browserslist": "^1.5.2", - "caniuse-api": "^1.5.2", - "postcss": "^5.0.4", - "postcss-selector-parser": "^2.2.2", - "vendors": "^1.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "browserslist": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", - "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", - "dev": true, - "requires": { - "caniuse-db": "^1.0.30000639", - "electron-to-chromium": "^1.2.7" - } - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-message-helpers": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz", - "integrity": "sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4=", - "dev": true - }, - "postcss-minify-font-values": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz", - "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=", - "dev": true, - "requires": { - "object-assign": "^4.0.1", - "postcss": "^5.0.4", - "postcss-value-parser": "^3.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-minify-gradients": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz", - "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", - "dev": true, - "requires": { - "postcss": "^5.0.12", - "postcss-value-parser": "^3.3.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-minify-params": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz", - "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=", - "dev": true, - "requires": { - "alphanum-sort": "^1.0.1", - "postcss": "^5.0.2", - "postcss-value-parser": "^3.0.2", - "uniqs": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-minify-selectors": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz", - "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=", - "dev": true, - "requires": { - "alphanum-sort": "^1.0.2", - "has": "^1.0.1", - "postcss": "^5.0.14", - "postcss-selector-parser": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" } } } }, "postcss-modules-extract-imports": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.1.tgz", - "integrity": "sha512-6jt9XZwUhwmRUhb/CkyJY020PYaPJsCyt3UjbaWo6XEbH/94Hmv6MP7fG2C5NDU/BcHzyGYxNtHvM+LTf9HrYw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", "dev": true, "requires": { - "postcss": "^6.0.1" + "postcss": "^7.0.5" } }, "postcss-modules-local-by-default": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", - "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-2.0.4.tgz", + "integrity": "sha512-WvuSaTKXUqYJbnT7R3YrsNrHv/C5vRfr5VglS4bFOk0MYT4CLBfc/xgExA+x2RftlYgiBDvWmVs191Xv8S8gZQ==", "dev": true, "requires": { "css-selector-tokenizer": "^0.7.0", - "postcss": "^6.0.1" + "postcss": "^7.0.6", + "postcss-value-parser": "^3.3.1" } }, "postcss-modules-scope": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", - "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.0.1.tgz", + "integrity": "sha512-7+6k9c3/AuZ5c596LJx9n923A/j3nF3ormewYBF1RrIQvjvjXe1xE8V8A1KFyFwXbvnshT6FBZFX0k/F1igneg==", "dev": true, "requires": { "css-selector-tokenizer": "^0.7.0", - "postcss": "^6.0.1" + "postcss": "^7.0.6" } }, "postcss-modules-values": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", - "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-2.0.0.tgz", + "integrity": "sha512-Ki7JZa7ff1N3EIMlPnGTZfUMe69FFwiQPnVSXC9mnn3jozCRBYIxiZd44yJOV2AmabOo4qFf8s0dC/+lweG7+w==", "dev": true, "requires": { "icss-replace-symbols": "^1.1.0", - "postcss": "^6.0.1" - } - }, - "postcss-normalize-charset": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz", - "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", - "dev": true, - "requires": { - "postcss": "^5.0.5" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-normalize-url": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz", - "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=", - "dev": true, - "requires": { - "is-absolute-url": "^2.0.0", - "normalize-url": "^1.4.0", - "postcss": "^5.0.14", - "postcss-value-parser": "^3.2.3" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-ordered-values": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz", - "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=", - "dev": true, - "requires": { - "postcss": "^5.0.4", - "postcss-value-parser": "^3.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-reduce-idents": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz", - "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", - "dev": true, - "requires": { - "postcss": "^5.0.4", - "postcss-value-parser": "^3.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-reduce-initial": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz", - "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", - "dev": true, - "requires": { - "postcss": "^5.0.4" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-reduce-transforms": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz", - "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", - "dev": true, - "requires": { - "has": "^1.0.1", - "postcss": "^5.0.8", - "postcss-value-parser": "^3.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-selector-parser": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", - "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", - "dev": true, - "requires": { - "flatten": "^1.0.2", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - }, - "postcss-svgo": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz", - "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=", - "dev": true, - "requires": { - "is-svg": "^2.0.0", - "postcss": "^5.0.14", - "postcss-value-parser": "^3.2.3", - "svgo": "^0.7.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-unique-selectors": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz", - "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=", - "dev": true, - "requires": { - "alphanum-sort": "^1.0.1", - "postcss": "^5.0.4", - "uniqs": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } + "postcss": "^7.0.6" } }, "postcss-value-parser": { @@ -7517,85 +5512,6 @@ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", "dev": true }, - "postcss-zindex": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz", - "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", - "dev": true, - "requires": { - "has": "^1.0.1", - "postcss": "^5.0.4", - "uniqs": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true - }, "preserve": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", @@ -7693,28 +5609,12 @@ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "dev": true }, - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", - "dev": true - }, "qs": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true }, - "query-string": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", - "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", - "dev": true, - "requires": { - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" - } - }, "querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", @@ -7825,42 +5725,6 @@ "strip-indent": "^1.0.1" } }, - "reduce-css-calc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", - "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", - "dev": true, - "requires": { - "balanced-match": "^0.4.2", - "math-expression-evaluator": "^1.2.14", - "reduce-function-call": "^1.0.1" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - } - } - }, - "reduce-function-call": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.2.tgz", - "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=", - "dev": true, - "requires": { - "balanced-match": "^0.4.2" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - } - } - }, "regenerate": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", @@ -8139,12 +6003,6 @@ "semver": "^5.5.0" } }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, "schema-utils": { "version": "0.4.5", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz", @@ -8432,15 +6290,6 @@ "kind-of": "^3.2.0" } }, - "sort-keys": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", - "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", - "dev": true, - "requires": { - "is-plain-obj": "^1.0.0" - } - }, "sortablejs": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.7.0.tgz", @@ -8551,12 +6400,12 @@ } }, "ssri": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", - "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", "dev": true, "requires": { - "safe-buffer": "^5.1.1" + "figgy-pudding": "^3.5.1" } }, "static-extend": { @@ -8660,12 +6509,6 @@ "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", "dev": true }, - "strict-uri-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", - "dev": true - }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -8731,13 +6574,50 @@ } }, "style-loader": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.21.0.tgz", - "integrity": "sha512-T+UNsAcl3Yg+BsPKs1vd22Fr8sVT+CJMtzqc6LEw9bbJZb43lm9GoeIfUcDEefBSWC0BhYbcdupV1GtI4DGzxg==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.1.tgz", + "integrity": "sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg==", "dev": true, "requires": { "loader-utils": "^1.1.0", - "schema-utils": "^0.4.5" + "schema-utils": "^1.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.8.1.tgz", + "integrity": "sha512-eqxCp82P+JfqL683wwsL73XmFs1eG6qjw+RD3YHx+Jll1r0jNd4dh8QG9NYAeNGA/hnZjeEDgtTskgJULbxpWQ==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } } }, "supports-color": { @@ -8749,21 +6629,6 @@ "has-flag": "^3.0.0" } }, - "svgo": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.2.tgz", - "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=", - "dev": true, - "requires": { - "coa": "~1.0.1", - "colors": "~1.1.2", - "csso": "~2.3.1", - "js-yaml": "~3.7.0", - "mkdirp": "~0.5.1", - "sax": "~1.2.1", - "whet.extend": "~0.9.9" - } - }, "tapable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.0.tgz", @@ -9128,30 +6993,130 @@ "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.5.tgz", "integrity": "sha512-JoLI4g5zv5qNyT09f4YAvEZIIV1oOjqnewYg5D38dkQljIzpPT296dbIGvKro3digYI1bkb7W6EP1y4uDlmzLg==" }, - "uglify-es": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", - "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", + "uglify-js": { + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", + "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", "dev": true, "requires": { - "commander": "~2.13.0", + "commander": "~2.17.1", "source-map": "~0.6.1" } }, "uglifyjs-webpack-plugin": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.3.0.tgz", - "integrity": "sha512-ovHIch0AMlxjD/97j9AYovZxG5wnHOPkL7T1GKochBADp/Zwc44pEWNqpKl1Loupp1WhFg7SlYmHZRUfdAacgw==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-2.1.1.tgz", + "integrity": "sha512-TQEcyMNkObX/H+FfcKjiDgs5RcXX8vW2UUUrDTOfQgg3lrafztfeM5WAwXo+AzqozJK6NP9w98xNpG/dutzSsg==", "dev": true, "requires": { - "cacache": "^10.0.4", - "find-cache-dir": "^1.0.0", - "schema-utils": "^0.4.5", + "cacache": "^11.2.0", + "find-cache-dir": "^2.0.0", + "schema-utils": "^1.0.0", "serialize-javascript": "^1.4.0", "source-map": "^0.6.1", - "uglify-es": "^3.3.4", + "uglify-js": "^3.0.0", "webpack-sources": "^1.1.0", "worker-farm": "^1.5.2" + }, + "dependencies": { + "ajv": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.8.1.tgz", + "integrity": "sha512-eqxCp82P+JfqL683wwsL73XmFs1eG6qjw+RD3YHx+Jll1r0jNd4dh8QG9NYAeNGA/hnZjeEDgtTskgJULbxpWQ==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "find-cache-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.0.0.tgz", + "integrity": "sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } } }, "ultron": { @@ -9223,18 +7188,6 @@ } } }, - "uniq": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", - "dev": true - }, - "uniqs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", - "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", - "dev": true - }, "unique-filename": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", @@ -9399,12 +7352,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "vendors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.2.tgz", - "integrity": "sha512-w/hry/368nO21AN9QljsaIhb9ZiZtZARoVH5f3CsFbawdLdayCgKRPup7CggujvySMxx0I91NOyxdVENohprLQ==", - "dev": true - }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", @@ -10356,12 +8303,6 @@ "source-map": "~0.6.1" } }, - "whet.extend": { - "version": "0.9.9", - "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", - "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=", - "dev": true - }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", diff --git a/package.json b/package.json index dc90689d3..1cbfdb3e9 100644 --- a/package.json +++ b/package.json @@ -13,17 +13,17 @@ "@babel/core": "^7.1.6", "@babel/polyfill": "^7.0.0", "@babel/preset-env": "^7.1.6", - "autoprefixer": "^8.6.5", + "autoprefixer": "^9.4.7", "babel-loader": "^8.0.4", - "css-loader": "^0.28.11", - "extract-text-webpack-plugin": "^4.0.0-beta.0", + "css-loader": "^2.1.0", "livereload": "^0.7.0", + "mini-css-extract-plugin": "^0.5.0", "node-sass": "^4.10.0", "npm-run-all": "^4.1.5", - "postcss-loader": "^2.1.6", + "postcss-loader": "^3.0.0", "sass-loader": "^7.1.0", - "style-loader": "^0.21.0", - "uglifyjs-webpack-plugin": "^1.3.0", + "style-loader": "^0.23.1", + "uglifyjs-webpack-plugin": "^2.1.1", "webpack": "^4.26.1", "webpack-cli": "^3.1.2" }, diff --git a/resources/assets/icons/add.svg b/resources/assets/icons/add.svg index 75e3753dc..edd367b2d 100644 --- a/resources/assets/icons/add.svg +++ b/resources/assets/icons/add.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/resources/assets/icons/books.svg b/resources/assets/icons/books.svg new file mode 100644 index 000000000..240201fb3 --- /dev/null +++ b/resources/assets/icons/books.svg @@ -0,0 +1,71 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/resources/assets/icons/bookshelf.svg b/resources/assets/icons/bookshelf.svg index 03da68f96..f1e45eaf9 100644 --- a/resources/assets/icons/bookshelf.svg +++ b/resources/assets/icons/bookshelf.svg @@ -1,2 +1 @@ - - + \ No newline at end of file diff --git a/resources/assets/icons/check.svg b/resources/assets/icons/check.svg new file mode 100644 index 000000000..93607ef7e --- /dev/null +++ b/resources/assets/icons/check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/assets/icons/chevron-right.svg b/resources/assets/icons/chevron-right.svg new file mode 100644 index 000000000..96540b9ea --- /dev/null +++ b/resources/assets/icons/chevron-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/assets/icons/sort-down.svg b/resources/assets/icons/sort-down.svg new file mode 100644 index 000000000..61fa6c7f7 --- /dev/null +++ b/resources/assets/icons/sort-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/assets/icons/sort-up.svg b/resources/assets/icons/sort-up.svg new file mode 100644 index 000000000..985cc626f --- /dev/null +++ b/resources/assets/icons/sort-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/assets/js/components/breadcrumb-listing.js b/resources/assets/js/components/breadcrumb-listing.js new file mode 100644 index 000000000..1e2fe9ea4 --- /dev/null +++ b/resources/assets/js/components/breadcrumb-listing.js @@ -0,0 +1,58 @@ + + +class BreadcrumbListing { + + constructor(elem) { + this.elem = elem; + this.searchInput = elem.querySelector('input'); + this.loadingElem = elem.querySelector('.loading-container'); + this.entityListElem = elem.querySelector('.breadcrumb-listing-entity-list'); + this.toggleElem = elem.querySelector('[dropdown-toggle]'); + + // this.loadingElem.style.display = 'none'; + const entityDescriptor = elem.getAttribute('breadcrumb-listing').split(':'); + this.entityType = entityDescriptor[0]; + this.entityId = Number(entityDescriptor[1]); + + this.toggleElem.addEventListener('click', this.onShow.bind(this)); + this.searchInput.addEventListener('input', this.onSearch.bind(this)); + } + + onShow() { + this.loadEntityView(); + } + + onSearch() { + const input = this.searchInput.value.toLowerCase().trim(); + const listItems = this.entityListElem.querySelectorAll('.entity-list-item'); + for (let listItem of listItems) { + const match = !input || listItem.textContent.toLowerCase().includes(input); + listItem.style.display = match ? 'flex' : 'none'; + } + } + + loadEntityView() { + this.toggleLoading(true); + + const params = { + 'entity_id': this.entityId, + 'entity_type': this.entityType, + }; + + window.$http.get('/search/entity/siblings', {params}).then(resp => { + this.entityListElem.innerHTML = resp.data; + }).catch(err => { + console.error(err); + }).then(() => { + this.toggleLoading(false); + this.onSearch(); + }); + } + + toggleLoading(show = false) { + this.loadingElem.style.display = show ? 'block' : 'none'; + } + +} + +export default BreadcrumbListing; \ No newline at end of file diff --git a/resources/assets/js/components/dropdown.js b/resources/assets/js/components/dropdown.js index dda42e868..400ddb576 100644 --- a/resources/assets/js/components/dropdown.js +++ b/resources/assets/js/components/dropdown.js @@ -6,7 +6,7 @@ class DropDown { constructor(elem) { this.container = elem; - this.menu = elem.querySelector('ul'); + this.menu = elem.querySelector('ul, [dropdown-menu]'); this.toggle = elem.querySelector('[dropdown-toggle]'); this.setupListeners(); } diff --git a/resources/assets/js/components/entity-selector.js b/resources/assets/js/components/entity-selector.js index 461bf7321..58879a20c 100644 --- a/resources/assets/js/components/entity-selector.js +++ b/resources/assets/js/components/entity-selector.js @@ -5,15 +5,17 @@ class EntitySelector { this.elem = elem; this.search = ''; this.lastClick = 0; + this.selectedItemData = null; - let entityTypes = elem.hasAttribute('entity-types') ? elem.getAttribute('entity-types') : 'page,book,chapter'; - let entityPermission = elem.hasAttribute('entity-permission') ? elem.getAttribute('entity-permission') : 'view'; + const entityTypes = elem.hasAttribute('entity-types') ? elem.getAttribute('entity-types') : 'page,book,chapter'; + const entityPermission = elem.hasAttribute('entity-permission') ? elem.getAttribute('entity-permission') : 'view'; this.searchUrl = window.baseUrl(`/ajax/search/entities?types=${encodeURIComponent(entityTypes)}&permission=${encodeURIComponent(entityPermission)}`); this.input = elem.querySelector('[entity-selector-input]'); this.searchInput = elem.querySelector('[entity-selector-search]'); this.loading = elem.querySelector('[entity-selector-loading]'); this.resultsContainer = elem.querySelector('[entity-selector-results]'); + this.addButton = elem.querySelector('[entity-selector-add-button]'); this.elem.addEventListener('click', this.onClick.bind(this)); @@ -26,10 +28,20 @@ class EntitySelector { this.searchEntities(this.searchInput.value); }, 200); }); + this.searchInput.addEventListener('keydown', event => { if (event.keyCode === 13) event.preventDefault(); }); + if (this.addButton) { + this.addButton.addEventListener('click', event => { + if (this.selectedItemData) { + this.confirmSelection(this.selectedItemData); + this.unselectAll(); + } + }); + } + this.showLoading(); this.initialLoad(); } @@ -53,7 +65,7 @@ class EntitySelector { searchEntities(searchTerm) { this.input.value = ''; - let url = this.searchUrl + `&term=${encodeURIComponent(searchTerm)}`; + let url = `${this.searchUrl}&term=${encodeURIComponent(searchTerm)}`; window.$http.get(url).then(resp => { this.resultsContainer.innerHTML = resp.data; this.hideLoading(); @@ -68,49 +80,54 @@ class EntitySelector { } onClick(event) { - let t = event.target; - - if (t.matches('.entity-list-item *')) { + const listItem = event.target.closest('[data-entity-type]'); + if (listItem) { event.preventDefault(); event.stopPropagation(); - let item = t.closest('[data-entity-type]'); - this.selectItem(item); - } else if (t.matches('[data-entity-type]')) { - this.selectItem(t) + this.selectItem(listItem); } - } selectItem(item) { - let isDblClick = this.isDoubleClick(); - let type = item.getAttribute('data-entity-type'); - let id = item.getAttribute('data-entity-id'); - let isSelected = !item.classList.contains('selected') || isDblClick; + const isDblClick = this.isDoubleClick(); + const type = item.getAttribute('data-entity-type'); + const id = item.getAttribute('data-entity-id'); + const isSelected = (!item.classList.contains('selected') || isDblClick); this.unselectAll(); this.input.value = isSelected ? `${type}:${id}` : ''; - if (!isSelected) window.$events.emit('entity-select-change', null); + const link = item.getAttribute('href'); + const name = item.querySelector('.entity-list-item-name').textContent; + const data = {id: Number(id), name: name, link: link}; + if (isSelected) { item.classList.add('selected'); - item.classList.add('primary-background'); + this.selectedItemData = data; + } else { + window.$events.emit('entity-select-change', null) } + if (!isDblClick && !isSelected) return; - let link = item.querySelector('.entity-list-item-link').getAttribute('href'); - let name = item.querySelector('.entity-list-item-name').textContent; - let data = {id: Number(id), name: name, link: link}; + if (isDblClick) { + this.confirmSelection(data); + } + if (isSelected) { + window.$events.emit('entity-select-change', data) + } + } - if (isDblClick) window.$events.emit('entity-select-confirm', data); - if (isSelected) window.$events.emit('entity-select-change', data); + confirmSelection(data) { + window.$events.emit('entity-select-confirm', data); } unselectAll() { let selected = this.elem.querySelectorAll('.selected'); - for (let i = 0, len = selected.length; i < len; i++) { - selected[i].classList.remove('selected'); - selected[i].classList.remove('primary-background'); + for (let selectedElem of selected) { + selectedElem.classList.remove('selected', 'primary-background'); } + this.selectedItemData = null; } } diff --git a/resources/assets/js/components/expand-toggle.js b/resources/assets/js/components/expand-toggle.js index 6f317db62..a6a389818 100644 --- a/resources/assets/js/components/expand-toggle.js +++ b/resources/assets/js/components/expand-toggle.js @@ -3,8 +3,13 @@ class ExpandToggle { constructor(elem) { this.elem = elem; - this.isOpen = false; + + // Component state + this.isOpen = elem.getAttribute('expand-toggle-is-open') === 'yes'; + this.updateEndpoint = elem.getAttribute('expand-toggle-update-endpoint'); this.selector = elem.getAttribute('expand-toggle'); + + // Listener setup elem.addEventListener('click', this.click.bind(this)); } @@ -53,11 +58,20 @@ class ExpandToggle { click(event) { event.preventDefault(); - let matchingElems = document.querySelectorAll(this.selector); - for (let i = 0, len = matchingElems.length; i < len; i++) { - this.isOpen ? this.close(matchingElems[i]) : this.open(matchingElems[i]); + + const matchingElems = document.querySelectorAll(this.selector); + for (let match of matchingElems) { + this.isOpen ? this.close(match) : this.open(match); } + this.isOpen = !this.isOpen; + this.updateSystemAjax(this.isOpen); + } + + updateSystemAjax(isOpen) { + window.$http.patch(this.updateEndpoint, { + expand: isOpen ? 'true' : 'false' + }); } } diff --git a/resources/assets/js/components/header-mobile-toggle.js b/resources/assets/js/components/header-mobile-toggle.js new file mode 100644 index 000000000..eccd4b8f0 --- /dev/null +++ b/resources/assets/js/components/header-mobile-toggle.js @@ -0,0 +1,31 @@ + +class HeaderMobileToggle { + + constructor(elem) { + this.elem = elem; + this.toggleButton = elem.querySelector('.mobile-menu-toggle'); + this.menu = elem.querySelector('.header-links'); + this.open = false; + + this.toggleButton.addEventListener('click', this.onToggle.bind(this)); + this.onWindowClick = this.onWindowClick.bind(this); + } + + onToggle(event) { + this.open = !this.open; + this.menu.classList.toggle('show', this.open); + if (this.open) { + window.addEventListener('click', this.onWindowClick) + } else { + window.removeEventListener('click', this.onWindowClick) + } + event.stopPropagation(); + } + + onWindowClick(event) { + this.onToggle(event); + } + +} + +module.exports = HeaderMobileToggle; \ No newline at end of file diff --git a/resources/assets/js/components/index.js b/resources/assets/js/components/index.js index bf6fbf619..355b96473 100644 --- a/resources/assets/js/components/index.js +++ b/resources/assets/js/components/index.js @@ -18,7 +18,11 @@ import toggleSwitch from "./toggle-switch"; import pageDisplay from "./page-display"; import shelfSort from "./shelf-sort"; import homepageControl from "./homepage-control"; - +import headerMobileToggle from "./header-mobile-toggle"; +import listSortControl from "./list-sort-control"; +import triLayout from "./tri-layout"; +import breadcrumbListing from "./breadcrumb-listing"; +import permissionsTable from "./permissions-table"; const componentMapping = { 'dropdown': dropdown, @@ -41,6 +45,11 @@ const componentMapping = { 'page-display': pageDisplay, 'shelf-sort': shelfSort, 'homepage-control': homepageControl, + 'header-mobile-toggle': headerMobileToggle, + 'list-sort-control': listSortControl, + 'tri-layout': triLayout, + 'breadcrumb-listing': breadcrumbListing, + 'permissions-table': permissionsTable, }; window.components = {}; @@ -79,4 +88,4 @@ function initAll(parentElement) { window.components.init = initAll; -export default initAll; \ No newline at end of file +export default initAll; diff --git a/resources/assets/js/components/list-sort-control.js b/resources/assets/js/components/list-sort-control.js new file mode 100644 index 000000000..d463ed0b7 --- /dev/null +++ b/resources/assets/js/components/list-sort-control.js @@ -0,0 +1,42 @@ +/** + * ListSortControl + * Manages the logic for the control which provides list sorting options. + */ +class ListSortControl { + + constructor(elem) { + this.elem = elem; + + this.sortInput = elem.querySelector('[name="sort"]'); + this.orderInput = elem.querySelector('[name="order"]'); + this.form = elem.querySelector('form'); + + this.elem.addEventListener('click', event => { + if (event.target.closest('[data-sort-value]') !== null) { + this.sortOptionClick(event); + } + if (event.target.closest('[data-sort-dir]') !== null) { + this.sortDirectionClick(event); + } + }) + + } + + sortOptionClick(event) { + const sortOption = event.target.closest('[data-sort-value]'); + this.sortInput.value = sortOption.getAttribute('data-sort-value'); + event.preventDefault(); + this.form.submit(); + } + + sortDirectionClick(event) { + const currentDir = this.orderInput.value; + const newDir = (currentDir === 'asc') ? 'desc' : 'asc'; + this.orderInput.value = newDir; + event.preventDefault(); + this.form.submit(); + } + +} + +export default ListSortControl; \ No newline at end of file diff --git a/resources/assets/js/components/markdown-editor.js b/resources/assets/js/components/markdown-editor.js index b8e2bc040..96cc1e6d1 100644 --- a/resources/assets/js/components/markdown-editor.js +++ b/resources/assets/js/components/markdown-editor.js @@ -71,6 +71,19 @@ class MarkdownEditor { if (action === 'insertDrawing') this.actionStartDrawing(); }); + // Mobile section toggling + this.elem.addEventListener('click', event => { + const toolbarLabel = event.target.closest('.editor-toolbar-label'); + if (!toolbarLabel) return; + + const currentActiveSections = this.elem.querySelectorAll('.markdown-editor-wrap'); + for (let activeElem of currentActiveSections) { + activeElem.classList.remove('active'); + } + + toolbarLabel.closest('.markdown-editor-wrap').classList.add('active'); + }); + window.$events.listen('editor-markdown-update', value => { this.cm.setValue(value); this.updateAndRender(); diff --git a/resources/assets/js/components/overlay.js b/resources/assets/js/components/overlay.js index 2dbf4eb9a..1ba5efcea 100644 --- a/resources/assets/js/components/overlay.js +++ b/resources/assets/js/components/overlay.js @@ -6,7 +6,7 @@ class Overlay { elem.addEventListener('click', event => { if (event.target === elem) return this.hide(); }); - let closeButtons = elem.querySelectorAll('.overlay-close'); + let closeButtons = elem.querySelectorAll('.popup-header-close'); for (let i=0; i < closeButtons.length; i++) { closeButtons[i].addEventListener('click', this.hide.bind(this)); } diff --git a/resources/assets/js/components/page-comments.js b/resources/assets/js/components/page-comments.js index c86b90d2c..975ff5a82 100644 --- a/resources/assets/js/components/page-comments.js +++ b/resources/assets/js/components/page-comments.js @@ -54,7 +54,7 @@ class PageComments { commentElem.querySelector('[comment-edit-container]').style.display = 'block'; let textArea = commentElem.querySelector('[comment-edit-container] textarea'); let lineCount = textArea.value.split('\n').length; - textArea.style.height = (lineCount * 20) + 'px'; + textArea.style.height = ((lineCount * 20) + 40) + 'px'; this.editingComment = commentElem; } @@ -88,6 +88,7 @@ class PageComments { commentElem.parentNode.removeChild(commentElem); window.$events.emit('success', window.trans('entities.comment_deleted_success')); this.updateCount(); + this.hideForm(); }); } @@ -129,7 +130,7 @@ class PageComments { showForm() { this.formContainer.style.display = 'block'; this.formContainer.parentNode.style.display = 'block'; - this.elem.querySelector('[comment-add-button]').style.display = 'none'; + this.elem.querySelector('[comment-add-button-container]').style.display = 'none'; this.formInput.focus(); window.scrollToElement(this.formInput); } @@ -137,7 +138,18 @@ class PageComments { hideForm() { this.formContainer.style.display = 'none'; this.formContainer.parentNode.style.display = 'none'; - this.elem.querySelector('[comment-add-button]').style.display = 'block'; + const addButtonContainer = this.elem.querySelector('[comment-add-button-container]'); + if (this.getCommentCount() > 0) { + this.elem.appendChild(addButtonContainer) + } else { + const countBar = this.elem.querySelector('[comment-count-bar]'); + countBar.appendChild(addButtonContainer); + } + addButtonContainer.style.display = 'block'; + } + + getCommentCount() { + return this.elem.querySelectorAll('.comment-box[comment]').length; } setReply(commentElem) { diff --git a/resources/assets/js/components/page-display.js b/resources/assets/js/components/page-display.js index bca641cb6..1aeeaf248 100644 --- a/resources/assets/js/components/page-display.js +++ b/resources/assets/js/components/page-display.js @@ -208,8 +208,8 @@ class PageDisplay { let pageNavObserver = new IntersectionObserver(headingVisibilityChange, intersectOpts); // observe each heading - for (let i = 0; i !== headings.length; ++i) { - pageNavObserver.observe(headings[i]); + for (let heading of headings) { + pageNavObserver.observe(heading); } } @@ -221,14 +221,9 @@ class PageDisplay { } function toggleAnchorHighlighting(elementId, shouldHighlight) { - let anchorsToHighlight = pageNav.querySelectorAll('a[href="#' + elementId + '"]'); - for (let i = 0; i < anchorsToHighlight.length; i++) { - // Change below to use classList.toggle when IE support is dropped. - if (shouldHighlight) { - anchorsToHighlight[i].classList.add('current-heading'); - } else { - anchorsToHighlight[i].classList.remove('current-heading'); - } + const anchorsToHighlight = pageNav.querySelectorAll('a[href="#' + elementId + '"]'); + for (let anchor of anchorsToHighlight) { + anchor.closest('li').classList.toggle('current-heading', shouldHighlight); } } } diff --git a/resources/assets/js/components/permissions-table.js b/resources/assets/js/components/permissions-table.js new file mode 100644 index 000000000..baad75258 --- /dev/null +++ b/resources/assets/js/components/permissions-table.js @@ -0,0 +1,66 @@ + +class PermissionsTable { + + constructor(elem) { + this.container = elem; + + // Handle toggle all event + const toggleAll = elem.querySelector('[permissions-table-toggle-all]'); + toggleAll.addEventListener('click', this.toggleAllClick.bind(this)); + + // Handle toggle row event + const toggleRowElems = elem.querySelectorAll('[permissions-table-toggle-all-in-row]'); + for (let toggleRowElem of toggleRowElems) { + toggleRowElem.addEventListener('click', this.toggleRowClick.bind(this)); + } + + // Handle toggle column event + const toggleColumnElems = elem.querySelectorAll('[permissions-table-toggle-all-in-column]'); + for (let toggleColElem of toggleColumnElems) { + toggleColElem.addEventListener('click', this.toggleColumnClick.bind(this)); + } + } + + toggleAllClick(event) { + event.preventDefault(); + this.toggleAllInElement(this.container); + } + + toggleRowClick(event) { + event.preventDefault(); + this.toggleAllInElement(event.target.closest('tr')); + } + + toggleColumnClick(event) { + event.preventDefault(); + + const tableCell = event.target.closest('th,td'); + const colIndex = Array.from(tableCell.parentElement.children).indexOf(tableCell); + const tableRows = tableCell.closest('table').querySelectorAll('tr'); + const inputsToToggle = []; + + for (let row of tableRows) { + const targetCell = row.children[colIndex]; + if (targetCell) { + inputsToToggle.push(...targetCell.querySelectorAll('input[type=checkbox]')); + } + } + this.toggleAllInputs(inputsToToggle); + } + + toggleAllInElement(domElem) { + const inputsToToggle = domElem.querySelectorAll('input[type=checkbox]'); + this.toggleAllInputs(inputsToToggle); + } + + toggleAllInputs(inputsToToggle) { + const currentState = inputsToToggle.length > 0 ? inputsToToggle[0].checked : false; + for (let checkbox of inputsToToggle) { + checkbox.checked = !currentState; + checkbox.dispatchEvent(new Event('change')); + } + } + +} + +export default PermissionsTable; \ No newline at end of file diff --git a/resources/assets/js/components/toggle-switch.js b/resources/assets/js/components/toggle-switch.js index 957a41642..3be67d5dc 100644 --- a/resources/assets/js/components/toggle-switch.js +++ b/resources/assets/js/components/toggle-switch.js @@ -3,15 +3,15 @@ class ToggleSwitch { constructor(elem) { this.elem = elem; - this.input = elem.querySelector('input'); + this.input = elem.querySelector('input[type=hidden]'); + this.checkbox = elem.querySelector('input[type=checkbox]'); - this.elem.onclick = this.onClick.bind(this); + this.checkbox.addEventListener('change', this.onClick.bind(this)); } onClick(event) { - let checked = this.input.value !== 'true'; + let checked = this.checkbox.checked; this.input.value = checked ? 'true' : 'false'; - checked ? this.elem.classList.add('active') : this.elem.classList.remove('active'); } } diff --git a/resources/assets/js/components/tri-layout.js b/resources/assets/js/components/tri-layout.js new file mode 100644 index 000000000..0ae7df976 --- /dev/null +++ b/resources/assets/js/components/tri-layout.js @@ -0,0 +1,95 @@ + +class TriLayout { + + constructor(elem) { + this.elem = elem; + + this.lastLayoutType = 'none'; + this.onDestroy = null; + this.scrollCache = { + 'content': 0, + 'info': 0, + }; + this.lastTabShown = 'content'; + + // Bind any listeners + this.mobileTabClick = this.mobileTabClick.bind(this); + + // Watch layout changes + this.updateLayout(); + window.addEventListener('resize', event => { + this.updateLayout(); + }, {passive: true}); + } + + updateLayout() { + let newLayout = 'tablet'; + if (window.innerWidth <= 1000) newLayout = 'mobile'; + if (window.innerWidth >= 1400) newLayout = 'desktop'; + if (newLayout === this.lastLayoutType) return; + + if (this.onDestroy) { + this.onDestroy(); + this.onDestroy = null; + } + + if (newLayout === 'desktop') { + this.setupDesktop(); + } else if (newLayout === 'mobile') { + this.setupMobile(); + } + + this.lastLayoutType = newLayout; + } + + setupMobile() { + const layoutTabs = document.querySelectorAll('[tri-layout-mobile-tab]'); + for (let tab of layoutTabs) { + tab.addEventListener('click', this.mobileTabClick); + } + + this.onDestroy = () => { + for (let tab of layoutTabs) { + tab.removeEventListener('click', this.mobileTabClick); + } + } + } + + setupDesktop() { + // + } + + + /** + * Action to run when the mobile info toggle bar is clicked/tapped + * @param event + */ + mobileTabClick(event) { + const tab = event.target.getAttribute('tri-layout-mobile-tab'); + this.scrollCache[this.lastTabShown] = document.documentElement.scrollTop; + + // Set tab status + const activeTabs = document.querySelectorAll('.tri-layout-mobile-tab.active'); + for (let tab of activeTabs) { + tab.classList.remove('active'); + } + event.target.classList.add('active'); + + // Toggle section + const showInfo = (tab === 'info'); + this.elem.classList.toggle('show-info', showInfo); + + // Set the scroll position from cache + const pageHeader = document.querySelector('header'); + const defaultScrollTop = pageHeader.getBoundingClientRect().bottom; + document.documentElement.scrollTop = this.scrollCache[tab] || defaultScrollTop; + setTimeout(() => { + document.documentElement.scrollTop = this.scrollCache[tab] || defaultScrollTop; + }, 50); + + this.lastTabShown = tab; + } + +} + +export default TriLayout; \ No newline at end of file diff --git a/resources/assets/js/components/wysiwyg-editor.js b/resources/assets/js/components/wysiwyg-editor.js index 9deb1d0a7..ce5cfbf4e 100644 --- a/resources/assets/js/components/wysiwyg-editor.js +++ b/resources/assets/js/components/wysiwyg-editor.js @@ -432,7 +432,7 @@ class WysiwygEditor { plugins: this.plugins, imagetools_toolbar: 'imageoptions', toolbar: this.getToolBar(), - content_style: "body {padding-left: 15px !important; padding-right: 15px !important; margin:0!important; margin-left:auto!important;margin-right:auto!important;}", + content_style: "html, body {background: #FFF;} body {padding-left: 15px !important; padding-right: 15px !important; margin:0!important; margin-left:auto!important;margin-right:auto!important;}", style_formats: [ {title: "Header Large", format: "h2"}, {title: "Header Medium", format: "h3"}, @@ -517,6 +517,16 @@ class WysiwygEditor { if (scrollId) { scrollToText(scrollId); } + + // Override for touch events to allow scroll on mobile + const container = editor.getContainer(); + const toolbarButtons = container.querySelectorAll('.mce-btn'); + for (let button of toolbarButtons) { + button.addEventListener('touchstart', event => { + event.stopPropagation(); + }); + } + window.editor = editor; }); function editorChange() { @@ -600,6 +610,7 @@ class WysiwygEditor { // Paste image-uploads editor.on('paste', event => editorPaste(event, editor, context)); + } }; } diff --git a/resources/assets/sass/_animations.scss b/resources/assets/sass/_animations.scss index c03553d15..85fd96206 100644 --- a/resources/assets/sass/_animations.scss +++ b/resources/assets/sass/_animations.scss @@ -36,26 +36,6 @@ } } -.anim.menuIn { - transform-origin: 100% 0%; - animation-name: menuIn; - animation-duration: 120ms; - animation-delay: 0s; - animation-timing-function: cubic-bezier(.62, .28, .23, .99); -} - -@keyframes menuIn { - from { - opacity: 0; - transform: scale3d(0, 0, 1); - } - - to { - opacity: 1; - transform: scale3d(1, 1, 1); - } -} - @keyframes loadingBob { 0% { transform: translate3d(0, 0, 0); @@ -89,8 +69,4 @@ animation-duration: 180ms; animation-delay: 0s; animation-timing-function: cubic-bezier(.62, .28, .23, .99); -} - -.selectFade { - transition: background-color ease-in-out 3000ms; } \ No newline at end of file diff --git a/resources/assets/sass/_blocks.scss b/resources/assets/sass/_blocks.scss index c0f02ed7d..efdefc016 100644 --- a/resources/assets/sass/_blocks.scss +++ b/resources/assets/sass/_blocks.scss @@ -1,136 +1,7 @@ -/* -* This file container all block styling including background shading, -* margins, paddings & borders. -*/ - - -/* -* Background Shading -*/ -.shaded { - background-color: #f1f1f1; - &.pos { - background-color: lighten($positive, 40%); - } - &.neg { - background-color: lighten($negative, 20%); - } - &.primary { - background-color: lighten($primary, 40%); - } - &.secondary { - background-color: lighten($secondary, 30%); - } -} - -/* -* Bordering -*/ -.bordered { - border: 1px solid #BBB; - &.pos { - border-color: $positive; - } - &.neg { - border-color: $negative; - } - &.primary { - border-color: $primary; - } - &.secondary { - border-color: $secondary; - } - &.thick { - border-width: 2px; - } -} -.rounded { - border-radius: 3px; -} - -/* -* Padding -*/ -.nopadding { - padding: 0; -} -.padded { - padding: $-l; - &.large { - padding: $-xl; - } - >h1, >h2, >h3, >h4 { - &:first-child { - margin-top: 0.1em; - } - } -} -.padded-vertical, .padded-top { - padding-top: $-m; - &.large { - padding-top: $-xl; - } -} - -.padded-vertical, .padded-bottom { - padding-bottom: $-m; - &.large { - padding-bottom: $-xl; - } -} -.padded-horizontal, .padded-left { - padding-left: $-m; - &.large { - padding-left: $-xl; - } -} -.padded-horizontal, .padded-right { - padding-right: $-m; - &.large { - padding-right: $-xl; - } -} - -/* -* Margins -*/ -.margins { - margin: $-l; - &.large { - margin: $-xl; - } -} -.margins-vertical, .margin-top { - margin-top: $-m; - &.large { - margin-top: $-xl; - } -} -.margins-vertical, .margin-bottom { - margin-bottom: $-m; - &.large { - margin-bottom: $-xl; - } -} -.margins-horizontal, .margin-left { - margin-left: $-m; - &.large { - margin-left: $-xl; - } -} -.margins-horizontal, .margin-right { - margin-right: $-m; - &.large { - margin-right: $-xl; - } -} - - /** * Callouts */ - .callout { border-left: 3px solid #BBB; background-color: #EEE; @@ -182,19 +53,22 @@ } } +/** + * Card-style blocks + */ + .card { - margin: $-m; background-color: #FFF; - box-shadow: 0 0 1px 0 rgba(0, 0, 0, 0.2); + box-shadow: $bs-card; + border-radius: 3px; + border: 1px solid transparent; h3 { - padding: $-m; - border-bottom: 1px solid #E8E8E8; + padding: $-m $-m $-xs; margin: 0; - font-size: $fs-s; - color: #888; - fill: #888; + font-size: $fs-m; + color: #222; + fill: #222; font-weight: 400; - text-transform: uppercase; } h3 a { line-height: 1; @@ -208,18 +82,11 @@ } } -.sidebar .card { - h3, .body, .empty-text { - padding: $-s $-m; - } -} - .card.drag-card { border: 1px solid #DDD; border-radius: 4px; display: flex; - padding: 0; - padding-left: $-s + 28px; + padding: 0 0 0 ($-s + 28px); margin: $-s 0; position: relative; .drag-card-action { @@ -227,14 +94,12 @@ } .handle, .drag-card-action { display: flex; - padding: 0; align-items: center; text-align: center; justify-content: center; width: 28px; flex-grow: 0; - padding-left: $-xs; - padding-right: $-xs; + padding: 0 $-xs; &:hover { background-color: #EEE; } @@ -246,9 +111,6 @@ margin: $-s 0; width: 100%; } - > div.padded { - padding: $-s 0 !important; - } .handle { background-color: #EEE; left: 0; @@ -263,12 +125,89 @@ } } -.well { - background-color: #F8F8F8; - padding: $-m; - border: 1px solid #DDD; +.grid-card { + display: flex; + flex-direction: column; + border: 1px solid #ddd; + margin-bottom: $-l; + border-radius: 4px; + overflow: hidden; + min-width: 100px; + color: $text-dark; + transition: border-color ease-in-out 120ms, box-shadow ease-in-out 120ms; + &:hover { + color: $text-dark; + text-decoration: none; + box-shadow: $bs-card; + } + h2 { + width: 100%; + font-size: 1.5em; + margin: 0 0 10px; + } + p { + font-size: .7rem; + margin: 0; + line-height: 1.6em; + } + .grid-card-content { + flex: 1; + border-top: 0; + border-bottom-width: 2px; + } + .grid-card-content, .grid-card-footer { + padding: $-l; + } + .grid-card-content + .grid-card-footer { + padding-top: 0; + } } +.bookshelf-grid-item .grid-card-content h2 a { + color: $color-bookshelf; + fill: $color-bookshelf; +} + +.book-grid-item .grid-card-footer { + p.small { + font-size: .8em; + margin: 0; + } +} + +.content-wrap.card { + padding: $-m $-xxl; + margin-left: auto; + margin-right: auto; + margin-bottom: $-xl; + overflow: auto; + min-height: 60vh; + &.auto-height { + min-height: 0; + } + &.fill-width { + width: 100%; + } +} +@include smaller-than($xxl) { + .content-wrap.card { + padding: $-l $-xl; + } +} +@include smaller-than($m) { + .content-wrap.card { + padding: $-m $-l; + } +} +@include smaller-than($s) { + .content-wrap.card { + padding: $-m $-s; + } +} + +/** + * Tags + */ .tag-item { display: inline-flex; margin-bottom: $-xs; diff --git a/resources/assets/sass/_buttons.scss b/resources/assets/sass/_buttons.scss index 2c20c3f41..eb7a09342 100644 --- a/resources/assets/sass/_buttons.scss +++ b/resources/assets/sass/_buttons.scss @@ -1,15 +1,14 @@ +button { + font-size: 100%; +} @mixin generate-button-colors($textColor, $backgroundColor) { background-color: $backgroundColor; color: $textColor; fill: $textColor; - text-transform: uppercase; border: 1px solid $backgroundColor; - vertical-align: top; &:hover { background-color: lighten($backgroundColor, 8%); - //box-shadow: $bs-med; - text-decoration: none; color: $textColor; } &:active { @@ -18,7 +17,6 @@ &:focus { background-color: lighten($backgroundColor, 4%); box-shadow: $bs-light; - text-decoration: none; color: $textColor; } } @@ -26,42 +24,36 @@ // Button Specific Variables $button-border-radius: 2px; -.button-base { +.button { text-decoration: none; - font-size: $fs-m; + font-size: 0.85rem; line-height: 1.4em; padding: $-xs*1.3 $-m; - margin: $-xs $-xs $-xs 0; + margin-top: $-xs; + margin-bottom: $-xs; display: inline-block; - border: none; font-weight: 400; outline: 0; border-radius: $button-border-radius; cursor: pointer; - transition: all ease-in-out 120ms; - box-shadow: 0; - @include generate-button-colors(#EEE, $primary); -} - -.button, input[type="button"], input[type="submit"] { - @extend .button-base; - &.pos { - @include generate-button-colors(#EEE, $positive); + transition: background-color ease-in-out 120ms, box-shadow ease-in-out 120ms; + box-shadow: none; + background-color: $primary; + color: #FFF; + fill: #FFF; + text-transform: uppercase; + border: 1px solid $primary; + vertical-align: top; + &:hover, &:focus { + text-decoration: none; } - &.neg { - @include generate-button-colors(#EEE, $negative); - } - &.secondary { - @include generate-button-colors(#EEE, $secondary); - } - &.muted { - @include generate-button-colors(#EEE, #AAA); - } - &.muted-light { - @include generate-button-colors(#666, #e4e4e4); + &:active { + background-color: darken($primary, 8%); } } - +.button.primary { + @include generate-button-colors(#FFFFFF, $primary); +} .button.outline { background-color: transparent; color: #888; @@ -71,78 +63,38 @@ $button-border-radius: 2px; box-shadow: none; background-color: #EEE; } - &.page { - border-color: $color-page; - color: $color-page; - fill: $color-page; - &:hover, &:focus, &:active { - background-color: $color-page; - color: #FFF; - fill: #FFF; - } - } - &.chapter { - border-color: $color-chapter; - color: $color-chapter; - fill: $color-chapter; - &:hover, &:focus, &:active { - background-color: $color-chapter; - color: #FFF; - fill: #FFF; - } - } - &.book { - border-color: $color-book; - color: $color-book; - fill: $color-book; - &:hover, &:focus, &:active { - background-color: $color-book; - color: #FFF; - fill: #FFF; - } - } +} + +.button + .button { + margin-left: $-s; +} + +.button.small { + font-size: 0.75rem; + padding: $-xs*1.2 $-s; } .text-button { - @extend .link; + cursor: pointer; background-color: transparent; padding: 0; margin: 0; border: none; user-select: none; + font-size: 0.75rem; + line-height: 1.4em; &:focus, &:active { outline: 0; } &:hover { text-decoration: none; } - &.neg { - color: $negative; - } -} - -.button-group { - @include clearfix; - .button, button[type="button"] { - margin: $-xs 0 $-xs 0; - float: left; - border-radius: 0; - &:first-child { - border-radius: $button-border-radius 0 0 $button-border-radius; - } - &:last-child { - border-radius: 0 $button-border-radius $button-border-radius 0; - } - } } .button.block { width: 100%; - text-align: center; + text-align: left; display: block; - &.text-left { - text-align: left; - } } .button.icon { @@ -160,9 +112,7 @@ $button-border-radius: 2px; width: 24px; height: 24px; } - padding: $-s $-m; - padding-bottom: $-s - 2px; - padding-left: $-m*2 + 24px; + padding: $-s $-m ($-s - 2px) ($-m*2 + 24px); } .button[disabled] { diff --git a/resources/assets/sass/_colors.scss b/resources/assets/sass/_colors.scss new file mode 100644 index 000000000..4dfc9d4c3 --- /dev/null +++ b/resources/assets/sass/_colors.scss @@ -0,0 +1,72 @@ + +/* + * Status text colors + */ +.text-pos, .text-pos:hover, .text-pos-hover:hover { + color: $positive !important; + fill: $positive !important; +} + +.text-warn, .text-warn:hover, .text-warn-hover:hover { + color: $warning !important; + fill: $warning !important; +} + +.text-neg, .text-neg:hover, .text-neg-hover:hover { + color: $negative !important; + fill: $negative !important; +} + +/* + * Style text colors + */ +.text-primary, .text-primary:hover, .text-primary-hover:hover { + color: $primary !important; + fill: $primary !important; +} + +.text-muted { + color: lighten($text-dark, 26%) !important; + fill: lighten($text-dark, 26%) !important; + &.small, .small { + color: lighten($text-dark, 32%) !important; + fill: lighten($text-dark, 32%) !important; + } +} + +/* + * Entity text colors + */ +.text-bookshelf, .text-bookshelf:hover { + color: $color-bookshelf; + fill: $color-bookshelf; +} +.text-book, .text-book:hover { + color: $color-book; + fill: $color-book; +} +.text-page, .text-page:hover { + color: $color-page; + fill: $color-page; +} +.text-page.draft, .text-page.draft:hover { + color: $color-page-draft; + fill: $color-page-draft; +} +.text-chapter, .text-chapter:hover { + color: $color-chapter; + fill: $color-chapter; +} + +/* + * Entity background colors + */ +.bg-book { + background-color: $color-book; +} +.bg-chapter { + background-color: $color-chapter; +} +.bg-shelf { + background-color: $color-bookshelf; +} \ No newline at end of file diff --git a/resources/assets/sass/_components.scss b/resources/assets/sass/_components.scss index 1f34166c6..33bc5e71d 100644 --- a/resources/assets/sass/_components.scss +++ b/resources/assets/sass/_components.scss @@ -54,13 +54,18 @@ transition: all ease-in-out 180ms; user-select: none; svg[data-icon="caret-right"] { + margin-right: 0; + font-size: 1rem; transition: all ease-in-out 180ms; transform: rotate(0deg); - transform-origin: 25% 50%; + transform-origin: 50% 50%; } &.open svg[data-icon="caret-right"] { transform: rotate(90deg); } + svg[data-icon="caret-right"] + * { + margin-left: $-xs; + } } [overlay] { @@ -110,7 +115,7 @@ } } -.corner-button { +.popup-footer button, .popup-header-close { position: absolute; top: 0; right: 0; @@ -118,6 +123,16 @@ height: 40px; border-radius: 0; box-shadow: none; + &:active { + outline: 0; + } +} +.popup-header-close { + background-color: transparent; + border: 0; + color: #FFF; + font-size: 16px; + padding: 0 $-m; } .popup-header, .popup-footer { @@ -130,6 +145,9 @@ padding: 8px $-m; } } +.popup-footer { + margin-top: 1px; +} body.flexbox-support #entity-selector-wrap .popup-body .form-group { height: 444px; min-height: 444px; @@ -137,6 +155,9 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group { #entity-selector-wrap .popup-body .form-group { margin: 0; } +.popup-body .entity-selector-container { + flex: 1; +} .image-manager-body { min-height: 70vh; @@ -583,27 +604,26 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group { } .comment-box { - clear: left; border: 1px solid #DDD; - margin-bottom: $-s; - border-radius: 3px; + border-radius: 4px; + background-color: #FFF; .content { - padding: $-s; font-size: 0.666em; p, ul, ol { font-size: $fs-m; margin: .5em 0; } } - .reply-row { - padding: $-xs $-s; + .actions { + opacity: 0; + transition: opacity ease-in-out 120ms; + } + &:hover .actions { + opacity: 1; } } .comment-box .header { - padding: $-xs $-s; - background-color: #f8f8f8; - border-bottom: 1px solid #DDD; .meta { img, a, span { display: inline-block; @@ -626,4 +646,11 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group { #tag-manager .drag-card { max-width: 500px; +} + +.permissions-table [permissions-table-toggle-all-in-row] { + display: none; +} +.permissions-table tr:hover [permissions-table-toggle-all-in-row] { + display: inline; } \ No newline at end of file diff --git a/resources/assets/sass/_forms.scss b/resources/assets/sass/_forms.scss index 6b3ed3815..f40c92a19 100644 --- a/resources/assets/sass/_forms.scss +++ b/resources/assets/sass/_forms.scss @@ -63,6 +63,34 @@ } } +@include smaller-than($m) { + #markdown-editor { + flex-direction: column; + } + #markdown-editor .markdown-editor-wrap { + width: 100%; + max-width: 100%; + } + #markdown-editor .editor-toolbar { + padding: 0; + } + #markdown-editor .editor-toolbar > * { + padding: $-xs $-s; + } + .editor-toolbar-label { + float: none !important; + border-bottom: 1px solid #DDD; + display: block; + } + .markdown-editor-wrap:not(.active) .editor-toolbar + div, .markdown-editor-wrap:not(.active) .editor-toolbar .buttons { + display: none; + } + #markdown-editor .markdown-editor-wrap:not(.active) { + flex-grow: 0; + flex: none; + } +} + .markdown-display { padding: 0 $-m 0; margin-left: -1px; @@ -98,7 +126,7 @@ label { line-height: 1.4em; font-size: 0.94em; font-weight: 400; - color: #999; + color: #666; padding-bottom: 2px; margin-bottom: 0.2em; &.inline { @@ -139,56 +167,77 @@ input[type=date] { } .toggle-switch { - display: inline-block; - background-color: #BBB; - width: 36px; - height: 14px; - border-radius: 7px; - position: relative; - transition: all ease-in-out 120ms; - cursor: pointer; user-select: none; - &:after { - content: ''; - display: block; - position: relative; - left: 0; - margin-top: -3px; - width: 20px; - height: 20px; - border-radius: 50%; - background-color: #fafafa; - border: 1px solid #CCC; - box-shadow: 0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12); - transition: all ease-in-out 120ms; - } - &.active { - background-color: rgba($positive, 0.4); - &:after { - left: 16px; - background-color: $positive; - border: darken($positive, 20%); + display: inline-grid; + grid-template-columns: (16px + $-s) 1fr; + align-items: center; + margin: $-m 0; + .custom-checkbox { + width: 16px; + height: 16px; + border-radius: 2px; + display: inline-block; + border: 2px solid currentColor; + opacity: 0.6; + overflow: hidden; + fill: currentColor; + .svg-icon { + width: 100%; + height: 100%; + margin: 0; + bottom: auto; + top: -1.5px; + left: 0; + transition: transform ease-in-out 120ms; + transform: scale(0); + transform-origin: center center; } } + input[type=checkbox] { + display: none; + } + input[type=checkbox]:checked + .custom-checkbox .svg-icon { + transform: scale(1); + } + .custom-checkbox:hover { + background-color: rgba(0, 0, 0, 0.05); + opacity: 0.8; + } } -.toggle-switch-checkbox { - display: none; -} -input:checked + .toggle-switch { - background-color: rgba($positive, 0.4); - &:after { - left: 16px; - background-color: $positive; - border: darken($positive, 20%); +.toggle-switch-list { + .toggle-switch { + margin: $-xs 0; + } + &.compact .toggle-switch { + margin: 1px 0; } } .form-group { margin-bottom: $-s; - textarea { - display: block; +} + +.setting-list > div { + border-bottom: 1px solid #DDD; + padding: $-xl 0; + &:last-child { + border-bottom: none; + } +} +.setting-list-label { + color: #222; + font-size: 1rem; +} +.setting-list-label + p.small { + margin-bottom: 0; +} +.setting-list-label + .grid { + margin-top: $-m; +} + +.setting-list .grid, .stretch-inputs { + input[type=text], input[type=email], input[type=password], select { width: 100%; - min-height: 64px; } } @@ -197,6 +246,8 @@ input:checked + .toggle-switch { font-family: monospace; font-size: 12px; min-height: 100px; + display: block; + width: 100%; } .form-group { @@ -206,11 +257,9 @@ input:checked + .toggle-switch { } .form-group[collapsible] { - margin-left: -$-m; - margin-right: -$-m; padding: 0 $-m; - border-top: 1px solid #DDD; - border-bottom: 1px solid #DDD; + border: 1px solid #DDD; + border-radius: 4px; .collapse-title { margin-left: -$-m; margin-right: -$-m; @@ -238,9 +287,6 @@ input:checked + .toggle-switch { &.open .collapse-title label:before { transform: rotate(90deg); } - &+.form-group[collapsible] { - margin-top: -($-s + 1); - } } .inline-input-style { @@ -304,6 +350,13 @@ div[editor-type="markdown"] .title-input.page-title input[type="text"] { width: 300px; max-width: 100%; } + &.flexible input { + width: 100%; + } + .search-box-cancel { + left: auto; + right: 0; + } } .outline > input { @@ -317,13 +370,6 @@ div[editor-type="markdown"] .title-input.page-title input[type="text"] { } } -#login-form label[for="remember"] { - margin: 0; -} -#login-form label.toggle-switch { - margin-left: $-xl; -} - .image-picker img { background-color: #BBB; } diff --git a/resources/assets/sass/_grid.scss b/resources/assets/sass/_grid.scss deleted file mode 100644 index 0e1f85ce6..000000000 --- a/resources/assets/sass/_grid.scss +++ /dev/null @@ -1,930 +0,0 @@ - -/** Flexbox styling rules **/ -body.flexbox { - display: flex; - flex-direction: column; - align-items: stretch; - height: 100%; - min-height: 100%; - max-height: 100%; - overflow: hidden; - #content { - flex: 1; - display: flex; - min-height: 0; - } -} - -.flex-fill { - display: flex; - align-items: stretch; - min-height: 0; - max-width: 100%; - position: relative; - &.rows { - flex-direction: row; - } - &.columns { - flex-direction: column; - } -} - -.flex { - min-height: 0; - flex: 1; -} - -.flex.scroll { - //overflow-y: auto; - display: flex; - &.sidebar { - margin-right: -14px; - } -} -.flex.scroll .scroll-body { - overflow-y: scroll; - flex: 1; -} - -.flex-child > div { - flex: 1; -} - -.flex.sidebar { - flex: 1; - background-color: #F2F2F2; - max-width: 360px; - min-height: 90vh; - section { - margin: $-m; - } -} -.flex.sidebar + .flex.content { - flex: 3; - background-color: #FFFFFF; - padding: 0 $-l; - border-left: 1px solid #DDD; - max-width: 100%; -} -.flex.sidebar .sidebar-toggle { - display: none; -} - -@include smaller-than($xl) { - body.sidebar-layout { - padding-left: 30px; - } - .flex.sidebar { - position: fixed; - top: 0; - left: 0; - bottom: 0; - z-index: 100; - padding-right: 30px; - width: 360px; - box-shadow: none; - transform: translate3d(-330px, 0, 0); - transition: transform ease-in-out 120ms; - display: flex; - flex-direction: column; - } - .flex.sidebar.open { - box-shadow: 1px 2px 2px 1px rgba(0,0,0,.10); - transform: translate3d(0, 0, 0); - .sidebar-toggle i { - transform: rotate(180deg); - } - } - .flex.sidebar .sidebar-toggle { - display: block; - position: absolute; - opacity: 0.9; - right: 0; - top: 0; - bottom: 0; - width: 30px; - fill: #666; - font-size: 20px; - vertical-align: middle; - text-align: center; - border: 1px solid #DDD; - border-top: 1px solid #BBB; - padding-top: $-m; - cursor: pointer; - svg { - opacity: 0.5; - transition: all ease-in-out 120ms; - margin: 0; - } - &:hover i { - opacity: 1; - } - } - .sidebar .scroll-body { - flex: 1; - overflow-y: scroll; - } - #sidebar .scroll-body.fixed { - width: auto !important; - } -} - -@include larger-than($xl) { - #sidebar .scroll-body.fixed { - z-index: 5; - position: fixed; - top: 0; - padding-right: $-m; - width: 30%; - left: 0; - height: 100%; - overflow-y: auto; - -ms-overflow-style: none; - //background-color: $primary-faded; - border-left: 1px solid #DDD; - &::-webkit-scrollbar { width: 0 !important } - } -} - - -/** Rules for all columns */ -div[class^="col-"] img { - max-width: 100%; -} - -.container { - max-width: $max-width; - margin-left: auto; - margin-right: auto; - padding-left: $-m; - padding-right: $-m; - &.fluid { - max-width: 100%; - } - &.medium { - max-width: 992px; - } - &.small { - max-width: 840px; - } - &.nopad { - padding-left: 0; - padding-right: 0; - } -} - -.row { - margin-left: -$-m; - margin-right: -$-m; -} - -.grid { - display: grid; - grid-column-gap: $-l; - grid-row-gap: $-l; - &.third { - grid-template-columns: 1fr 1fr 1fr; - } -} - -.grid-card { - display: flex; - flex-direction: column; - border: 1px solid #ddd; - min-width: 100px; - h2 { - width: 100%; - font-size: 1.5em; - margin: 0 0 10px; - } - h2 a { - display: block; - width: 100%; - line-height: 1.2; - text-decoration: none; - } - p { - font-size: .85em; - margin: 0; - line-height: 1.6em; - } - .grid-card-content { - flex: 1; - border-top: 0; - border-bottom-width: 2px; - } - .grid-card-content, .grid-card-footer { - padding: $-l; - } - .grid-card-content + .grid-card-footer { - padding-top: 0; - } -} - -.book-grid-item .grid-card-content h2 a { - color: $color-book; - fill: $color-book; -} - -.bookshelf-grid-item .grid-card-content h2 a { - color: $color-bookshelf; - fill: $color-bookshelf; -} - -.book-grid-item .grid-card-footer { - p.small { - font-size: .8em; - margin: 0; - } -} - -@include smaller-than($m) { - .grid.third { - grid-template-columns: 1fr 1fr; - } -} - -@include smaller-than($s) { - .grid.third { - grid-template-columns: 1fr; - } -} - -.float { - float: left; - &.right { - float: right; - } -} - -.block { - display: block; - position: relative; -} - -.inline { - display: inline; -} - -.block.inline { - display: inline-block; -} - -.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { - position: relative; - min-height: 1px; - padding-left: $-m; - padding-right: $-m; -} -.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { - float: left; -} -.col-xs-12 { - width: 100%; -} -.col-xs-11 { - width: 91.66666667%; -} -.col-xs-10 { - width: 83.33333333%; -} -.col-xs-9 { - width: 75%; -} -.col-xs-8 { - width: 66.66666667%; -} -.col-xs-7 { - width: 58.33333333%; -} -.col-xs-6 { - width: 50%; -} -.col-xs-5 { - width: 41.66666667%; -} -.col-xs-4 { - width: 33.33333333%; -} -.col-xs-3 { - width: 25%; -} -.col-xs-2 { - width: 16.66666667%; -} -.col-xs-1 { - width: 8.33333333%; -} -.col-xs-pull-12 { - right: 100%; -} -.col-xs-pull-11 { - right: 91.66666667%; -} -.col-xs-pull-10 { - right: 83.33333333%; -} -.col-xs-pull-9 { - right: 75%; -} -.col-xs-pull-8 { - right: 66.66666667%; -} -.col-xs-pull-7 { - right: 58.33333333%; -} -.col-xs-pull-6 { - right: 50%; -} -.col-xs-pull-5 { - right: 41.66666667%; -} -.col-xs-pull-4 { - right: 33.33333333%; -} -.col-xs-pull-3 { - right: 25%; -} -.col-xs-pull-2 { - right: 16.66666667%; -} -.col-xs-pull-1 { - right: 8.33333333%; -} -.col-xs-pull-0 { - right: auto; -} -.col-xs-push-12 { - left: 100%; -} -.col-xs-push-11 { - left: 91.66666667%; -} -.col-xs-push-10 { - left: 83.33333333%; -} -.col-xs-push-9 { - left: 75%; -} -.col-xs-push-8 { - left: 66.66666667%; -} -.col-xs-push-7 { - left: 58.33333333%; -} -.col-xs-push-6 { - left: 50%; -} -.col-xs-push-5 { - left: 41.66666667%; -} -.col-xs-push-4 { - left: 33.33333333%; -} -.col-xs-push-3 { - left: 25%; -} -.col-xs-push-2 { - left: 16.66666667%; -} -.col-xs-push-1 { - left: 8.33333333%; -} -.col-xs-push-0 { - left: auto; -} -.col-xs-offset-12 { - margin-left: 100%; -} -.col-xs-offset-11 { - margin-left: 91.66666667%; -} -.col-xs-offset-10 { - margin-left: 83.33333333%; -} -.col-xs-offset-9 { - margin-left: 75%; -} -.col-xs-offset-8 { - margin-left: 66.66666667%; -} -.col-xs-offset-7 { - margin-left: 58.33333333%; -} -.col-xs-offset-6 { - margin-left: 50%; -} -.col-xs-offset-5 { - margin-left: 41.66666667%; -} -.col-xs-offset-4 { - margin-left: 33.33333333%; -} -.col-xs-offset-3 { - margin-left: 25%; -} -.col-xs-offset-2 { - margin-left: 16.66666667%; -} -.col-xs-offset-1 { - margin-left: 8.33333333%; -} -.col-xs-offset-0 { - margin-left: 0%; -} -@media (min-width: $screen-sm) { - .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { - float: left; - } - .col-sm-12 { - width: 100%; - } - .col-sm-11 { - width: 91.66666667%; - } - .col-sm-10 { - width: 83.33333333%; - } - .col-sm-9 { - width: 75%; - } - .col-sm-8 { - width: 66.66666667%; - } - .col-sm-7 { - width: 58.33333333%; - } - .col-sm-6 { - width: 50%; - } - .col-sm-5 { - width: 41.66666667%; - } - .col-sm-4 { - width: 33.33333333%; - } - .col-sm-3 { - width: 25%; - } - .col-sm-2 { - width: 16.66666667%; - } - .col-sm-1 { - width: 8.33333333%; - } - .col-sm-pull-12 { - right: 100%; - } - .col-sm-pull-11 { - right: 91.66666667%; - } - .col-sm-pull-10 { - right: 83.33333333%; - } - .col-sm-pull-9 { - right: 75%; - } - .col-sm-pull-8 { - right: 66.66666667%; - } - .col-sm-pull-7 { - right: 58.33333333%; - } - .col-sm-pull-6 { - right: 50%; - } - .col-sm-pull-5 { - right: 41.66666667%; - } - .col-sm-pull-4 { - right: 33.33333333%; - } - .col-sm-pull-3 { - right: 25%; - } - .col-sm-pull-2 { - right: 16.66666667%; - } - .col-sm-pull-1 { - right: 8.33333333%; - } - .col-sm-pull-0 { - right: auto; - } - .col-sm-push-12 { - left: 100%; - } - .col-sm-push-11 { - left: 91.66666667%; - } - .col-sm-push-10 { - left: 83.33333333%; - } - .col-sm-push-9 { - left: 75%; - } - .col-sm-push-8 { - left: 66.66666667%; - } - .col-sm-push-7 { - left: 58.33333333%; - } - .col-sm-push-6 { - left: 50%; - } - .col-sm-push-5 { - left: 41.66666667%; - } - .col-sm-push-4 { - left: 33.33333333%; - } - .col-sm-push-3 { - left: 25%; - } - .col-sm-push-2 { - left: 16.66666667%; - } - .col-sm-push-1 { - left: 8.33333333%; - } - .col-sm-push-0 { - left: auto; - } - .col-sm-offset-12 { - margin-left: 100%; - } - .col-sm-offset-11 { - margin-left: 91.66666667%; - } - .col-sm-offset-10 { - margin-left: 83.33333333%; - } - .col-sm-offset-9 { - margin-left: 75%; - } - .col-sm-offset-8 { - margin-left: 66.66666667%; - } - .col-sm-offset-7 { - margin-left: 58.33333333%; - } - .col-sm-offset-6 { - margin-left: 50%; - } - .col-sm-offset-5 { - margin-left: 41.66666667%; - } - .col-sm-offset-4 { - margin-left: 33.33333333%; - } - .col-sm-offset-3 { - margin-left: 25%; - } - .col-sm-offset-2 { - margin-left: 16.66666667%; - } - .col-sm-offset-1 { - margin-left: 8.33333333%; - } - .col-sm-offset-0 { - margin-left: 0%; - } -} -@media (min-width: $screen-md) { - .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { - float: left; - } - .col-md-12 { - width: 100%; - } - .col-md-11 { - width: 91.66666667%; - } - .col-md-10 { - width: 83.33333333%; - } - .col-md-9 { - width: 75%; - } - .col-md-8 { - width: 66.66666667%; - } - .col-md-7 { - width: 58.33333333%; - } - .col-md-6 { - width: 50%; - } - .col-md-5 { - width: 41.66666667%; - } - .col-md-4 { - width: 33.33333333%; - } - .col-md-3 { - width: 25%; - } - .col-md-2 { - width: 16.66666667%; - } - .col-md-1 { - width: 8.33333333%; - } - .col-md-pull-12 { - right: 100%; - } - .col-md-pull-11 { - right: 91.66666667%; - } - .col-md-pull-10 { - right: 83.33333333%; - } - .col-md-pull-9 { - right: 75%; - } - .col-md-pull-8 { - right: 66.66666667%; - } - .col-md-pull-7 { - right: 58.33333333%; - } - .col-md-pull-6 { - right: 50%; - } - .col-md-pull-5 { - right: 41.66666667%; - } - .col-md-pull-4 { - right: 33.33333333%; - } - .col-md-pull-3 { - right: 25%; - } - .col-md-pull-2 { - right: 16.66666667%; - } - .col-md-pull-1 { - right: 8.33333333%; - } - .col-md-pull-0 { - right: auto; - } - .col-md-push-12 { - left: 100%; - } - .col-md-push-11 { - left: 91.66666667%; - } - .col-md-push-10 { - left: 83.33333333%; - } - .col-md-push-9 { - left: 75%; - } - .col-md-push-8 { - left: 66.66666667%; - } - .col-md-push-7 { - left: 58.33333333%; - } - .col-md-push-6 { - left: 50%; - } - .col-md-push-5 { - left: 41.66666667%; - } - .col-md-push-4 { - left: 33.33333333%; - } - .col-md-push-3 { - left: 25%; - } - .col-md-push-2 { - left: 16.66666667%; - } - .col-md-push-1 { - left: 8.33333333%; - } - .col-md-push-0 { - left: auto; - } - .col-md-offset-12 { - margin-left: 100%; - } - .col-md-offset-11 { - margin-left: 91.66666667%; - } - .col-md-offset-10 { - margin-left: 83.33333333%; - } - .col-md-offset-9 { - margin-left: 75%; - } - .col-md-offset-8 { - margin-left: 66.66666667%; - } - .col-md-offset-7 { - margin-left: 58.33333333%; - } - .col-md-offset-6 { - margin-left: 50%; - } - .col-md-offset-5 { - margin-left: 41.66666667%; - } - .col-md-offset-4 { - margin-left: 33.33333333%; - } - .col-md-offset-3 { - margin-left: 25%; - } - .col-md-offset-2 { - margin-left: 16.66666667%; - } - .col-md-offset-1 { - margin-left: 8.33333333%; - } - .col-md-offset-0 { - margin-left: 0%; - } -} -@media (min-width: $screen-lg) { - .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { - float: left; - } - .col-lg-12 { - width: 100%; - } - .col-lg-11 { - width: 91.66666667%; - } - .col-lg-10 { - width: 83.33333333%; - } - .col-lg-9 { - width: 75%; - } - .col-lg-8 { - width: 66.66666667%; - } - .col-lg-7 { - width: 58.33333333%; - } - .col-lg-6 { - width: 50%; - } - .col-lg-5 { - width: 41.66666667%; - } - .col-lg-4 { - width: 33.33333333%; - } - .col-lg-3 { - width: 25%; - } - .col-lg-2 { - width: 16.66666667%; - } - .col-lg-1 { - width: 8.33333333%; - } - .col-lg-pull-12 { - right: 100%; - } - .col-lg-pull-11 { - right: 91.66666667%; - } - .col-lg-pull-10 { - right: 83.33333333%; - } - .col-lg-pull-9 { - right: 75%; - } - .col-lg-pull-8 { - right: 66.66666667%; - } - .col-lg-pull-7 { - right: 58.33333333%; - } - .col-lg-pull-6 { - right: 50%; - } - .col-lg-pull-5 { - right: 41.66666667%; - } - .col-lg-pull-4 { - right: 33.33333333%; - } - .col-lg-pull-3 { - right: 25%; - } - .col-lg-pull-2 { - right: 16.66666667%; - } - .col-lg-pull-1 { - right: 8.33333333%; - } - .col-lg-pull-0 { - right: auto; - } - .col-lg-push-12 { - left: 100%; - } - .col-lg-push-11 { - left: 91.66666667%; - } - .col-lg-push-10 { - left: 83.33333333%; - } - .col-lg-push-9 { - left: 75%; - } - .col-lg-push-8 { - left: 66.66666667%; - } - .col-lg-push-7 { - left: 58.33333333%; - } - .col-lg-push-6 { - left: 50%; - } - .col-lg-push-5 { - left: 41.66666667%; - } - .col-lg-push-4 { - left: 33.33333333%; - } - .col-lg-push-3 { - left: 25%; - } - .col-lg-push-2 { - left: 16.66666667%; - } - .col-lg-push-1 { - left: 8.33333333%; - } - .col-lg-push-0 { - left: auto; - } - .col-lg-offset-12 { - margin-left: 100%; - } - .col-lg-offset-11 { - margin-left: 91.66666667%; - } - .col-lg-offset-10 { - margin-left: 83.33333333%; - } - .col-lg-offset-9 { - margin-left: 75%; - } - .col-lg-offset-8 { - margin-left: 66.66666667%; - } - .col-lg-offset-7 { - margin-left: 58.33333333%; - } - .col-lg-offset-6 { - margin-left: 50%; - } - .col-lg-offset-5 { - margin-left: 41.66666667%; - } - .col-lg-offset-4 { - margin-left: 33.33333333%; - } - .col-lg-offset-3 { - margin-left: 25%; - } - .col-lg-offset-2 { - margin-left: 16.66666667%; - } - .col-lg-offset-1 { - margin-left: 8.33333333%; - } - .col-lg-offset-0 { - margin-left: 0%; - } -} -.clearfix:before, -.clearfix:after, -.container:before, -.container:after, -.container-fluid:before, -.container-fluid:after, -.row:before, -.row:after { - content: " "; - display: table; -} -.clearfix:after, -.container:after, -.container-fluid:after, -.row:after { - clear: both; -} -.center-block { - display: block; - margin-left: auto; - margin-right: auto; -} diff --git a/resources/assets/sass/_header.scss b/resources/assets/sass/_header.scss index b66bab394..7fd6d7ae9 100644 --- a/resources/assets/sass/_header.scss +++ b/resources/assets/sass/_header.scss @@ -2,21 +2,31 @@ * Includes the main navigation header and the faded toolbar. */ +header .grid { + grid-template-columns: auto min-content auto; +} + +@include smaller-than($l) { + header .grid { + grid-template-columns: 1fr; + grid-row-gap: 0; + } +} + header { + position: relative; display: block; - z-index: 2; + z-index: 6; top: 0; background-color: $primary-dark; color: #fff; fill: #fff; - .padded { - padding: $-m; - } border-bottom: 1px solid #DDD; + box-shadow: $bs-card; + padding: $-xxs 0; .links { display: inline-block; vertical-align: top; - margin-left: $-m; } .links a { display: inline-block; @@ -28,15 +38,6 @@ header { padding-left: $-m; padding-right: 0; } - @include smaller-than($screen-md) { - .links a { - padding-left: $-s; - padding-right: $-s; - } - .dropdown-container { - padding-left: $-s; - } - } .avatar, .user-name { display: inline-block; } @@ -63,27 +64,17 @@ header { padding-top: 4px; font-size: 18px; } - @include smaller-than($screen-md) { + @include between($l, $xl) { padding-left: $-xs; .name { display: none; } } } - @include smaller-than($screen-sm) { - text-align: center; - .float.right { - float: none; - } - .links a { - padding: $-s; - } - .user-name { - padding-top: $-s; - } - } } + + .header-search { display: inline-block; } @@ -92,13 +83,16 @@ header .search-box { margin-top: 10px; input { background-color: rgba(0, 0, 0, 0.2); - border: 1px solid rgba(255, 255, 255, 0.3); + border: 1px solid rgba(255, 255, 255, 0.2); + border-radius: 40px; color: #EEE; z-index: 2; + padding-left: 40px; } button { fill: #EEE; z-index: 1; + left: 16px; svg { margin-right: 0; } @@ -115,20 +109,11 @@ header .search-box { :-moz-placeholder { /* Firefox 18- */ color: #DDD; } - @include smaller-than($screen-lg) { - max-width: 250px; - } - @include smaller-than($l) { + @include between($l, $xl) { max-width: 200px; } } -@include smaller-than($s) { - .header-search { - display: block; - } -} - .logo { display: inline-block; &:hover { @@ -151,10 +136,184 @@ header .search-box { height: 43px; } -.breadcrumbs span.sep { - color: #aaa; +.mobile-menu-toggle { + color: #FFF; + fill: #FFF; + font-size: 2em; + border: 2px solid rgba(255, 255, 255, 0.8); + border-radius: 4px; padding: 0 $-xs; + position: absolute; + right: $-m; + top: 13px; + line-height: 1; + cursor: pointer; + user-select: none; + svg { + margin: 0; + bottom: -2px; + } } + +@include smaller-than($l) { + header .header-links { + display: none; + background-color: #FFF; + z-index: 10; + right: $-m; + border-radius: 4px; + overflow: hidden; + position: absolute; + box-shadow: $bs-hover; + margin-top: -$-xs; + &.show { + display: block; + } + } + header .links a, header .dropdown-container ul li a { + text-align: left; + display: block; + padding: $-s $-m; + color: $text-dark; + fill: $text-dark; + svg { + margin-right: $-s; + } + &:hover { + background-color: #EEE; + color: #444; + fill: #444; + text-decoration: none; + } + } + header .dropdown-container { + display: block; + padding-left: 0; + } + header .links { + display: block; + } + header .dropdown-container ul { + display: block !important; + position: relative; + background-color: transparent; + border: 0; + padding: 0; + margin: 0; + box-shadow: none; + } +} + +.tri-layout-mobile-tabs { + position: sticky; + top: 0; + z-index: 5; + background-color: #FFF; + border-bottom: 1px solid #DDD; + box-shadow: $bs-card; +} +.tri-layout-mobile-tab { + text-align: center; + border-bottom: 3px solid #BBB; + &:first-child { + border-right: 1px solid #DDD; + } + &.active { + border-bottom-color: currentColor; + } +} + +.breadcrumbs { + display: flex; + flex-direction: row; + align-items: center; + justify-content: flex-start; + flex-wrap: wrap; + opacity: 0.7; + .icon-list-item { + width: auto; + padding-top: $-xs; + padding-bottom: $-xs; + } + .separator { + display: inline-block; + fill: #aaa; + font-size: 1.6em; + line-height: 0.8; + margin: -2px 0 0; + } + &:hover { + opacity: 1; + } +} + +@include smaller-than($l) { + .breadcrumbs .icon-list-item { + padding: $-xs; + > span + span { + display: none; + } + > span:first-child { + margin-right: 0; + } + } +} + +.breadcrumb-listing { + position: relative; + .breadcrumb-listing-toggle { + padding: 6px; + border: 1px solid transparent; + border-radius: 4px; + &:hover { + border-color: #DDD; + } + } + .svg-icon { + margin-right: 0; + } +} + +.breadcrumb-listing-dropdown { + box-shadow: $bs-med; + overflow: hidden; + min-height: 100px; + width: 240px; + display: none; + position: absolute; + z-index: 80; + right: -$-m; + .breadcrumb-listing-search .svg-icon { + position: absolute; + left: $-s; + top: 11px; + fill: #888; + pointer-events: none; + } + .breadcrumb-listing-entity-list { + max-height: 400px; + overflow-y: scroll; + text-align: left; + } + input { + padding-left: $-xl; + border-radius: 0; + border: 0; + border-bottom: 1px solid #DDD; + } +} + +@include smaller-than($m) { + .breadcrumb-listing-dropdown { + position: fixed; + right: auto; + left: $-m; + } + .breadcrumb-listing-dropdown .breadcrumb-listing-entity-list { + max-height: 240px; + } +} + .faded { a, button, span, span > div { color: #666; @@ -175,20 +334,9 @@ header .search-box { padding: $-s; } -.faded-small { - color: #000; - fill: #000; - font-size: 0.9em; - background-color: $primary-faded; -} - -.toolbar-container { - background-color: #FFF; -} - -.breadcrumbs .text-button, .action-buttons .text-button { +.action-buttons .text-button { display: inline-block; - padding: $-s; + padding: $-xs $-s; &:last-child { padding-right: 0; } @@ -217,28 +365,12 @@ header .search-box { } @include smaller-than($m) { - .breadcrumbs .text-button, .action-buttons .text-button { + .action-buttons .text-button { padding: $-xs $-xs; } .action-buttons .dropdown-container:last-child a { padding-left: $-xs; } - .breadcrumbs .text-button { - font-size: 0; - } - .breadcrumbs .text-button svg { - font-size: $fs-m; - } - .breadcrumbs a i { - font-size: $fs-m; - padding-right: 0; - } - .breadcrumbs span.sep { - padding: 0 $-xxs; - } - .toolbar .col-xs-1:first-child { - padding-right: 0; - } } .nav-tabs { @@ -253,7 +385,4 @@ header .search-box { border-bottom: 2px solid $primary; } } -} -.faded-small .nav-tabs a { - padding: $-s $-m; } \ No newline at end of file diff --git a/resources/assets/sass/_html.scss b/resources/assets/sass/_html.scss index 65f05a71d..7c3a3c49b 100644 --- a/resources/assets/sass/_html.scss +++ b/resources/assets/sass/_html.scss @@ -3,27 +3,18 @@ } html { - background-color: #FFFFFF; height: 100%; overflow-y: scroll; + background-color: #F2F2F2; &.flexbox { overflow-y: hidden; } - &.shaded { - background-color: #F2F2F2; - } } body { font-size: $fs-m; line-height: 1.6; - color: #616161; + color: #444; -webkit-font-smoothing: antialiased; - &.shaded { - background-color: #F2F2F2; - } -} - -button { - font-size: 100%; + background-color: #F2F2F2; } \ No newline at end of file diff --git a/resources/assets/sass/_layout.scss b/resources/assets/sass/_layout.scss new file mode 100644 index 000000000..137048935 --- /dev/null +++ b/resources/assets/sass/_layout.scss @@ -0,0 +1,312 @@ + +/** + * Generic content container + */ +.container { + max-width: $xxl; + margin-left: auto; + margin-right: auto; + padding-left: $-m; + padding-right: $-m; + &.small { + max-width: 840px; + } + &.very-small { + max-width: 480px; + } +} + +/** + * Core grid layout system + */ +.grid { + display: grid; + grid-column-gap: $-l; + grid-row-gap: $-l; + &.half { + grid-template-columns: 1fr 1fr; + } + &.third { + grid-template-columns: 1fr 1fr 1fr; + } + &.left-focus { + grid-template-columns: 2fr 1fr; + } + &.right-focus { + grid-template-columns: 1fr 3fr; + } + &.gap-y-xs { + grid-row-gap: $-xs; + } + &.gap-xl { + grid-column-gap: $-xl; + grid-row-gap: $-xl; + } + &.gap-xxl { + grid-column-gap: $-xxl; + grid-row-gap: $-xxl; + } + &.v-center { + align-items: center; + } + &.no-gap { + grid-row-gap: 0; + grid-column-gap: 0; + } + &.no-row-gap { + grid-row-gap: 0; + } +} + +@include smaller-than($m) { + .grid.third { + grid-template-columns: 1fr 1fr; + } + .grid.half:not(.no-break), .grid.left-focus:not(.no-break), .grid.right-focus:not(.no-break) { + grid-template-columns: 1fr; + } + .grid.half.collapse-xs { + grid-template-columns: 1fr 1fr; + } + .grid.gap-xl { + grid-column-gap: $-m; + grid-row-gap: $-m; + } + .grid.right-focus.reverse-collapse > *:nth-child(2) { + order: 0; + } + .grid.right-focus.reverse-collapse > *:nth-child(1) { + order: 1; + } +} + +@include smaller-than($s) { + .grid.third { + grid-template-columns: 1fr; + } +} + +@include smaller-than($xs) { + .grid.half.collapse-xs { + grid-template-columns: 1fr; + } +} + +/** + * Flexbox layout system + */ +body.flexbox { + display: flex; + flex-direction: column; + align-items: stretch; + height: 100%; + min-height: 100%; + max-height: 100%; + overflow: hidden; + #content { + flex: 1; + display: flex; + min-height: 0; + } +} + +.flex-fill { + display: flex; + align-items: stretch; + min-height: 0; + max-width: 100%; + position: relative; +} + +.flex { + min-height: 0; + flex: 1; +} + + +/** + * Display and float utilities + */ +.block { + display: block; + position: relative; +} + +.inline { + display: inline; +} + +.block.inline { + display: inline-block; +} + +.float { + float: left; + &.right { + float: right; + } +} + +/** + * Visibility + */ +@each $sizeLetter, $size in $screen-sizes { + @include smaller-than($size) { + .hide-under-#{$sizeLetter} { + display: none !important; + } + } + @include larger-than($size) { + .hide-over-#{$sizeLetter} { + display: none !important; + } + } +} + +/** + * Inline content columns + */ +.dual-column-content { + columns: 2; +} + +@include smaller-than($m) { + .dual-column-content { + columns: 1; + } +} + + +/** + * Fixes + */ +.clearfix:before, +.clearfix:after { + content: " "; + display: table; +} +.clearfix:after { + clear: both; +} + +/** + * View Layouts + */ +.tri-layout-container { + display: grid; + margin-left: $-xl; + margin-right: $-xl; + grid-template-columns: 1fr 4fr 1fr; + grid-template-areas: "a b c"; + grid-column-gap: $-xxl; + .tri-layout-right { + grid-area: c; + min-width: 0; + } + .tri-layout-left { + grid-area: a; + min-width: 0; + } + .tri-layout-middle { + grid-area: b; + padding-top: $-m; + } +} +@include smaller-than($xxl) { + .tri-layout-container { + grid-template-areas: "c b b" + "a b b"; + grid-template-columns: 1fr 3fr; + grid-template-rows: max-content min-content; + padding-right: $-l; + } +} +@include larger-than($xxl) { + .tri-layout-left-contents, .tri-layout-right-contents { + padding: $-m; + position: sticky; + top: $-m; + max-height: 100vh; + min-height: 50vh; + overflow-y: scroll; + overflow-x: hidden; + scrollbar-width: none; + -ms-overflow-style: none; + &::-webkit-scrollbar { + display: none; + } + } + .tri-layout-middle-contents { + max-width: 940px; + margin: 0 auto; + } +} + +@include smaller-than($l) { + .tri-layout-container { + grid-template-areas: none; + grid-template-columns: 1fr; + grid-column-gap: 0; + padding-right: $-xs; + padding-left: $-xs; + .tri-layout-left-contents, .tri-layout-right-contents { + padding-left: $-m; + padding-right: $-m; + } + .tri-layout-right-contents > div, .tri-layout-left-contents > div { + opacity: 0.6; + z-index: 0; + } + .tri-layout-left > *, .tri-layout-right > * { + display: none; + pointer-events: none; + } + .tri-layout-left, .tri-layout-right { + grid-area: none; + grid-column: 1/1; + grid-row: 1; + padding-top: 0 !important; + } + .tri-layout-middle { + grid-area: none; + grid-row: 3; + grid-column: 1/1; + z-index: 1; + overflow: hidden; + transition: transform ease-in-out 240ms; + } + .tri-layout-left { + grid-row: 2; + } + &.show-info { + overflow: hidden; + .tri-layout-middle { + display: none; + } + .tri-layout-right > *, .tri-layout-left > * { + display: block; + pointer-events: auto; + } + } + } +} +@include larger-than($l) { + .tri-layout-mobile-tabs { + display: none; + } +} + +@include smaller-than($m) { + .tri-layout-container { + margin-left: 0; + margin-right: 0; + } +} + +.tri-layout-left-contents > div, .tri-layout-right-contents > div { + opacity: 0.6; + transition: opacity ease-in-out 120ms; + &:hover { + opacity: 1; + } +} \ No newline at end of file diff --git a/resources/assets/sass/_lists.scss b/resources/assets/sass/_lists.scss index 18a7ea9ce..dc4dc8816 100644 --- a/resources/assets/sass/_lists.scss +++ b/resources/assets/sass/_lists.scss @@ -1,182 +1,217 @@ -.page-list { - h4 { - margin: $-l 0 $-xs 0; - font-size: 1.666em; + +.book-contents .entity-list-item { + .icon { + width: 4px; + border-radius: 1px; + justify-self: stretch; + align-self: stretch; + height: auto; + margin-right: $-l; } - a.chapter { - color: $color-chapter; + .icon:after { + opacity: 0.5; } - .inset-list { + .icon svg { display: none; - overflow: hidden; } - h5 { - display: block; - margin: $-s 0 0 0; - border-left: 5px solid $color-page; - padding: $-xs 0 $-xs $-m; - font-size: 1.1em; - font-weight: normal; - &.draft { - border-left-color: $color-page-draft; - } + p { + margin-bottom: 0; } - .entity-list-item { - margin-bottom: $-m; - } - hr { - margin-top: 0; - } - .page, .chapter, .book { - padding-left: $-l; - } - .page { - border-left: 5px solid $color-page; - } - .page.draft { - border-left: 5px solid $color-page-draft; - .text-page { - color: $color-page-draft; - fill: $color-page-draft; - } - } - .chapter { - border-left: 5px solid $color-chapter; - } - .book { - border-left: 5px solid $color-book; - } - .meta { - margin-top: -$-m; - font-size: 0.95em; - } - .meta span { - margin-right: $-s; + .inner-page { + padding-top: 0; + padding-bottom: 0; } } -@include smaller-than($s) { - .page-list h4 { - font-size: 1.333em; +.entity-list-item + .chapter-expansion { + display: flex; + padding: 0 $-m $-m $-m; + align-items: center; + border: 0; + width: 100%; + position: relative; + > .icon { + width: 4px; + height: auto; + border-radius: 0 0 1px 1px; + align-self: stretch; + flex-shrink: 0; + &:before { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 1px; + background-color: currentColor; + content: ''; + opacity: 0.5; + } + &:after { + opacity: 0.5; + } + } + .icon svg { + display: none; + } + > .content { + flex: 1; + } + .chapter-expansion-toggle { + border-radius: 0 4px 4px 0; + padding: $-xs $-m; + } + .chapter-expansion-toggle:hover { + background-color: rgba(0, 0, 0, 0.06); + } +} + +.entity-list-item.has-children { + padding-bottom: 0; + > .icon { + border-radius: 4px 4px 0 0; + } +} + +.inset-list { + display: none; + .entity-list-item-name { + font-size: 1rem; + } + .entity-list-item-children { + padding-top: 0; + padding-bottom: 0; } } .sidebar-page-nav { - $nav-indent: $-s; + $nav-indent: $-m; list-style: none; - margin: $-s 0 $-m 2px; - border-left: 2px dotted #BBB; + margin: $-s 0 $-m $-xs; + position: relative; + &:after { + content: ''; + display: block; + position: absolute; + left: 0; + background-color: rgba(0, 0, 0, 0.2); + width: 2px; + top: 5px; + bottom: 5px; + z-index: 0; + } li { - padding-left: $-s; margin-bottom: 4px; font-size: 0.95em; + position: relative; } .h1 { - margin-left: -2px; + padding-left: $nav-indent; } .h2 { - margin-left: -2px; + padding-left: $nav-indent; } .h3 { - margin-left: $nav-indent; + padding-left: $nav-indent * 2; } .h4 { - margin-left: $nav-indent*2; + padding-left: $nav-indent * 2.5; } .h5 { - margin-left: $nav-indent*3; + padding-left: $nav-indent*3; } .h6 { - margin-left: $nav-indent*4; + padding-left: $nav-indent*3.5; } .current-heading { font-weight: bold; } + li:not(.current-heading) .sidebar-page-nav-bullet { + background-color: #BBB !important; + } + .sidebar-page-nav-bullet { + width: 6px; + height: 6px; + position: absolute; + left: -2px; + top: 30%; + border-radius: 50%; + box-shadow: 0 0 0 6px #F2F2F2; + z-index: 1; + } } // Sidebar list -.book-tree { - transition: ease-in-out 240ms; - transition-property: right, border; -} -.book-tree h4 { - padding: $-m $-s 0 $-s; - i { - padding-right: $-s; - } -} -.book-tree .sidebar-page-list { +.book-tree .sidebar-page-list { list-style: none; - margin: $-xs 0 0; + margin: $-xs -$-s 0 -$-s; padding-left: 0; - border-left: 5px solid $color-book; - li a { + padding-right: 0; + position: relative; + + &:after, .sub-menu:after { + content: ''; display: block; - border-bottom: none; - padding: $-xs 0 $-xs $-s; - &:hover { - text-decoration: none; - } - } - li a i { - padding-right: $-xs + 2px; - } - li, a { - display: block; - } - a.bold { - color: #EEE !important; - fill: #EEE !important; + position: absolute; + left: $-m; + top: 1rem; + bottom: 1rem; + border-left: 4px solid rgba(0, 0, 0, 0.1); + z-index: 0; } + ul { list-style: none; + padding-left: 1rem; + padding-right: 0; + } + .entity-list-item { + padding-top: $-xxs; + padding-bottom: $-xxs; + .content { + padding-top: $-xs; + padding-bottom: $-xs; + max-width: calc(100% - 20px); + } + } + .entity-list-item.no-hover { + margin-top: -$-xs; + padding-right: 0; + } + .entity-list-item-name { + font-size: 1em; margin: 0; } - .book { - color: $color-book !important; - fill: $color-book !important; - &.selected { - background-color: rgba($color-book, 0.29); - } - } - .chapter { - color: $color-chapter !important; - fill: $color-chapter !important; - &.selected { - background-color: rgba($color-chapter, 0.12); - } - } - .page { - color: $color-page !important; - fill: $color-page !important; - border-bottom: none; - &.selected { - background-color: rgba($color-page, 0.1); - } + .chapter-child-menu { + font-size: .8rem; + margin-top: -.2rem; + margin-left: -1rem; } [chapter-toggle] { - padding-left: $-s; + padding-left: .7rem; + padding-bottom: .2rem; } - .list-item-chapter { - border-left: 5px solid $color-chapter; - margin: 10px 10px; - display: block; + .entity-list-item .icon { + z-index: 2; + width: 4px; + height: auto; + align-self: stretch; + flex-shrink: 0; + border-radius: 1px; + opacity: 0.6; } - .list-item-page { - border-bottom: none; - border-left: 5px solid $color-page; - margin: 10px 10px; + .entity-list-item .icon:after { + opacity: 1; } - .list-item-page.draft { - border-left: 5px solid $color-page-draft; + .entity-list-item .icon svg { + display: none; } - .page.draft .page, .list-item-page.draft a.page { - color: $color-page-draft !important; - fill: $color-page-draft !important; - } - .sub-menu { +} + +.chapter-child-menu { + ul.sub-menu { display: none; padding-left: 0; + position: relative; } [chapter-toggle].open + .sub-menu { display: block; @@ -186,26 +221,41 @@ // Sortable Lists .sortable-page-list, .sortable-page-list ul { list-style: none; - background-color: #FFF; } .sort-box { margin-bottom: $-m; - padding: 0 $-l 0 $-l; - border-left: 4px solid $color-book; + border: 2px solid rgba($color-book, 0.6); + padding: $-m $-xl; + border-radius: 4px; +} +.sort-box-options { + display: flex; + flex-wrap: wrap; + justify-content: space-between; +} +.sort-box-options .button { + margin-left: 0; } .sortable-page-list { margin-left: 0; + padding: 0; + .entity-list-item > span:first-child { + align-self: flex-start; + } + .entity-list-item > div { + display: block; + flex: 1; + } > ul { margin-left: 0; } ul { - margin-bottom: 0; + margin-bottom: $-m; margin-top: 0; - box-shadow: 0 0 1px 0 rgba(0, 0, 0, 0.1); + padding-left: $-m; } li { border: 1px solid #DDD; - padding: $-xs $-s; margin-top: -1px; min-height: 38px; &.text-chapter { @@ -228,18 +278,26 @@ .activity-list-item { padding: $-s 0; + display: grid; + grid-template-columns: min-content 1fr; + grid-column-gap: $-m; color: #888; fill: #888; - border-bottom: 1px solid #EEE; font-size: 0.9em; - .left { - float: left; - } - .left + .right { - margin-left: 30px + $-s; - } - &:last-of-type { - border-bottom: 0; +} +.card .activity-list-item { + padding: $-s $-m; +} + +.user-list-item { + display: inline-grid; + padding: $-s; + grid-template-columns: min-content 1fr; + grid-column-gap: $-m; + font-size: 0.9em; + align-items: center; + > div:first-child { + line-height: 0; } } @@ -280,10 +338,8 @@ ul.pagination { margin: 0; } -.entity-list { - > div { - padding: $-m 0; - } +.entity-list, .icon-list { + margin: 0 (-$-m); h4 { margin: 0; } @@ -302,15 +358,125 @@ ul.pagination { color: $color-page-draft; fill: $color-page-draft; } + > .dropdown-container { + display: block; + } } -.card .entity-list-item, .card .activity-list-item { - padding-left: $-m; - padding-right: $-m; +.icon-list hr { + margin: $-s $-m; + max-width: 140px; + opacity: 0.25; + height: 1.1px; +} + +.icon-list hr + hr, .icon-list hr:first-child, .icon-list hr:last-child { + display: none; +} + +.entity-list-item, .icon-list-item { + padding: $-s $-m; + display: flex; + align-items: center; + background-color: transparent; + border: 0; + width: 100%; + position: relative; + word-break: break-word; + h4 a { + color: #666; + } + > span:first-child { + margin-right: $-m; + flex-basis: 1.88em; + flex: none; + } + > span:last-child { + flex: 1; + text-align: left; + } + &:not(.no-hover) { + cursor: pointer; + } + &:not(.no-hover):hover { + text-decoration: none; + background-color: rgba(0, 0, 0, 0.1); + border-radius: 4px; + } + &.outline-hover { + border: 1px solid transparent; + } + &.outline-hover:hover { + background-color: transparent; + border-color: rgba(0, 0, 0, 0.1); + } +} + +.entity-list-item-path-sep { + display: inline-block; + vertical-align: top; + position: relative; + top: 1px; + svg { + margin-right: 0; + } +} + +.card .entity-list-item:not(.no-hover):hover { + background-color: #F2F2F2; +} +.card .entity-list-item .entity-list-item:hover { + background-color: #EEEEEE; +} + +.entity-list-item-children { + padding: $-m; + > div { + overflow: hidden; + padding: $-xs 0; + margin-top: -$-xs; + } + .entity-chip { + text-overflow: ellipsis; + height: 2.5em; + overflow: hidden; + text-align: left; + display: block; + white-space: nowrap; + } +} + +.entity-list-item-image { + align-self: stretch; + width: 140px; + flex: none; + background-size: cover; + background-position: 50% 50%; + border-radius: 3px; + position: relative; + margin-right: $-l; + + .svg-icon { + color: #FFF; + fill: #FFF; + font-size: 1.66rem; + margin-right: 0; + position: absolute; + bottom: $-xs; + left: $-xs; + } + + @include smaller-than($m) { + width: 80px; + } +} + +.chapter > .entity-list-item-image { + width: 60px; } .entity-list.compact { - font-size: 0.6em; + font-size: 0.6 * $fs-m; h4, a { line-height: 1.2; } @@ -331,6 +497,11 @@ ul.pagination { hr { margin: 0; } + @include smaller-than($m) { + h4 { + font-size: 1.666em; + } + } } .dropdown-container { @@ -363,9 +534,8 @@ ul.pagination { color: #999; fill: #999; } - li.padded { - padding: $-xs $-m; - line-height: 1.2; + li.active a { + font-weight: 600; } a, button { display: block; @@ -396,7 +566,10 @@ ul.pagination { .featured-image-container { position: relative; overflow: hidden; - background: #F2F2F2; + min-height: 140px; + background-size: cover; + background-position: 50% 50%; + transition: opacity ease-in-out 240ms; a { display: block; } @@ -405,11 +578,46 @@ ul.pagination { width: 100%; max-width: 100%; height: auto; - transition: all .5s ease-in-out; - } - img:hover { - transform: scale(1.15); - opacity: .5; } } +.featured-image-container-wrap { + position: relative; + .svg-icon { + color: #FFF; + fill: #FFF; + font-size: 2rem; + margin-right: 0; + position: absolute; + bottom: 10px; + left: 6px; + } +} +.grid-card:hover .featured-image-container { + opacity: .5; +} +.action-link-list { + //padding: $-s 0; +} +.action-link { + background: transparent; + border: none; + color: currentColor; + padding: $-m 0; +} + +.active-link-list { + a { + display: inline-block; + padding: $-s; + } + a:not(.active) { + color: #444; + fill: #444; + } + a:hover { + background-color: rgba(0, 0, 0, 0.05); + border-radius: 3px; + text-decoration: none; + } +} \ No newline at end of file diff --git a/resources/assets/sass/_mixins.scss b/resources/assets/sass/_mixins.scss index 3d3101ca7..1c45ebd30 100644 --- a/resources/assets/sass/_mixins.scss +++ b/resources/assets/sass/_mixins.scss @@ -5,12 +5,6 @@ @mixin larger-than($size) { @media screen and (min-width: $size) { @content; } } -@mixin clearfix() { - &:after { - display: block; - content: ''; - font-size: 0; - clear: both; - position: relative; - } +@mixin between($min, $max) { + @media screen and (min-width: $min) and (max-width: $max) { @content; } } diff --git a/resources/assets/sass/_pages.scss b/resources/assets/sass/_pages.scss index 84280319d..969682c3b 100755 --- a/resources/assets/sass/_pages.scss +++ b/resources/assets/sass/_pages.scss @@ -3,12 +3,12 @@ flex-direction: column; align-items: stretch; overflow: hidden; - .faded-small { - height: auto; - } + background-color: #FFF; + .edit-area { flex: 1; flex-direction: column; + z-index: 1; } .mce-tinymce { @@ -20,6 +20,39 @@ } } +@include smaller-than($l) { + .page-edit-toolbar { + overflow-x: scroll; + overflow-y: visible; + z-index: 4; + } + .page-edit-toolbar .grid.third { + display: block; + white-space: nowrap; + > div { + display: inline-block; + } + } +} + +@include smaller-than($l) { + .page-edit-toolbar #save-button { + position: fixed; + z-index: 30; + background-color: #FFF; + border-radius: 50%; + width: 42px; + height: 42px; + font-size: 16px; + right: $-m; + bottom: $-xs; + box-shadow: $bs-med; + span { + display: none; + } + } +} + .draft-notification { pointer-events: none; transform: scale(0); @@ -38,11 +71,7 @@ width: 100%; max-width: 840px; margin: 0 auto; - margin-top: $-xxl; overflow-wrap: break-word; - &.flex { - margin-top: $-m; - } .align-left { text-align: left; } @@ -248,13 +277,6 @@ min-height: 0px; overflow-y: scroll; } - div[toolbox-tab-content] .padded { - flex: 1; - padding-top: 0; - } - div[toolbox-tab-content] .padded.files { - overflow-x: hidden; - } h4 { font-size: 24px; margin: $-m 0 0 0; @@ -349,16 +371,10 @@ } } -.comments-container { - width: 100%; - border-top: 1px solid #DDD; - margin-top: $-xl; - margin-bottom: $-m; - h5 { - color: #888; - font-weight: normal; - margin-top: 0.5em; - } +.comments-container h5 { + color: #888; + font-weight: normal; + margin-top: 0.5em; } .comment-editor .CodeMirror, .comment-editor .CodeMirror-scroll { @@ -370,4 +386,60 @@ .mce-open { display: none; } +} + +.entity-list-item > span:first-child, .icon-list-item > span:first-child, .chapter-expansion > .icon { + font-size: 0.8rem; + width: 1.88em; + height: 1.88em; + display: flex; + align-items: center; + justify-content: center; + text-align: center; + border-radius: 1em; + position: relative; + overflow: hidden; + svg { + margin: 0; + bottom: 0; + } + &:after { + content: ''; + position: absolute; + background-color: currentColor; + opacity: 0.2; + left: 0; + top: 0; + width: 100%; + height: 100%; + } +} + +.entity-chip { + display: inline-block; + align-items: center; + justify-content: center; + text-align: center; + font-size: 0.9em; + border-radius: 3px; + position: relative; + overflow: hidden; + padding: $-xs $-s; + fill: currentColor; + opacity: 0.85; + transition: opacity ease-in-out 120ms; + &:after { + content: ''; + position: absolute; + background-color: currentColor; + opacity: 0.15; + left: 0; + top: 0; + width: 100%; + height: 100%; + } + &:hover { + text-decoration: none; + opacity: 1; + } } \ No newline at end of file diff --git a/resources/assets/sass/_spacing.scss b/resources/assets/sass/_spacing.scss new file mode 100644 index 000000000..69ed5a2d3 --- /dev/null +++ b/resources/assets/sass/_spacing.scss @@ -0,0 +1,32 @@ +// Here we generate spacing utility classes for our sizes for all box sides and axis. +// These will output to classes like .px-m (Padding on x-axis, medium size) or .mr-l (Margin right, large size) + +@mixin spacing($prop, $propLetter) { + @each $sizeLetter, $size in $spacing { + .#{$propLetter}-#{$sizeLetter} { + #{$prop}: $size !important; + } + .#{$propLetter}x-#{$sizeLetter} { + #{$prop}-left: $size !important; + #{$prop}-right: $size !important; + } + .#{$propLetter}y-#{$sizeLetter} { + #{$prop}-top: $size !important; + #{$prop}-bottom: $size !important; + } + .#{$propLetter}t-#{$sizeLetter} { + #{$prop}-top: $size !important; + } + .#{$propLetter}r-#{$sizeLetter} { + #{$prop}-right: $size !important; + } + .#{$propLetter}b-#{$sizeLetter} { + #{$prop}-bottom: $size !important; + } + .#{$propLetter}l-#{$sizeLetter} { + #{$prop}-left: $size !important; + } + } +} +@include spacing('margin', 'm') +@include spacing('padding', 'p') \ No newline at end of file diff --git a/resources/assets/sass/_tables.scss b/resources/assets/sass/_tables.scss index ec24e2fa6..a1a2fef0a 100644 --- a/resources/assets/sass/_tables.scss +++ b/resources/assets/sass/_tables.scss @@ -19,13 +19,13 @@ table { table.table { width: 100%; - tr { - border-bottom: 1px solid #DDD; + tr td, tr th { + border-bottom: 1px solid rgba(0, 0, 0, 0.05); } th, td { text-align: left; border: none; - padding: $-xs $-xs; + padding: $-s $-s; vertical-align: middle; margin: 0; } @@ -44,6 +44,9 @@ table.table { td.actions { overflow: visible; } + a { + display: inline-block; + } } table.no-style { diff --git a/resources/assets/sass/_text.scss b/resources/assets/sass/_text.scss index 0063c4672..dd1c74d24 100644 --- a/resources/assets/sass/_text.scss +++ b/resources/assets/sass/_text.scss @@ -42,7 +42,7 @@ h1, h2, h3, h4, h5, h6 { font-weight: 400; position: relative; display: block; - color: #555; + color: #222; .subheader { font-size: 0.5em; line-height: 1em; @@ -79,10 +79,18 @@ h5, h6 { } } +.list-heading { + font-size: 2rem; +} + +h2.list-heading { + font-size: 1.333rem; +} + /* * Link styling */ -a, .link { +a { color: $primary; cursor: pointer; text-decoration: none; @@ -141,11 +149,8 @@ em, i, .italic { } small, p.small, span.small, .text-small { - font-size: 0.8em; - color: lighten($text-dark, 20%); - small, p.small, span.small, .text-small { - font-size: 1em; - } + font-size: 0.75rem; + color: lighten($text-dark, 10%); } sup, .superscript { @@ -233,106 +238,6 @@ pre code { display: block; line-height: 1.6; } -/* - * Text colors - */ -p.pos, p .pos, span.pos, .text-pos { - color: $positive; - fill: $positive; - &:hover { - color: $positive; - fill: $positive; - } -} - -p.neg, p .neg, span.neg, .text-neg { - color: $negative; - fill: $negative; - &:hover { - color: $negative; - fill: $negative; - } -} - -p.muted, p .muted, span.muted, .text-muted { - color: lighten($text-dark, 26%); - fill: lighten($text-dark, 26%); - &.small, .small { - color: lighten($text-dark, 32%); - fill: lighten($text-dark, 32%); - } -} - -p.primary, p .primary, span.primary, .text-primary { - color: $primary; - fill: $primary; - &:hover { - color: $primary; - fill: $primary; - } -} - -p.secondary, p .secondary, span.secondary, .text-secondary { - color: $secondary; - fill: $secondary; - &:hover { - color: $secondary; - fill: $secondary; - } -} - -.text-bookshelf { - color: $color-bookshelf; - fill: $color-bookshelf; - &:hover { - color: $color-bookshelf; - fill: $color-bookshelf; - } -} -.text-book { - color: $color-book; - fill: $color-book; - &:hover { - color: $color-book; - fill: $color-book; - } -} -.text-page { - color: $color-page; - fill: $color-page; - &:hover { - color: $color-page; - fill: $color-page; - } - &.draft { - color: $color-page-draft; - fill: $color-page-draft; - } - &.draft:hover { - color: $color-page-draft; - fill: $color-page-draft; - } -} -.text-chapter { - color: $color-chapter; - fill: $color-chapter; - &:hover { - color: $color-chapter; - fill: $color-chapter; - } -} -.faded .text-book:hover { - color: $color-book !important; - fill: $color-book !important; -} -.faded .text-chapter:hover { - color: $color-chapter !important; - fill: $color-chapter !important; -} -.faded .text-page:hover { - color: $color-page !important; - fill: $color-page !important; -} span.highlight { //background-color: rgba($primary, 0.2); @@ -435,10 +340,6 @@ span.sep { /** * Icons */ -i { - padding-right: $-xs; -} - .svg-icon { width: 1em; height: 1em; @@ -446,5 +347,6 @@ i { position: relative; bottom: -0.105em; margin-right: $-xs; + pointer-events: none; } diff --git a/resources/assets/sass/_tinymce.scss b/resources/assets/sass/_tinymce.scss index c758619d6..2dbf69164 100644 --- a/resources/assets/sass/_tinymce.scss +++ b/resources/assets/sass/_tinymce.scss @@ -21,6 +21,13 @@ text-align: center; } +@include smaller-than($l) { + .mce-container-body.mce-flow-layout { + overflow-x: scroll; + white-space: nowrap; + } +} + .edit-area.flex > div > .mce-tinymce.mce-container.mce-panel { flex: 1 1 auto; display: flex !important; diff --git a/resources/assets/sass/_variables.scss b/resources/assets/sass/_variables.scss index 006d1b3f0..25b8e09b7 100644 --- a/resources/assets/sass/_variables.scss +++ b/resources/assets/sass/_variables.scss @@ -1,14 +1,12 @@ // Variables /////////////// -// Sizes -$max-width: 1400px; - // Screen breakpoints +$xxl: 1400px; $xl: 1100px; $ipad-width: 1028px; // Is actually 1024 but we go over to ensure functionality. $l: 1000px; -$m: 800px; +$m: 880px; $s: 600px; $xs: 400px; $xxs: 360px; @@ -16,6 +14,9 @@ $screen-lg: 1200px; $screen-md: 992px; $screen-sm: 768px; +// List of screen sizes +$screen-sizes: (('xxs', $xxs), ('xs', $xs), ('s', $s), ('m', $m), ('l', $l), ('xl', $xl)); + // Spacing (Margins+Padding) $-xxxl: 64px; $-xxl: 48px; @@ -26,6 +27,9 @@ $-s: 12px; $-xs: 6px; $-xxs: 3px; +// List of our spacing sizes +$spacing: (('none', 0), ('xxs', $-xxs), ('xs', $-xs), ('s', $-s), ('m', $-m), ('l', $-l), ('xl', $-xl), ('xxl', $-xxl)); + // Fonts $text: -apple-system, BlinkMacSystemFont, "Segoe UI", "Oxygen", "Ubuntu", "Roboto", "Cantarell", @@ -33,8 +37,8 @@ $text: -apple-system, BlinkMacSystemFont, sans-serif; $mono: "Lucida Console", "DejaVu Sans Mono", "Ubunto Mono", Monaco, monospace; $heading: $text; -$fs-m: 15px; -$fs-s: 14px; +$fs-m: 14px; +$fs-s: 12px; // Colours $primary: #0288D1; @@ -49,7 +53,7 @@ $primary-faded: rgba(21, 101, 192, 0.15); // Item Colors $color-bookshelf: #af5a5a; $color-book: #009688; -$color-chapter: #ef7c3c; +$color-chapter: #d7804a; $color-page: $primary; $color-page-draft: #9A60DA; @@ -60,5 +64,5 @@ $text-light: #EEE; // Shadows $bs-light: 0 0 4px 1px #CCC; $bs-med: 0 1px 3px 1px rgba(76, 76, 76, 0.26); -$bs-card: 0 1px 3px 1px rgba(76, 76, 76, 0.26), 0 1px 12px 0px rgba(76, 76, 76, 0.2); +$bs-card: 0 1px 6px -1px rgba(0, 0, 0, 0.1); $bs-hover: 0 2px 2px 1px rgba(0,0,0,.13); \ No newline at end of file diff --git a/resources/assets/sass/export-styles.scss b/resources/assets/sass/export-styles.scss index cc90d5372..4cc782dc0 100644 --- a/resources/assets/sass/export-styles.scss +++ b/resources/assets/sass/export-styles.scss @@ -1,8 +1,9 @@ @import "variables"; @import "mixins"; +@import "spacing"; @import "html"; @import "text"; -@import "grid"; +@import "layout"; @import "blocks"; @import "forms"; @import "tables"; @@ -12,6 +13,9 @@ body { font-family: 'DejaVu Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", "Oxygen", "Ubuntu", "Roboto", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; + background-color: #FFF; + margin: 0; + padding: 0; } table { @@ -19,6 +23,10 @@ table { border-collapse: collapse; } +.page-content { + overflow: hidden; +} + // Prevent code block overflow on export pre { padding-left: 12px; diff --git a/resources/assets/sass/print-styles.scss b/resources/assets/sass/print-styles.scss index c67f98642..44107f2d4 100644 --- a/resources/assets/sass/print-styles.scss +++ b/resources/assets/sass/print-styles.scss @@ -8,10 +8,6 @@ body { font-size: 12px; } -.faded-small { - display: none; -} - .page-content { margin: 0 auto; } diff --git a/resources/assets/sass/styles.scss b/resources/assets/sass/styles.scss index 49ef77f39..424074a0d 100644 --- a/resources/assets/sass/styles.scss +++ b/resources/assets/sass/styles.scss @@ -1,9 +1,11 @@ @import "reset"; @import "variables"; @import "mixins"; +@import "spacing"; @import "html"; @import "text"; -@import "grid"; +@import "colors"; +@import "layout"; @import "blocks"; @import "buttons"; @import "tables"; @@ -94,17 +96,6 @@ $loadingSize: 10px; } } - -// Search results -.search-results > h3 a { - font-size: 0.66em; - color: $primary; - padding-left: $-m; - i { - padding-right: $-s; - } -} - // Back to top link $btt-size: 40px; [back-to-top] { @@ -186,22 +177,28 @@ $btt-size: 40px; overflow-y: scroll; height: 400px; background-color: #EEEEEE; + margin-right: 0; + margin-left: 0; + } + .entity-list-item { + background-color: #FFF; + } + .entity-list-item p { + margin-bottom: 0; + } + .entity-list-item.selected { + background-color: rgba(0, 0, 0, 0.15) !important; } .loading { height: 400px; padding-top: $-l; } - .entity-list > p { - text-align: center; - padding-top: $-l; - font-size: 1.333em; - } - .entity-list > div { - padding-left: $-m; - padding-right: $-m; - background-color: #FFF; - transition: all ease-in-out 120ms; - cursor: pointer; + .entity-selector-add button { + margin: 0; + display: block; + width: 100%; + border: 0; + border-top: 1px solid #DDD; } &.compact { font-size: 10px; @@ -211,12 +208,6 @@ $btt-size: 40px; } } -.entity-list-item.selected { - h3, i, p ,a, span { - color: #EEE; - } -} - .scroll-box { max-height: 250px; overflow-y: scroll; @@ -254,3 +245,39 @@ $btt-size: 40px; height:100%; z-index: 150; } + +.list-sort-container { + display: inline-block; + form { + display: inline-block; + } + .list-sort { + display: inline-grid; + margin-left: $-s; + grid-template-columns: 120px 40px; + border: 2px solid #DDD; + border-radius: 4px; + } + .list-sort-label { + font-weight: bold; + display: inline-block; + color: #888; + } + .list-sort-type { + text-align: left; + } + .list-sort-type, .list-sort-dir { + padding: $-xs $-s; + cursor: pointer; + } + .list-sort-dir { + border-left: 2px solid #DDD; + fill: #888; + .svg-icon { + transition: transform ease-in-out 120ms; + } + &:hover .svg-icon { + transform: rotate(180deg); + } + } +} \ No newline at end of file diff --git a/resources/lang/en/common.php b/resources/lang/en/common.php index ac2edc621..ed880afcf 100644 --- a/resources/lang/en/common.php +++ b/resources/lang/en/common.php @@ -11,6 +11,7 @@ return [ 'save' => 'Save', 'continue' => 'Continue', 'select' => 'Select', + 'toggle_all' => 'Toggle All', 'more' => 'More', // Form Labels @@ -23,6 +24,7 @@ return [ // Actions 'actions' => 'Actions', 'view' => 'View', + 'view_all' => 'View All', 'create' => 'Create', 'update' => 'Update', 'edit' => 'Edit', @@ -37,6 +39,11 @@ return [ 'remove' => 'Remove', 'add' => 'Add', + // Sort Options + 'sort_name' => 'Name', + 'sort_created_at' => 'Created Date', + 'sort_updated_at' => 'Updated Date', + // Misc 'deleted_user' => 'Deleted User', 'no_activity' => 'No activity to show', @@ -53,7 +60,11 @@ return [ 'view_profile' => 'View Profile', 'edit_profile' => 'Edit Profile', + // Layout tabs + 'tab_info' => 'Info', + 'tab_content' => 'Content', + // Email Content 'email_action_help' => 'If you’re having trouble clicking the ":actionText" button, copy and paste the URL below into your web browser:', 'email_rights' => 'All rights reserved', -]; \ No newline at end of file +]; diff --git a/resources/lang/en/entities.php b/resources/lang/en/entities.php index 2a64f57a3..c2c15d72f 100644 --- a/resources/lang/en/entities.php +++ b/resources/lang/en/entities.php @@ -11,6 +11,7 @@ return [ 'recently_updated_pages' => 'Recently Updated Pages', 'recently_created_chapters' => 'Recently Created Chapters', 'recently_created_books' => 'Recently Created Books', + 'recently_created_shelves' => 'Recently Created Shelves', 'recently_update' => 'Recently Updated', 'recently_viewed' => 'Recently Viewed', 'recent_activity' => 'Recent Activity', @@ -67,6 +68,7 @@ return [ // Shelves 'shelf' => 'Shelf', 'shelves' => 'Shelves', + 'x_shelves' => ':count Shelf|:count Shelves', 'shelves_long' => 'Bookshelves', 'shelves_empty' => 'No shelves have been created', 'shelves_create' => 'Create New Shelf', @@ -117,7 +119,6 @@ return [ 'books_permissions_updated' => 'Book Permissions Updated', 'books_empty_contents' => 'No pages or chapters have been created for this book.', 'books_empty_create_page' => 'Create a new page', - 'books_empty_or' => 'or', 'books_empty_sort_current_book' => 'Sort the current book', 'books_empty_add_chapter' => 'Add a chapter', 'books_permissions_active' => 'Book Permissions Active', @@ -125,6 +126,11 @@ return [ 'books_navigation' => 'Book Navigation', 'books_sort' => 'Sort Book Contents', 'books_sort_named' => 'Sort Book :bookName', + 'books_sort_name' => 'Sort by Name', + 'books_sort_created' => 'Sort by Created Date', + 'books_sort_updated' => 'Sort by Updated Date', + 'books_sort_chapters_first' => 'Chapters First', + 'books_sort_chapters_last' => 'Chapters Last', 'books_sort_show_other' => 'Show Other Books', 'books_sort_save' => 'Save New Order', @@ -202,6 +208,8 @@ return [ 'pages_revisions_created_by' => 'Created By', 'pages_revisions_date' => 'Revision Date', 'pages_revisions_number' => '#', + 'pages_revisions_numbered' => 'Revision #:id', + 'pages_revisions_numbered_changes' => 'Revision #:id Changes', 'pages_revisions_changelog' => 'Changelog', 'pages_revisions_changes' => 'Changes', 'pages_revisions_current' => 'Current Version', @@ -267,6 +275,7 @@ return [ 'profile_not_created_pages' => ':userName has not created any pages', 'profile_not_created_chapters' => ':userName has not created any chapters', 'profile_not_created_books' => ':userName has not created any books', + 'profile_not_created_shelves' => ':userName has not created any shelves', // Comments 'comment' => 'Comment', diff --git a/resources/lang/en/settings.php b/resources/lang/en/settings.php index c38068afc..e6c24f5a1 100755 --- a/resources/lang/en/settings.php +++ b/resources/lang/en/settings.php @@ -12,34 +12,44 @@ return [ 'settings_save_success' => 'Settings saved', // App Settings - 'app_settings' => 'App Settings', - 'app_name' => 'Application name', - 'app_name_desc' => 'This name is shown in the header and any emails.', - 'app_name_header' => 'Show Application name in header?', + 'app_customization' => 'Customization', + 'app_features_security' => 'Features & Security', + 'app_name' => 'Application Name', + 'app_name_desc' => 'This name is shown in the header and in any system-sent emails.', + 'app_name_header' => 'Show name in header', + 'app_public_access' => 'Public Access', + 'app_public_access_desc' => 'Enabling this option will allow visitors, that are not logged-in, to access content in your BookStack instance.', + 'app_public_access_desc_guest' => 'Access for public visitors can be controlled through the "Guest" user.', + 'app_public_access_toggle' => 'Allow public access', 'app_public_viewing' => 'Allow public viewing?', - 'app_secure_images' => 'Enable higher security image uploads?', + 'app_secure_images' => 'Higher Security Image Uploads', + 'app_secure_images_toggle' => 'Enable higher security image uploads', 'app_secure_images_desc' => 'For performance reasons, all images are public. This option adds a random, hard-to-guess string in front of image urls. Ensure directory indexes are not enabled to prevent easy access.', - 'app_editor' => 'Page editor', + 'app_editor' => 'Page Editor', 'app_editor_desc' => 'Select which editor will be used by all users to edit pages.', - 'app_custom_html' => 'Custom HTML head content', + 'app_custom_html' => 'Custom HTML Head Content', 'app_custom_html_desc' => 'Any content added here will be inserted into the bottom of the section of every page. This is handy for overriding styles or adding analytics code.', - 'app_logo' => 'Application logo', + 'app_logo' => 'Application Logo', 'app_logo_desc' => 'This image should be 43px in height.
Large images will be scaled down.', - 'app_primary_color' => 'Application primary color', + 'app_primary_color' => 'Application Primary Color', 'app_primary_color_desc' => 'This should be a hex value.
Leave empty to reset to the default color.', 'app_homepage' => 'Application Homepage', 'app_homepage_desc' => 'Select a view to show on the homepage instead of the default view. Page permissions are ignored for selected pages.', 'app_homepage_select' => 'Select a page', - 'app_disable_comments' => 'Disable comments', - 'app_disable_comments_desc' => 'Disable comments across all pages in the application. Existing comments are not shown.', + 'app_disable_comments' => 'Disable Comments', + 'app_disable_comments_toggle' => 'Disable comments', + 'app_disable_comments_desc' => 'Disables comments across all pages in the application.
Existing comments are not shown.', // Registration Settings - 'reg_settings' => 'Registration Settings', - 'reg_allow' => 'Allow registration?', + 'reg_settings' => 'Registration', + 'reg_enable' => 'Enable Registration', + 'reg_enable_toggle' => 'Enable registration', + 'reg_enable_desc' => 'When registration is enabled user will be able to sign themselves up as an application user. Upon registration they are given a single, default user role.', 'reg_default_role' => 'Default user role after registration', - 'reg_confirm_email' => 'Require email confirmation?', - 'reg_confirm_email_desc' => 'If domain restriction is used then email confirmation will be required and the below value will be ignored.', - 'reg_confirm_restrict_domain' => 'Restrict registration to domain', + 'reg_email_confirmation' => 'Email Confirmation', + 'reg_email_confirmation_toggle' => 'Require email confirmation', + 'reg_confirm_email_desc' => 'If domain restriction is used then email confirmation will be required and this option will be ignored.', + 'reg_confirm_restrict_domain' => 'Domain Restriction', 'reg_confirm_restrict_domain_desc' => 'Enter a comma separated list of email domains you would like to restrict registration to. Users will be sent an email to confirm their address before being allowed to interact with the application.
Note that users will be able to change their email addresses after successful registration.', 'reg_confirm_restrict_domain_placeholder' => 'No restriction set', @@ -91,9 +101,16 @@ return [ 'user_profile' => 'User Profile', 'users_add_new' => 'Add New User', 'users_search' => 'Search Users', + 'users_details' => 'User Details', + 'users_details_desc' => 'Set a display name and an email address for this user. The email address will be used for logging into the application.', + 'users_details_desc_no_email' => 'Set a display name for this user so others can recognise them.', 'users_role' => 'User Roles', + 'users_role_desc' => 'Select which roles this user will be assigned to. If a user is assigned to multiple roles the permissions from those roles will stack and they will receive all abilities of the assigned roles.', + 'users_password' => 'User Password', + 'users_password_desc' => 'Set a password used to log-in to the application. This must be at least 5 characters long.', 'users_external_auth_id' => 'External Authentication ID', - 'users_password_warning' => 'Only fill the below if you would like to change your password:', + 'users_external_auth_id_desc' => 'This is the ID used to match this user when communicating with your LDAP system.', + 'users_password_warning' => 'Only fill the below if you would like to change your password.', 'users_system_public' => 'This user represents any guest users that visit your instance. It cannot be used to log in but is assigned automatically.', 'users_delete' => 'Delete User', 'users_delete_named' => 'Delete user :userName', @@ -104,8 +121,9 @@ return [ 'users_edit_profile' => 'Edit Profile', 'users_edit_success' => 'User successfully updated', 'users_avatar' => 'User Avatar', - 'users_avatar_desc' => 'This image should be approx 256px square.', + 'users_avatar_desc' => 'Select an image to represent this user. This should be approx 256px square.', 'users_preferred_language' => 'Preferred Language', + 'users_preferred_language_desc' => 'This option will change the language used for the user-interface of the application. This will not affect any user-created content.', 'users_social_accounts' => 'Social Accounts', 'users_social_accounts_info' => 'Here you can connect your other accounts for quicker and easier login. Disconnecting an account here does not previously authorized access. Revoke access from your profile settings on the connected social account.', 'users_social_connect' => 'Connect Account', diff --git a/resources/views/auth/forms/login/ldap.blade.php b/resources/views/auth/forms/login/ldap.blade.php index b52b5f13e..ecdda6520 100644 --- a/resources/views/auth/forms/login/ldap.blade.php +++ b/resources/views/auth/forms/login/ldap.blade.php @@ -1,12 +1,12 @@
- @include('form/text', ['name' => 'username', 'tabindex' => 1]) + @include('form.text', ['name' => 'username', 'tabindex' => 1])
@if(session('request-email', false) === true)
- @include('form/text', ['name' => 'email', 'tabindex' => 1]) + @include('form.text', ['name' => 'email', 'tabindex' => 1]) {{ trans('auth.ldap_email_hint') }} @@ -15,5 +15,5 @@
- @include('form/password', ['name' => 'password', 'tabindex' => 2]) + @include('form.password', ['name' => 'password', 'tabindex' => 2])
\ No newline at end of file diff --git a/resources/views/auth/forms/login/standard.blade.php b/resources/views/auth/forms/login/standard.blade.php index 4ea1f35ba..a12fbd753 100644 --- a/resources/views/auth/forms/login/standard.blade.php +++ b/resources/views/auth/forms/login/standard.blade.php @@ -1,10 +1,10 @@
- @include('form/text', ['name' => 'email', 'tabindex' => 1]) + @include('form.text', ['name' => 'email', 'tabindex' => 1])
- @include('form/password', ['name' => 'password', 'tabindex' => 2]) - {{ trans('auth.forgot_password') }} + @include('form.password', ['name' => 'password', 'tabindex' => 1]) + {{ trans('auth.forgot_password') }}
\ No newline at end of file diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php index f3847bb04..eb7ca2da8 100644 --- a/resources/views/auth/login.blade.php +++ b/resources/views/auth/login.blade.php @@ -1,44 +1,48 @@ -@extends('public') - -@section('header-buttons') - @if(setting('registration-enabled', false)) - @icon('new-user') {{ trans('auth.sign_up') }} - @endif -@stop +@extends('simple-layout') @section('content') -
-
-

@icon('login') {{ title_case(trans('auth.log_in')) }}

+
-
-
- {!! csrf_field() !!} +
 
- @include('auth/forms/login/' . $authMethod) +
+

{{ title_case(trans('auth.log_in')) }}

-
- - - + + {!! csrf_field() !!} + +
+ @include('auth.forms.login.' . $authMethod) +
+ +
+
+ @include('components.custom-checkbox', [ + 'name' => 'remember', + 'checked' => false, + 'value' => 'on', + 'label' => trans('auth.remember_me'), + ])
- -
- +
+
- +
- @if(count($socialDrivers) > 0) -
- @foreach($socialDrivers as $driver => $name) - + + + @if(count($socialDrivers) > 0) +
+ @foreach($socialDrivers as $driver => $name) +
+
+ @endforeach + @endif
diff --git a/resources/views/auth/passwords/email.blade.php b/resources/views/auth/passwords/email.blade.php index 38f5cc07a..de4edff0a 100644 --- a/resources/views/auth/passwords/email.blade.php +++ b/resources/views/auth/passwords/email.blade.php @@ -1,37 +1,25 @@ -@extends('public') - -@section('header-buttons') - @icon('login') {{ trans('auth.log_in') }} - @if(setting('registration-enabled')) - @icon('new-user') {{ trans('auth.sign_up') }} - @endif -@stop +@extends('simple-layout') @section('content') +
+
+

{{ trans('auth.reset_password') }}

+

{{ trans('auth.reset_password_send_instructions') }}

-
-
-

@icon('permission') {{ trans('auth.reset_password') }}

+
+ {!! csrf_field() !!} -
-

{{ trans('auth.reset_password_send_instructions') }}

+
+ + @include('form.text', ['name' => 'email']) +
- - {!! csrf_field() !!} - -
- - @include('form/text', ['name' => 'email']) -
- -
- -
- -
+
+ +
+
- @stop \ No newline at end of file diff --git a/resources/views/auth/passwords/reset.blade.php b/resources/views/auth/passwords/reset.blade.php index 0f66bd473..fa6ad5b9a 100644 --- a/resources/views/auth/passwords/reset.blade.php +++ b/resources/views/auth/passwords/reset.blade.php @@ -1,43 +1,34 @@ -@extends('public') - -@section('header-buttons') - @icon('login') {{ trans('auth.log_in') }} - @if(setting('registration-enabled')) - @icon('new-user') {{ trans('auth.sign_up') }} - @endif -@stop +@extends('simple-layout') @section('content') -
-
-

@icon('permission') {{ trans('auth.reset_password') }}

+
+
+

{{ trans('auth.reset_password') }}

-
-
- {!! csrf_field() !!} - + + {!! csrf_field() !!} + -
- - @include('form/text', ['name' => 'email']) -
+
+ + @include('form.text', ['name' => 'email']) +
-
- - @include('form/password', ['name' => 'password']) -
+
+ + @include('form.password', ['name' => 'password']) +
-
- - @include('form/password', ['name' => 'password_confirmation']) -
+
+ + @include('form.password', ['name' => 'password_confirmation']) +
-
- -
-
-
+
+ +
+
diff --git a/resources/views/auth/register-confirm.blade.php b/resources/views/auth/register-confirm.blade.php index 22d0f4acb..8fbf8abbb 100644 --- a/resources/views/auth/register-confirm.blade.php +++ b/resources/views/auth/register-confirm.blade.php @@ -1,19 +1,11 @@ -@extends('public') - -@section('header-buttons') - @if(!$signedIn) - @icon('login') {{ trans('auth.log_in') }} - @endif -@stop +@extends('simple-layout') @section('content') -
-
-

@icon('users') {{ trans('auth.register_thanks') }}

-
-

{{ trans('auth.register_confirm', ['appName' => setting('app-name')]) }}

-
+
+
+

{{ trans('auth.register_thanks') }}

+

{{ trans('auth.register_confirm', ['appName' => setting('app-name')]) }}

diff --git a/resources/views/auth/register.blade.php b/resources/views/auth/register.blade.php index 900b394e3..d1e69e0a0 100644 --- a/resources/views/auth/register.blade.php +++ b/resources/views/auth/register.blade.php @@ -1,50 +1,54 @@ -@extends('public') - -@section('header-buttons') - @icon('login') {{ trans('auth.log_in') }} -@stop +@extends('simple-layout') @section('content') +
-
-
-

@icon('new-user') {{ title_case(trans('auth.sign_up')) }}

-
-
- {!! csrf_field() !!} +
 
-
- - @include('form/text', ['name' => 'name']) +
+

{{ title_case(trans('auth.sign_up')) }}

+ + + {!! csrf_field() !!} + +
+ + @include('form.text', ['name' => 'name']) +
+ +
+ + @include('form.text', ['name' => 'email']) +
+ +
+ + @include('form.password', ['name' => 'password', 'placeholder' => trans('auth.password_hint')]) +
+ +
+ - -
- - @include('form/text', ['name' => 'email']) +
+
+
-
- - @include('form/password', ['name' => 'password', 'placeholder' => trans('auth.password_hint')]) -
-
- -
- + - @if(count($socialDrivers) > 0) -
- @foreach($socialDrivers as $driver => $name) - + @if(count($socialDrivers) > 0) +
+ @foreach($socialDrivers as $driver => $name) +
+
+ @endforeach + @endif
- - @stop diff --git a/resources/views/auth/user-unconfirmed.blade.php b/resources/views/auth/user-unconfirmed.blade.php index b02d45d22..54bf6eda3 100644 --- a/resources/views/auth/user-unconfirmed.blade.php +++ b/resources/views/auth/user-unconfirmed.blade.php @@ -1,34 +1,34 @@ -@extends('public') +@extends('simple-layout') @section('content') -
-

 

-
-

@icon('users') {{ trans('auth.email_not_confirmed') }}

-
-

{{ trans('auth.email_not_confirmed_text') }}
- {{ trans('auth.email_not_confirmed_click_link') }}
- {{ trans('auth.email_not_confirmed_resend') }} -

-
-
- {!! csrf_field() !!} -
- - @if(auth()->check()) - @include('form/text', ['name' => 'email', 'model' => auth()->user()]) - @else - @include('form/text', ['name' => 'email']) - @endif -
-
- -
-
-
-
+
+
+

{{ trans('auth.email_not_confirmed') }}

+

{{ trans('auth.email_not_confirmed_text') }}
+ {{ trans('auth.email_not_confirmed_click_link') }} +

+

+ {{ trans('auth.email_not_confirmed_resend') }} +

+ +
+ {!! csrf_field() !!} +
+ + @if(auth()->check()) + @include('form.text', ['name' => 'email', 'model' => auth()->user()]) + @else + @include('form.text', ['name' => 'email']) + @endif +
+
+ +
+
+ +
@stop diff --git a/resources/views/base.blade.php b/resources/views/base.blade.php index fdd248091..367a2cd8b 100644 --- a/resources/views/base.blade.php +++ b/resources/views/base.blade.php @@ -17,75 +17,29 @@ @yield('head') - - @include('partials/custom-styles') - + @include('partials.custom-styles') @include('partials.custom-head') + + @stack('head') - + - @include('partials/notifications') - - + @include('partials.notifications') + @include('common.header')
@yield('content')
-
+
@icon('chevron-up') {{ trans('common.back_to_top') }}
-@yield('bottom') - -@yield('scripts') + + @yield('bottom') + + @yield('scripts') + diff --git a/resources/views/books/create.blade.php b/resources/views/books/create.blade.php index 2d5e6c455..9079a3bf9 100644 --- a/resources/views/books/create.blade.php +++ b/resources/views/books/create.blade.php @@ -1,28 +1,27 @@ @extends('simple-layout') -@section('toolbar') - -@stop - @section('body') +
+
+ @include('partials.breadcrumbs', ['crumbs' => [ + '/books' => [ + 'text' => trans('entities.books'), + 'icon' => 'book' + ], + '/create-book' => [ + 'text' => trans('entities.books_create'), + 'icon' => 'add' + ] + ]]) +
-
-

 

-
-

@icon('add') {{ trans('entities.books_create') }}

-
+
+

{{ trans('entities.books_create') }}

- @include('books/form') + @include('books.form')
-
-


+ @include('components.image-manager', ['imageType' => 'cover']) @stop \ No newline at end of file diff --git a/resources/views/books/delete.blade.php b/resources/views/books/delete.blade.php index 0ac98e895..2860e8bcd 100644 --- a/resources/views/books/delete.blade.php +++ b/resources/views/books/delete.blade.php @@ -1,28 +1,30 @@ @extends('simple-layout') -@section('toolbar') -
- @include('books._breadcrumbs', ['book' => $book]) -
-@stop - @section('body')
-

 

-
-

@icon('delete') {{ trans('entities.books_delete') }}

-
-

{{ trans('entities.books_delete_explain', ['bookName' => $book->name]) }}

-

{{ trans('entities.books_delete_confirmation') }}

-
- {!! csrf_field() !!} - - {{ trans('common.cancel') }} - -
-
+
+ @include('partials.breadcrumbs', ['crumbs' => [ + $book, + $book->getUrl('/delete') => [ + 'text' => trans('entities.books_delete'), + 'icon' => 'delete', + ] + ]]) +
+ +
+

{{ trans('entities.books_delete') }}

+

{{ trans('entities.books_delete_explain', ['bookName' => $book->name]) }}

+

{{ trans('entities.books_delete_confirmation') }}

+ +
+ {!! csrf_field() !!} + + {{ trans('common.cancel') }} + +
diff --git a/resources/views/books/edit.blade.php b/resources/views/books/edit.blade.php index cb1ffc461..f048b543b 100644 --- a/resources/views/books/edit.blade.php +++ b/resources/views/books/edit.blade.php @@ -1,24 +1,27 @@ @extends('simple-layout') -@section('toolbar') -
- @include('books._breadcrumbs', ['book' => $book]) -
-@stop - @section('body')
-

 

-
-

@icon('edit') {{ trans('entities.books_edit') }}

-
-
- - @include('books/form', ['model' => $book]) -
-
+ +
+ @include('partials.breadcrumbs', ['crumbs' => [ + $book, + $book->getUrl('/edit') => [ + 'text' => trans('entities.books_edit'), + 'icon' => 'edit', + ] + ]]) +
+ +
+

{{ trans('entities.books_edit') }}

+
+ + @include('books.form', ['model' => $book]) +
-@include('components.image-manager', ['imageType' => 'cover']) + + @include('components.image-manager', ['imageType' => 'cover']) @stop \ No newline at end of file diff --git a/resources/views/books/export.blade.php b/resources/views/books/export.blade.php index 18440a74d..e1fabd800 100644 --- a/resources/views/books/export.blade.php +++ b/resources/views/books/export.blade.php @@ -31,51 +31,51 @@ @include('partials.custom-head') -
-
-
-
-

{{$book->name}}

+
-

{{ $book->description }}

+

{{$book->name}}

- @if(count($bookChildren) > 0) -
    - @foreach($bookChildren as $bookChild) -
  • {{ $bookChild->name }}
  • - @if($bookChild->isA('chapter') && count($bookChild->pages) > 0) - - @endif - @endforeach -
+

{{ $book->description }}

+ + @if(count($bookChildren) > 0) +
    + @foreach($bookChildren as $bookChild) +
  • {{ $bookChild->name }}
  • + @if($bookChild->isA('chapter') && count($bookChild->pages) > 0) + @endif + @endforeach +
+ @endif - @foreach($bookChildren as $bookChild) + @foreach($bookChildren as $bookChild) +
+

{{ $bookChild->name }}

+ + @if($bookChild->isA('chapter')) +

{{ $bookChild->description }}

+ + @if(count($bookChild->pages) > 0) + @foreach($bookChild->pages as $page)
-

{{ $bookChild->name }}

- @if($bookChild->isA('chapter')) -

{{ $bookChild->description }}

- @if(count($bookChild->pages) > 0) - @foreach($bookChild->pages as $page) -
-
{{$bookChild->name}}
-

{{ $page->name }}

- {!! $page->html !!} - @endforeach - @endif - @else - {!! $bookChild->html !!} - @endif +
{{$bookChild->name}}
+

{{ $page->name }}

+ {!! $page->html !!} @endforeach + @endif + + @else + {!! $bookChild->html !!} + @endif + + @endforeach -
-
-
+ diff --git a/resources/views/books/form.blade.php b/resources/views/books/form.blade.php index bf94b5b07..ebbc279fd 100644 --- a/resources/views/books/form.blade.php +++ b/resources/views/books/form.blade.php @@ -2,12 +2,12 @@ {{ csrf_field() }}
- @include('form/text', ['name' => 'name']) + @include('form.text', ['name' => 'name'])
- @include('form/textarea', ['name' => 'description']) + @include('form.textarea', ['name' => 'description'])
@@ -41,5 +41,5 @@
{{ trans('common.cancel') }} - +
\ No newline at end of file diff --git a/resources/views/books/grid-item.blade.php b/resources/views/books/grid-item.blade.php index 9bbf69100..e1d37753a 100644 --- a/resources/views/books/grid-item.blade.php +++ b/resources/views/books/grid-item.blade.php @@ -1,18 +1,19 @@ -
-