diff --git a/lib/classes/JsonApi/Routes/Blubber/ThreadsUpdate.php b/lib/classes/JsonApi/Routes/Blubber/ThreadsUpdate.php index a85db30e95ce9aae9e6a4be69441ac1204d629ba..5c698a35c7e36cf19aa9bb6b0535073deda897a3 100644 --- a/lib/classes/JsonApi/Routes/Blubber/ThreadsUpdate.php +++ b/lib/classes/JsonApi/Routes/Blubber/ThreadsUpdate.php @@ -35,12 +35,21 @@ class ThreadsUpdate extends JsonApiController throw new AuthorizationFailedException(); } - $visitedAt = self::arrayGet($json, 'data.attributes.visited-at'); - if ($visitedAt) { + if (self::arrayHas($json, 'data.attributes.visited-at')) { + $visitedAt = self::arrayGet($json, 'data.attributes.visited-at'); $visitedDate = self::fromISO8601($visitedAt)->getTimestamp(); $GLOBALS['user']->cfg->store('BLUBBERTHREAD_VISITED_' . $thread->getId(), $visitedDate); } + if (self::arrayHas($json, 'data.attributes.is-followed')) { + $isFollowed = self::arrayGet($json, 'data.attributes.is-followed'); + if ($isFollowed) { + $thread->addFollowingByUser($user->id); + } else { + $thread->removeFollowingByUser($user->id); + } + } + return $this->getContentResponse($thread); } @@ -52,5 +61,12 @@ class ThreadsUpdate extends JsonApiController return '`visited-at` is not an ISO 8601 timestamp.'; } } + + if (self::arrayHas($json, 'data.attributes.is-followed')) { + $isFollowed = self::arrayGet($json, 'data.attributes.is-followed'); + if (!is_bool($isFollowed)) { + return '`is-followed` is not a boolean value.'; + } + } } } diff --git a/resources/assets/javascripts/lib/blubber.js b/resources/assets/javascripts/lib/blubber.js index 44d91bd9c102328ed35b78d8fdb3de67bc9b2951..3e93985e493ec9878142dcf98ff6c5be4a9e751e 100644 --- a/resources/assets/javascripts/lib/blubber.js +++ b/resources/assets/javascripts/lib/blubber.js @@ -41,19 +41,16 @@ const Blubber = { } elements.addClass('loading'); - const promise = follow - ? STUDIP.api.POST(`blubber/threads/${thread_id}/follow`) - : STUDIP.api.DELETE(`blubber/threads/${thread_id}/follow`); - - return promise - .then(() => { - elements.toggleClass('unfollowed', !follow); - return follow; - }) - .always(() => { - elements.removeClass('loading'); - }) - .promise(); + return STUDIP.Vue.load().then(async ({ store }) => { + return store.dispatch('studip/blubber/changeThreadSubscription', { + id: thread_id, + subscribe: follow, + }); + }).then(() => { + elements.toggleClass('unfollowed', !follow); + }).finally(() => { + elements.removeClass('loading'); + }); }, Composer: { vue: null, diff --git a/resources/vue/store/blubber.js b/resources/vue/store/blubber.js index c6730801f0d2ba550541729adadc996877d907ee..9cc474a5b1d9c52514b5041ebc07e00b910da63b 100644 --- a/resources/vue/store/blubber.js +++ b/resources/vue/store/blubber.js @@ -119,12 +119,9 @@ export default { }, actions: { changeThreadSubscription({ dispatch, rootGetters }, { id, subscribe }) { - return STUDIP.Blubber.followunfollow(id, subscribe).done((state) => { - const thread = rootGetters['blubber-threads/byId']({ id }); - thread.attributes['is-followed'] = state; - - return dispatch('blubber-threads/storeRecord', thread, { root: true }); - }); + const thread = rootGetters['blubber-threads/byId']({ id }); + thread.attributes['is-followed'] = subscribe; + return dispatch('blubber-threads/update', thread, { root: true }); }, createComment({ dispatch, rootGetters }, { id, content }) {