]> BookStack Code Mirror - bookstack/commitdiff
Added support for changing the draw.io instance URL
authorDan Brown <redacted>
Sun, 5 Apr 2020 16:27:16 +0000 (17:27 +0100)
committerDan Brown <redacted>
Sun, 5 Apr 2020 16:27:16 +0000 (17:27 +0100)
- Allowed DRAWIO env option to be passed as URL to point to instance.
- Updated tests to check URL gets passed to pages correctly.
- Update default URL to be the default theme.

For #826

.env.example.complete
app/Http/Controllers/Images/DrawioImageController.php
resources/js/components/markdown-editor.js
resources/js/components/wysiwyg-editor.js
resources/js/services/drawio.js
resources/views/pages/form.blade.php
tests/Uploads/DrawioTest.php [new file with mode: 0644]
tests/Uploads/ImageTest.php

index 86a7351c215a675685eebeea1714982eaff5e6bb..472ca051b336388715aab7781c8ec7ab5658978c 100644 (file)
@@ -238,7 +238,10 @@ DISABLE_EXTERNAL_SERVICES=false
 # Example: AVATAR_URL=https://seccdn.libravatar.org/avatar/${hash}?s=${size}&d=identicon
 AVATAR_URL=
 
-# Enable Draw.io integration
+# Enable draw.io integration
+# Can simply be true/false to enable/disable the integration.
+# Alternatively, It can be URL to the draw.io instance you want to use.
+# For URLs, The following URL parameters should be included: embed=1&proto=json&spin=1
 DRAWIO=true
 
 # Default item listing view
index 3595790f71d5e557760601205ba683468c04d531..106dfd63089a6111f042bfc76a32fd4c6ebdde2f 100644 (file)
@@ -4,6 +4,7 @@ namespace BookStack\Http\Controllers\Images;
 
 use BookStack\Exceptions\ImageUploadException;
 use BookStack\Uploads\ImageRepo;
+use Exception;
 use Illuminate\Http\Request;
 use BookStack\Http\Controllers\Controller;
 
