]> BookStack Code Mirror - bookstack/commitdiff
Converted entity-dash from vue to a component
authorDan Brown <redacted>
Sun, 28 Jun 2020 20:15:00 +0000 (21:15 +0100)
committerDan Brown <redacted>
Sun, 28 Jun 2020 20:15:00 +0000 (21:15 +0100)
dev/docs/components.md
resources/js/components/entity-search.js [new file with mode: 0644]
resources/js/vues/entity-dashboard.js [deleted file]
resources/js/vues/vues.js
resources/views/books/show.blade.php
resources/views/chapters/show.blade.php
resources/views/partials/entity-dashboard-search-box.blade.php [deleted file]
resources/views/partials/entity-dashboard-search-results.blade.php [deleted file]
resources/views/partials/entity-search-form.blade.php [new file with mode: 0644]
resources/views/partials/entity-search-results.blade.php [new file with mode: 0644]

index 2f59ae3448d86520ea1691a03c345e3627a07ccd..ac0e929cdfe416a4454abf6ffa02929232a15c79 100644 (file)
@@ -1,16 +1,22 @@
 # JavaScript Components
 
-This document details the format for JavaScript components in BookStack.
+This document details the format for JavaScript components in BookStack. This is a really simple class-based setup with a few helpers provided.
 
 #### Defining a Component in JS
 
 ```js
 class Dropdown {
     setup() {
+        this.toggle = this.$refs.toggle;
+        this.menu = this.$refs.menu;
+    
+        this.speed = parseInt(this.$opts.speed);
     }
 }
 ```
 
+All usage of $refs, $manyRefs and $opts should be done at the top of the `setup` function so any requirements can be easily seen.
+
 #### Using a Component in HTML
 
 A component is used like so:
diff --git a/resources/js/components/entity-search.js b/resources/js/components/entity-search.js
new file mode 100644 (file)
index 0000000..8b1861e
--- /dev/null
@@ -0,0 +1,59 @@
+import {onSelect} from "../services/dom";
+
+/**
+ * Class EntitySearch
+ * @extends {Component}
+ */
+class EntitySearch {
+    setup() {
+        this.entityId = this.$opts.entityId;
+        this.entityType = this.$opts.entityType;
+
+        this.contentView = this.$refs.contentView;
+        this.searchView = this.$refs.searchView;
+        this.searchResults = this.$refs.searchResults;
+        this.searchInput = this.$refs.searchInput;
+        this.searchForm = this.$refs.searchForm;
+        this.clearButton = this.$refs.clearButton;
+        this.loadingBlock = this.$refs.loadingBlock;
+
+        this.setupListeners();
+    }
+
+    setupListeners() {
+        this.searchInput.addEventListener('change', this.runSearch.bind(this));
+        this.searchForm.addEventListener('submit', e => {
+            e.preventDefault();
+            this.runSearch();
+        });
+
+        onSelect(this.clearButton, this.clearSearch.bind(this));
+    }
+
+    runSearch() {
+        const term = this.searchInput.value.trim();
+        if (term.length === 0) {
+            return this.clearSearch();
+        }
+
+        this.searchView.classList.remove('hidden');
+        this.contentView.classList.add('hidden');
+        this.loadingBlock.classList.remove('hidden');
+
+        const url = window.baseUrl(`/search/${this.entityType}/${this.entityId}`);
+        window.$http.get(url, {term}).then(resp => {
+            this.searchResults.innerHTML = resp.data;
+        }).catch(console.error).then(() => {
+            this.loadingBlock.classList.add('hidden');
+        });
+    }
+
+    clearSearch() {
+        this.searchView.classList.add('hidden');
+        this.contentView.classList.remove('hidden');
+        this.loadingBlock.classList.add('hidden');
+        this.searchInput.value = '';
+    }
+}
+
+export default EntitySearch;
\ No newline at end of file
diff --git a/resources/js/vues/entity-dashboard.js b/resources/js/vues/entity-dashboard.js
deleted file mode 100644 (file)
index d10da70..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-let data = {
-    id: null,
-    type: '',
-    searching: false,
-    searchTerm: '',
-    searchResults: '',
-};
-
-let computed = {
-
-};
-
-let methods = {
-
-    searchBook() {
-        if (this.searchTerm.trim().length === 0) return;
-        this.searching = true;
-        this.searchResults = '';
-        let url = window.baseUrl(`/search/${this.type}/${this.id}`);
-        url += `?term=${encodeURIComponent(this.searchTerm)}`;
-        this.$http.get(url).then(resp => {
-            this.searchResults = resp.data;
-        });
-    },
-
-    checkSearchForm() {
-        this.searching = this.searchTerm > 0;
-    },
-
-    clearSearch() {
-        this.searching = false;
-        this.searchTerm = '';
-    }
-
-};
-
-function mounted() {
-    this.id = Number(this.$el.getAttribute('entity-id'));
-    this.type = this.$el.getAttribute('entity-type');
-}
-
-export default {
-    data, computed, methods, mounted
-};
\ No newline at end of file
index a53adf53fd0693635d3d4cad77f7549daabcc831..f1872492903f28d0bdfd4681e73c3fcb7f73bab1 100644 (file)
@@ -4,14 +4,12 @@ function exists(id) {
     return document.getElementById(id) !== null;
 }
 
