mirror of
https://github.com/idanoo/autobrr
synced 2025-07-22 16:29:12 +00:00
fix: blank page loading filters (#107)
* fix(filters): load indexers separate * feat: add ctx to filter related db methods
This commit is contained in:
parent
10a2ab2c96
commit
26f558859a
10 changed files with 90 additions and 115 deletions
|
@ -16,7 +16,7 @@ func NewActionRepo(db *SqliteDB) domain.ActionRepo {
|
|||
return &ActionRepo{db: db}
|
||||
}
|
||||
|
||||
func (r *ActionRepo) FindByFilterID(filterID int) ([]domain.Action, error) {
|
||||
func (r *ActionRepo) FindByFilterID(ctx context.Context, filterID int) ([]domain.Action, error) {
|
||||
//r.db.lock.RLock()
|
||||
//defer r.db.lock.RUnlock()
|
||||
|
||||
|
|
|
@ -19,11 +19,11 @@ func NewFilterRepo(db *SqliteDB) domain.FilterRepo {
|
|||
return &FilterRepo{db: db}
|
||||
}
|
||||
|
||||
func (r *FilterRepo) ListFilters() ([]domain.Filter, error) {
|
||||
func (r *FilterRepo) ListFilters(ctx context.Context) ([]domain.Filter, error) {
|
||||
//r.db.lock.RLock()
|
||||
//defer r.db.lock.RUnlock()
|
||||
|
||||
rows, err := r.db.handler.Query("SELECT id, enabled, name, match_releases, except_releases, created_at, updated_at FROM filter ORDER BY name ASC")
|
||||
rows, err := r.db.handler.QueryContext(ctx, "SELECT id, enabled, name, match_releases, except_releases, created_at, updated_at FROM filter ORDER BY name ASC")
|
||||
if err != nil {
|
||||
log.Error().Stack().Err(err).Msg("filters_list: error query data")
|
||||
return nil, err
|
||||
|
@ -54,18 +54,16 @@ func (r *FilterRepo) ListFilters() ([]domain.Filter, error) {
|
|||
return filters, nil
|
||||
}
|
||||
|
||||
func (r *FilterRepo) FindByID(filterID int) (*domain.Filter, error) {
|
||||
func (r *FilterRepo) FindByID(ctx context.Context, filterID int) (*domain.Filter, error) {
|
||||
//r.db.lock.RLock()
|
||||
//defer r.db.lock.RUnlock()
|
||||
|
||||
row := r.db.handler.QueryRow("SELECT id, enabled, name, min_size, max_size, delay, match_releases, except_releases, use_regex, match_release_groups, except_release_groups, scene, freeleech, freeleech_percent, shows, seasons, episodes, resolutions, codecs, sources, containers, match_hdr, except_hdr, years, artists, albums, release_types_match, formats, quality, media, log_score, has_log, has_cue, perfect_flac, match_categories, except_categories, match_uploaders, except_uploaders, tags, except_tags, created_at, updated_at FROM filter WHERE id = ?", filterID)
|
||||
|
||||
var f domain.Filter
|
||||
|
||||
row := r.db.handler.QueryRowContext(ctx, "SELECT id, enabled, name, min_size, max_size, delay, match_releases, except_releases, use_regex, match_release_groups, except_release_groups, scene, freeleech, freeleech_percent, shows, seasons, episodes, resolutions, codecs, sources, containers, match_hdr, except_hdr, years, artists, albums, release_types_match, formats, quality, media, log_score, has_log, has_cue, perfect_flac, match_categories, except_categories, match_uploaders, except_uploaders, tags, except_tags, created_at, updated_at FROM filter WHERE id = ?", filterID)
|
||||
if err := row.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var f domain.Filter
|
||||
var minSize, maxSize, matchReleases, exceptReleases, matchReleaseGroups, exceptReleaseGroups, freeleechPercent, shows, seasons, episodes, years, artists, albums, matchCategories, exceptCategories, matchUploaders, exceptUploaders, tags, exceptTags sql.NullString
|
||||
var useRegex, scene, freeleech, hasLog, hasCue, perfectFlac sql.NullBool
|
||||
var delay, logScore sql.NullInt32
|
||||
|
|
|
@ -64,7 +64,8 @@ func (r *IndexerRepo) List() ([]domain.Indexer, error) {
|
|||
|
||||
rows, err := r.db.handler.Query("SELECT id, enabled, name, identifier, settings FROM indexer ORDER BY name ASC")
|
||||
if err != nil {
|
||||
log.Fatal().Err(err)
|
||||
log.Error().Stack().Err(err).Msg("indexer.list: error query indexer")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
@ -78,8 +79,6 @@ func (r *IndexerRepo) List() ([]domain.Indexer, error) {
|
|||
|
||||
if err := rows.Scan(&f.ID, &f.Enabled, &f.Name, &f.Identifier, &settings); err != nil {
|
||||
log.Error().Stack().Err(err).Msg("indexer.list: error scanning data to struct")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -100,17 +99,18 @@ func (r *IndexerRepo) List() ([]domain.Indexer, error) {
|
|||
return indexers, nil
|
||||
}
|
||||
|
||||
func (r *IndexerRepo) FindByFilterID(id int) ([]domain.Indexer, error) {
|
||||
func (r *IndexerRepo) FindByFilterID(ctx context.Context, id int) ([]domain.Indexer, error) {
|
||||
//r.db.lock.RLock()
|
||||
//defer r.db.lock.RUnlock()
|
||||
|
||||
rows, err := r.db.handler.Query(`
|
||||
rows, err := r.db.handler.QueryContext(ctx, `
|
||||
SELECT i.id, i.enabled, i.name, i.identifier
|
||||
FROM indexer i
|
||||
JOIN filter_indexer fi on i.id = fi.indexer_id
|
||||
WHERE fi.filter_id = ?`, id)
|
||||
if err != nil {
|
||||
log.Fatal().Err(err)
|
||||
log.Error().Stack().Err(err).Msg("indexer.find_by_filter_id: error query indexer")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
@ -123,9 +123,7 @@ func (r *IndexerRepo) FindByFilterID(id int) ([]domain.Indexer, error) {
|
|||
//var settingsMap map[string]string
|
||||
|
||||
if err := rows.Scan(&f.ID, &f.Enabled, &f.Name, &f.Identifier); err != nil {
|
||||
log.Error().Stack().Err(err).Msg("indexer.list: error scanning data to struct")
|
||||
}
|
||||
if err != nil {
|
||||
log.Error().Stack().Err(err).Msg("indexer.find_by_filter_id: error scanning data to struct")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ type ActionRepo interface {
|
|||
Store(ctx context.Context, action Action) (*Action, error)
|
||||
StoreFilterActions(ctx context.Context, actions []Action, filterID int64) ([]Action, error)
|
||||
DeleteByFilterID(ctx context.Context, filterID int) error
|
||||
FindByFilterID(filterID int) ([]Action, error)
|
||||
FindByFilterID(ctx context.Context, filterID int) ([]Action, error)
|
||||
List() ([]Action, error)
|
||||
Delete(actionID int) error
|
||||
ToggleEnabled(actionID int) error
|
||||
|
|
|
@ -11,9 +11,9 @@ https://autodl-community.github.io/autodl-irssi/configuration/filter/
|
|||
*/
|
||||
|
||||
type FilterRepo interface {
|
||||
FindByID(filterID int) (*Filter, error)
|
||||
FindByID(ctx context.Context, filterID int) (*Filter, error)
|
||||
FindByIndexerIdentifier(indexer string) ([]Filter, error)
|
||||
ListFilters() ([]Filter, error)
|
||||
ListFilters(ctx context.Context) ([]Filter, error)
|
||||
Store(filter Filter) (*Filter, error)
|
||||
Update(ctx context.Context, filter Filter) (*Filter, error)
|
||||
ToggleEnabled(ctx context.Context, filterID int, enabled bool) error
|
||||
|
|
|
@ -11,7 +11,7 @@ type IndexerRepo interface {
|
|||
Update(indexer Indexer) (*Indexer, error)
|
||||
List() ([]Indexer, error)
|
||||
Delete(ctx context.Context, id int) error
|
||||
FindByFilterID(id int) ([]Indexer, error)
|
||||
FindByFilterID(ctx context.Context, id int) ([]Indexer, error)
|
||||
}
|
||||
|
||||
type Indexer struct {
|
||||
|
|
|
@ -13,10 +13,10 @@ import (
|
|||
)
|
||||
|
||||
type Service interface {
|
||||
FindByID(filterID int) (*domain.Filter, error)
|
||||
FindByID(ctx context.Context, filterID int) (*domain.Filter, error)
|
||||
FindByIndexerIdentifier(indexer string) ([]domain.Filter, error)
|
||||
FindAndCheckFilters(release *domain.Release) (bool, *domain.Filter, error)
|
||||
ListFilters() ([]domain.Filter, error)
|
||||
ListFilters(ctx context.Context) ([]domain.Filter, error)
|
||||
Store(filter domain.Filter) (*domain.Filter, error)
|
||||
Update(ctx context.Context, filter domain.Filter) (*domain.Filter, error)
|
||||
ToggleEnabled(ctx context.Context, filterID int, enabled bool) error
|
||||
|
@ -39,9 +39,9 @@ func NewService(repo domain.FilterRepo, actionRepo domain.ActionRepo, apiService
|
|||
}
|
||||
}
|
||||
|
||||
func (s *service) ListFilters() ([]domain.Filter, error) {
|
||||
func (s *service) ListFilters(ctx context.Context) ([]domain.Filter, error) {
|
||||
// get filters
|
||||
filters, err := s.repo.ListFilters()
|
||||
filters, err := s.repo.ListFilters(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ func (s *service) ListFilters() ([]domain.Filter, error) {
|
|||
var ret []domain.Filter
|
||||
|
||||
for _, filter := range filters {
|
||||
indexers, err := s.indexerSvc.FindByFilterID(filter.ID)
|
||||
indexers, err := s.indexerSvc.FindByFilterID(ctx, filter.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -61,22 +61,22 @@ func (s *service) ListFilters() ([]domain.Filter, error) {
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
func (s *service) FindByID(filterID int) (*domain.Filter, error) {
|
||||
func (s *service) FindByID(ctx context.Context, filterID int) (*domain.Filter, error) {
|
||||
// find filter
|
||||
filter, err := s.repo.FindByID(filterID)
|
||||
filter, err := s.repo.FindByID(ctx, filterID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// find actions and attach
|
||||
actions, err := s.actionRepo.FindByFilterID(filter.ID)
|
||||
actions, err := s.actionRepo.FindByFilterID(ctx, filter.ID)
|
||||
if err != nil {
|
||||
log.Error().Msgf("could not find filter actions: %+v", &filter.ID)
|
||||
}
|
||||
filter.Actions = actions
|
||||
|
||||
// find indexers and attach
|
||||
indexers, err := s.indexerSvc.FindByFilterID(filter.ID)
|
||||
indexers, err := s.indexerSvc.FindByFilterID(ctx, filter.ID)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msgf("could not find indexers for filter: %+v", &filter.Name)
|
||||
return nil, err
|
||||
|
@ -276,7 +276,7 @@ func (s *service) FindAndCheckFilters(release *domain.Release) (bool, *domain.Fi
|
|||
}
|
||||
|
||||
// found matching filter, lets find the filter actions and attach
|
||||
actions, err := s.actionRepo.FindByFilterID(f.ID)
|
||||
actions, err := s.actionRepo.FindByFilterID(context.TODO(), f.ID)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msgf("could not find actions for filter: %+v", f.Name)
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@ import (
|
|||
)
|
||||
|
||||
type filterService interface {
|
||||
ListFilters() ([]domain.Filter, error)
|
||||
FindByID(filterID int) (*domain.Filter, error)
|
||||
ListFilters(ctx context.Context) ([]domain.Filter, error)
|
||||
FindByID(ctx context.Context, filterID int) (*domain.Filter, error)
|
||||
Store(filter domain.Filter) (*domain.Filter, error)
|
||||
Delete(ctx context.Context, filterID int) error
|
||||
Update(ctx context.Context, filter domain.Filter) (*domain.Filter, error)
|
||||
|
@ -44,7 +44,7 @@ func (h filterHandler) Routes(r chi.Router) {
|
|||
func (h filterHandler) getFilters(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
trackers, err := h.service.ListFilters()
|
||||
trackers, err := h.service.ListFilters(ctx)
|
||||
if err != nil {
|
||||
//
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ func (h filterHandler) getByID(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
id, _ := strconv.Atoi(filterID)
|
||||
|
||||
filter, err := h.service.FindByID(id)
|
||||
filter, err := h.service.FindByID(ctx, id)
|
||||
if err != nil {
|
||||
h.encoder.StatusNotFound(ctx, w)
|
||||
return
|
||||
|
@ -69,22 +69,6 @@ func (h filterHandler) getByID(w http.ResponseWriter, r *http.Request) {
|
|||
h.encoder.StatusResponse(ctx, w, filter, http.StatusOK)
|
||||
}
|
||||
|
||||
func (h filterHandler) storeFilterAction(w http.ResponseWriter, r *http.Request) {
|
||||
var (
|
||||
ctx = r.Context()
|
||||
filterID = chi.URLParam(r, "filterID")
|
||||
)
|
||||
|
||||
id, _ := strconv.Atoi(filterID)
|
||||
|
||||
filter, err := h.service.FindByID(id)
|
||||
if err != nil {
|
||||
//
|
||||
}
|
||||
|
||||
h.encoder.StatusResponse(ctx, w, filter, http.StatusCreated)
|
||||
}
|
||||
|
||||
func (h filterHandler) store(w http.ResponseWriter, r *http.Request) {
|
||||
var (
|
||||
ctx = r.Context()
|
||||
|
|
|
@ -16,7 +16,7 @@ type Service interface {
|
|||
Store(indexer domain.Indexer) (*domain.Indexer, error)
|
||||
Update(indexer domain.Indexer) (*domain.Indexer, error)
|
||||
Delete(ctx context.Context, id int) error
|
||||
FindByFilterID(id int) ([]domain.Indexer, error)
|
||||
FindByFilterID(ctx context.Context, id int) ([]domain.Indexer, error)
|
||||
List() ([]domain.Indexer, error)
|
||||
GetAll() ([]*domain.IndexerDefinition, error)
|
||||
GetTemplates() ([]domain.IndexerDefinition, error)
|
||||
|
@ -92,8 +92,8 @@ func (s *service) Delete(ctx context.Context, id int) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *service) FindByFilterID(id int) ([]domain.Indexer, error) {
|
||||
filters, err := s.repo.FindByFilterID(id)
|
||||
func (s *service) FindByFilterID(ctx context.Context, id int) ([]domain.Indexer, error) {
|
||||
filters, err := s.repo.FindByFilterID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -115,7 +115,7 @@ export default function FilterDetails() {
|
|||
let history = useHistory();
|
||||
let { filterId }: any = useParams();
|
||||
|
||||
const { isLoading, data } = useQuery<Filter, Error>(['filter', parseInt(filterId)], () => APIClient.filters.getByID(parseInt(filterId)),
|
||||
const { isLoading, data: filter } = useQuery<Filter, Error>(['filter', parseInt(filterId)], () => APIClient.filters.getByID(parseInt(filterId)),
|
||||
{
|
||||
retry: false,
|
||||
refetchOnWindowFocus: false,
|
||||
|
@ -125,12 +125,6 @@ export default function FilterDetails() {
|
|||
},
|
||||
)
|
||||
|
||||
const { data: indexers } = useQuery<Indexer[], Error>(["filter", "indexer_list"], APIClient.indexers.getOptions,
|
||||
{
|
||||
refetchOnWindowFocus: false
|
||||
}
|
||||
)
|
||||
|
||||
const updateMutation = useMutation((filter: Filter) => APIClient.filters.update(filter), {
|
||||
onSuccess: (filter) => {
|
||||
// queryClient.setQueryData(['filter', filter.id], data)
|
||||
|
@ -142,7 +136,7 @@ export default function FilterDetails() {
|
|||
|
||||
const deleteMutation = useMutation((id: number) => APIClient.filters.delete(id), {
|
||||
onSuccess: () => {
|
||||
toast.custom((t) => <Toast type="success" body={`${data?.name} was deleted`} t={t} />)
|
||||
toast.custom((t) => <Toast type="success" body={`${filter?.name} was deleted`} t={t} />)
|
||||
|
||||
// redirect
|
||||
history.push("/filters")
|
||||
|
@ -153,7 +147,7 @@ export default function FilterDetails() {
|
|||
return null
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
if (!filter) {
|
||||
return null
|
||||
}
|
||||
|
||||
|
@ -162,7 +156,7 @@ export default function FilterDetails() {
|
|||
}
|
||||
|
||||
const deleteAction = () => {
|
||||
deleteMutation.mutate(data.id)
|
||||
deleteMutation.mutate(filter.id)
|
||||
}
|
||||
|
||||
const handleMobileNav = (e: any, href: string) => {
|
||||
|
@ -183,7 +177,7 @@ export default function FilterDetails() {
|
|||
</NavLink>
|
||||
</h1>
|
||||
<ChevronRightIcon className="h-6 w-6 text-gray-500" aria-hidden="true" />
|
||||
<h1 className="text-3xl font-bold text-white capitalize">{data.name}</h1>
|
||||
<h1 className="text-3xl font-bold text-white capitalize">{filter.name}</h1>
|
||||
</div>
|
||||
</header>
|
||||
<div className="max-w-7xl mx-auto pb-12 px-4 sm:px-6 lg:px-8">
|
||||
|
@ -220,46 +214,46 @@ export default function FilterDetails() {
|
|||
|
||||
<Formik
|
||||
initialValues={{
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
enabled: data.enabled || false,
|
||||
min_size: data.min_size,
|
||||
max_size: data.max_size,
|
||||
delay: data.delay,
|
||||
shows: data.shows,
|
||||
years: data.years,
|
||||
resolutions: data.resolutions || [],
|
||||
sources: data.sources || [],
|
||||
codecs: data.codecs || [],
|
||||
containers: data.containers || [],
|
||||
match_hdr: data.match_hdr || [],
|
||||
except_hdr: data.except_hdr || [],
|
||||
seasons: data.seasons,
|
||||
episodes: data.episodes,
|
||||
match_releases: data.match_releases,
|
||||
except_releases: data.except_releases,
|
||||
match_release_groups: data.match_release_groups,
|
||||
except_release_groups: data.except_release_groups,
|
||||
match_categories: data.match_categories,
|
||||
except_categories: data.except_categories,
|
||||
tags: data.tags,
|
||||
except_tags: data.except_tags,
|
||||
match_uploaders: data.match_uploaders,
|
||||
except_uploaders: data.except_uploaders,
|
||||
freeleech: data.freeleech,
|
||||
freeleech_percent: data.freeleech_percent,
|
||||
indexers: data.indexers || [],
|
||||
actions: data.actions || [],
|
||||
formats: data.formats || [],
|
||||
quality: data.quality || [],
|
||||
media: data.media || [],
|
||||
match_release_types: data.match_release_types || [],
|
||||
log_score: data.log_score,
|
||||
log: data.log,
|
||||
cue: data.cue,
|
||||
perfect_flac: data.perfect_flac,
|
||||
artists: data.artists,
|
||||
albums: data.albums,
|
||||
id: filter.id,
|
||||
name: filter.name,
|
||||
enabled: filter.enabled || false,
|
||||
min_size: filter.min_size,
|
||||
max_size: filter.max_size,
|
||||
delay: filter.delay,
|
||||
shows: filter.shows,
|
||||
years: filter.years,
|
||||
resolutions: filter.resolutions || [],
|
||||
sources: filter.sources || [],
|
||||
codecs: filter.codecs || [],
|
||||
containers: filter.containers || [],
|
||||
match_hdr: filter.match_hdr || [],
|
||||
except_hdr: filter.except_hdr || [],
|
||||
seasons: filter.seasons,
|
||||
episodes: filter.episodes,
|
||||
match_releases: filter.match_releases,
|
||||
except_releases: filter.except_releases,
|
||||
match_release_groups: filter.match_release_groups,
|
||||
except_release_groups: filter.except_release_groups,
|
||||
match_categories: filter.match_categories,
|
||||
except_categories: filter.except_categories,
|
||||
tags: filter.tags,
|
||||
except_tags: filter.except_tags,
|
||||
match_uploaders: filter.match_uploaders,
|
||||
except_uploaders: filter.except_uploaders,
|
||||
freeleech: filter.freeleech,
|
||||
freeleech_percent: filter.freeleech_percent,
|
||||
indexers: filter.indexers || [],
|
||||
actions: filter.actions || [],
|
||||
formats: filter.formats || [],
|
||||
quality: filter.quality || [],
|
||||
media: filter.media || [],
|
||||
match_release_types: filter.match_release_types || [],
|
||||
log_score: filter.log_score,
|
||||
log: filter.log,
|
||||
cue: filter.cue,
|
||||
perfect_flac: filter.perfect_flac,
|
||||
artists: filter.artists,
|
||||
albums: filter.albums,
|
||||
} as Filter}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
|
@ -267,7 +261,7 @@ export default function FilterDetails() {
|
|||
<Form>
|
||||
<RouteSwitch>
|
||||
<Route exact path={url}>
|
||||
<General indexers={indexers as any} />
|
||||
<General />
|
||||
</Route>
|
||||
|
||||
<Route path={`${url}/movies-tv`}>
|
||||
|
@ -283,7 +277,7 @@ export default function FilterDetails() {
|
|||
</Route>
|
||||
|
||||
<Route path={`${url}/actions`}>
|
||||
<FilterActions filter={data} values={values} />
|
||||
<FilterActions filter={filter} values={values} />
|
||||
</Route>
|
||||
</RouteSwitch>
|
||||
|
||||
|
@ -303,13 +297,14 @@ export default function FilterDetails() {
|
|||
)
|
||||
}
|
||||
|
||||
interface GeneralProps {
|
||||
indexers: Indexer[];
|
||||
}
|
||||
|
||||
function General({ indexers }: GeneralProps) {
|
||||
|
||||
let opts = indexers ? indexers.map(v => ({
|
||||
function General() {
|
||||
const { isLoading, data: indexers } = useQuery<Indexer[], Error>(["filter", "indexer_list"], APIClient.indexers.getOptions,
|
||||
{
|
||||
refetchOnWindowFocus: false
|
||||
}
|
||||
)
|
||||
|
||||
let opts = indexers && indexers.length > 0 ? indexers.map(v => ({
|
||||
label: v.name,
|
||||
value: {
|
||||
id: v.id,
|
||||
|
@ -327,7 +322,7 @@ function General({ indexers }: GeneralProps) {
|
|||
<TextField name="name" label="Filter name" columns={6} placeholder="eg. Filter 1" />
|
||||
|
||||
<div className="col-span-6">
|
||||
<IndexerMultiSelect name="indexers" options={opts} label="Indexers" columns={6} />
|
||||
{!isLoading && <IndexerMultiSelect name="indexers" options={opts} label="Indexers" columns={6} />}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue