]> BookStack Code Mirror - bookstack/commitdiff
Improves sortable ux
authorDan Brown <redacted>
Fri, 27 Jan 2023 11:16:17 +0000 (11:16 +0000)
committerDan Brown <redacted>
Fri, 27 Jan 2023 11:16:17 +0000 (11:16 +0000)
- Fixes multi-select functionality.
- Updated other books to be sticky.
- Added some general intro/desc text.
- Updated sort boxes to be collapsible.
- Cleaned up other books styling.

resources/js/components/book-sort.js
resources/lang/en/entities.php
resources/sass/_layout.scss
resources/sass/_lists.scss
resources/sass/styles.scss
resources/views/books/parts/sort-box.blade.php
resources/views/books/sort.blade.php

index 3ffadf99150d3813b06faea5d706e789257a3e8d..2722eb586f5c3d3d108f889ec39a416a9271869c 100644 (file)
@@ -1,4 +1,4 @@
-import Sortable from "sortablejs";
+import Sortable, {MultiDrag} from "sortablejs";
 import {Component} from "./component";
 import {htmlToDom} from "../services/dom";
 
@@ -44,6 +44,8 @@ export class BookSort extends Component {
         this.sortContainer = this.$refs.sortContainer;
         this.input = this.$refs.input;
 
+        Sortable.mount(new MultiDrag());
+
         const initialSortBox = this.container.querySelector('.sort-box');
         this.setupBookSortable(initialSortBox);
         this.setupSortPresets();
@@ -104,7 +106,7 @@ export class BookSort extends Component {
     }
 
     /**
-     * Setup the given book container element to have sortable items.
+     * Set up the given book container element to have sortable items.
      * @param {Element} bookContainer
      */
     setupBookSortable(bookContainer) {
@@ -125,8 +127,8 @@ export class BookSort extends Component {
             }
         };
 
-        for (let sortElem of sortElems) {
-            new Sortable(sortElem, {
+        for (const sortElem of sortElems) {
+            Sortable.create(sortElem, {
                 group: sortElem.classList.contains('sort-list') ? bookGroupConfig : chapterGroupConfig,
                 animation: 150,
                 fallbackOnBody: true,
@@ -135,7 +137,7 @@ export class BookSort extends Component {
                 dragClass: 'bg-white',
                 ghostClass: 'primary-background-light',
                 multiDrag: true,
-                multiDragKey: 'CTRL',
+                multiDragKey: 'Control',
                 selectedClass: 'sortable-selected',
             });
         }
index fa2586f8d75cab171ec753065eaf73f4efcafe5d..5b019e84860098ae6230c41ee36d50f15fb3cc60 100644 (file)
@@ -141,6 +141,7 @@ return [
     'books_search_this' => 'Search this book',
     'books_navigation' => 'Book Navigation',
     'books_sort' => 'Sort Book Contents',
+    'books_sort_desc' => 'Move chapters and pages within a book to reorganise its contents. Other books can be added which allows easy moving of chapters and pages between books.',
     'books_sort_named' => 'Sort Book :bookName',
     'books_sort_name' => 'Sort by Name',
     'books_sort_created' => 'Sort by Created Date',
@@ -148,6 +149,7 @@ return [
     'books_sort_chapters_first' => 'Chapters First',
     'books_sort_chapters_last' => 'Chapters Last',
     'books_sort_show_other' => 'Show Other Books',
+    'books_sort_show_other_desc' => 'Add other books here to include them in the sort operation, and allow easy cross-book reorganisation.',
     'books_sort_save' => 'Save New Order',
     'books_copy' => 'Copy Book',
     'books_copy_success' => 'Book successfully copied',
index 4c7de600b84c8f33787720051d4e8fe058ee913a..3fc41904627b98673558578596c7ae7ccb89c578 100644 (file)
@@ -268,6 +268,11 @@ body.flexbox {
   }
 }
 
+.sticky-top-m {
+  position: sticky;
+  top: $-m;
+}
+
 /**
  * Visibility
  */
index 86a89051f05976ee55d34e5013bf0701ceb71bfd..1ae801267b4596de98af7c3d485933782038ca34 100644 (file)
 .sortable-page-list li.placeholder:before {
   position: absolute;
 }
+.sort-box summary {
+  list-style: none;
+  font-size: .9rem;
+  cursor: pointer;
+}
+.sort-box summary::-webkit-details-marker {
+  display: none;
+}
+details.sort-box summary .caret-container svg {
+  transition: transform ease-in-out 120ms;
+}
+details.sort-box[open] summary .caret-container svg {
+  transform: rotate(90deg);
+}
 
 .activity-list-item {
   padding: $-s 0;
index 23959d1f85699c878d68361dfc518a44144e0570..398d16fac3afe34ef75bf5348764f7dac0f399a2 100644 (file)
@@ -199,6 +199,9 @@ $loadingSize: 10px;
     .entity-item-snippet {
       display: none;
     }
+    h4 {
+      font-size: 14px;
+    }
   }
 }
 
index ef9929e46486b9e9fd944ca8cc1652a5551f366d..819f1e063bfd6c10275e412fec0f8c19f6ebd760 100644 (file)
@@ -1,8 +1,15 @@
-<div class="sort-box" data-type="book" data-id="{{ $book->id }}">
-    <h5 class="text-book entity-list-item no-hover py-xs pl-none">
-        <span>@icon('book')</span>
-        <span>{{ $book->name }}</span>
-    </h5>
+<details class="sort-box" data-type="book" data-id="{{ $book->id }}" open>
+    <summary>
+        <h5 class="flex-container-row items-center justify-flex-start gap-xs">
+            <div class="text-book text-bigger caret-container">
+                @icon('caret-right')
+            </div>
+            <div class="entity-list-item no-hover py-s text-book px-none">
+                <span>@icon('book')</span>
+                <span>{{ $book->name }}</span>
+            </div>
+        </h5>
+    </summary>
     <div class="sort-box-options pb-sm">
         <button type="button" data-sort="name" class="button outline small">{{ trans('entities.books_sort_name') }}</button>
         <button type="button" data-sort="created" class="button outline small">{{ trans('entities.books_sort_created') }}</button>
@@ -45,4 +52,4 @@
         @endforeach
 
     </ul>
-</div>
\ No newline at end of file
+</details>
\ No newline at end of file
index 077da101d13bddb518f141ad2cde2fe60e2173e1..b778398a83136b82e634d9a07f113bb5e8edca74 100644 (file)
 
         <div class="grid left-focus gap-xl">
             <div>
-                <div component="book-sort" class="card content-wrap">
-                    <h1 class="list-heading mb-l">{{ trans('entities.books_sort') }}</h1>
+                <div component="book-sort" class="card content-wrap auto-height">
+                    <h1 class="list-heading">{{ trans('entities.books_sort') }}</h1>
+                    <p class="text-muted">{{ trans('entities.books_sort_desc') }}</p>
+
                     <div refs="book-sort@sortContainer">
                         @include('books.parts.sort-box', ['book' => $book, 'bookChildren' => $bookChildren])
                     </div>
@@ -35,8 +37,9 @@
             </div>
 
             <div>
-                <main class="card content-wrap">
-                    <h2 class="list-heading mb-m">{{ trans('entities.books_sort_show_other') }}</h2>
+                <main class="card content-wrap auto-height sticky-top-m">
+                    <h2 class="list-heading">{{ trans('entities.books_sort_show_other') }}</h2>
+                    <p class="text-muted">{{ trans('entities.books_sort_show_other_desc') }}</p>
 
                     @include('entities.selector', ['name' => 'books_list', 'selectorSize' => 'compact', 'entityTypes' => 'book', 'entityPermission' => 'update', 'showAdd' => true])