-import entityDashboard from "./entity-dashboard";
 import imageManager from "./image-manager";
 import tagManager from "./tag-manager";
 import attachmentManager from "./attachment-manager";
 import pageEditor from "./page-editor";
 
 let vueMapping = {
-    'entity-dashboard': entityDashboard,
     'image-manager': imageManager,
     'tag-manager': tagManager,
     'attachment-manager': attachmentManager,
index e3a536fc9cd7d8ab5931927198af77e31791af54..def198bddac2450b34958534cd4572da01ee0ba5 100644 (file)
@@ -1,9 +1,9 @@
 @extends('tri-layout')
 
 @section('container-attrs')
-    id="entity-dashboard"
-    entity-id="{{ $book->id }}"
-    entity-type="book"
+    component="entity-search"
+    option:entity-search:entity-id="{{ $book->id }}"
+    option:entity-search:entity-type="book"
 @stop
 
 @section('body')
     </div>
 
     <main class="content-wrap card">
-        <h1 class="break-text" v-pre>{{$book->name}}</h1>
-        <div class="book-content" v-show="!searching">
-            <p class="text-muted" v-pre>{!! nl2br(e($book->description)) !!}</p>
+        <h1 class="break-text">{{$book->name}}</h1>
+        <div refs="entity-search@contentView" class="book-content">
+            <p class="text-muted">{!! nl2br(e($book->description)) !!}</p>
             @if(count($bookChildren) > 0)
-                <div class="entity-list book-contents" v-pre>
+                <div class="entity-list book-contents">
                     @foreach($bookChildren as $childElement)
                         @if($childElement->isA('chapter'))
                             @include('chapters.list-item', ['chapter' => $childElement])
@@ -29,7 +29,7 @@
                     @endforeach
                 </div>
             @else
-                <div class="mt-xl" v-pre>
+                <div class="mt-xl">
                     <hr>
                     <p class="text-muted italic mb-m mt-xl">{{ trans('entities.books_empty_contents') }}</p>
 
@@ -52,7 +52,7 @@
             @endif
         </div>
 
-        @include('partials.entity-dashboard-search-results')
+        @include('partials.entity-search-results')
     </main>
 
 @stop
 
 @section('left')
 
-    @include('partials.entity-dashboard-search-box')
+    @include('partials.entity-search-form', ['label' => trans('entities.books_search_this')])
 
     @if($book->tags->count() > 0)
         <div class="mb-xl">
index 105cda760ff496c909aadf723c274fd12b64637b..db02ebcc4f9ae6b6d686a591a8eb2398f5d905d8 100644 (file)
@@ -1,9 +1,9 @@
 @extends('tri-layout')
 
 @section('container-attrs')
-    id="entity-dashboard"
-    entity-id="{{ $chapter->id }}"
-    entity-type="chapter"
+    component="entity-search"
+    option:entity-search:entity-id="{{ $chapter->id }}"
+    option:entity-search:entity-type="chapter"
 @stop
 
 @section('body')
     </div>
 
     <main class="content-wrap card">
-        <h1 class="break-text" v-pre>{{ $chapter->name }}</h1>
-        <div class="chapter-content" v-show="!searching">
-            <p v-pre class="text-muted break-text">{!! nl2br(e($chapter->description)) !!}</p>
+        <h1 class="break-text">{{ $chapter->name }}</h1>
+        <div refs="entity-search@contentView" class="chapter-content">
+            <p class="text-muted break-text">{!! nl2br(e($chapter->description)) !!}</p>
             @if(count($pages) > 0)
-                <div v-pre class="entity-list book-contents">
+                <div class="entity-list book-contents">
                     @foreach($pages as $page)
                         @include('pages.list-item', ['page' => $page])
                     @endforeach
                 </div>
             @else
-                <div class="mt-xl" v-pre>
+                <div class="mt-xl">
                     <hr>
                     <p class="text-muted italic mb-m mt-xl">{{ trans('entities.chapters_empty') }}</p>
 
@@ -49,7 +49,7 @@
             @endif
         </div>
 
-        @include('partials.entity-dashboard-search-results')
+        @include('partials.entity-search-results')
     </main>
 
 @stop
 
 @section('left')
 
-    @include('partials.entity-dashboard-search-box')
+    @include('partials.entity-search-form', ['label' => trans('entities.chapters_search_this')])
 
     @if($chapter->tags->count() > 0)
         <div class="mb-xl">
diff --git a/resources/views/partials/entity-dashboard-search-box.blade.php b/resources/views/partials/entity-dashboard-search-box.blade.php
deleted file mode 100644 (file)
index 2e03952..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<div class="mb-xl">
-    <form v-on:submit.prevent="searchBook" class="search-box flexible" role="search">
-        <input v-model="searchTerm" v-on:change="checkSearchForm" type="text" aria-label="{{ trans('entities.books_search_this') }}" name="term" placeholder="{{ trans('entities.books_search_this') }}">
-        <button type="submit" aria-label="{{ trans('common.search') }}">@icon('search')</button>
-        <button v-if="searching" v-cloak class="search-box-cancel text-neg" v-on:click="clearSearch"
-                type="button" aria-label="{{ trans('common.search_clear') }}">@icon('close')</button>
-    </form>
-</div>
\ No newline at end of file
diff --git a/resources/views/partials/entity-dashboard-search-results.blade.php b/resources/views/partials/entity-dashboard-search-results.blade.php
deleted file mode 100644 (file)
index 68c6f53..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-<div class="search-results" v-cloak v-show="searching">
-    <div class="grid half v-center">
-        <h3 class="text-muted px-none">
-            {{ trans('entities.search_results') }}
-        </h3>
-        <div class="text-right">
-            <a v-if="searching" v-on:click="clearSearch" class="button outline">{{ trans('entities.search_clear') }}</a>
-        </div>
-    </div>
-
-    <div v-if="!searchResults">
-        @include('partials.loading-icon')
-    </div>
-    <div class="book-contents" v-html="searchResults"></div>
-</div>
\ No newline at end of file
diff --git a/resources/views/partials/entity-search-form.blade.php b/resources/views/partials/entity-search-form.blade.php
new file mode 100644 (file)
index 0000000..b65d5df
--- /dev/null
@@ -0,0 +1,10 @@
+{{--
+@label - Placeholder/aria-label text
+--}}
+<div class="mb-xl">
+    <form refs="entity-search@searchForm" class="search-box flexible" role="search">
+        <input refs="entity-search@searchInput" type="text"
+               aria-label="{{ $label }}" name="term" placeholder="{{ $label }}">
+        <button type="submit" aria-label="{{ trans('common.search') }}">@icon('search')</button>
+    </form>
+</div>
\ No newline at end of file
diff --git a/resources/views/partials/entity-search-results.blade.php b/resources/views/partials/entity-search-results.blade.php
new file mode 100644 (file)
index 0000000..7461983
--- /dev/null
@@ -0,0 +1,15 @@
+<div refs="entity-search@searchView" class="search-results hidden">
+    <div class="grid half v-center">
+        <h3 class="text-muted px-none">
+            {{ trans('entities.search_results') }}
+        </h3>
+        <div class="text-right">
+            <a refs="entity-search@clearButton" class="button outline">{{ trans('entities.search_clear') }}</a>
+        </div>
+    </div>
+
+    <div refs="entity-search@loadingBlock">
+        @include('partials.loading-icon')
+    </div>
+    <div class="book-contents" refs="entity-search@searchResults"></div>
+</div>
\ No newline at end of file