Skip to content

Commit 1ce9b2d

Browse files
authored
Merge pull request #6629 from WoltLab/63-refactor-reaction-ts
Refactor reaction handler Typescript
2 parents f721d76 + 39f6d4b commit 1ce9b2d

24 files changed

Lines changed: 1147 additions & 88 deletions

File tree

com.woltlab.wcf/templates/article.tpl

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@
6767

6868
<div
6969
class="section entry article"
70-
{unsafe:$__wcf->getReactionHandler()->getDataAttributes('com.woltlab.wcf.likeableArticle', $article->articleID)}
7170
>
7271
{if $articleContent->getImage() && $articleContent->getImage()->hasThumbnail('large')}
7372
<div
@@ -122,7 +121,7 @@
122121
<footer class="entry__footer">
123122
{if MODULE_LIKE && ARTICLE_ENABLE_LIKE && $__wcf->session->getPermission('user.like.canViewLike')}
124123
<div class="article__reactionSummary">
125-
{include file="reactionSummaryList" reactionData=$articleLikeData objectType="com.woltlab.wcf.likeableArticle" objectID=$article->articleID}
124+
{include file="reactionSummary" reactionData=$article->getReactionData()}
126125
</div>
127126
{/if}
128127

@@ -140,15 +139,8 @@
140139
{icon name='triangle-exclamation'}
141140
</button>
142141
{/if}
143-
{if MODULE_LIKE && ARTICLE_ENABLE_LIKE && $__wcf->session->getPermission('user.like.canLike') && $article->userID != $__wcf->user->userID}
144-
<button
145-
type="button"
146-
class="button jsTooltip reactButton{if $articleLikeData[$article->articleID]|isset && $articleLikeData[$article->articleID]->reactionTypeID} active{/if}"
147-
title="{lang}wcf.reactions.react{/lang}"
148-
data-reaction-type-id="{if $articleLikeData[$article->articleID]|isset && $articleLikeData[$article->articleID]->reactionTypeID}{$articleLikeData[$article->articleID]->reactionTypeID}{else}0{/if}"
149-
>
150-
{icon name='face-smile'}
151-
</button>
142+
{if $article->canReact()}
143+
{include file="reactionButton" reactionData=$article->getReactionData()}
152144
{/if}
153145

154146
{event name='articleLikeButtons'}{* deprecated: use footerButtons instead *}
@@ -264,19 +256,4 @@
264256

265257
{unsafe:$article->getDiscussionProvider()->renderDiscussions()}
266258

267-
{if MODULE_LIKE && ARTICLE_ENABLE_LIKE}
268-
<script data-relocate="true">
269-
require(['WoltLabSuite/Core/Ui/Reaction/Handler'], function(UiReactionHandler) {
270-
new UiReactionHandler('com.woltlab.wcf.likeableArticle', {
271-
// permissions
272-
canReact: {if $__wcf->getUser()->userID}true{else}false{/if},
273-
canReactToOwnContent: false,
274-
275-
// selectors
276-
containerSelector: '.article',
277-
});
278-
});
279-
</script>
280-
{/if}
281-
282259
{include file='footer'}

com.woltlab.wcf/templates/commentList.tpl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,7 @@
103103
<div class="comment__footer">
104104
<div class="comment__reactions">
105105
{if MODULE_LIKE && $commentManager->supportsLike() && $likeData|isset}
106-
{include file="reactionSummaryList" isTiny=true reactionData=$likeData[comment] objectType="com.woltlab.wcf.comment" objectID=$comment->commentID}
107-
{else}
108-
<a href="#" class="reactionSummaryList reactionSummaryListTiny" data-object-type="com.woltlab.wcf.comment" data-object-id="{$comment->commentID}" title="{lang}wcf.reactions.summary.listReactions{/lang}" style="display: none;"></a>
106+
{include file="reactionSummaryList" reactionData=$likeData[comment] objectType="com.woltlab.wcf.comment" objectID=$comment->commentID}
109107
{/if}
110108
</div>
111109

