Replaces #559, which conflicted. Model: opus-5-5
This commit is contained in:
@@ -57,3 +57,157 @@
|
||||
init();
|
||||
}
|
||||
})();
|
||||
|
||||
// Asks before a form with a data-confirm attribute is sent, such as a
|
||||
// delete form on the webhook page. The browser's own prompt shows the
|
||||
// attribute's text, and the form is sent only if the user accepts.
|
||||
document.addEventListener("submit", function (event) {
|
||||
"use strict";
|
||||
|
||||
const message = event.target.getAttribute("data-confirm");
|
||||
if (message !== null && !window.confirm(message)) {
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
// Alpine.js components.
|
||||
//
|
||||
// The pages' Content-Security-Policy forbids eval, so the UI loads
|
||||
// Alpine's CSP build, which cannot run expressions written in the
|
||||
// markup: a directive in templates/ may only name a property or method,
|
||||
// and each x-data names a component registered here. This script runs
|
||||
// before Alpine, whose script tag is deferred, so this listener is in
|
||||
// place when Alpine starts.
|
||||
document.addEventListener("alpine:init", function () {
|
||||
"use strict";
|
||||
|
||||
// Something a click shows and hides: the mobile menu, an add form,
|
||||
// an entrypoint's edit form, an event in the event log or in the
|
||||
// recent events, a delivery's attempts, the new webhook page's
|
||||
// archive pruning and rotation choices. It starts hidden, or shown
|
||||
// when its element has the data-open attribute.
|
||||
window.Alpine.data("collapsible", function () {
|
||||
return {
|
||||
open: false,
|
||||
// The timer of the toggle a single click is waiting to make.
|
||||
pendingToggle: null,
|
||||
init() {
|
||||
this.open = this.$root.hasAttribute("data-open");
|
||||
},
|
||||
toggle() {
|
||||
this.open = !this.open;
|
||||
},
|
||||
// Toggles on a click, except one that selects text, such as
|
||||
// selecting an event's ID to copy it. A single click toggles
|
||||
// only after 500 ms, the usual double-click interval, and the
|
||||
// second press of a double- or triple-click cancels that (see
|
||||
// cancelPendingToggle), so nothing moves under the pointer
|
||||
// while it selects text.
|
||||
toggleUnlessSelecting(event) {
|
||||
if (
|
||||
event.detail === 1 &&
|
||||
window.getSelection().toString() === ""
|
||||
) {
|
||||
this.pendingToggle = setTimeout(() => this.toggle(), 500);
|
||||
}
|
||||
},
|
||||
// Runs when the mouse button goes down, so the second press
|
||||
// of a double- or triple-click cancels the toggle its first
|
||||
// click is waiting to make, however long that press lasts.
|
||||
cancelPendingToggle(event) {
|
||||
if (event.detail > 1) {
|
||||
clearTimeout(this.pendingToggle);
|
||||
}
|
||||
},
|
||||
get closed() {
|
||||
return !this.open;
|
||||
},
|
||||
// Turns a downward caret up while open.
|
||||
get caretClass() {
|
||||
return { "rotate-180": this.open };
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
// The targets section's add target form, in three steps: closed,
|
||||
// choosing a type, then filling in that type's fields. targetType
|
||||
// is empty until Next takes it from the type select.
|
||||
//
|
||||
// The reason and the fields' values come from the properties below
|
||||
// rather than from the markup, because each type's fields are made
|
||||
// afresh from the markup whenever that type is chosen. A refused
|
||||
// submission comes back with its type, reason and values in the
|
||||
// section's data attributes, and starts on that type's fields with
|
||||
// them. Cancel empties these properties and resets the form, which
|
||||
// holds whatever was typed, so the next Add starts with an empty
|
||||
// form and no reason.
|
||||
window.Alpine.data("targetForm", function () {
|
||||
return {
|
||||
choosing: false,
|
||||
targetType: "",
|
||||
reason: "",
|
||||
name: "",
|
||||
url: "",
|
||||
headers: "",
|
||||
timeout: "",
|
||||
forwardQuery: false,
|
||||
maxAttempts: "",
|
||||
expiry: "",
|
||||
rotation: "",
|
||||
init() {
|
||||
const refused = this.$root.dataset;
|
||||
|
||||
this.targetType = refused.type;
|
||||
this.reason = refused.reason;
|
||||
this.name = refused.name;
|
||||
this.url = refused.destination;
|
||||
this.headers = refused.headers;
|
||||
this.timeout = refused.timeout;
|
||||
this.forwardQuery =
|
||||
this.$root.hasAttribute("data-forward-query");
|
||||
this.maxAttempts = refused.maxAttempts;
|
||||
this.expiry = refused.expiry;
|
||||
this.rotation = refused.rotation;
|
||||
},
|
||||
add() {
|
||||
this.choosing = true;
|
||||
},
|
||||
next() {
|
||||
this.targetType = this.$refs.type.value;
|
||||
this.choosing = false;
|
||||
},
|
||||
cancel() {
|
||||
this.choosing = false;
|
||||
this.targetType = "";
|
||||
this.reason = "";
|
||||
this.name = "";
|
||||
this.url = "";
|
||||
this.headers = "";
|
||||
this.timeout = "";
|
||||
this.forwardQuery = false;
|
||||
this.maxAttempts = "";
|
||||
this.expiry = "";
|
||||
this.rotation = "";
|
||||
this.$refs.form.reset();
|
||||
},
|
||||
get filling() {
|
||||
return this.targetType !== "";
|
||||
},
|
||||
get closed() {
|
||||
return !this.choosing && !this.filling;
|
||||
},
|
||||
get isHttp() {
|
||||
return this.targetType === "http";
|
||||
},
|
||||
get isSlack() {
|
||||
return this.targetType === "slack";
|
||||
},
|
||||
get isDatabase() {
|
||||
return this.targetType === "database";
|
||||
},
|
||||
get isLog() {
|
||||
return this.targetType === "log";
|
||||
},
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user