]> BookStack Code Mirror - bookstack/commitdiff
Updated view toggle to store date
authorDan Brown <redacted>
Sun, 14 Apr 2019 12:01:51 +0000 (13:01 +0100)
committerDan Brown <redacted>
Sun, 14 Apr 2019 12:01:51 +0000 (13:01 +0100)
Also added test for user list order preferences

app/Http/Controllers/UserController.php
app/Settings/SettingService.php
resources/assets/js/components/expand-toggle.js
resources/views/base.blade.php
resources/views/common/home-book.blade.php
resources/views/common/home-custom.blade.php
resources/views/common/home-shelves.blade.php
resources/views/common/home.blade.php
resources/views/components/expand-toggle.blade.php [new file with mode: 0644]
routes/web.php
tests/UserPreferencesTest.php [new file with mode: 0644]

index 63de0bc441664f491e7b793733912d90299b4cf3..1bb5d46cdabba8ad19b86aac81060438ec257cfa 100644 (file)
@@ -299,7 +299,6 @@ class UserController extends Controller
      */
     public function changeSort(string $id, string $type, Request $request)
     {
-        // TODO - Test this endpoint
         $validSortTypes = ['books', 'bookshelves'];
         if (!in_array($type, $validSortTypes)) {
             return redirect()->back(500);
@@ -307,6 +306,28 @@ class UserController extends Controller
         return $this->changeListSort($id, $request, $type);
     }
 
+    /**
+     * Update the stored section expansion preference for the given user.
+     * @param string $id
+     * @param string $key
+     * @param Request $request
+     * @return \Illuminate\Contracts\Routing\ResponseFactory|\Symfony\Component\HttpFoundation\Response
+     */
+    public function updateExpansionPreference(string $id, string $key, Request $request)
+    {
+        $this->checkPermissionOrCurrentUser('users-manage', $id);
+        $keyWhitelist = ['home-details'];
+        if (!in_array($key, $keyWhitelist)) {
+            return response("Invalid key", 500);
+        }
+
+        $newState = $request->get('expand', 'false');
+
+        $user = $this->user->findOrFail($id);
+        setting()->putUser($user, 'section_expansion#' . $key, $newState);
+        return response("", 204);
+    }
+
     /**
      * Changed the stored preference for a list sort order.
      * @param int $userId
index 663a6ae3275954a2fa944c3d80fa07d832861038..48ae7d0f24302813b94cce18ef0645b3a9546d38 100644 (file)
@@ -67,6 +67,17 @@ class SettingService
         return $this->get($this->userKey($user->id, $key), $default);
     }
 
+    /**
+     * Get a value for the current logged-in user.
+     * @param $key
+     * @param bool $default
+     * @return bool|string
+     */
+    public function getForCurrentUser($key, $default = false)
+    {
+        return $this->getUser(auth()->user(), $key, $default);
+    }
+
     /**
      * Gets a setting value from the cache or database.
      * Looks at the system defaults if not cached or in database.
index 6f317db62bd3c55259a037647bcf6aed8f8bea8a..a6a38981838e990f3c5de8a3b7e20315a5faf063 100644 (file)
@@ -3,8 +3,13 @@ class ExpandToggle {
 
     constructor(elem) {
         this.elem = elem;
-        this.isOpen = false;
+
+        // Component state
+        this.isOpen = elem.getAttribute('expand-toggle-is-open') === 'yes';
+        this.updateEndpoint = elem.getAttribute('expand-toggle-update-endpoint');
         this.selector = elem.getAttribute('expand-toggle');
+
+        // Listener setup
         elem.addEventListener('click', this.click.bind(this));
     }
 
@@ -53,11 +58,20 @@ class ExpandToggle {
 
     click(event) {
         event.preventDefault();
-        let matchingElems = document.querySelectorAll(this.selector);
-        for (let i = 0, len = matchingElems.length; i < len; i++) {
-            this.isOpen ?  this.close(matchingElems[i]) : this.open(matchingElems[i]);
+
+        const matchingElems = document.querySelectorAll(this.selector);
+        for (let match of matchingElems) {
+            this.isOpen ?  this.close(match) : this.open(match);
         }
+
         this.isOpen = !this.isOpen;
+        this.updateSystemAjax(this.isOpen);
+    }
+
+    updateSystemAjax(isOpen) {
+        window.$http.patch(this.updateEndpoint, {
+            expand: isOpen ? 'true' : 'false'
+        });
     }
 
 }
index 03d6f680aa965ceedf3039f0722e69f4042d6f69..367a2cd8b9ba69536d985dc85cbf1a14681c7395 100644 (file)
@@ -20,6 +20,7 @@
     @include('partials.custom-styles')
     @include('partials.custom-head')
 
+    @stack('head')
 </head>
 <body class="@yield('body-class')">
 
index 139c77c07e1bd4234f0e135101d0c827c8beed2f..0efaa32ec7305c94526a201e55d28b3832b9d0b9 100644 (file)
@@ -9,10 +9,7 @@
                     <h5>{{ trans('common.actions') }}</h5>
                     <div class="icon-list text-primary">
                         @include('partials.view-toggle', ['view' => $view, 'type' => 'book'])
-                        <a expand-toggle=".entity-list.compact .entity-item-snippet" class="icon-list-item">
-                            <span>@icon('expand-text')</span>
-                            <span>{{ trans('common.toggle_details') }}</span>
-                        </a>
+                        @include('components.expand-toggle', ['target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details'])
                     </div>
                 </div>
 
index 0ef3c2e25848d6f1d5f5ff04925038302d959bdc..f1133a60755afa3ade5697d537dc017d5e54a9d8 100644 (file)
@@ -8,10 +8,7 @@
                 <div class="actions mb-xl">
                     <h5>{{ trans('common.actions') }}</h5>
                     <div class="icon-list text-primary">
-                        <a expand-toggle=".entity-list.compact .entity-item-snippet" class="icon-list-item">
-                            <span>@icon('expand-text')</span>
-                            <span>{{ trans('common.toggle_details') }}</span>
-                        </a>
+                        @include('components.expand-toggle', ['target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details'])
                     </div>
                 </div>
 
index 8cb99b9078fcf967bb5c9622a7d2e98a3c12a7f7..f09bfd4169659d136e54544bdcf620a82e67b114 100644 (file)
@@ -9,10 +9,7 @@
                     <h5>{{ trans('common.actions') }}</h5>
                     <div class="icon-list text-primary">
                         @include('partials.view-toggle', ['view' => $view, 'type' => 'shelf'])
-                        <a expand-toggle=".entity-list.compact .entity-item-snippet" class="icon-list-item">
-                            <span>@icon('expand-text')</span>
-                            <span>{{ trans('common.toggle_details') }}</span>
-                        </a>
+                        @include('components.expand-toggle', ['target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details'])
                     </div>
                 </div>
 
index 53da79fd24a30b40276d2bd052dde88437f17da6..35e45c9c86fd43534e51aa50ec4e3895b4751f97 100644 (file)
@@ -1,10 +1,11 @@
 @extends('simple-layout')
 
-
 @section('body')
 
-    <div class="container px-xl py-l">
-        <a expand-toggle=".entity-list.compact .entity-item-snippet" class="text-muted">@icon('expand-text'){{ trans('common.toggle_details') }}</a>
+    <div class="container px-xl py-s">
+        <div class="icon-list inline block">
+            @include('components.expand-toggle', ['target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details'])
+        </div>
     </div>
 
     <div class="container" id="home-default">
diff --git a/resources/views/components/expand-toggle.blade.php b/resources/views/components/expand-toggle.blade.php
new file mode 100644 (file)
index 0000000..231b137
--- /dev/null
@@ -0,0 +1,19 @@
+{{--
+$target - CSS selector of items to expand
+$key - Unique key for checking existing stored state.
+--}}
+<?php $isOpen = setting()->getForCurrentUser('section_expansion#'. $key); ?>
+<a expand-toggle="{{ $target }}"
+   expand-toggle-update-endpoint="{{ baseUrl('/settings/users/'. auth()->user()->id .'/update-expansion-preference/' . $key) }}"
+   expand-toggle-is-open="{{ $isOpen ? 'yes' : 'no' }}"
+   class="text-muted icon-list-item text-primary">
+    <span>@icon('expand-text')</span>
+    <span>{{ trans('common.toggle_details') }}</span>
+</a>
+@if($isOpen)
+    @push('head')
+        <style>
+            {{ $target }} {display: block;}
+        </style>
+    @endpush
+@endif
\ No newline at end of file
index 41da967d9000cd44fe2ce907db7d53cd58c76dec..7c2c5917e7510b391bd78c5eed4a7b75aa487bea 100644 (file)
@@ -177,6 +177,7 @@ Route::group(['middleware' => 'auth'], function () {
         Route::patch('/users/{id}/switch-book-view', 'UserController@switchBookView');
         Route::patch('/users/{id}/switch-shelf-view', 'UserController@switchShelfView');
         Route::patch('/users/{id}/change-sort/{type}', 'UserController@changeSort');
+        Route::patch('/users/{id}/update-expansion-preference/{key}', 'UserController@updateExpansionPreference');
         Route::post('/users/create', 'UserController@store');
         Route::get('/users/{id}', 'UserController@edit');
         Route::put('/users/{id}', 'UserController@update');
diff --git a/tests/UserPreferencesTest.php b/tests/UserPreferencesTest.php
new file mode 100644 (file)
index 0000000..b816642
--- /dev/null
@@ -0,0 +1,76 @@
+<?php namespace Tests;
+
+class UserPreferencesTest extends TestCase
+{
+
+    public function test_update_sort_preference()
+    {
+        $editor = $this->getEditor();
+        $this->actingAs($editor);
+
+        $updateRequest = $this->patch('/settings/users/' . $editor->id.'/change-sort/books', [
+            'sort' => 'created_at',
+            'order' => 'desc'
+        ]);
+        $updateRequest->assertStatus(302);
+
+        $this->assertDatabaseHas('settings', [
+            'setting_key' => 'user:' . $editor->id . ':books_sort',
+            'value' => 'created_at'
+        ]);
+        $this->assertDatabaseHas('settings', [
+            'setting_key' => 'user:' . $editor->id . ':books_sort_order',
+            'value' => 'desc'
+        ]);
+        $this->assertEquals('created_at', setting()->getForCurrentUser('books_sort'));
+        $this->assertEquals('desc', setting()->getForCurrentUser('books_sort_order'));
+    }
+
+    public function test_update_sort_preference_defaults()
+    {
+        $editor = $this->getEditor();
+        $this->actingAs($editor);
+
+        $updateRequest = $this->patch('/settings/users/' . $editor->id.'/change-sort/bookshelves', [
+            'sort' => 'cat',
+            'order' => 'dog'
+        ]);
+        $updateRequest->assertStatus(302);
+
+        $this->assertEquals('name', setting()->getForCurrentUser('bookshelves_sort'));
+        $this->assertEquals('asc', setting()->getForCurrentUser('bookshelves_sort_order'));
+    }
+
+    public function test_update_sort_bad_entity_type_handled()
+    {
+        $editor = $this->getEditor();
+        $this->actingAs($editor);
+
+        $updateRequest = $this->patch('/settings/users/' . $editor->id.'/change-sort/dogs', [
+            'sort' => 'name',
+            'order' => 'asc'
+        ]);
+        $updateRequest->assertStatus(500);
+
+        $this->assertNotEmpty('name', setting()->getForCurrentUser('bookshelves_sort'));
+        $this->assertNotEmpty('asc', setting()->getForCurrentUser('bookshelves_sort_order'));
+    }
+
+    public function test_update_expansion_preference()
+    {
+        $editor = $this->getEditor();
+        $this->actingAs($editor);
+
+        $updateRequest = $this->patch('/settings/users/' . $editor->id.'/update-expansion-preference/home-details', ['expand' => 'true']);
+        $updateRequest->assertStatus(204);
+
+        $this->assertDatabaseHas('settings', [
+            'setting_key' => 'user:' . $editor->id . ':section_expansion#home-details',
+            'value' => 'true'
+        ]);
+        $this->assertEquals(true, setting()->getForCurrentUser('section_expansion#home-details'));
+
+        $invalidKeyRequest = $this->patch('/settings/users/' . $editor->id.'/update-expansion-preference/my-home-details', ['expand' => 'true']);
+        $invalidKeyRequest->assertStatus(500);
+    }
+}
\ No newline at end of file