feat(ombi): Add Ombi PALDRA integration for request management
Docs Check / Markdown lint (push) Successful in 1m43s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 2m1s
CI / Security audit (push) Successful in 2m48s
Docs Check / Mermaid diagram parse check (push) Successful in 3m8s
CI / Tests & coverage (push) Failing after 3m33s
CI / Swagger Validation & Coverage (push) Successful in 3m34s
Build and Push Docker Image / build (push) Successful in 4m36s
Docs Check / Markdown lint (push) Successful in 1m43s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 2m1s
CI / Security audit (push) Successful in 2m48s
Docs Check / Mermaid diagram parse check (push) Successful in 3m8s
CI / Tests & coverage (push) Failing after 3m33s
CI / Swagger Validation & Coverage (push) Successful in 3m34s
Build and Push Docker Image / build (push) Successful in 4m36s
- Add OmbiRetriever extending ArrRetriever for PALDRA compliance - Add OmbiClient for low-level Ombi API communication - Add getOmbiInstances() to config.js following multi-instance pattern - Register Ombi in PALDRA registry with Ombi-specific methods - Add external ID matching (TMDB/TVDB/IMDB) to Ombi requests - Update DownloadMatcher to be async and enrich downloads with Ombi links - Add getOmbiLink/getOmbiSearchLink helpers to DownloadAssembler - Implement new service icon layout (Ombi + Sonarr/Radarr icons) - Add CSS styling for service icons - Update dashboard routes to include Ombi configuration - Extend OpenAPI with Ombi tag and NormalizedDownload properties - Update documentation (README, ARCHITECTURE, SECURITY, CHANGELOG) - Add Ombi configuration to .env.sample
This commit is contained in:
@@ -50,6 +50,48 @@ function createClientLogo(download) {
|
||||
return clientLogoWrapper;
|
||||
}
|
||||
|
||||
function createServiceIcons(download) {
|
||||
const container = document.createElement('span');
|
||||
container.className = 'service-icons-container';
|
||||
|
||||
// Add Ombi icon for all users if ombiLink exists
|
||||
if (download.ombiLink) {
|
||||
const ombiIcon = document.createElement('img');
|
||||
ombiIcon.className = 'service-icon ombi';
|
||||
ombiIcon.src = '/images/ombi.svg';
|
||||
ombiIcon.alt = 'Ombi';
|
||||
ombiIcon.title = download.ombiTooltip || 'Ombi';
|
||||
ombiIcon.href = download.ombiLink;
|
||||
const ombiLink = document.createElement('a');
|
||||
ombiLink.href = download.ombiLink;
|
||||
ombiLink.target = '_blank';
|
||||
ombiLink.appendChild(ombiIcon);
|
||||
container.appendChild(ombiLink);
|
||||
}
|
||||
|
||||
// Add Sonarr/Radarr icon for admin users if arrLink exists
|
||||
if (state.isAdmin && download.arrLink) {
|
||||
const arrIcon = document.createElement('img');
|
||||
if (download.arrType === 'sonarr') {
|
||||
arrIcon.className = 'service-icon sonarr';
|
||||
arrIcon.src = '/images/sonarr.svg';
|
||||
arrIcon.alt = 'Sonarr';
|
||||
} else if (download.arrType === 'radarr') {
|
||||
arrIcon.className = 'service-icon radarr';
|
||||
arrIcon.src = '/images/radarr.svg';
|
||||
arrIcon.alt = 'Radarr';
|
||||
}
|
||||
arrIcon.title = download.arrType === 'sonarr' ? 'Sonarr' : 'Radarr';
|
||||
const arrLink = document.createElement('a');
|
||||
arrLink.href = download.arrLink;
|
||||
arrLink.target = '_blank';
|
||||
arrLink.appendChild(arrIcon);
|
||||
container.appendChild(arrLink);
|
||||
}
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
export function renderDownloads() {
|
||||
const downloadsList = document.getElementById('downloads-list');
|
||||
const noDownloads = document.getElementById('no-downloads');
|
||||
@@ -346,11 +388,19 @@ export function createDownloadCard(download) {
|
||||
if (download.seriesName) {
|
||||
const series = document.createElement('p');
|
||||
series.className = 'download-series';
|
||||
if (state.isAdmin && download.arrLink) {
|
||||
series.innerHTML = 'Series: <a href="' + escapeHtml(download.arrLink) + '" target="_blank" class="arr-link">' + escapeHtml(download.seriesName) + '</a>';
|
||||
} else {
|
||||
series.textContent = `Series: ${download.seriesName}`;
|
||||
|
||||
// Add service icons
|
||||
const serviceIcons = createServiceIcons(download);
|
||||
if (serviceIcons.hasChildNodes()) {
|
||||
series.appendChild(serviceIcons);
|
||||
series.appendChild(document.createTextNode(' '));
|
||||
}
|
||||
|
||||
// Series name is now plain text for all users (no link)
|
||||
const seriesText = document.createElement('span');
|
||||
seriesText.textContent = `Series: ${download.seriesName}`;
|
||||
series.appendChild(seriesText);
|
||||
|
||||
infoDiv.appendChild(series);
|
||||
const epEl = formatEpisodeInfo(download.episodes);
|
||||
if (epEl) infoDiv.appendChild(epEl);
|
||||
@@ -359,11 +409,19 @@ export function createDownloadCard(download) {
|
||||
if (download.movieName) {
|
||||
const movie = document.createElement('p');
|
||||
movie.className = 'download-movie';
|
||||
if (state.isAdmin && download.arrLink) {
|
||||
movie.innerHTML = 'Movie: <a href="' + escapeHtml(download.arrLink) + '" target="_blank" class="arr-link">' + escapeHtml(download.movieName) + '</a>';
|
||||
} else {
|
||||
movie.textContent = `Movie: ${download.movieName}`;
|
||||
|
||||
// Add service icons
|
||||
const serviceIcons = createServiceIcons(download);
|
||||
if (serviceIcons.hasChildNodes()) {
|
||||
movie.appendChild(serviceIcons);
|
||||
movie.appendChild(document.createTextNode(' '));
|
||||
}
|
||||
|
||||
// Movie name is now plain text for all users (no link)
|
||||
const movieText = document.createElement('span');
|
||||
movieText.textContent = `Movie: ${download.movieName}`;
|
||||
movie.appendChild(movieText);
|
||||
|
||||
infoDiv.appendChild(movie);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,47 @@ import { saveHistoryDays, saveIgnoreAvailable } from '../utils/storage.js';
|
||||
import { formatDate, formatEpisodeInfo, escapeHtml } from '../utils/format.js';
|
||||
import { renderTagBadges } from './downloads.js';
|
||||
|
||||
function createServiceIcons(item) {
|
||||
const container = document.createElement('span');
|
||||
container.className = 'service-icons-container';
|
||||
|
||||
// Add Ombi icon for all users if ombiLink exists
|
||||
if (item.ombiLink) {
|
||||
const ombiIcon = document.createElement('img');
|
||||
ombiIcon.className = 'service-icon ombi';
|
||||
ombiIcon.src = '/images/ombi.svg';
|
||||
ombiIcon.alt = 'Ombi';
|
||||
ombiIcon.title = item.ombiTooltip || 'Ombi';
|
||||
const ombiLink = document.createElement('a');
|
||||
ombiLink.href = item.ombiLink;
|
||||
ombiLink.target = '_blank';
|
||||
ombiLink.appendChild(ombiIcon);
|
||||
container.appendChild(ombiLink);
|
||||
}
|
||||
|
||||
// Add Sonarr/Radarr icon for admin users if arrLink exists
|
||||
if (state.isAdmin && item.arrLink) {
|
||||
const arrIcon = document.createElement('img');
|
||||
if (item.arrType === 'sonarr') {
|
||||
arrIcon.className = 'service-icon sonarr';
|
||||
arrIcon.src = '/images/sonarr.svg';
|
||||
arrIcon.alt = 'Sonarr';
|
||||
} else if (item.arrType === 'radarr') {
|
||||
arrIcon.className = 'service-icon radarr';
|
||||
arrIcon.src = '/images/radarr.svg';
|
||||
arrIcon.alt = 'Radarr';
|
||||
}
|
||||
arrIcon.title = item.arrType === 'sonarr' ? 'Sonarr' : 'Radarr';
|
||||
const arrLink = document.createElement('a');
|
||||
arrLink.href = item.arrLink;
|
||||
arrLink.target = '_blank';
|
||||
arrLink.appendChild(arrIcon);
|
||||
container.appendChild(arrLink);
|
||||
}
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
export function initHistoryControls() {
|
||||
const daysInput = document.getElementById('history-days');
|
||||
const refreshBtn = document.getElementById('history-refresh-btn');
|
||||
@@ -158,15 +199,23 @@ export function createHistoryCard(item) {
|
||||
title.textContent = item.title;
|
||||
info.appendChild(title);
|
||||
|
||||
// Series/movie name with optional arr link
|
||||
// Series/movie name with service icons
|
||||
if (item.seriesName) {
|
||||
const p = document.createElement('p');
|
||||
p.className = 'history-media-name';
|
||||
if (state.isAdmin && item.arrLink) {
|
||||
p.innerHTML = 'Series: <a href="' + escapeHtml(item.arrLink) + '" target="_blank" class="arr-link">' + escapeHtml(item.seriesName) + '</a>';
|
||||
} else {
|
||||
p.textContent = 'Series: ' + item.seriesName;
|
||||
|
||||
// Add service icons
|
||||
const serviceIcons = createServiceIcons(item);
|
||||
if (serviceIcons.hasChildNodes()) {
|
||||
p.appendChild(serviceIcons);
|
||||
p.appendChild(document.createTextNode(' '));
|
||||
}
|
||||
|
||||
// Series name is now plain text for all users (no link)
|
||||
const seriesText = document.createElement('span');
|
||||
seriesText.textContent = 'Series: ' + item.seriesName;
|
||||
p.appendChild(seriesText);
|
||||
|
||||
info.appendChild(p);
|
||||
const epEl = formatEpisodeInfo(item.episodes);
|
||||
if (epEl) info.appendChild(epEl);
|
||||
@@ -174,11 +223,19 @@ export function createHistoryCard(item) {
|
||||
if (item.movieName) {
|
||||
const p = document.createElement('p');
|
||||
p.className = 'history-media-name';
|
||||
if (state.isAdmin && item.arrLink) {
|
||||
p.innerHTML = 'Movie: <a href="' + escapeHtml(item.arrLink) + '" target="_blank" class="arr-link">' + escapeHtml(item.movieName) + '</a>';
|
||||
} else {
|
||||
p.textContent = 'Movie: ' + item.movieName;
|
||||
|
||||
// Add service icons
|
||||
const serviceIcons = createServiceIcons(item);
|
||||
if (serviceIcons.hasChildNodes()) {
|
||||
p.appendChild(serviceIcons);
|
||||
p.appendChild(document.createTextNode(' '));
|
||||
}
|
||||
|
||||
// Movie name is now plain text for all users (no link)
|
||||
const movieText = document.createElement('span');
|
||||
movieText.textContent = 'Movie: ' + item.movieName;
|
||||
p.appendChild(movieText);
|
||||
|
||||
info.appendChild(p);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user