feat(filters): list actions count (#372)

This commit is contained in:
ze0s 2022-07-23 18:06:11 +02:00 committed by GitHub
parent 4f3091a4a7
commit 2b3fab28c1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 87 additions and 78 deletions

View file

@ -27,18 +27,22 @@ func NewFilterRepo(log logger.Logger, db *DB) domain.FilterRepo {
} }
func (r *FilterRepo) ListFilters(ctx context.Context) ([]domain.Filter, error) { func (r *FilterRepo) ListFilters(ctx context.Context) ([]domain.Filter, error) {
actionCountQuery := r.db.squirrel.
Select("COUNT(*)").
From("action a").
Where("a.filter_id = f.id")
queryBuilder := r.db.squirrel. queryBuilder := r.db.squirrel.
Select( Select(
"id", "f.id",
"enabled", "f.enabled",
"name", "f.name",
"match_releases", "f.created_at",
"except_releases", "f.updated_at",
"created_at",
"updated_at",
). ).
From("filter"). Column(sq.Alias(actionCountQuery, "action_count")).
OrderBy("name ASC") From("filter f").
OrderBy("f.name ASC")
query, args, err := queryBuilder.ToSql() query, args, err := queryBuilder.ToSql()
if err != nil { if err != nil {
@ -56,15 +60,10 @@ func (r *FilterRepo) ListFilters(ctx context.Context) ([]domain.Filter, error) {
for rows.Next() { for rows.Next() {
var f domain.Filter var f domain.Filter
var matchReleases, exceptReleases sql.NullString if err := rows.Scan(&f.ID, &f.Enabled, &f.Name, &f.CreatedAt, &f.UpdatedAt, &f.ActionsCount); err != nil {
if err := rows.Scan(&f.ID, &f.Enabled, &f.Name, &matchReleases, &exceptReleases, &f.CreatedAt, &f.UpdatedAt); err != nil {
return nil, errors.Wrap(err, "error scanning row") return nil, errors.Wrap(err, "error scanning row")
} }
f.MatchReleases = matchReleases.String
f.ExceptReleases = exceptReleases.String
filters = append(filters, f) filters = append(filters, f)
} }
if err := rows.Err(); err != nil { if err := rows.Err(); err != nil {

View file

@ -54,62 +54,63 @@ type Filter struct {
Enabled bool `json:"enabled"` Enabled bool `json:"enabled"`
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"` UpdatedAt time.Time `json:"updated_at"`
MinSize string `json:"min_size"` MinSize string `json:"min_size,omitempty"`
MaxSize string `json:"max_size"` MaxSize string `json:"max_size,omitempty"`
Delay int `json:"delay"` Delay int `json:"delay,omitempty"`
Priority int32 `json:"priority"` Priority int32 `json:"priority,omitempty"`
MaxDownloads int `json:"max_downloads"` MaxDownloads int `json:"max_downloads,omitempty"`
MaxDownloadsUnit FilterMaxDownloadsUnit `json:"max_downloads_unit"` MaxDownloadsUnit FilterMaxDownloadsUnit `json:"max_downloads_unit,omitempty"`
MatchReleases string `json:"match_releases"` MatchReleases string `json:"match_releases,omitempty"`
ExceptReleases string `json:"except_releases"` ExceptReleases string `json:"except_releases,omitempty"`
UseRegex bool `json:"use_regex"` UseRegex bool `json:"use_regex,omitempty"`
MatchReleaseGroups string `json:"match_release_groups"` MatchReleaseGroups string `json:"match_release_groups,omitempty"`
ExceptReleaseGroups string `json:"except_release_groups"` ExceptReleaseGroups string `json:"except_release_groups,omitempty"`
Scene bool `json:"scene"` Scene bool `json:"scene,omitempty"`
Origins []string `json:"origins"` Origins []string `json:"origins,omitempty"`
Bonus []string `json:"bonus"` Bonus []string `json:"bonus,omitempty"`
Freeleech bool `json:"freeleech"` Freeleech bool `json:"freeleech,omitempty"`
FreeleechPercent string `json:"freeleech_percent"` FreeleechPercent string `json:"freeleech_percent,omitempty"`
Shows string `json:"shows"` Shows string `json:"shows,omitempty"`
Seasons string `json:"seasons"` Seasons string `json:"seasons,omitempty"`
Episodes string `json:"episodes"` Episodes string `json:"episodes,omitempty"`
Resolutions []string `json:"resolutions"` // SD, 480i, 480p, 576p, 720p, 810p, 1080i, 1080p. Resolutions []string `json:"resolutions,omitempty"` // SD, 480i, 480p, 576p, 720p, 810p, 1080i, 1080p.
Codecs []string `json:"codecs"` // XviD, DivX, x264, h.264 (or h264), mpeg2 (or mpeg-2), VC-1 (or VC1), WMV, Remux, h.264 Remux (or h264 Remux), VC-1 Remux (or VC1 Remux). Codecs []string `json:"codecs,omitempty"` // XviD, DivX, x264, h.264 (or h264), mpeg2 (or mpeg-2), VC-1 (or VC1), WMV, Remux, h.264 Remux (or h264 Remux), VC-1 Remux (or VC1 Remux).
Sources []string `json:"sources"` // DSR, PDTV, HDTV, HR.PDTV, HR.HDTV, DVDRip, DVDScr, BDr, BD5, BD9, BDRip, BRRip, DVDR, MDVDR, HDDVD, HDDVDRip, BluRay, WEB-DL, TVRip, CAM, R5, TELESYNC, TS, TELECINE, TC. TELESYNC and TS are synonyms (you don't need both). Same for TELECINE and TC Sources []string `json:"sources,omitempty"` // DSR, PDTV, HDTV, HR.PDTV, HR.HDTV, DVDRip, DVDScr, BDr, BD5, BD9, BDRip, BRRip, DVDR, MDVDR, HDDVD, HDDVDRip, BluRay, WEB-DL, TVRip, CAM, R5, TELESYNC, TS, TELECINE, TC. TELESYNC and TS are synonyms (you don't need both). Same for TELECINE and TC
Containers []string `json:"containers"` Containers []string `json:"containers,omitempty"`
MatchHDR []string `json:"match_hdr"` MatchHDR []string `json:"match_hdr,omitempty"`
ExceptHDR []string `json:"except_hdr"` ExceptHDR []string `json:"except_hdr,omitempty"`
MatchOther []string `json:"match_other"` MatchOther []string `json:"match_other,omitempty"`
ExceptOther []string `json:"except_other"` ExceptOther []string `json:"except_other,omitempty"`
Years string `json:"years"` Years string `json:"years,omitempty"`
Artists string `json:"artists"` Artists string `json:"artists,omitempty"`
Albums string `json:"albums"` Albums string `json:"albums,omitempty"`
MatchReleaseTypes []string `json:"match_release_types"` // Album,Single,EP MatchReleaseTypes []string `json:"match_release_types,omitempty"` // Album,Single,EP
ExceptReleaseTypes string `json:"except_release_types"` ExceptReleaseTypes string `json:"except_release_types,omitempty"`
Formats []string `json:"formats"` // MP3, FLAC, Ogg, AAC, AC3, DTS Formats []string `json:"formats,omitempty"` // MP3, FLAC, Ogg, AAC, AC3, DTS
Quality []string `json:"quality"` // 192, 320, APS (VBR), V2 (VBR), V1 (VBR), APX (VBR), V0 (VBR), q8.x (VBR), Lossless, 24bit Lossless, Other Quality []string `json:"quality,omitempty"` // 192, 320, APS (VBR), V2 (VBR), V1 (VBR), APX (VBR), V0 (VBR), q8.x (VBR), Lossless, 24bit Lossless, Other
Media []string `json:"media"` // CD, DVD, Vinyl, Soundboard, SACD, DAT, Cassette, WEB, Other Media []string `json:"media,omitempty"` // CD, DVD, Vinyl, Soundboard, SACD, DAT, Cassette, WEB, Other
PerfectFlac bool `json:"perfect_flac"` PerfectFlac bool `json:"perfect_flac,omitempty"`
Cue bool `json:"cue"` Cue bool `json:"cue,omitempty"`
Log bool `json:"log"` Log bool `json:"log,omitempty"`
LogScore int `json:"log_score"` LogScore int `json:"log_score,omitempty"`
MatchCategories string `json:"match_categories"` MatchCategories string `json:"match_categories,omitempty"`
ExceptCategories string `json:"except_categories"` ExceptCategories string `json:"except_categories,omitempty"`
MatchUploaders string `json:"match_uploaders"` MatchUploaders string `json:"match_uploaders,omitempty"`
ExceptUploaders string `json:"except_uploaders"` ExceptUploaders string `json:"except_uploaders,omitempty"`
Tags string `json:"tags"` Tags string `json:"tags,omitempty"`
ExceptTags string `json:"except_tags"` ExceptTags string `json:"except_tags,omitempty"`
TagsAny string `json:"tags_any"` TagsAny string `json:"tags_any,omitempty"`
ExceptTagsAny string `json:"except_tags_any"` ExceptTagsAny string `json:"except_tags_any,omitempty"`
ExternalScriptEnabled bool `json:"external_script_enabled"` ExternalScriptEnabled bool `json:"external_script_enabled,omitempty"`
ExternalScriptCmd string `json:"external_script_cmd"` ExternalScriptCmd string `json:"external_script_cmd,omitempty"`
ExternalScriptArgs string `json:"external_script_args"` ExternalScriptArgs string `json:"external_script_args,omitempty"`
ExternalScriptExpectStatus int `json:"external_script_expect_status"` ExternalScriptExpectStatus int `json:"external_script_expect_status,omitempty"`
ExternalWebhookEnabled bool `json:"external_webhook_enabled"` ExternalWebhookEnabled bool `json:"external_webhook_enabled,omitempty"`
ExternalWebhookHost string `json:"external_webhook_host"` ExternalWebhookHost string `json:"external_webhook_host,omitempty"`
ExternalWebhookData string `json:"external_webhook_data"` ExternalWebhookData string `json:"external_webhook_data,omitempty"`
ExternalWebhookExpectStatus int `json:"external_webhook_expect_status"` ExternalWebhookExpectStatus int `json:"external_webhook_expect_status,omitempty"`
Actions []*Action `json:"actions"` ActionsCount int `json:"actions_count"`
Actions []*Action `json:"actions,omitempty"`
Indexers []Indexer `json:"indexers"` Indexers []Indexer `json:"indexers"`
Downloads *FilterDownloads `json:"-"` Downloads *FilterDownloads `json:"-"`
} }

View file

@ -76,16 +76,16 @@ function FilterList({ filters }: FilterListProps) {
<table className="min-w-full"> <table className="min-w-full">
<thead className="bg-gray-50 dark:bg-gray-800 text-gray-500 dark:text-gray-400 border-b border-gray-200 dark:border-gray-700"> <thead className="bg-gray-50 dark:bg-gray-800 text-gray-500 dark:text-gray-400 border-b border-gray-200 dark:border-gray-700">
<tr> <tr>
{["Enabled", "Name", "Indexers"].map((label) => ( {["Enabled", "Name", "Actions", "Indexers"].map((label) => (
<th <th
key={`th-${label}`} key={`th-${label}`}
scope="col" scope="col"
className="px-6 pt-4 pb-3 text-left text-xs font-medium uppercase tracking-wider" className="px-4 pt-4 pb-3 text-left text-xs font-medium uppercase tracking-wider"
> >
{label} {label}
</th> </th>
))} ))}
<th scope="col" className="relative px-6 py-3"> <th scope="col" className="relative px-4 py-3">
<span className="sr-only">Edit</span> <span className="sr-only">Edit</span>
</th> </th>
</tr> </tr>
@ -297,7 +297,7 @@ function FilterListItem({ filter, idx }: FilterListItemProps) {
)} )}
> >
<td <td
className="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-100" className="px-4 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-100"
> >
<Switch <Switch
checked={enabled} checked={enabled}
@ -317,7 +317,7 @@ function FilterListItem({ filter, idx }: FilterListItemProps) {
/> />
</Switch> </Switch>
</td> </td>
<td className="px-6 w-full whitespace-nowrap text-sm font-medium text-gray-900 dark:text-gray-100"> <td className="px-4 w-full whitespace-nowrap text-sm font-medium text-gray-900 dark:text-gray-100">
<Link <Link
to={filter.id.toString()} to={filter.id.toString()}
className="hover:text-black dark:hover:text-gray-300 w-full py-4 flex" className="hover:text-black dark:hover:text-gray-300 w-full py-4 flex"
@ -325,7 +325,15 @@ function FilterListItem({ filter, idx }: FilterListItemProps) {
{filter.name} {filter.name}
</Link> </Link>
</td> </td>
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900"> <td className="px-4 w-full whitespace-nowrap text-sm font-medium text-gray-900 dark:text-gray-100">
<Link
to={`${filter.id.toString()}/actions`}
className="hover:text-black dark:hover:text-gray-300 w-full py-4 flex"
>
<span className={classNames(filter.actions_count == 0 ? "text-red-500" : "")}>{filter.actions_count}</span>
</Link>
</td>
<td className="px-4 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
{filter.indexers && filter.indexers.map((t) => ( {filter.indexers && filter.indexers.map((t) => (
<span <span
key={t.id} key={t.id}
@ -335,7 +343,7 @@ function FilterListItem({ filter, idx }: FilterListItemProps) {
</span> </span>
))} ))}
</td> </td>
<td className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"> <td className="px-4 py-4 whitespace-nowrap text-right text-sm font-medium">
<FilterItemDropdown <FilterItemDropdown
filter={filter} filter={filter}
onToggle={toggleActive} onToggle={toggleActive}

View file

@ -50,6 +50,7 @@ interface Filter {
except_tags: string; except_tags: string;
tags_any: string; tags_any: string;
except_tags_any: string; except_tags_any: string;
actions_count: number;
actions: Action[]; actions: Action[];
indexers: Indexer[]; indexers: Indexer[];
external_script_enabled: boolean; external_script_enabled: boolean;