diff --git a/internal/database/filter.go b/internal/database/filter.go index 74a71db..65354a4 100644 --- a/internal/database/filter.go +++ b/internal/database/filter.go @@ -390,6 +390,25 @@ func (r *FilterRepo) Update(ctx context.Context, filter domain.Filter) (*domain. return &filter, nil } +func (r *FilterRepo) ToggleEnabled(ctx context.Context, filterID int, enabled bool) error { + + var err error + _, err = r.db.ExecContext(ctx, ` + UPDATE filter SET + enabled = ?, + updated_at = CURRENT_TIMESTAMP + WHERE id = ?`, + enabled, + filterID, + ) + if err != nil { + log.Error().Stack().Err(err).Msg("error executing query") + return err + } + + return nil +} + func (r *FilterRepo) StoreIndexerConnections(ctx context.Context, filterID int, indexers []domain.Indexer) error { tx, err := r.db.BeginTx(ctx, nil) diff --git a/internal/domain/filter.go b/internal/domain/filter.go index 73c3e50..c3e8ed5 100644 --- a/internal/domain/filter.go +++ b/internal/domain/filter.go @@ -17,6 +17,7 @@ type FilterRepo interface { ListFilters() ([]Filter, error) Store(filter Filter) (*Filter, error) Update(ctx context.Context, filter Filter) (*Filter, error) + ToggleEnabled(ctx context.Context, filterID int, enabled bool) error Delete(ctx context.Context, filterID int) error StoreIndexerConnection(ctx context.Context, filterID int, indexerID int) error StoreIndexerConnections(ctx context.Context, filterID int, indexers []Indexer) error diff --git a/internal/filter/service.go b/internal/filter/service.go index fdf1087..127e47d 100644 --- a/internal/filter/service.go +++ b/internal/filter/service.go @@ -17,6 +17,7 @@ type Service interface { ListFilters() ([]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 Delete(ctx context.Context, filterID int) error } @@ -136,6 +137,17 @@ func (s *service) Update(ctx context.Context, filter domain.Filter) (*domain.Fil return f, nil } +func (s *service) ToggleEnabled(ctx context.Context, filterID int, enabled bool) error { + if err := s.repo.ToggleEnabled(ctx, filterID, enabled); err != nil { + log.Error().Err(err).Msg("could not update filter enabled") + return err + } + + log.Debug().Msgf("filter.toggle_enabled: update filter '%v' to '%v'", filterID, enabled) + + return nil +} + func (s *service) Delete(ctx context.Context, filterID int) error { if filterID == 0 { return nil diff --git a/internal/http/filter.go b/internal/http/filter.go index 90b3318..837b005 100644 --- a/internal/http/filter.go +++ b/internal/http/filter.go @@ -17,6 +17,7 @@ type filterService interface { Store(filter domain.Filter) (*domain.Filter, error) Delete(ctx context.Context, filterID int) error Update(ctx context.Context, filter domain.Filter) (*domain.Filter, error) + ToggleEnabled(ctx context.Context, filterID int, enabled bool) error } type filterHandler struct { @@ -36,6 +37,7 @@ func (h filterHandler) Routes(r chi.Router) { r.Get("/{filterID}", h.getByID) r.Post("/", h.store) r.Put("/{filterID}", h.update) + r.Put("/{filterID}/enabled", h.toggleEnabled) r.Delete("/{filterID}", h.delete) } @@ -123,6 +125,31 @@ func (h filterHandler) update(w http.ResponseWriter, r *http.Request) { h.encoder.StatusResponse(ctx, w, filter, http.StatusOK) } +func (h filterHandler) toggleEnabled(w http.ResponseWriter, r *http.Request) { + var ( + ctx = r.Context() + filterID = chi.URLParam(r, "filterID") + data struct { + Enabled bool `json:"enabled"` + } + ) + + id, _ := strconv.Atoi(filterID) + + if err := json.NewDecoder(r.Body).Decode(&data); err != nil { + // encode error + return + } + + err := h.service.ToggleEnabled(ctx, id, data.Enabled) + if err != nil { + // encode error + return + } + + h.encoder.StatusResponse(ctx, w, nil, http.StatusNoContent) +} + func (h filterHandler) delete(w http.ResponseWriter, r *http.Request) { var ( ctx = r.Context() diff --git a/web/src/api/APIClient.ts b/web/src/api/APIClient.ts index 52f6f36..cecb5d3 100644 --- a/web/src/api/APIClient.ts +++ b/web/src/api/APIClient.ts @@ -90,6 +90,7 @@ const APIClient = { getByID: (id: number) => appClient.Get(`api/filters/${id}`), create: (filter: Filter) => appClient.Post(`api/filters`, filter), update: (filter: Filter) => appClient.Put(`api/filters/${filter.id}`, filter), + toggleEnable: (id: number, enabled: boolean) => appClient.Put(`api/filters/${id}/enabled`, { enabled }), delete: (id: number) => appClient.Delete(`api/filters/${id}`), }, indexers: { diff --git a/web/src/screens/filters/list.tsx b/web/src/screens/filters/list.tsx index 751ca4b..49acaa4 100644 --- a/web/src/screens/filters/list.tsx +++ b/web/src/screens/filters/list.tsx @@ -7,10 +7,13 @@ import { } from "react-router-dom"; import { Filter } from "../../domain/interfaces"; import { useToggle } from "../../hooks/hooks"; -import { useQuery } from "react-query"; +import { useMutation, useQuery } from "react-query"; import { classNames } from "../../utils"; import { FilterAddForm } from "../../forms"; import APIClient from "../../api/APIClient"; +import Toast from "../../components/notifications/Toast"; +import toast from "react-hot-toast"; +import { queryClient } from "../../App"; export default function Filters() { const [createFilterIsOpen, toggleCreateFilter] = useToggle(false) @@ -116,10 +119,18 @@ interface FilterListItemProps { function FilterListItem({ filter, idx }: FilterListItemProps) { const [enabled, setEnabled] = useState(filter.enabled) + const updateMutation = useMutation((status: boolean) => APIClient.filters.toggleEnable(filter.id, status), { + onSuccess: () => { + toast.custom((t) => ) + + queryClient.invalidateQueries("filter"); + } + }) + const toggleActive = (status: boolean) => { - console.log(status) setEnabled(status) // call api + updateMutation.mutate(status) } return (