]> BookStack Code Mirror - bookstack/commitdiff
Merge branch 'master' of git://github.com/brennanmurphy/BookStack into brennanmurphy...
authorDan Brown <redacted>
Sat, 14 Jul 2018 13:17:55 +0000 (14:17 +0100)
committerDan Brown <redacted>
Sat, 14 Jul 2018 13:17:55 +0000 (14:17 +0100)
27 files changed:
.browserslistrc [new file with mode: 0644]
app/Http/Controllers/PageController.php
app/Page.php
resources/assets/js/components/markdown-editor.js
resources/assets/js/components/page-display.js
resources/assets/js/components/wysiwyg-editor.js
resources/assets/js/index.js
resources/assets/sass/_pages.scss
resources/lang/de/entities.php
resources/lang/en/entities.php
resources/lang/es/entities.php
resources/lang/es_AR/entities.php
resources/lang/fr/entities.php
resources/lang/it/entities.php
resources/lang/ja/entities.php
resources/lang/nl/entities.php
resources/lang/pl/entities.php
resources/lang/pt_BR/common.php
resources/lang/pt_BR/entities.php
resources/lang/ru/entities.php
resources/lang/sk/entities.php
resources/lang/sv/entities.php
resources/lang/zh_CN/entities.php
resources/lang/zh_TW/entities.php
resources/views/pages/show.blade.php
tests/Permissions/RestrictionsTest.php
webpack.config.js

diff --git a/.browserslistrc b/.browserslistrc
new file mode 100644 (file)
index 0000000..47c6836
--- /dev/null
@@ -0,0 +1,2 @@
+>0.25%
+not op_mini all
\ No newline at end of file
index 221e21a99e181b37c228c0fe4d1bbc95736556a4..25a0503ebeab00245d69a85389ddd28b5b7db804 100644 (file)
@@ -5,7 +5,6 @@ use BookStack\Exceptions\NotFoundException;
 use BookStack\Repos\EntityRepo;
 use BookStack\Repos\UserRepo;
 use BookStack\Services\ExportService;
-use Carbon\Carbon;
 use Illuminate\Http\Request;
 use Illuminate\Http\Response;
 use Views;
@@ -38,11 +37,18 @@ class PageController extends Controller
      * @param string $chapterSlug
      * @return Response
      * @internal param bool $pageSlug
+     * @throws NotFoundException
      */
     public function create($bookSlug, $chapterSlug = null)
     {
-        $book = $this->entityRepo->getBySlug('book', $bookSlug);
-        $chapter = $chapterSlug ? $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug) : null;
+        if ($chapterSlug !== null) {
+            $chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug);
+            $book = $chapter->book;
+        } else {
+            $chapter = null;
+            $book = $this->entityRepo->getBySlug('book', $bookSlug);
+        }
+
         $parent = $chapter ? $chapter : $book;
         $this->checkOwnablePermission('page-create', $parent);
 
@@ -52,7 +58,7 @@ class PageController extends Controller
             return redirect($draft->getUrl());
         }
 
-        // Otherwise show edit view
+        // Otherwise show the edit view if they're a guest
         $this->setPageTitle(trans('entities.pages_new'));
         return view('pages/guest-create', ['parent' => $parent]);
     }
@@ -71,8 +77,14 @@ class PageController extends Controller
             'name' => 'required|string|max:255'
         ]);
 
-        $book = $this->entityRepo->getBySlug('book', $bookSlug);
-        $chapter = $chapterSlug ? $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug) : null;
+        if ($chapterSlug !== null) {
+            $chapter = $this->entityRepo->getBySlug('chapter', $chapterSlug, $bookSlug);
+            $book = $chapter->book;
+        } else {
+            $chapter = null;
+            $book = $this->entityRepo->getBySlug('book', $bookSlug);
+        }
+
         $parent = $chapter ? $chapter : $book;
         $this->checkOwnablePermission('page-create', $parent);
 