@@ -11,10 +12,6 @@ class DrawioImageController extends Controller
 {
     protected $imageRepo;
 
-    /**
-     * DrawioImageController constructor.
-     * @param ImageRepo $imageRepo
-     */
     public function __construct(ImageRepo $imageRepo)
     {
         $this->imageRepo = $imageRepo;
@@ -24,8 +21,6 @@ class DrawioImageController extends Controller
     /**
      * Get a list of gallery images, in a list.
      * Can be paged and filtered by entity.
-     * @param Request $request
-     * @return \Illuminate\Http\JsonResponse
      */
     public function list(Request $request)
     {
@@ -40,9 +35,7 @@ class DrawioImageController extends Controller
 
     /**
      * Store a new gallery image in the system.
-     * @param Request $request
-     * @return Illuminate\Http\JsonResponse
-     * @throws \Exception
+     * @throws Exception
      */
     public function create(Request $request)
     {
@@ -66,8 +59,6 @@ class DrawioImageController extends Controller
 
     /**
      * Get the content of an image based64 encoded.
-     * @param $id
-     * @return \Illuminate\Http\JsonResponse|mixed
      */
     public function getAsBase64($id)
     {
index 25d6bde47aa9771b2fef3fbff890f51121dd0809..f88cb765104d617095bdf0fd95f9d9a24a24cc78 100644 (file)
@@ -411,17 +411,23 @@ class MarkdownEditor {
         });
     }
 
+    getDrawioUrl() {
+        const drawioUrlElem = document.querySelector('[drawio-url]');
+        return drawioUrlElem ? drawioUrlElem.getAttribute('drawio-url') : false;
+    }
+
     // Show draw.io if enabled and handle save.
     actionStartDrawing() {
-        if (document.querySelector('[drawio-enabled]').getAttribute('drawio-enabled') !== 'true') return;
-        let cursorPos = this.cm.getCursor('from');
+        const url = this.getDrawioUrl();
+        if (!url) return;
+
+        const cursorPos = this.cm.getCursor('from');
 
-        DrawIO.show(() => {
+        DrawIO.show(url,() => {
             return Promise.resolve('');
         }, (pngData) => {
-            // let id = "image-" + Math.random().toString(16).slice(2);
-            // let loadingImage = window.baseUrl('/loading.gif');
-            let data = {
+
+            const data = {
                 image: pngData,
                 uploaded_to: Number(document.getElementById('page-editor').getAttribute('page-id'))
             };
@@ -445,15 +451,15 @@ class MarkdownEditor {
 
     // Show draw.io if enabled and handle save.
     actionEditDrawing(imgContainer) {
-        const drawingDisabled = document.querySelector('[drawio-enabled]').getAttribute('drawio-enabled') !== 'true';
-        if (drawingDisabled) {
+        const drawioUrl = this.getDrawioUrl();
+        if (!drawioUrl) {
             return;
         }
 
         const cursorPos = this.cm.getCursor('from');
         const drawingId = imgContainer.getAttribute('drawio-diagram');
 
-        DrawIO.show(() => {
+        DrawIO.show(drawioUrl, () => {
             return DrawIO.load(drawingId);
         }, (pngData) => {
 
index 7818db260317c5feecba40af955496886baf6096..daacc7479ab8bd48b2d28c4d5a19da4f931d82b4 100644 (file)
@@ -238,7 +238,7 @@ function codePlugin() {
     });
 }
 
-function drawIoPlugin() {
+function drawIoPlugin(drawioUrl) {
 
     let pageEditor = null;
     let currentNode = null;
@@ -266,7 +266,7 @@ function drawIoPlugin() {
     function showDrawingEditor(mceEditor, selectedNode = null) {
         pageEditor = mceEditor;
         currentNode = selectedNode;
-        DrawIO.show(drawingInit, updateContent);
+        DrawIO.show(drawioUrl, drawingInit, updateContent);
     }
 
     async function updateContent(pngData) {
@@ -423,10 +423,14 @@ class WysiwygEditor {
     loadPlugins() {
         codePlugin();
         customHrPlugin();
-        if (document.querySelector('[drawio-enabled]').getAttribute('drawio-enabled') === 'true') {
-            drawIoPlugin();
+
+        const drawioUrlElem = document.querySelector('[drawio-url]');
+        if (drawioUrlElem) {
+            const url = drawioUrlElem.getAttribute('drawio-url');
+            drawIoPlugin(url);
             this.plugins += ' drawio';
         }
+
         if (this.textDirection === 'rtl') {
             this.plugins += ' directionality'
         }
index a570737d11f5bcc0d77964d46fc03a93ab41bd96..17e57cd6b9165d567aa09f48197ea95e8b62551f 100644 (file)
@@ -1,22 +1,21 @@
-
-const drawIoUrl = 'https://www.draw.io/?embed=1&ui=atlas&spin=1&proto=json';
 let iFrame = null;
 
 let onInit, onSave;
 
 /**
  * Show the draw.io editor.
- * @param onInitCallback - Must return a promise with the xml to load for the editor.
- * @param onSaveCallback - Is called with the drawing data on save.
+ * @param {String} drawioUrl
+ * @param {Function} onInitCallback - Must return a promise with the xml to load for the editor.
+ * @param {Function} onSaveCallback - Is called with the drawing data on save.
  */
-function show(onInitCallback, onSaveCallback) {
+function show(drawioUrl, onInitCallback, onSaveCallback) {
     onInit = onInitCallback;
     onSave = onSaveCallback;
 
     iFrame = document.createElement('iframe');
     iFrame.setAttribute('frameborder', '0');
     window.addEventListener('message', drawReceive);
-    iFrame.setAttribute('src', drawIoUrl);
+    iFrame.setAttribute('src', drawioUrl);
     iFrame.setAttribute('class', 'fullscreen');
     iFrame.style.backgroundColor = '#FFFFFF';
     document.body.appendChild(iFrame);
index ffc286c2cadadc32f3f9834dfd72ffb6be54ee3c..3c2b4f0b00658922444c3ad3f86b1459ceadd684 100644 (file)
@@ -1,6 +1,8 @@
 <div class="page-editor flex-fill flex" id="page-editor"
      drafts-enabled="{{ $draftsEnabled ? 'true' : 'false' }}"
-     drawio-enabled="{{ config('services.drawio') ? 'true' : 'false' }}"
+     @if(config('services.drawio'))
+        drawio-url="{{ is_string(config('services.drawio')) ? config('services.drawio') : 'https://www.draw.io/?embed=1&proto=json&spin=1' }}"
+     @endif
      editor-type="{{ setting('app-editor') }}"
      page-id="{{ $model->id ?? 0 }}"
      text-direction="{{ config('app.rtl') ? 'rtl' : 'ltr' }}"
diff --git a/tests/Uploads/DrawioTest.php b/tests/Uploads/DrawioTest.php
new file mode 100644 (file)
index 0000000..f940a0a
--- /dev/null
@@ -0,0 +1,79 @@
+<?php namespace Tests\Uploads;
+
+use BookStack\Entities\Page;
+use BookStack\Uploads\Image;
+use Tests\TestCase;
+
+class DrawioTest extends TestCase
+{
+    use UsesImages;
+
+    public function test_get_image_as_base64()
+    {
+        $page = Page::first();
+        $this->asAdmin();
+        $imageName = 'first-image.png';
+
+        $this->uploadImage($imageName, $page->id);
+        $image = Image::first();
+        $image->type = 'drawio';
+        $image->save();
+
+        $imageGet = $this->getJson("/images/drawio/base64/{$image->id}");
+        $imageGet->assertJson([
+            'content' => 'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEcDCo5iYNs+gAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAFElEQVQI12O0jN/KgASYGFABqXwAZtoBV6Sl3hIAAAAASUVORK5CYII='
+        ]);
+    }
+
+    public function test_drawing_base64_upload()
+    {
+        $page = Page::first();
+        $editor = $this->getEditor();
+        $this->actingAs($editor);
+
+        $upload = $this->postJson('images/drawio', [
+            'uploaded_to' => $page->id,
+            'image' => 'image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEcDCo5iYNs+gAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAFElEQVQI12O0jN/KgASYGFABqXwAZtoBV6Sl3hIAAAAASUVORK5CYII='
+        ]);
+
+        $upload->assertStatus(200);
+        $upload->assertJson([
+            'type' => 'drawio',
+            'uploaded_to' => $page->id,
+            'created_by' => $editor->id,
+            'updated_by' => $editor->id,
+        ]);
+
+        $image = Image::where('type', '=', 'drawio')->first();
+        $this->assertTrue(file_exists(public_path($image->path)), 'Uploaded image not found at path: '. public_path($image->path));
+
+        $testImageData = file_get_contents($this->getTestImageFilePath());
+        $uploadedImageData = file_get_contents(public_path($image->path));
+        $this->assertTrue($testImageData === $uploadedImageData, "Uploaded image file data does not match our test image as expected");
+    }
+
+    public function test_drawio_url_can_be_configured()
+    {
+        config()->set('services.drawio', 'http://cats.com?dog=tree');
+        $page = Page::first();
+        $editor = $this->getEditor();
+
+        $resp = $this->actingAs($editor)->get($page->getUrl('/edit'));
+        $resp->assertSee('drawio-url="http://cats.com?dog=tree"');
+    }
+
+    public function test_drawio_url_can_be_disabled()
+    {
+        config()->set('services.drawio', true);
+        $page = Page::first();
+        $editor = $this->getEditor();
+
+        $resp = $this->actingAs($editor)->get($page->getUrl('/edit'));
+        $resp->assertSee('drawio-url="https://www.draw.io/?embed=1&amp;proto=json&amp;spin=1"');
+
+        config()->set('services.drawio', false);
+        $resp = $this->actingAs($editor)->get($page->getUrl('/edit'));
+        $resp->assertDontSee('drawio-url');
+    }
+
+}
\ No newline at end of file
index 3f6c021a7f0f86c74ad972c4166b0e64b485518a..416927ac93170bb1649429d7fdd354932befb6af 100644 (file)
@@ -278,50 +278,6 @@ class ImageTest extends TestCase
         $this->assertFalse(file_exists(public_path($relPath)), 'Uploaded image has not been deleted as expected');
     }
 
-    public function testBase64Get()
-    {
-        $page = Page::first();
-        $this->asAdmin();
-        $imageName = 'first-image.png';
-
-        $this->uploadImage($imageName, $page->id);
-        $image = Image::first();
-        $image->type = 'drawio';
-        $image->save();
-
-        $imageGet = $this->getJson("/images/drawio/base64/{$image->id}");
-        $imageGet->assertJson([
-            'content' => 'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEcDCo5iYNs+gAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAFElEQVQI12O0jN/KgASYGFABqXwAZtoBV6Sl3hIAAAAASUVORK5CYII='
-        ]);
-    }
-
-    public function test_drawing_base64_upload()
-    {
-        $page = Page::first();
-        $editor = $this->getEditor();
-        $this->actingAs($editor);
-
-        $upload = $this->postJson('images/drawio', [
-            'uploaded_to' => $page->id,
-            'image' => 'image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEcDCo5iYNs+gAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAFElEQVQI12O0jN/KgASYGFABqXwAZtoBV6Sl3hIAAAAASUVORK5CYII='
-        ]);
-
-        $upload->assertStatus(200);
-        $upload->assertJson([
-            'type' => 'drawio',
-            'uploaded_to' => $page->id,
-            'created_by' => $editor->id,
-            'updated_by' => $editor->id,
-        ]);
-
-        $image = Image::where('type', '=', 'drawio')->first();
-        $this->assertTrue(file_exists(public_path($image->path)), 'Uploaded image not found at path: '. public_path($image->path));
-
-        $testImageData = file_get_contents($this->getTestImageFilePath());
-        $uploadedImageData = file_get_contents(public_path($image->path));
-        $this->assertTrue($testImageData === $uploadedImageData, "Uploaded image file data does not match our test image as expected");
-    }
-
     protected function getTestProfileImage()
     {
         $imageName = 'profile.png';
Morty Proxy This is a proxified and sanitized view of the page, visit original site.