auf Webseiten Modell umgestellt
This commit is contained in:
@@ -3,6 +3,7 @@ const state = {
|
||||
events: [],
|
||||
notifications: [],
|
||||
providerStatuses: [],
|
||||
watchSources: [],
|
||||
};
|
||||
|
||||
const watchItemsEl = document.querySelector("#watch-items");
|
||||
@@ -92,6 +93,12 @@ function renderStats() {
|
||||
}
|
||||
|
||||
function prettifyProviderName(value) {
|
||||
if (value?.startsWith("source:")) {
|
||||
const sourceId = Number(value.split(":")[1]);
|
||||
const source = state.watchSources.find((entry) => entry.id === sourceId);
|
||||
return source?.label || "Direkte Quelle";
|
||||
}
|
||||
|
||||
const names = {
|
||||
ticketmaster: "Ticketmaster",
|
||||
bandsintown: "Bandsintown",
|
||||
@@ -206,12 +213,71 @@ function renderWatchItems() {
|
||||
</div>
|
||||
</div>
|
||||
<p>${escapeHtml(item.notes || "Keine Notiz hinterlegt.")}</p>
|
||||
${renderSourceList(item.id)}
|
||||
<form class="source-form" data-watch-id="${item.id}">
|
||||
<input
|
||||
name="label"
|
||||
type="text"
|
||||
placeholder="Quelle, z. B. Kuenstlerseite"
|
||||
/>
|
||||
<input
|
||||
name="url"
|
||||
type="url"
|
||||
placeholder="https://..."
|
||||
required
|
||||
/>
|
||||
<button type="submit" class="action-button success">Quelle hinzufuegen</button>
|
||||
</form>
|
||||
</article>
|
||||
`
|
||||
)
|
||||
.join("");
|
||||
}
|
||||
|
||||
function renderSourceList(watchItemId) {
|
||||
const sources = state.watchSources.filter((source) => source.watch_item_id === watchItemId);
|
||||
if (!sources.length) {
|
||||
return '<div class="source-list muted">Noch keine direkten Quellen hinterlegt.</div>';
|
||||
}
|
||||
|
||||
return `
|
||||
<div class="source-list">
|
||||
${sources
|
||||
.map(
|
||||
(source) => `
|
||||
<div class="source-row">
|
||||
<div>
|
||||
<strong>${escapeHtml(source.label || "Quelle")}</strong>
|
||||
<a href="${escapeHtml(source.url)}" target="_blank" rel="noreferrer">
|
||||
${escapeHtml(source.url)}
|
||||
</a>
|
||||
<div class="pill-row">
|
||||
<span class="pill ${
|
||||
source.last_status === "ok"
|
||||
? "success"
|
||||
: source.last_status === "error"
|
||||
? "danger"
|
||||
: "warning"
|
||||
}">${escapeHtml(source.last_status)}</span>
|
||||
<span class="muted">${escapeHtml(source.last_message || "Noch nicht gescannt.")}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="action-row">
|
||||
<button class="action-button" data-action="toggle-source" data-id="${source.id}">
|
||||
${source.is_active ? "Pausieren" : "Aktivieren"}
|
||||
</button>
|
||||
<button class="action-button danger" data-action="delete-source" data-id="${source.id}">
|
||||
Loeschen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
)
|
||||
.join("")}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function getWatchNameById(id) {
|
||||
return state.watchItems.find((item) => item.id === id)?.name || `Watch #${id}`;
|
||||
}
|
||||
@@ -270,6 +336,13 @@ function renderEvents() {
|
||||
>
|
||||
${event.is_ticket_purchased ? "Ticket entfernen" : "Ticket gekauft"}
|
||||
</button>
|
||||
<button
|
||||
class="action-button danger"
|
||||
data-action="delete-event"
|
||||
data-id="${event.id}"
|
||||
>
|
||||
Loeschen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="event-meta">
|
||||
@@ -328,17 +401,19 @@ function updateSyncStatus(message) {
|
||||
}
|
||||
|
||||
async function loadData() {
|
||||
const [watchItems, events, notifications, providerStatuses] = await Promise.all([
|
||||
const [watchItems, events, notifications, providerStatuses, watchSources] = await Promise.all([
|
||||
apiFetch("/watch-items"),
|
||||
apiFetch("/events"),
|
||||
apiFetch("/notifications"),
|
||||
apiFetch("/provider-statuses"),
|
||||
apiFetch("/watch-sources"),
|
||||
]);
|
||||
|
||||
state.watchItems = watchItems;
|
||||
state.events = events;
|
||||
state.notifications = notifications;
|
||||
state.providerStatuses = providerStatuses;
|
||||
state.watchSources = watchSources;
|
||||
|
||||
renderStats();
|
||||
renderWatchItems();
|
||||
@@ -433,7 +508,60 @@ document.addEventListener("click", async (event) => {
|
||||
});
|
||||
await loadData();
|
||||
showToast("Ticketstatus aktualisiert.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (action === "delete-event") {
|
||||
await apiFetch(`/events/${id}`, { method: "DELETE" });
|
||||
await loadData();
|
||||
showToast("Event geloescht.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (action === "delete-source") {
|
||||
await apiFetch(`/watch-sources/${id}`, { method: "DELETE" });
|
||||
await loadData();
|
||||
showToast("Quelle geloescht.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (action === "toggle-source") {
|
||||
const source = state.watchSources.find((entry) => entry.id === Number(id));
|
||||
await apiFetch(`/watch-sources/${id}`, {
|
||||
method: "PATCH",
|
||||
body: JSON.stringify({ is_active: !source.is_active }),
|
||||
});
|
||||
await loadData();
|
||||
showToast("Quellenstatus aktualisiert.");
|
||||
}
|
||||
} catch (error) {
|
||||
showToast(error.message);
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener("submit", async (event) => {
|
||||
const form = event.target.closest(".source-form");
|
||||
if (!form) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
const watchId = form.dataset.watchId;
|
||||
const formData = new FormData(form);
|
||||
const payload = {
|
||||
label: formData.get("label")?.toString().trim() || null,
|
||||
url: formData.get("url")?.toString().trim(),
|
||||
parser_type: "auto",
|
||||
};
|
||||
|
||||
try {
|
||||
await apiFetch(`/watch-items/${watchId}/sources`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
form.reset();
|
||||
await loadData();
|
||||
showToast("Quelle hinzugefuegt.");
|
||||
} catch (error) {
|
||||
showToast(error.message);
|
||||
}
|
||||
|
||||
@@ -381,6 +381,37 @@ button:hover,
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
.source-list {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.source-row {
|
||||
display: flex;
|
||||
align-items: start;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
padding: 14px;
|
||||
border-radius: var(--radius-sm);
|
||||
background: rgba(46, 39, 30, 0.05);
|
||||
}
|
||||
|
||||
.source-row a {
|
||||
display: block;
|
||||
max-width: 46ch;
|
||||
margin: 4px 0 8px;
|
||||
overflow-wrap: anywhere;
|
||||
color: var(--primary-dark);
|
||||
}
|
||||
|
||||
.source-form {
|
||||
display: grid;
|
||||
grid-template-columns: 0.7fr 1.4fr auto;
|
||||
gap: 10px;
|
||||
margin-top: 14px;
|
||||
}
|
||||
|
||||
.action-button {
|
||||
min-height: 38px;
|
||||
padding: 0 14px;
|
||||
@@ -467,6 +498,7 @@ button:hover,
|
||||
}
|
||||
|
||||
.watch-form,
|
||||
.source-form,
|
||||
.status-panel {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user