@@ -93,7 +105,7 @@ class PageController extends Controller
     public function editDraft($bookSlug, $pageId)
     {
         $draft = $this->entityRepo->getById('page', $pageId, true);
-        $this->checkOwnablePermission('page-create', $draft->book);
+        $this->checkOwnablePermission('page-create', $draft->parent);
         $this->setPageTitle(trans('entities.pages_edit_draft'));
 
         $draftsEnabled = $this->signedIn;
@@ -119,12 +131,10 @@ class PageController extends Controller
         ]);
 
         $input = $request->all();
-        $book = $this->entityRepo->getBySlug('book', $bookSlug);
-
         $draftPage = $this->entityRepo->getById('page', $pageId, true);
+        $book = $draftPage->book;
 
-        $chapterId = intval($draftPage->chapter_id);
-        $parent = $chapterId !== 0 ? $this->entityRepo->getById('chapter', $chapterId) : $book;
+        $parent = $draftPage->parent;
         $this->checkOwnablePermission('page-create', $parent);
 
         if ($parent->isA('chapter')) {
index 38feb610da9ef73dc0f93668197e0dc680d0b299..9554504b35d2466e4c8741ce41bca05adaa8e966 100644 (file)
@@ -28,6 +28,15 @@ class Page extends Entity
         return $this->belongsTo(Book::class);
     }
 
