]> BookStack Code Mirror - bookstack/commitdiff
Started vueifying tag system
authorDan Brown <redacted>
Thu, 10 Aug 2017 19:11:25 +0000 (20:11 +0100)
committerDan Brown <redacted>
Thu, 10 Aug 2017 19:11:25 +0000 (20:11 +0100)
package.json
resources/assets/js/controllers.js
resources/assets/js/vues/tag-manager.js [new file with mode: 0644]
resources/assets/js/vues/vues.js
resources/assets/sass/_pages.scss
resources/assets/sass/_tables.scss
resources/views/pages/form-toolbox.blade.php

index 1ae0e7f68db2cca2691d6641a0af1af4b8b5de8a..f447ec786a226cf4ee85cbce41d174ec6487333b 100644 (file)
@@ -40,7 +40,8 @@
     "markdown-it": "^8.3.1",
     "markdown-it-task-lists": "^2.0.0",
     "moment": "^2.12.0",
-    "vue": "^2.2.6"
+    "vue": "^2.2.6",
+    "vuedraggable": "^2.14.1"
   },
   "browser": {
     "vue": "vue/dist/vue.common.js"
index de3ce81c65d3a57b8c1d65c35c5dd5331ea54cc9..c317da7539abdf2605490a64e0c07dfd49a73b7b 100644 (file)
@@ -157,74 +157,7 @@ module.exports = function (ngApp, events) {
                 containment: "parent",
                 axis: "y"
             };
-
-            /**
-             * Push an empty tag to the end of the scope tags.
-             */
-            function addEmptyTag() {
-                $scope.tags.push({
-                    name: '',
-                    value: ''
-                });
-            }
-            $scope.addEmptyTag = addEmptyTag;
-
-            /**
-             * Get all tags for the current book and add into scope.
-             */
-            function getTags() {
-                let url = window.baseUrl(`/ajax/tags/get/page/${pageId}`);
-                $http.get(url).then((responseData) => {
-                    $scope.tags = responseData.data;
-                    addEmptyTag();
-                });
-            }
-            getTags();
-
-            /**
-             * Set the order property on all tags.
-             */
-            function setTagOrder() {
-                for (let i = 0; i < $scope.tags.length; i++) {
-                    $scope.tags[i].order = i;
-                }
-            }
-
-            /**
-             * When an tag changes check if another empty editable
-             * field needs to be added onto the end.
-             * @param tag
-             */
-            $scope.tagChange = function(tag) {
-                let cPos = $scope.tags.indexOf(tag);
-                if (cPos !== $scope.tags.length-1) return;
-
-                if (tag.name !== '' || tag.value !== '') {
-                    addEmptyTag();
-                }
-            };
-
-            /**
-             * When an tag field loses focus check the tag to see if its
-             * empty and therefore could be removed from the list.
-             * @param tag
-             */
-            $scope.tagBlur = function(tag) {
-                let isLast = $scope.tags.length - 1 === $scope.tags.indexOf(tag);
-                if (tag.name === '' && tag.value === '' && !isLast) {
-                    let cPos = $scope.tags.indexOf(tag);
-                    $scope.tags.splice(cPos, 1);
-                }
-            };
-
-            /**
-             * Remove a tag from the current list.
-             * @param tag
-             */
-            $scope.removeTag = function(tag) {
-                let cIndex = $scope.tags.indexOf(tag);
-                $scope.tags.splice(cIndex, 1);
-            };
+            // TODO - Delete
 
         }]);
 
diff --git a/resources/assets/js/vues/tag-manager.js b/resources/assets/js/vues/tag-manager.js
new file mode 100644 (file)
index 0000000..cf3e4d3
--- /dev/null
@@ -0,0 +1,65 @@
+const draggable = require('vuedraggable');
+
+let data = {
+    pageId: false,
+    tags: [],
+};
+
+const components = {draggable};
+
+let computed = {
+
+};
+
+let methods = {
+
+    addEmptyTag() {
+        this.tags.push({name: '', value: '', key: Math.random().toString(36).substring(7)});
+    },
+
+    /**
+     * When an tag changes check if another empty editable field needs to be added onto the end.
+     * @param tag
+     */
+    tagChange(tag) {
+        let tagPos = this.tags.indexOf(tag);
+        if (tagPos !== this.tags.length-1 || tag.name !== '' || tag.value !== '') return;
+        this.addEmptyTag();
+    },
+
+    /**
+     * When an tag field loses focus check the tag to see if its
+     * empty and therefore could be removed from the list.
+     * @param tag
+     */
+    tagBlur(tag) {
+        let isLast = (this.tags.indexOf(tag) === this.tags.length-1);
+        if (tag.name !== '' || tag.value !== '' || isLast) return;
+        let cPos = this.tags.indexOf(tag);
+        this.tags.splice(cPos, 1);
+    },
+
+    removeTag(tag) {
+        let tagPos = this.tags.indexOf(tag);
+        if (tagPos === -1) return;
+        this.tags.splice(tagPos, 1);
+    }
+};
+
+function mounted() {
+    this.pageId = Number(this.$el.getAttribute('page-id'));
+
+    let url = window.baseUrl(`/ajax/tags/get/page/${this.pageId}`);
+    this.$http.get(url).then(response => {
+        let tags = response.data;
+        for (let i = 0, len = tags.length; i < len; i++) {
+            tags[i].key = Math.random().toString(36).substring(7);
+        }
+        this.tags = tags;
+        this.addEmptyTag();
+    });
+}
+
+module.exports = {
+    data, computed, methods, mounted, components
+};
\ No newline at end of file
index e6d4b9f5b886ff4031d221bf2af779902110def1..a3f6ec8e540c678587133d19a05c197cde37bbf1 100644 (file)
@@ -9,6 +9,7 @@ let vueMapping = {
     'entity-dashboard': require('./entity-search'),
     'code-editor': require('./code-editor'),
     'image-manager': require('./image-manager'),
+    'tag-manager': require('./tag-manager'),
 };
 
 window.vues = {};
