This commit is contained in:
kodi
2026-03-09 15:11:33 +01:00
parent 836d89f80e
commit cf8a079b77
5 changed files with 89 additions and 2 deletions
+10
View File
@@ -189,6 +189,16 @@ def delete_remembered_series():
return {"items": []}
@router.delete("/remembered-series/{series_id}")
def delete_remembered_series_item(series_id: str):
service = SessionService()
try:
items = service.remove_remembered_series(series_id)
except ValueError as exc:
raise HTTPException(status_code=400, detail=str(exc))
return {"items": items}
@router.get("/mapping-preview")
def get_mapping_preview(session_id: str = Query("default", min_length=1)):
service = SessionService()
+11
View File
@@ -286,6 +286,17 @@ class SessionService:
with self._connect() as conn:
conn.execute("DELETE FROM remembered_series")
def remove_remembered_series(self, series_id: str) -> list[dict]:
normalized = str(series_id or "").strip()
if not normalized:
raise ValueError("series_id is required")
with self._connect() as conn:
conn.execute(
"DELETE FROM remembered_series WHERE series_id = ?",
(normalized,),
)
return self.list_remembered_series()
def _enforce_remembered_series_limit(self, limit: int) -> None:
with self._connect() as conn:
conn.execute(
+37 -2
View File
@@ -323,6 +323,17 @@
renderRememberedDropdown();
}
async function removeRememberedSeriesItem(seriesId) {
const normalizedId = String(seriesId || "").trim();
if (!normalizedId) return;
const data = await api(`/api/session/remembered-series/${encodeURIComponent(normalizedId)}`, {
method: "DELETE",
});
state.rememberedSeries = data.items || [];
renderRememberedDropdown();
openRememberedDropdown();
}
function rememberedForQuery(query) {
const normalized = (query || "").trim().toLowerCase();
const rememberedItems = (state.rememberedSeries || []).map((entry) => entry.series || {});
@@ -352,16 +363,40 @@
function renderRememberedDropdown() {
const query = (el.searchInput.value || "").trim();
const items = rememberedForQuery(query);
const items = rememberedForQuery(query).slice().sort((a, b) => {
const aLabel = (a.display_name || a.name || "").toLowerCase();
const bLabel = (b.display_name || b.name || "").toLowerCase();
return aLabel.localeCompare(bLabel);
});
el.rememberedDropdownList.innerHTML = "";
items.forEach((item) => {
const li = document.createElement("li");
const left = document.createElement("span");
left.className = "remembered-item-title";
const label = item.display_name || item.name || "(series)";
left.textContent = label;
left.title = label;
li.appendChild(left);
li.addEventListener("click", () => withHandler(() => selectSeries(item), li));
const removeBtn = document.createElement("button");
removeBtn.type = "button";
removeBtn.className = "remembered-remove-btn";
removeBtn.textContent = "×";
removeBtn.setAttribute("aria-label", `Remove ${label}`);
removeBtn.title = `Remove ${label}`;
removeBtn.addEventListener("click", (event) => {
event.preventDefault();
event.stopPropagation();
withHandler(() => removeRememberedSeriesItem(item.id), removeBtn);
});
li.appendChild(removeBtn);
left.addEventListener("click", (event) => {
event.preventDefault();
event.stopPropagation();
withHandler(() => selectSeries(item), left);
});
el.rememberedDropdownList.appendChild(li);
});
}
+31
View File
@@ -141,6 +141,37 @@ body {
max-height: 220px;
}
#rememberedDropdownList li {
align-items: center;
}
#rememberedDropdownList .remembered-item-title {
flex: 1;
min-width: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
cursor: pointer;
}
#rememberedDropdownList .remembered-remove-btn {
border: none;
background: transparent;
color: #64748b;
width: 22px;
height: 22px;
line-height: 1;
border-radius: 4px;
padding: 0;
font-size: 15px;
cursor: pointer;
}
#rememberedDropdownList .remembered-remove-btn:hover {
background: #eef2f7;
color: #0f172a;
}
.stack {
display: flex;
flex-direction: column;
Binary file not shown.