+    /**
+     * Get the parent item
+     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
+     */
+    public function parent()
+    {
+        return $this->chapter_id ? $this->chapter() : $this->book();
+    }
+
     /**
      * Get the chapter that this page is in, If applicable.
      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
index 06426bf349a0bfba4d9cda94ec06c769aa99e4b6..9e2bb3915e4dc3a985b8a2e88da58cc7aa047847 100644 (file)
@@ -18,6 +18,13 @@ class MarkdownEditor {
 
         this.onMarkdownScroll = this.onMarkdownScroll.bind(this);
         this.init();
+
+        // Scroll to text if needed.
+        const queryParams = (new URL(window.location)).searchParams;
+        const scrollText = queryParams.get('content-text');
+        if (scrollText) {
+            this.scrollToText(scrollText);
+        }
     }
 
     init() {
@@ -387,6 +394,33 @@ class MarkdownEditor {
         });
     }
 
+    // Scroll to a specified text
+    scrollToText(searchText) {
+        if (!searchText) {
+            return;
+        }
+
+        const content = this.cm.getValue();
+        const lines = content.split(/\r?\n/);
+        let lineNumber = lines.findIndex(line => {
+            return line && line.indexOf(searchText) !== -1;
+        });
+
+        if (lineNumber === -1) {
+            return;
+        }
+
+        this.cm.scrollIntoView({
+            line: lineNumber,
+        }, 200);
+        this.cm.focus();
+        // set the cursor location.
+        this.cm.setCursor({
+            line: lineNumber,
+            char: lines[lineNumber].length
+        })
+    }
+
 }
 
 module.exports = MarkdownEditor ;
\ No newline at end of file
index 5eb5648cd809342ae6bfab9faa4e763bf3ca7e10..260600d3420b19c00652d0e5588d1516b9cf1e4f 100644 (file)
@@ -74,11 +74,23 @@ class PageDisplay {
             pointerShowing = false;
         });
 
-        let updatePointerContent = () => {
+        let updatePointerContent = ($elem) => {
             let inputText = pointerModeLink ? window.baseUrl(`/link/${this.pageId}#${pointerSectionId}`) : `{{@${this.pageId}#${pointerSectionId}}}`;
             if (pointerModeLink && inputText.indexOf('http') !== 0) inputText = window.location.protocol + "//" + window.location.host + inputText;
 
             $pointer.find('input').val(inputText);
+
+            // update anchor if present
+            const $editAnchor = $pointer.find('#pointer-edit');
+            if ($editAnchor.length !== 0 && $elem) {
+                const editHref = $editAnchor.data('editHref');
+                const element = $elem[0];
+                const elementId = element.id;
+
+                // get the first 50 characters.
+                let queryContent = element.textContent && element.textContent.substring(0, 50);
+                $editAnchor[0].href = `${editHref}?content-id=${elementId}&content-text=${encodeURIComponent(queryContent)}`;
+            }
         };
 
         // Show pointer when selecting a single block of tagged content
@@ -90,7 +102,7 @@ class PageDisplay {
             // Show pointer and set link
             let $elem = $(this);
             pointerSectionId = $elem.attr('id');
-            updatePointerContent();
+            updatePointerContent($elem);
 
             $elem.before($pointer);
             $pointer.show();
@@ -219,7 +231,6 @@ class PageDisplay {
             }
         }
     }
-
 }
 
-module.exports = PageDisplay;
\ No newline at end of file
+module.exports = PageDisplay;
index f7e9bfeedfe6e506662d851b156852f9a22d4554..a8a2ff175ed0c732b38cbe06be3fa394031c4694 100644 (file)
@@ -483,13 +483,36 @@ class WysiwygEditor {
             },
             setup: function (editor) {
 
-                editor.on('init ExecCommand change input NodeChange ObjectResized', editorChange);
+                editor.on('ExecCommand change input NodeChange ObjectResized', editorChange);
+
+                editor.on('init', () => {
+                    editorChange();
+                    // Scroll to the content if needed.
+                    const queryParams = (new URL(window.location)).searchParams;
+                    const scrollId = queryParams.get('content-id');
+                    if (scrollId) {
+                        scrollToText(scrollId);
+                    }
+                });
 
                 function editorChange() {
                     let content = editor.getContent();
                     window.$events.emit('editor-html-change', content);
                 }
 
+                function scrollToText(scrollId) {
+                    const element = editor.dom.get(encodeURIComponent(scrollId).replace(/!/g, '%21'));
+                    if (!element) {
+                        return;
+                    }
+
+                    // scroll the element into the view and put the cursor at the end.
+                    element.scrollIntoView();
+                    editor.selection.select(element, true);
+                    editor.selection.collapse(false);
+                    editor.focus();
+                }
+
                 window.$events.listen('editor-html-update', html => {
                     editor.setContent(html);
                     editor.selection.select(editor.getBody(), true);
index 6b24d5ee118820f204b10ce6b1b97982c0231f75..f202c322e52a813576195410e820a14e35227d7e 100644 (file)
@@ -1,5 +1,4 @@
 // Global Polyfills
-import "@babel/polyfill"
 import "./services/dom-polyfills"
 
 // Url retrieval function
index 4658b9c6a087d12f6e43ab5313674b1f0fb50eac..21fdf90dea234ad25c95365f6a45e89a20045ca0 100755 (executable)
   position: absolute;
   top: -60px;
   background-color:#FFF;
-  width: 272px;
+  width: 275px;
   z-index: 55;
+
+  &.is-page-editable {
+    width: 328px;
+  }
+
   &:before {
     position: absolute;
     left: 50%;
     width: 172px;
     z-index: 40;
   }
-  input, button {
+  input, button, a {
     position: relative;
     border-radius: 0;
     height: 28px;
     font-size: 12px;
     vertical-align: top;
+    padding: 5px 16px;
   }
   > i {
     color: #888;
     cursor: pointer;
     user-select: none;
   }
-  .button {
+  .input-group .button {
     line-height: 1;
     margin: 0 0 0 -4px;
     box-shadow: none;
   }
+  a.button {
+    margin: 0 0 0 0;
+
+    &:hover {
+      fill: #fff;
+    }
+  }
+  .svg-icon {
+    width: 1.2em;
+    height: 1.2em;
+  }
 }
 
 // Attribute form
index 250a86ea51dfeadc23ebd67353909f946d71a9df..96aaa9b0ef761e887265220003257a5a721d7e7a 100644 (file)
@@ -179,6 +179,7 @@ return [
     'pages_revisions_restore' => 'Wiederherstellen',
     'pages_revisions_none' => 'Diese Seite hat keine älteren Versionen.',
     'pages_copy_link' => 'Link kopieren',
+    'pages_edit_content_link' => 'Inhalt bearbeiten',
     'pages_permissions_active' => 'Seiten-Berechtigungen aktiv',
     'pages_initial_revision' => 'Erste Veröffentlichung',
     'pages_initial_name' => 'Neue Seite',
index 430655a87be82cd4993b6b822b0751923a5a7ad5..93025ffd4e235be72fa11ca297ccab83feff1a5f 100644 (file)
@@ -185,6 +185,7 @@ return [
     'pages_revisions_restore' => 'Restore',
     'pages_revisions_none' => 'This page has no revisions',
     'pages_copy_link' => 'Copy Link',
+    'pages_edit_content_link' => 'Edit Content',
     'pages_permissions_active' => 'Page Permissions Active',
     'pages_initial_revision' => 'Initial publish',
     'pages_initial_name' => 'New Page',
index 866a3c1a6833df9ac3f4ca81a50dae68e405a1d5..8c5c9f07f46181ee807f8a06654d82bb5acc2ae2 100644 (file)
@@ -185,6 +185,7 @@ return [
     'pages_revisions_restore' => 'Restaurar',
     'pages_revisions_none' => 'Esta página no tiene revisiones',
     'pages_copy_link' => 'Copiar Enlace',
+    'pages_edit_content_link' => 'Contenido editado',
     'pages_permissions_active' => 'Permisos de página activos',
     'pages_initial_revision' => 'Publicación inicial',
     'pages_initial_name' => 'Página nueva',
index b294f24f99244430c4e38c5c86aa9fecedbc9ec7..371f1b7aa458bab2b0e8a6888967667854c93c0b 100644 (file)
@@ -124,7 +124,7 @@ return [
     'chapters_permissions_active' => 'Permisos de capítulo activado',
     'chapters_permissions_success' => 'Permisos de capítulo actualizados',
     'chapters_search_this' => 'Buscar en este capítulo',
-    
+
     /**
      * Pages
      */