@@ -122,12 +120,14 @@
122120
{if MODULE_LIKE && $commentManager->supportsLike() && $__wcf->session->getPermission('user.like.canLike') && $comment->userID != $__wcf->user->userID}
123121
<button
124122
type="button"
125-
class="comment__button comment__button--react jsTooltip button small {if $likeData[comment][$comment->commentID]|isset && $likeData[comment][$comment->commentID]->reactionTypeID} active{/if}"
123+
class="reactionButton comment__button comment__button--react jsTooltip button small{if $likeData[comment][$comment->commentID]|isset && $likeData[comment][$comment->commentID]->reactionTypeID} active{/if}"
126124
title="{lang}wcf.reactions.react{/lang}"
125+
aria-pressed="{if $likeData[comment][$comment->commentID]|isset && $likeData[comment][$comment->commentID]->reactionTypeID}true{else}false{/if}"
127126
data-reaction-type-id="{if $likeData[comment][$comment->commentID]|isset && $likeData[comment][$comment->commentID]->reactionTypeID}{$likeData[comment][$comment->commentID]->reactionTypeID}{else}0{/if}"
127+
data-reaction-object-type="com.woltlab.wcf.comment"
128+
data-object-id="{$comment->commentID}"
128129
>
129130
{icon name='face-smile'}
130-
<span class="invisible">{lang}wcf.reactions.react{/lang}</span>
131131
</button>
132132
{/if}
133133

com.woltlab.wcf/templates/commentResponseList.tpl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,25 +100,25 @@
100100
<div class="commentResponse__footer">
101101
<div class="commentResponse__reactions">
102102
{if MODULE_LIKE && $commentManager->supportsLike() && $likeData|isset}
103-
{include file="reactionSummaryList" isTiny=true reactionData=$likeData[response] objectType="com.woltlab.wcf.comment.response" objectID=$response->responseID}
104-
{else}
105-
<a href="#" class="reactionSummaryList reactionSummaryListTiny jsOnly" data-object-type="com.woltlab.wcf.comment.response" data-object-id="{$response->responseID}" title="{lang}wcf.reactions.summary.listReactions{/lang}" style="display: none;"></a>
103+
{include file="reactionSummaryList" reactionData=$likeData[response] objectType="com.woltlab.wcf.comment.response" objectID=$response->responseID}
106104
{/if}
107105
</div>
108106

