Skip to content

Commit 21ba91c

Browse files
committed
API endpoint to get style chooser and change style
1 parent 27c362f commit 21ba91c

File tree

10 files changed

+246
-80
lines changed

10 files changed

+246
-80
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/**
2+
* Change the style of the current user.
3+
*
4+
* @author Olaf Braun
5+
* @copyright 2001-2025 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 { ApiResult, apiResultFromError, apiResultFromValue } from "../Result";
13+
14+
export async function changeStyle(styleId: number): Promise<ApiResult<[]>> {
15+
try {
16+
await prepareRequest(`${window.WSC_RPC_API_URL}core/styles/${styleId}/change`).post().fetchAsJson();
17+
} catch (e) {
18+
return apiResultFromError(e);
19+
}
20+
21+
return apiResultFromValue([]);
22+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* Change the style of the current user.
3+
*
4+
* @author Olaf Braun
5+
* @copyright 2001-2025 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 { ApiResult, apiResultFromError, apiResultFromValue } from "../Result";
13+
14+
type Response = {
15+
template: string;
16+
};
17+
18+
export async function getStyleChooser(): Promise<ApiResult<string>> {
19+
let response: Response;
20+
21+
try {
22+
response = (await prepareRequest(`${window.WSC_RPC_API_URL}core/styles/chooser`).get().fetchAsJson()) as Response;
23+
} catch (e) {
24+
return apiResultFromError(e);
25+
}
26+
27+
return apiResultFromValue(response.template);
28+
}

ts/WoltLabSuite/Core/Controller/Style/Changer.ts

Lines changed: 31 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -7,70 +7,61 @@
77
* @woltlabExcludeBundle all
88
*/
99

10-
import * as Ajax from "../../Ajax";
11-
import * as Language from "../../Language";
12-
import UiDialog from "../../Ui/Dialog";
13-
import { DialogCallbackSetup } from "../../Ui/Dialog/Data";
10+
import { getPhrase } from "../../Language";
11+
import { changeStyle } from "WoltLabSuite/Core/Api/Styles/ChangeStyle";
12+
import { dialogFactory } from "WoltLabSuite/Core/Component/Dialog";
13+
import { promiseMutex } from "WoltLabSuite/Core/Helper/PromiseMutex";
14+
import { getStyleChooser } from "WoltLabSuite/Core/Api/Styles/GetStyleChooser";
1415

