Add subscription status filter to subscriber list query and admin UI.

This commit is contained in:
Kailash Nadh 2023-12-23 16:43:28 +05:30
parent 8f12c03a8a
commit 51af75cfef
6 changed files with 31 additions and 17 deletions

View file

@ -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
}

View file

@ -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

View file

@ -99,7 +99,10 @@
<div class="fields stats">
<p v-for="(count, status) in filterStatuses(props.row)" :key="status">
<label>{{ $tc(`subscribers.status.${status}`, count) }}</label>
<span :class="status">{{ $utils.formatNumber(count) }}</span>
<router-link :to="`/subscribers/lists/${props.row.id}?subscription_status=${status}`"
:class="status">
{{ $utils.formatNumber(count) }}
</router-link>
</p>
</div>
</b-table-column>

View file

@ -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;
}
},
});
</script>

View file

@ -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)))
}

View file

@ -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;