-
Notifications
You must be signed in to change notification settings - Fork 148
Expand file tree
/
Copy pathStandaloneButton.ts
More file actions
117 lines (97 loc) · 3.11 KB
/
StandaloneButton.ts
File metadata and controls
117 lines (97 loc) · 3.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/**
* Represents a button that provides a context menu with interactions.
*
* @author Marcel Werk
* @copyright 2001-2025 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @since 6.2
*/
import { getObject } from "WoltLabSuite/Core/Api/GetObject";
import { getContextMenuOptions } from "WoltLabSuite/Core/Api/Interactions/GetContextMenuOptions";
import UiDropdownSimple from "WoltLabSuite/Core/Ui/Dropdown/Simple";
interface HeaderContent {
template: string;
}
export class StandaloneButton {
#container: HTMLElement;
#providerClassName: string;
#objectId: string | number;
#redirectUrl: string;
#reloadHeaderEndpoint: string;
constructor(
container: HTMLElement,
providerClassName: string,
objectId: string | number,
redirectUrl: string,
reloadHeaderEndpoint: string,
) {
this.#container = container;
this.#providerClassName = providerClassName;
this.#objectId = objectId;
this.#redirectUrl = redirectUrl;
this.#reloadHeaderEndpoint = reloadHeaderEndpoint;
this.#initInteractions();
this.#initEventListeners();
}
async #refreshContextMenu(): Promise<void> {
const response = (await getContextMenuOptions(this.#providerClassName, this.#objectId)).unwrap();
const dropdown = this.#getDropdownMenu();
if (!dropdown) {
return;
}
dropdown.innerHTML = response.template;
this.#initInteractions();
}
async #refreshHeader(): Promise<void> {
if (!this.#reloadHeaderEndpoint) {
return;
}
const header = document.querySelector(".contentHeaderTitle");
if (!header) {
return;
}
const result = await getObject<HeaderContent>(`${window.WSC_RPC_API_URL}${this.#reloadHeaderEndpoint}`);
if (!result.ok) {
return;
}
header.outerHTML = result.value.template;
}
#getDropdownMenu(): HTMLElement | undefined {
const button = this.#container.querySelector<HTMLButtonElement>(".dropdownToggle");
if (!button) {
return undefined;
}
let dropdown = UiDropdownSimple.getDropdownMenu(button.dataset.target!);
if (!dropdown) {
dropdown = button.closest(".dropdown")!.querySelector<HTMLElement>(".dropdownMenu")!;
}
return dropdown;
}
#initInteractions(): void {
this.#getDropdownMenu()
?.querySelectorAll<HTMLButtonElement>("[data-interaction]")
.forEach((element) => {
element.addEventListener("click", () => {
this.#container.dispatchEvent(
new CustomEvent("interaction:execute", {
detail: element.dataset,
bubbles: true,
}),
);
});
});
}
#initEventListeners(): void {
this.#container.addEventListener("interaction:invalidate", () => {
void this.#refreshContextMenu();
void this.#refreshHeader();
});
this.#container.addEventListener("interaction:invalidate-all", () => {
void this.#refreshContextMenu();
void this.#refreshHeader();
});
this.#container.addEventListener("interaction:remove", () => {
window.location.href = this.#redirectUrl;
});
}
}