109107
<div class="commentResponse__buttons">
110108
{if MODULE_LIKE && $commentManager->supportsLike() && $__wcf->session->getPermission('user.like.canLike') && $response->userID != $__wcf->user->userID}
111109
<button
112110
type="button"
113-
class="commentResponse__button commentResponse__button--react jsTooltip button small {if $likeData[response][$response->responseID]|isset && $likeData[response][$response->responseID]->reactionTypeID} active{/if}"
111+
class="reactionButton commentResponse__button commentResponse__button--react jsTooltip button small{if $likeData[response][$response->responseID]|isset && $likeData[response][$response->responseID]->reactionTypeID} active{/if}"
114112
title="{lang}wcf.reactions.react{/lang}"
113+
aria-pressed="{if $likeData[response][$response->responseID]|isset && $likeData[response][$response->responseID]->reactionTypeID}true{else}false{/if}"
115114
data-reaction-type-id="{if $likeData[response][$response->responseID]|isset && $likeData[response][$response->responseID]->reactionTypeID}{$likeData[response][$response->responseID]->reactionTypeID}{else}0{/if}"
115+
data-reaction-object-type="com.woltlab.wcf.comment.response"
116+
data-object-id="{$response->responseID}"
116117
>
117118
{icon name='face-smile'}
118-
<span class="invisible">{lang}wcf.reactions.react{/lang}</span>
119119
</button>
120120
{/if}
121-
121+
122122
{event name='commentResponseButtons'}
123123
</div>
124124

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<button
2+
type="button"
3+
class="reactionButton jsTooltip button small{if $reactionData->reactionTypeID} active{/if}"
4+
title="{lang}wcf.reactions.react{/lang}"
5+
aria-pressed="{if $reactionData->reactionTypeID}true{else}false{/if}"
6+
data-reaction-type-id="{$reactionData->reactionTypeID}"
7+
data-reaction-object-type="{$reactionData->objectType}"
8+
data-object-id="{$reactionData->objectID}"
9+
>
10+
{icon name='face-smile'}
11+
</button>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<woltlab-core-reaction-summary
2+
data="{$reactionData->reactionsJson}"
3+
object-type="{$reactionData->objectType}"
4+
object-id="{$reactionData->objectID}"
5+
selected-reaction="{$reactionData->reactionTypeID}"
6+
></woltlab-core-reaction-summary>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* Reverts a reaction on an object.
3+
*
4+
* @author Marcel Werk
5+
* @copyright 2001-2026 WoltLab GmbH
6+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
7+
* @since 6.3
8+
* @woltlabExcludeBundle tiny
9+
*/
10+
11+
import { prepareRequest } from "WoltLabSuite/Core/Ajax/Backend";
12+
import { fromInfallibleApiRequest } from "../Result";
13+
14+
type Response = {
15+
reactions: Record<number, number>;
16+
};
17+
18+
export async function revertReaction(objectType: string, objectID: number): Promise<Response> {
19+
return fromInfallibleApiRequest(() => {
20+
return prepareRequest(`${window.WSC_RPC_API_URL}core/reactions/revert`)
21+
.post({
22+
objectType,
23+
objectID,
24+
})
25+
.fetchAsJson();
26+
});
27+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* Sets a reaction on an object.
3+
*
4+
* @author Marcel Werk
5+
* @copyright 2001-2026 WoltLab GmbH
6+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
7+
* @since 6.3
8+
* @woltlabExcludeBundle tiny
9+
*/
10+
11+
import { prepareRequest } from "WoltLabSuite/Core/Ajax/Backend";
12+
import { fromInfallibleApiRequest } from "../Result";
13+
14+
type Response = {
15+
reactions: Record<number, number>;
16+
};
17+
18+
export async function setReaction(objectType: string, objectID: number, reactionTypeID: number): Promise<Response> {
19+
return fromInfallibleApiRequest(() => {
20+
return prepareRequest(`${window.WSC_RPC_API_URL}core/reactions/set`)
21+
.post({
22+
objectType,
23+
objectID,
24+
reactionTypeID,
25+
})
26+
.fetchAsJson();
27+
});
28+
}

ts/WoltLabSuite/Core/BootstrapFrontend.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,4 +165,7 @@ export function setup(options: BootstrapOptions): void {
165165
whenFirstSeen("[data-report-content]", () => {
166166
void import("./Ui/Moderation/Report").then(({ setup }) => setup(options.reportEndpoint));
167167
});
168+
whenFirstSeen("[data-reaction-object-type]", () => {
169+
void import("./Component/Reaction/Button").then(({ setup }) => setup());
170+
});
168171
}

ts/WoltLabSuite/Core/Component/Comment/List.ts

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import { getPhrase } from "../../Language";
1414
import { CommentAdd } from "./Add";
1515
import { CommentResponseAdd } from "./Response/Add";
1616
import * as UiScroll from "../../Ui/Scroll";
17-
import UiReactionHandler from "../../Ui/Reaction/Handler";
1817

1918
import type WoltlabCoreCommentElement from "./woltlab-core-comment";
2019
import type WoltlabCoreCommentResponseElement from "./Response/woltlab-core-comment-response";
@@ -35,23 +34,6 @@ class CommentList {
3534
this.#initLoadNextComments();
3635
this.#initCommentAdd();
3736
this.#initHashHandling();
38-
this.#initReactions();
39-
}
40-
41-
#initReactions(): void {
42-
if (this.#container.dataset.enableReactions !== "true") {
43-
return;
44-
}
45-
46-
new UiReactionHandler("com.woltlab.wcf.comment", {
47-
containerSelector: `#${this.#container.id} .commentList__item`,
48-
buttonSelector: ".comment__button--react",
49-
});
50-
51-
new UiReactionHandler("com.woltlab.wcf.comment.response", {
52-
containerSelector: `#${this.#container.id} .commentResponseList__item`,
53-
buttonSelector: ".commentResponse__button--react",
54-
});
5537
}
5638

5739
#initHashHandling(): void {

0 commit comments

Comments
 (0)