diff --git a/cmd/subscribers.go b/cmd/subscribers.go index db6313099..ed5074175 100644 --- a/cmd/subscribers.go +++ b/cmd/subscribers.go @@ -87,10 +87,11 @@ func handleQuerySubscribers(c echo.Context) error { pg = app.paginator.NewFromURL(c.Request().URL.Query()) // The "WHERE ?" bit. - query = sanitizeSQLExp(c.FormValue("query")) - orderBy = c.FormValue("order_by") - order = c.FormValue("order") - out models.PageResults + query = sanitizeSQLExp(c.FormValue("query")) + subStatus = c.FormValue("subscription_status") + orderBy = c.FormValue("order_by") + order = c.FormValue("order") + out models.PageResults ) // Limit the subscribers to specific lists? @@ -99,7 +100,7 @@ func handleQuerySubscribers(c echo.Context) error { return echo.NewHTTPError(http.StatusBadRequest, app.i18n.T("globals.messages.invalidID")) } - res, total, err := app.core.QuerySubscribers(query, listIDs, order, orderBy, pg.Offset, pg.Limit) + res, total, err := app.core.QuerySubscribers(query, listIDs, subStatus, order, orderBy, pg.Offset, pg.Limit) if err != nil { return err } diff --git a/docs/docs/content/apis/subscribers.md b/docs/docs/content/apis/subscribers.md index 3bac3199f..08cce1ffc 100644 --- a/docs/docs/content/apis/subscribers.md +++ b/docs/docs/content/apis/subscribers.md @@ -24,13 +24,15 @@ Retrieve all subscribers. ##### Query parameters -| Name | Type | Required | Description | -|:---------|:-------|:---------|:---------------------------------------------------------------------| -| query | string | | Subscriber search term by name. | -| order_by | string | | Result sorting field. Options: name, status, created_at, updated_at. | -| order | string | | Sorting order: ASC for ascending, DESC for descending. | -| page | number | | Page number for paginated results. | -| per_page | number | | Results per page. Set as 'all' for all results. | +| Name | Type | Required | Description | +|:--------------------|:-------|:---------|:----------------------------------------------------------------------| +| query | string | | Subscriber search by SQL expression. | +| list_id | int[] | | ID of lists to filter by. Repeat in the query for multiple values. | +| subscription_status | string | | Subscription status to filter by if there are one or more `list_id`s. | +| order_by | string | | Result sorting field. Options: name, status, created_at, updated_at. | +| order | string | | Sorting order: ASC for ascending, DESC for descending. | +| page | number | | Page number for paginated results. | +| per_page | number | | Results per page. Set as 'all' for all results. | ##### Example Request diff --git a/frontend/src/views/Lists.vue b/frontend/src/views/Lists.vue index 2fa4b272c..1d170f3cd 100644 --- a/frontend/src/views/Lists.vue +++ b/frontend/src/views/Lists.vue @@ -99,7 +99,10 @@

- {{ $utils.formatNumber(count) }} + + {{ $utils.formatNumber(count) }} +

diff --git a/frontend/src/views/Subscribers.vue b/frontend/src/views/Subscribers.vue index 510fb7a2f..20910b496 100644 --- a/frontend/src/views/Subscribers.vue +++ b/frontend/src/views/Subscribers.vue @@ -251,6 +251,7 @@ export default Vue.extend({ page: 1, orderBy: 'id', order: 'desc', + subStatus: null, }, }; }, @@ -357,6 +358,7 @@ export default Vue.extend({ list_id: this.queryParams.listID, query: this.queryParams.queryExp, page: this.queryParams.page, + subscription_status: this.queryParams.subStatus, order_by: this.queryParams.orderBy, order: this.queryParams.order, }).then(() => { @@ -515,6 +517,10 @@ export default Vue.extend({ // Get subscribers on load. this.querySubscribers(); } + + if (this.$route.query.subscription_status) { + this.queryParams.subStatus = this.$route.query.subscription_status; + } }, }); diff --git a/internal/core/subscribers.go b/internal/core/subscribers.go index 3b0920b04..665935454 100644 --- a/internal/core/subscribers.go +++ b/internal/core/subscribers.go @@ -66,7 +66,7 @@ func (c *Core) GetSubscribersByEmail(emails []string) (models.Subscribers, error } // QuerySubscribers queries and returns paginated subscrribers based on the given params including the total count. -func (c *Core) QuerySubscribers(query string, listIDs []int, order, orderBy string, offset, limit int) (models.Subscribers, int, error) { +func (c *Core) QuerySubscribers(query string, listIDs []int, subStatus string, order, orderBy string, offset, limit int) (models.Subscribers, int, error) { // There's an arbitrary query condition. cond := "" if query != "" { @@ -98,7 +98,7 @@ func (c *Core) QuerySubscribers(query string, listIDs []int, order, orderBy stri // Execute the readonly query and get the count of results. total := 0 - if err := tx.Get(&total, stmt, pq.Array(listIDs)); err != nil { + if err := tx.Get(&total, stmt, pq.Array(listIDs), subStatus); err != nil { return nil, 0, echo.NewHTTPError(http.StatusInternalServerError, c.i18n.Ts("globals.messages.errorFetching", "name", "{globals.terms.subscribers}", "error", pqErrMsg(err))) } @@ -112,7 +112,7 @@ func (c *Core) QuerySubscribers(query string, listIDs []int, order, orderBy stri var out models.Subscribers stmt = strings.ReplaceAll(c.q.QuerySubscribers, "%query%", cond) stmt = strings.ReplaceAll(stmt, "%order%", orderBy+" "+order) - if err := tx.Select(&out, stmt, pq.Array(listIDs), offset, limit); err != nil { + if err := tx.Select(&out, stmt, pq.Array(listIDs), subStatus, offset, limit); err != nil { return nil, 0, echo.NewHTTPError(http.StatusInternalServerError, c.i18n.Ts("globals.messages.errorFetching", "name", "{globals.terms.subscribers}", "error", pqErrMsg(err))) } diff --git a/queries.sql b/queries.sql index d4a965830..cad622337 100644 --- a/queries.sql +++ b/queries.sql @@ -306,10 +306,11 @@ SELECT subscribers.* FROM subscribers -- Optional list filtering. (CASE WHEN CARDINALITY($1::INT[]) > 0 THEN true ELSE false END) AND subscriber_lists.subscriber_id = subscribers.id + AND ($2 = '' OR subscriber_lists.status = $2::subscription_status) ) WHERE (CARDINALITY($1) = 0 OR subscriber_lists.list_id = ANY($1::INT[])) %query% - ORDER BY %order% OFFSET $2 LIMIT (CASE WHEN $3 < 1 THEN NULL ELSE $3 END); + ORDER BY %order% OFFSET $3 LIMIT (CASE WHEN $4 < 1 THEN NULL ELSE $4 END); -- name: query-subscribers-count -- Replica of query-subscribers for obtaining the results count. @@ -319,6 +320,7 @@ SELECT COUNT(*) AS total FROM subscribers -- Optional list filtering. (CASE WHEN CARDINALITY($1::INT[]) > 0 THEN true ELSE false END) AND subscriber_lists.subscriber_id = subscribers.id + AND ($2 = '' OR subscriber_lists.status = $2::subscription_status) ) WHERE (CARDINALITY($1) = 0 OR subscriber_lists.list_id = ANY($1::INT[])) %s;