index b06892c1d9e566d201cce0bb6f89649526530ae6..65fdfbc4be25ffb1727b9cd96648c725660fb178 100755 (executable)
     width: 100%;
     min-width: 50px;
   }
-  .tags td {
+  .tags td, .tag-table > div > div > div {
     padding-right: $-s;
     padding-top: $-s;
     position: relative;
index 21553b8394d01f76392132b1fbeb3b2c269bbeed..ea517fee3974f717887b51d6b025c834f5c5da6b 100644 (file)
@@ -67,4 +67,17 @@ table.file-table {
   .ui-sortable-helper {
     display: table;
   }
+}
+
+.fake-table {
+  display: table;
+  > div {
+    display: table-row-group;
+  }
+  > div > div {
+    display: table-row;
+  }
+  > div > div > div {
+    display: table-cell;
+  }
 }
\ No newline at end of file
index ecf7619b766c29e99ea3ffb503e978cd7fe6a9c2..9b8cd4ed33e819b3f2e0cbfb148d6410297ba081 100644 (file)
@@ -9,31 +9,36 @@
         @endif
     </div>
 
-    <div toolbox-tab-content="tags" ng-controller="PageTagController" page-id="{{ $page->id or 0 }}">
+    <div toolbox-tab-content="tags" id="tag-manager" page-id="{{ $page->id or 0 }}">
         <h4>{{ trans('entities.page_tags') }}</h4>
         <div class="padded tags">
             <p class="muted small">{!! nl2br(e(trans('entities.tags_explain'))) !!}</p>
-            <table class="no-style" tag-autosuggestions style="width: 100%;">
-                <tbody ui-sortable="sortOptions" ng-model="tags" >
-                    <tr ng-repeat="tag in tags track by $index">
-                        <td width="20" ><i class="handle zmdi zmdi-menu"></i></td>
-                        <td><input autosuggest="{{ baseUrl('/ajax/tags/suggest/names') }}" autosuggest-type="name" class="outline" ng-attr-name="tags[@{{$index}}][name]" type="text" ng-model="tag.name" ng-change="tagChange(tag)" ng-blur="tagBlur(tag)" placeholder="{{ trans('entities.tag') }}"></td>
-                        <td><input autosuggest="{{ baseUrl('/ajax/tags/suggest/values') }}" autosuggest-type="value" class="outline" ng-attr-name="tags[@{{$index}}][value]" type="text" ng-model="tag.value" ng-change="tagChange(tag)" ng-blur="tagBlur(tag)" placeholder="{{ trans('entities.tag_value') }}"></td>
-                        <td width="10" ng-show="tags.length != 1" class="text-center text-neg" style="padding: 0;" ng-click="removeTag(tag)"><i class="zmdi zmdi-close"></i></td>
-                    </tr>
-                </tbody>
-            </table>
+
+            <draggable class="fake-table no-style tag-table" :options="{handle: '.handle'}" :list="tags" element="div" style="width: 100%;">
+                <transition-group name="test" tag="div">
+                    <div v-for="(tag, i) in tags" :key="tag.key">
+                        <div width="20" class="handle" ><i class="zmdi zmdi-menu"></i></div>
+                        <div><input autosuggest="{{ baseUrl('/ajax/tags/suggest/names') }}" autosuggest-type="name" class="outline" :name="tags[i].name"
+                                   v-model="tag.name" @change="tagChange(tag)" @blur="tagBlur(tag)" placeholder="{{ trans('entities.tag') }}"></div>
+                        <div><input autosuggest="{{ baseUrl('/ajax/tags/suggest/values') }}" autosuggest-type="value" class="outline" :name="tags[i].value"
+                                   v-model="tag.value" @change="tagChange(tag)" @blur="tagBlur(tag)" placeholder="{{ trans('entities.tag_value') }}"></div>
+                        <div width="10" v-show="tags.length !== 1" class="text-center text-neg" style="padding: 0;" @click="removeTag(tag)"><i class="zmdi zmdi-close"></i></div>
+                    </div>
+                </transition-group>
+            </draggable>
+
             <table class="no-style" style="width: 100%;">
                 <tbody>
                 <tr class="unsortable">
-                    <td  width="34"></td>
-                    <td ng-click="addEmptyTag()">
+                    <td width="34"></td>
+                    <td @click="addEmptyTag">
                         <button type="button" class="text-button">{{ trans('entities.tags_add') }}</button>
                     </td>
                     <td></td>
                 </tr>
                 </tbody>
             </table>
+
         </div>
     </div>
 
Morty Proxy This is a proxified and sanitized view of the page, visit original site.