feat(filters): show current download count in list (#2001)

* feat(filters): show current and max downloads in list

* feat(filters): remove unused func param
This commit is contained in:
ze0s 2025-03-16 18:33:47 +01:00 committed by GitHub
parent c85fa3f31a
commit ef7317dde6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 63 additions and 9 deletions

View file

@ -62,6 +62,8 @@ func (r *FilterRepo) find(ctx context.Context, params domain.FilterQueryParams)
"f.enabled", "f.enabled",
"f.name", "f.name",
"f.priority", "f.priority",
"f.max_downloads",
"f.max_downloads_unit",
"f.created_at", "f.created_at",
"f.updated_at", "f.updated_at",
). ).
@ -108,10 +110,21 @@ func (r *FilterRepo) find(ctx context.Context, params domain.FilterQueryParams)
for rows.Next() { for rows.Next() {
var f domain.Filter var f domain.Filter
if err := rows.Scan(&f.ID, &f.Enabled, &f.Name, &f.Priority, &f.CreatedAt, &f.UpdatedAt, &f.ActionsCount, &f.ActionsEnabledCount, &f.IsAutoUpdated); err != nil { var maxDownloadsUnit sql.Null[string]
var maxDownloads sql.Null[int32]
if err := rows.Scan(&f.ID, &f.Enabled, &f.Name, &f.Priority, &maxDownloads, &maxDownloadsUnit, &f.CreatedAt, &f.UpdatedAt, &f.ActionsCount, &f.ActionsEnabledCount, &f.IsAutoUpdated); err != nil {
return nil, errors.Wrap(err, "error scanning row") return nil, errors.Wrap(err, "error scanning row")
} }
if maxDownloads.Valid {
f.MaxDownloads = int(maxDownloads.V)
}
if maxDownloadsUnit.Valid {
f.MaxDownloadsUnit = domain.FilterMaxDownloadsUnit(maxDownloadsUnit.V)
}
filters = append(filters, f) filters = append(filters, f)
} }
if err := rows.Err(); err != nil { if err := rows.Err(); err != nil {

View file

@ -45,11 +45,11 @@ type FilterRepo interface {
} }
type FilterDownloads struct { type FilterDownloads struct {
HourCount int HourCount int `json:"hour_count"`
DayCount int DayCount int `json:"day_count"`
WeekCount int WeekCount int `json:"week_count"`
MonthCount int MonthCount int `json:"month_count"`
TotalCount int TotalCount int `json:"total_count"`
} }
func (f *FilterDownloads) String() string { func (f *FilterDownloads) String() string {
@ -172,7 +172,7 @@ type Filter struct {
Indexers []Indexer `json:"indexers"` Indexers []Indexer `json:"indexers"`
ReleaseProfileDuplicateID int64 `json:"release_profile_duplicate_id,omitempty"` ReleaseProfileDuplicateID int64 `json:"release_profile_duplicate_id,omitempty"`
DuplicateHandling *DuplicateReleaseProfile `json:"release_profile_duplicate"` DuplicateHandling *DuplicateReleaseProfile `json:"release_profile_duplicate"`
Downloads *FilterDownloads `json:"-"` Downloads *FilterDownloads `json:"downloads,omitempty"`
Rejections []string `json:"-"` Rejections []string `json:"-"`
RejectReasons *RejectionReasons `json:"-"` RejectReasons *RejectionReasons `json:"-"`
} }

View file

@ -94,6 +94,15 @@ func (s *service) Find(ctx context.Context, params domain.FilterQueryParams) ([]
} }
filter.Indexers = indexers filter.Indexers = indexers
if filter.MaxDownloads > 0 && filter.MaxDownloadsUnit != "" {
counts, err := s.repo.GetDownloadsByFilterId(ctx, filter.ID)
if err != nil {
return ret, err
}
filter.Downloads = counts
}
ret = append(ret, filter) ret = append(ret, filter)
} }

View file

@ -612,7 +612,7 @@ function FilterListItem({ filter, idx }: FilterListItemProps) {
className="flex items-center cursor-pointer hover:text-black dark:hover:text-gray-300" className="flex items-center cursor-pointer hover:text-black dark:hover:text-gray-300"
> >
<span className={filter.actions_count === 0 || filter.actions_enabled_count === 0 ? "text-red-500 hover:text-red-400 dark:hover:text-red-400" : ""}> <span className={filter.actions_count === 0 || filter.actions_enabled_count === 0 ? "text-red-500 hover:text-red-400 dark:hover:text-red-400" : ""}>
Actions: {filter.actions_enabled_count}/{filter.actions_count} Actions: {filter.actions_enabled_count}/{filter.actions_count}
</span> </span>
</Link> </Link>
} }
@ -636,11 +636,16 @@ function FilterListItem({ filter, idx }: FilterListItemProps) {
className="flex items-center cursor-pointer hover:text-black dark:hover:text-gray-300" className="flex items-center cursor-pointer hover:text-black dark:hover:text-gray-300"
> >
<span> <span>
Actions: {filter.actions_enabled_count}/{filter.actions_count} Actions: {filter.actions_enabled_count}/{filter.actions_count}
</span> </span>
</Link> </Link>
)} )}
</span> </span>
{filter.max_downloads_unit !== "" && filter.downloads !== undefined && (
<span className="ml-2 whitespace-nowrap text-xs font-medium text-gray-600 dark:text-gray-400">
Downloads: {renderMaxDownloads(filter.max_downloads_unit, filter.downloads)}/{filter.max_downloads} per {filter.max_downloads_unit}
</span>
)}
</div> </div>
</div> </div>
<span className="hidden md:flex px-4 whitespace-nowrap text-sm font-medium text-gray-900"> <span className="hidden md:flex px-4 whitespace-nowrap text-sm font-medium text-gray-900">
@ -656,6 +661,23 @@ function FilterListItem({ filter, idx }: FilterListItemProps) {
); );
} }
function renderMaxDownloads(unit: string, downloads: FilterDownloads): number {
switch (unit) {
case "HOUR":
return downloads.hour_count
case "DAY":
return downloads.day_count
case "WEEK":
return downloads.week_count
case "MONTH":
return downloads.month_count
case "EVER":
return downloads.total_count
default:
return 0
}
}
interface IndexerTagProps { interface IndexerTagProps {
indexer: Indexer; indexer: Indexer;
} }

View file

@ -82,6 +82,7 @@ interface Filter {
actions: Action[]; actions: Action[];
indexers: Indexer[]; indexers: Indexer[];
external: ExternalFilter[]; external: ExternalFilter[];
downloads?: FilterDownloads;
release_profile_duplicate_id?: number; release_profile_duplicate_id?: number;
} }
@ -152,3 +153,12 @@ interface ExternalFilter {
webhook_retry_delay_seconds?: number; webhook_retry_delay_seconds?: number;
filter_id?: number; filter_id?: number;
} }
interface FilterDownloads {
hour_count: number;
day_count: number;
week_count: number;
month_count: number;
year_count: number;
total_count: number;
}