1516
class ControllerStyleChanger {
1617
/**
1718
* Adds the style changer to the bottom navigation.
1819
*/
1920
constructor() {
2021
document.querySelectorAll(".jsButtonStyleChanger").forEach((link: HTMLAnchorElement) => {
21-
link.addEventListener("click", (ev) => this.showDialog(ev));
22+
link.addEventListener(
23+
"click",
24+
promiseMutex((ev) => this.showDialog(ev)),
25+
);
2226
});
2327
}
2428

2529
/**
2630
* Loads and displays the style change dialog.
2731
*/
28-
showDialog(event: MouseEvent): void {
32+
async showDialog(event: MouseEvent): Promise<void> {
2933
event.preventDefault();
3034

31-
UiDialog.open(this);
32-
}
35+
const response = await getStyleChooser();
36+
if (!response.ok) {
37+
throw new Error("Failed to load style chooser.");
38+
}
39+
40+
const dialog = dialogFactory().fromHtml(response.value).withoutControls();
41+
42+
dialog.content.querySelectorAll(".styleList > li").forEach((style: HTMLLIElement) => {
43+
style.classList.add("pointer");
44+
style.addEventListener("click", (ev) => this.#click(ev));
45+
});
3346

34-
_dialogSetup(): ReturnType<DialogCallbackSetup> {
35-
return {
36-
id: "styleChanger",
37-
options: {
38-
disableContentPadding: true,
39-
title: Language.get("wcf.style.changeStyle"),
40-
},
41-
source: {
42-
data: {
43-
actionName: "getStyleChooser",
44-
className: "wcf\\data\\style\\StyleAction",
45-
},
46-
after: (content) => {
47-
content.querySelectorAll(".styleList > li").forEach((style: HTMLLIElement) => {
48-
style.classList.add("pointer");
49-
style.addEventListener("click", (ev) => this.click(ev));
50-
});
51-
},
52-
},
53-
};
47+
dialog.show(getPhrase("wcf.style.changeStyle"));
5448
}
5549

5650
/**
5751
* Changes the style and reloads current page.
5852
*/
59-
private click(event: MouseEvent): void {
53+
async #click(event: MouseEvent): Promise<void> {
6054
event.preventDefault();
6155

6256
const listElement = event.currentTarget as HTMLLIElement;
57+
const styleId = parseInt(listElement.dataset.styleId!, 10);
58+
const response = await changeStyle(styleId);
6359

64-
Ajax.apiOnce({
65-
data: {
66-
actionName: "changeStyle",
67-
className: "wcf\\data\\style\\StyleAction",
68-
objectIDs: [listElement.dataset.styleId],
69-
},
70-
success: function () {
71-
window.location.reload();
72-
},
73-
});
60+
if (!response.ok) {
61+
throw new Error("Failed to change style.");
62+
}
63+
64+
window.location.reload();
7465
}
7566
}
7667

@@ -89,5 +80,5 @@ export function setup(): void {
8980
* Loads and displays the style change dialog.
9081
*/
9182
export function showDialog(event: MouseEvent): void {
92-
controllerStyleChanger.showDialog(event);
83+
void controllerStyleChanger.showDialog(event);
9384
}

wcfsetup/install/files/js/WoltLabSuite/Core/Api/Styles/ChangeStyle.js

Lines changed: 23 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

wcfsetup/install/files/js/WoltLabSuite/Core/Api/Styles/GetStyleChooser.js

Lines changed: 24 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

wcfsetup/install/files/js/WoltLabSuite/Core/Controller/Style/Changer.js

Lines changed: 21 additions & 40 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

wcfsetup/install/files/lib/bootstrap/com.woltlab.wcf.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ static function (\wcf\event\endpoint\ControllerCollecting $event) {
169169
$event->register(new \wcf\system\endpoint\controller\core\styles\DisableStyle());
170170
$event->register(new \wcf\system\endpoint\controller\core\styles\EnableStyle());
171171
$event->register(new \wcf\system\endpoint\controller\core\styles\SetStyleAsDefault());
172+
$event->register(new \wcf\system\endpoint\controller\core\styles\ChangeStyle());
173+
$event->register(new \wcf\system\endpoint\controller\core\styles\GetStyleChooser());
172174
$event->register(new \wcf\system\endpoint\controller\core\users\options\DeleteOption());
173175
$event->register(new \wcf\system\endpoint\controller\core\users\options\DisableOption());
174176
$event->register(new \wcf\system\endpoint\controller\core\users\options\EnableOption());

wcfsetup/install/files/lib/data/style/StyleAction.class.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,8 @@ public function changeStyle()
547547
* Validates the 'getStyleChooser' action.
548548
*
549549
* @return void
550+
*
551+
* @deprecated 6.3
550552
*/
551553
public function validateGetStyleChooser()
552554
{
@@ -557,6 +559,8 @@ public function validateGetStyleChooser()
557559
* Returns the style chooser dialog.
558560
*
559561
* @return array{actionName: string, template: string}
562+
*
563+
* @deprecated 6.3 Use the `\wcf\system\endpoint\controller\core\styles\GetStyleChooser` API-Endpoint instead.
560564
*/
561565
public function getStyleChooser()
562566
{
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
namespace wcf\system\endpoint\controller\core\styles;
4+
5+
use Laminas\Diactoros\Response\JsonResponse;
6+
use Psr\Http\Message\ResponseInterface;
7+
use Psr\Http\Message\ServerRequestInterface;
8+
use wcf\data\style\Style;
9+
use wcf\http\Helper;
10+
use wcf\system\endpoint\IController;
11+
use wcf\system\endpoint\PostRequest;
12+
use wcf\system\exception\PermissionDeniedException;
13+
use wcf\system\WCF;
14+
15+
/**
16+
* API endpoint to change the style for the current user.
17+
*
18+
* @author Olaf Braun
19+
* @copyright 2001-2025 WoltLab GmbH
20+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
21+
* @since 6.3
22+
*/
23+
#[PostRequest('/core/styles/{id:\d+}/change')]
24+
final class ChangeStyle implements IController
25+
{
26+
#[\Override]
27+
public function __invoke(ServerRequestInterface $request, array $variables): ResponseInterface
28+
{
29+
$style = Helper::fetchObjectFromRequestParameter($variables['id'], Style::class);
30+
31+
$this->assertStyleCanBeChanged($style);
32+
33+
(new \wcf\command\style\ChangeStyle($style))();
34+
35+
return new JsonResponse([]);
36+
}
37+
38+
private function assertStyleCanBeChanged(Style $style): void
39+
{
40+
if ($style->isDisabled && !WCF::getSession()->getPermission('admin.style.canUseDisabledStyle')) {
41+
throw new PermissionDeniedException();
42+
}
43+
}
44+
}

0 commit comments

Comments
 (0)