-
Notifications
You must be signed in to change notification settings - Fork 142
/
Action.ts
116 lines (99 loc) · 3.82 KB
/
Action.ts
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
/**
* Handles actions that can be executed on (database) objects by clicking on specific action buttons.
*
* @author Matthias Schmidt
* @copyright 2001-2021 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
*/
import * as Ajax from "../../Ajax";
import * as EventHandler from "../../Event/Handler";
import { DatabaseObjectActionResponse, ResponseData } from "../../Ajax/Data";
import { ObjectActionData } from "./Data";
import * as UiConfirmation from "../Confirmation";
import * as Language from "../../Language";
import * as StringUtil from "../../StringUtil";
import DomChangeListener from "../../Dom/Change/Listener";
const containerSelector = ".jsObjectActionContainer[data-object-action-class-name]";
const objectSelector = ".jsObjectActionObject[data-object-id]";
const actionSelector = ".jsObjectAction[data-object-action]";
function executeAction(event: Event): void {
event.preventDefault();
const actionElement = event.currentTarget as HTMLElement;
const objectAction = actionElement.dataset.objectAction!;
// To support additional actions added by plugins, action elements can override the default object
// action class name and object id.
let objectActionClassName = (actionElement.closest(containerSelector) as HTMLElement).dataset.objectActionClassName;
if (actionElement.dataset.objectActionClassName) {
objectActionClassName = actionElement.dataset.objectActionClassName;
}
let objectId = (actionElement.closest(objectSelector) as HTMLElement).dataset.objectId;
if (actionElement.dataset.objectId) {
objectId = actionElement.dataset.objectId;
}
// Collect additional request parameters.
const parameters = {};
Object.entries(actionElement.dataset).forEach(([key, value]) => {
let matches = /^objectActionParameterData(.+)/.exec(key);
if (matches) {
if (!Object.prototype.hasOwnProperty.call(parameters, "data")) {
parameters["data"] = {};
}
parameters["data"][StringUtil.lcfirst(matches[1])] = value;
} else {
matches = /^objectActionParameter(.+)/.exec(key);
if (matches) {
const key = StringUtil.lcfirst(matches[1]);
if (key === "data") {
throw new Error("Additional object action parameters may not use 'data' as key.");
}
parameters[key] = value;
}
}
});
function sendRequest(): void {
Ajax.apiOnce({
data: {
actionName: objectAction,
className: objectActionClassName,
objectIDs: [objectId],
parameters: parameters,
},
success: (data) => processAction(actionElement, data),
});
}
if (actionElement.dataset.confirmMessage) {
UiConfirmation.show({
confirm: sendRequest,
message: Language.get(actionElement.dataset.confirmMessage),
messageIsHtml: true,
});
} else {
sendRequest();
}
}
function processAction(actionElement: HTMLElement, data: ResponseData | DatabaseObjectActionResponse): void {
if (actionElement.dataset.objectActionSuccess === "reload") {
window.location.reload();
} else {
EventHandler.fire("WoltLabSuite/Core/Ui/Object/Action", actionElement.dataset.objectAction!, {
containerElement: actionElement.closest(containerSelector),
data,
objectElement: actionElement.closest(objectSelector),
} as ObjectActionData);
}
}
const actions = new Set<HTMLElement>();
function registerElements(): void {
document
.querySelectorAll(`${containerSelector} ${objectSelector} ${actionSelector}`)
.forEach((action: HTMLElement) => {
if (!actions.has(action)) {
action.addEventListener("click", (ev) => executeAction(ev));
actions.add(action);
}
});
}
export function setup(): void {
registerElements();
DomChangeListener.add("WoltLabSuite/Core/Ui/Action", () => registerElements());
}