@@ -185,6 +185,7 @@ return [
     'pages_revisions_restore' => 'Restaurar',
     'pages_revisions_none' => 'Esta página no tiene revisiones',
     'pages_copy_link' => 'Copiar enlace',
+    'pages_edit_content_link' => 'Contenido editado',
     'pages_permissions_active' => 'Permisos de página activos',
     'pages_initial_revision' => 'Publicación inicial',
     'pages_initial_name' => 'Página nueva',
index 7d0696c2a710e99063eac26901b7a5f29597c2dd..c8503241eba453a1d67a28407d750a9daaa03a64 100644 (file)
@@ -182,6 +182,7 @@ return [
     'pages_revisions_restore' => 'Restaurer',
     'pages_revisions_none' => 'Cette page n\'a aucune révision',
     'pages_copy_link' => 'Copier le lien',
+    'pages_edit_content_link' => 'Modifier le contenu',
     'pages_permissions_active' => 'Permissions de page actives',
     'pages_initial_revision' => 'Publication initiale',
     'pages_initial_name' => 'Nouvelle page',
index e3e44bfed32c2165ab56c8e4d9bf8f1e7b78e263..1941ffb1e62a98193c707bb22ce1dc731e96063c 100755 (executable)
@@ -182,6 +182,7 @@ return [
     'pages_revisions_restore' => 'Ripristina',
     'pages_revisions_none' => 'Questa pagina non ha versioni',
     'pages_copy_link' => 'Copia Link',
+    'pages_edit_content_link' => 'Modifica contenuto',
     'pages_permissions_active' => 'Permessi Pagina Attivi',
     'pages_initial_revision' => 'Pubblicazione iniziale',
     'pages_initial_name' => 'Nuova Pagina',
index d3699a4c489f1ddbb0d5fa2741fa42e0a9fd2bf3..c08c4998bdd2c2412f410e5df326c309208d1fc0 100644 (file)
@@ -179,6 +179,7 @@ return [
     'pages_revisions_restore' => '復元',
     'pages_revisions_none' => 'このページにはリビジョンがありません',
     'pages_copy_link' => 'リンクをコピー',
+    'pages_edit_content_link' => 'コンテンツの編集',
     'pages_permissions_active' => 'ページの権限は有効です',
     'pages_initial_revision' => '初回の公開',
     'pages_initial_name' => '新規ページ',
index 3b67979750260b232b11bf397a5f36e48828e452..a807c84cea93d1eddecd78c286958e28647f3d85 100644 (file)
@@ -14,7 +14,7 @@ return [
     'recent_activity' => 'Recente Activiteit',
     'create_now' => 'Maak er zelf één',
     'revisions' => 'Revisies',
-    'meta_revision' => 'Revisie #:revisionCount',        
+    'meta_revision' => 'Revisie #:revisionCount',
     'meta_created' => 'Aangemaakt :timeLength',
     'meta_created_name' => 'Aangemaakt: :timeLength door :user',
     'meta_updated' => ':timeLength Aangepast',
@@ -44,7 +44,7 @@ return [
      * Search
      */
     'search_results' => 'Zoekresultaten',
-    'search_total_results_found' => ':count resultaten gevonden|:count resultaten gevonden', 
+    'search_total_results_found' => ':count resultaten gevonden|:count resultaten gevonden',
     'search_clear' => 'Zoekopdracht wissen',
     'search_no_pages' => 'Er zijn geen pagina\'s gevonden',
     'search_for_term' => 'Zoeken op :term',
@@ -105,7 +105,7 @@ return [
      */
     'chapter' => 'Hoofdstuk',
     'chapters' => 'Hoofdstukken',
-    'x_chapters' => ':count Hoofdstuk|:count Hoofdstukken',                                                                                                     
+    'x_chapters' => ':count Hoofdstuk|:count Hoofdstukken',
     'chapters_popular' => 'Populaire Hoofdstukken',
     'chapters_new' => 'Nieuw Hoofdstuk',
     'chapters_create' => 'Hoofdstuk Toevoegen',
@@ -124,14 +124,14 @@ return [
     'chapters_empty' => 'Er zijn geen pagina\'s in dit hoofdstuk aangemaakt.',
     'chapters_permissions_active' => 'Hoofdstuk Permissies Actief',
     'chapters_permissions_success' => 'Hoofdstuk Permissies Bijgewerkt',
-    'chapters_search_this' => 'Doorzoek dit hoofdstuk',                                                                                        
+    'chapters_search_this' => 'Doorzoek dit hoofdstuk',
 
     /**
      * Pages
      */
     'page' => 'Pagina',
     'pages' => 'Pagina\'s',
-    'x_pages' => ':count Pagina|:count Pagina\'s',                                                                                     
+    'x_pages' => ':count Pagina|:count Pagina\'s',
     'pages_popular' => 'Populaire Pagina\'s',
     'pages_new' => 'Nieuwe Pagina',
     'pages_attachments' => 'Bijlages',
@@ -168,7 +168,7 @@ return [
     'pages_move_success' => 'Pagina verplaatst naar ":parentName"',
     'pages_permissions' => 'Pagina Permissies',
     'pages_permissions_success' => 'Pagina Permissies bijgwerkt',
-    'pages_revision' => 'Revisie',                                        
+    'pages_revision' => 'Revisie',
     'pages_revisions' => 'Pagina Revisies',
     'pages_revisions_named' => 'Pagina Revisies voor :pageName',
     'pages_revision_named' => 'Pagina Revisie voor :pageName',
@@ -182,6 +182,7 @@ return [
     'pages_revisions_restore' => 'Herstellen',
     'pages_revisions_none' => 'Deze pagina heeft geen revisies',
     'pages_copy_link' => 'Link Kopiëren',
+    'pages_edit_content_link' => 'Bewerk inhoud',
     'pages_permissions_active' => 'Pagina Permissies Actief',
     'pages_initial_revision' => 'Eerste publicatie',
     'pages_initial_name' => 'Nieuwe Pagina',
index cc00c32ffa9dd9e0f3f2415e4bca99639edf8cd3..0407b139682ec4becf561920dc633d69264c4b7e 100644 (file)
@@ -179,6 +179,7 @@ return [
     'pages_revisions_restore' => 'Przywróć',
     'pages_revisions_none' => 'Ta strona nie posiada żadnych rewizji',
     'pages_copy_link' => 'Kopiuj link',
+    'pages_edit_content_link' => 'Edytuj zawartość',
     'pages_permissions_active' => 'Uprawnienia strony aktywne',
     'pages_initial_revision' => 'Wydanie pierwotne',
     'pages_initial_name' => 'Nowa strona',
index 991cb0b7e4fbfde96fe75a270cd2176125f5a8c6..5b5ed1f6379bc46286d3915af03e4deb70ad55b5 100644 (file)
@@ -20,6 +20,7 @@ return [
     'role' => 'Regra',
     'cover_image' => 'Imagem de capa',
     'cover_image_description' => 'Esta imagem deve ser aproximadamente 300x170px.',
+    
     /**
      * Actions
      */
@@ -30,6 +31,7 @@ return [
     'edit' => 'Editar',
     'sort' => 'Ordenar',
     'move' => 'Mover',
+    'copy' => 'Copiar',
     'reply' => 'Responder',
     'delete' => 'Excluir',
     'search' => 'Pesquisar',
@@ -48,6 +50,8 @@ return [
     'toggle_details' => 'Alternar Detalhes',
     'toggle_thumbnails' => 'Alternar Miniaturas',
     'details' => 'Detalhes',
+    'grid_view' => 'Visualização em Grade',
+    'list_view' => 'Visualização em Lista',
 
     /**
      * Header
index 20527b16dc73f4d6c019acf20a96c94285d6bc11..4dbf9c935776f72c63de6d925b497923b92e08bd 100644 (file)
@@ -181,6 +181,7 @@ return [
     'pages_revisions_restore' => 'Restaurar',
     'pages_revisions_none' => 'Essa página não tem revisões',
     'pages_copy_link' => 'Copia Link',
+    'pages_edit_content_link' => 'Editar conteúdo',
     'pages_permissions_active' => 'Permissões de Página Ativas',
     'pages_initial_revision' => 'Publicação Inicial',
     'pages_initial_name' => 'Nova Página',
index 124726c1aa44325d3a4d6ea7368d602c00ce7991..a0322d622ea2391cc59525ff7ba7bba94f63d5ab 100644 (file)
@@ -181,6 +181,7 @@ return [
     'pages_revisions_restore' => 'Восстановить',
     'pages_revisions_none' => 'У этой страницы нет других версий',
     'pages_copy_link' => 'Копировать ссылку',
+    'pages_edit_content_link' => 'Изменить содержание',
     'pages_permissions_active' => 'Действующие разрешения на страницу',
     'pages_initial_revision' => 'Первоначальное издание',
     'pages_initial_name' => 'Новая страница',
index 25a1af140bad58d7539839fa2314f20c169ff071..8f9a57d1f760dc8c90dbac5939cc71c2f07bc23a 100644 (file)
@@ -166,6 +166,7 @@ return [
     'pages_revisions_restore' => 'Obnoviť',
     'pages_revisions_none' => 'Táto stránka nemá žiadne revízie',
     'pages_copy_link' => 'Kopírovať odkaz',
+    'pages_edit_content_link' => 'Upraviť obsah',
     'pages_permissions_active' => 'Oprávnienia stránky aktívne',
     'pages_initial_revision' => 'Prvé zverejnenie',
     'pages_initial_name' => 'Nová stránka',
index 6aa537b2d2cbf6e0f3a0d8dbe14f5e701735d1a2..e9d588a9ff7f7cb07b134379e04d54cb3f83b892 100644 (file)
@@ -182,6 +182,7 @@ return [
     'pages_revisions_restore' => 'Återställ',
     'pages_revisions_none' => 'Sidan har inga revisioner',
     'pages_copy_link' => 'Kopiera länk',
+    'pages_edit_content_link' => 'Redigera innehåll',
     'pages_permissions_active' => 'Anpassade rättigheter är i bruk',
     'pages_initial_revision' => 'Första publicering',
     'pages_initial_name' => 'Ny sida',
index 3c04c442d65229e03d5a3e2893df488413d6ceb1..eed6b9532f770d97c665056eb27151042b377f0d 100644 (file)
@@ -181,6 +181,7 @@ return [
     'pages_revisions_restore' => '恢复',
     'pages_revisions_none' => '此页面没有修订',
     'pages_copy_link' => '复制链接',
+    'pages_edit_content_link' => '编辑内容',
     'pages_permissions_active' => '有效的页面权限',
     'pages_initial_revision' => '初始发布',
     'pages_initial_name' => '新页面',
index b354a2f2fac115ef6464c58e7fe5c98daf00ffb7..664917eaa686fa5e56cf16df857877f6e0a02761 100644 (file)
@@ -182,6 +182,7 @@ return [
     'pages_revisions_restore' => '恢複',
     'pages_revisions_none' => '此頁面沒有修訂',
     'pages_copy_link' => '複製連結',
+    'pages_edit_content_link' => '编辑内容',
     'pages_permissions_active' => '有效的頁面權限',
     'pages_initial_revision' => '初次發布',
     'pages_initial_name' => '新頁面',
index 3b8b7abff79e71fba9b21406682a6d06140acadc..0b6aa7d14bbba3c4e395486d3a6ac8d2e69ace53 100644 (file)
     <div class="page-content flex" page-display="{{ $page->id }}">
 
         <div class="pointer-container" id="pointer">
-            <div class="pointer anim" >
+            <div class="pointer anim {{ userCan('page-update', $page) ? 'is-page-editable' : ''}}" >
                 <span class="icon text-primary">@icon('link') @icon('include', ['style' => 'display:none;'])</span>
-                <input readonly="readonly" type="text" id="pointer-url" placeholder="url">
-                <button class="button icon" data-clipboard-target="#pointer-url" type="button" title="{{ trans('entities.pages_copy_link') }}">@icon('copy')</button>
+                <span class="input-group">
+                    <input readonly="readonly" type="text" id="pointer-url" placeholder="url">
+                    <button class="button icon" data-clipboard-target="#pointer-url" type="button" title="{{ trans('entities.pages_copy_link') }}">@icon('copy')</button>
+                </span>
+                @if(userCan('page-update', $page))
+                    <a href="{{ $page->getUrl('/edit') }}" id="pointer-edit" data-edit-href="{{ $page->getUrl('/edit') }}"
+                        class="button icon heading-edit-icon" title="{{ trans('entities.pages_edit_content_link')}}">@icon('edit')</a>
+                @endif
             </div>
         </div>
 
index 53e7ad3f35871d65dcaa52fc7888da2a8929675e..2bbb1a5faeee9d08a37ebf704834da732ec4f70f 100644 (file)
@@ -592,4 +592,26 @@ class RestrictionsTest extends BrowserKitTest
                 ->see('You do not have permission')
                 ->seePageIs('/');
     }
+
+    public function test_can_create_page_if_chapter_has_permissions_when_book_not_visible()
+    {
+        $book = Book::first();
+        $this->setEntityRestrictions($book, []);
+        $bookChapter = $book->chapters->first();
+        $this->setEntityRestrictions($bookChapter, ['view']);
+
+        $this->actingAs($this->user)->visit($bookChapter->getUrl())
+            ->dontSee('New Page');
+
+        $this->setEntityRestrictions($bookChapter, ['view', 'create']);
+
+        $this->actingAs($this->user)->visit($bookChapter->getUrl())
+            ->click('New Page')
+            ->seeStatusCode(200)
+            ->type('test page', 'name')
+            ->type('test content', 'html')
+            ->press('Save Page')
+            ->seePageIs($book->getUrl('/page/test-page'))
+            ->seeStatusCode(200);
+    }
 }
index c5ce4829fde1c99caf55ccd6025cbfb91c6971ae..5c0501e3ba627136916f1052e53f59e7bb30dc8a 100644 (file)
@@ -25,7 +25,11 @@ const config = {
                 use: {
                     loader: 'babel-loader',
                     options: {
-                        presets: ['@babel/preset-env']
+                        presets: [[
+                            '@babel/preset-env', {
+                                useBuiltIns: 'usage'
+                            }
+                        ]]
                     }
                 }
             },