diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 63de0bc44..1bb5d46cd 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -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 diff --git a/app/Settings/SettingService.php b/app/Settings/SettingService.php index 663a6ae32..48ae7d0f2 100644 --- a/app/Settings/SettingService.php +++ b/app/Settings/SettingService.php @@ -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. diff --git a/resources/assets/js/components/expand-toggle.js b/resources/assets/js/components/expand-toggle.js index 6f317db62..a6a389818 100644 --- a/resources/assets/js/components/expand-toggle.js +++ b/resources/assets/js/components/expand-toggle.js @@ -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' + }); } } diff --git a/resources/views/base.blade.php b/resources/views/base.blade.php index 03d6f680a..367a2cd8b 100644 --- a/resources/views/base.blade.php +++ b/resources/views/base.blade.php @@ -20,6 +20,7 @@ @include('partials.custom-styles') @include('partials.custom-head') + @stack('head') diff --git a/resources/views/common/home-book.blade.php b/resources/views/common/home-book.blade.php index 139c77c07..0efaa32ec 100644 --- a/resources/views/common/home-book.blade.php +++ b/resources/views/common/home-book.blade.php @@ -9,10 +9,7 @@
{{ trans('common.actions') }}
@include('partials.view-toggle', ['view' => $view, 'type' => 'book']) - - @icon('expand-text') - {{ trans('common.toggle_details') }} - + @include('components.expand-toggle', ['target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details'])
diff --git a/resources/views/common/home-custom.blade.php b/resources/views/common/home-custom.blade.php index 0ef3c2e25..f1133a607 100644 --- a/resources/views/common/home-custom.blade.php +++ b/resources/views/common/home-custom.blade.php @@ -8,10 +8,7 @@
{{ trans('common.actions') }}
- - @icon('expand-text') - {{ trans('common.toggle_details') }} - + @include('components.expand-toggle', ['target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details'])
diff --git a/resources/views/common/home-shelves.blade.php b/resources/views/common/home-shelves.blade.php index 8cb99b907..f09bfd416 100644 --- a/resources/views/common/home-shelves.blade.php +++ b/resources/views/common/home-shelves.blade.php @@ -9,10 +9,7 @@
{{ trans('common.actions') }}
@include('partials.view-toggle', ['view' => $view, 'type' => 'shelf']) - - @icon('expand-text') - {{ trans('common.toggle_details') }} - + @include('components.expand-toggle', ['target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details'])
diff --git a/resources/views/common/home.blade.php b/resources/views/common/home.blade.php index 53da79fd2..35e45c9c8 100644 --- a/resources/views/common/home.blade.php +++ b/resources/views/common/home.blade.php @@ -1,10 +1,11 @@ @extends('simple-layout') - @section('body') -
- @icon('expand-text'){{ trans('common.toggle_details') }} +
+
+ @include('components.expand-toggle', ['target' => '.entity-list.compact .entity-item-snippet', 'key' => 'home-details']) +
diff --git a/resources/views/components/expand-toggle.blade.php b/resources/views/components/expand-toggle.blade.php new file mode 100644 index 000000000..231b13741 --- /dev/null +++ b/resources/views/components/expand-toggle.blade.php @@ -0,0 +1,19 @@ +{{-- +$target - CSS selector of items to expand +$key - Unique key for checking existing stored state. +--}} +getForCurrentUser('section_expansion#'. $key); ?> + + @icon('expand-text') + {{ trans('common.toggle_details') }} + +@if($isOpen) + @push('head') + + @endpush +@endif \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index 41da967d9..7c2c5917e 100644 --- a/routes/web.php +++ b/routes/web.php @@ -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 index 000000000..b81664275 --- /dev/null +++ b/tests/UserPreferencesTest.php @@ -0,0 +1,76 @@ +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