Add pagination to the lists page
This commit is contained in:
parent
b467c9bc3f
commit
d9585a7365
|
@ -184,9 +184,28 @@ class CreateFormDef extends React.PureComponent {
|
||||||
const CreateForm = Form.create()(CreateFormDef)
|
const CreateForm = Form.create()(CreateFormDef)
|
||||||
|
|
||||||
class Lists extends React.PureComponent {
|
class Lists extends React.PureComponent {
|
||||||
|
defaultPerPage = 20
|
||||||
state = {
|
state = {
|
||||||
formType: null,
|
formType: null,
|
||||||
record: {}
|
record: {},
|
||||||
|
queryParams: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pagination config.
|
||||||
|
paginationOptions = {
|
||||||
|
hideOnSinglePage: false,
|
||||||
|
showSizeChanger: true,
|
||||||
|
showQuickJumper: true,
|
||||||
|
defaultPageSize: this.defaultPerPage,
|
||||||
|
pageSizeOptions: ["20", "50", "70", "100"],
|
||||||
|
position: "both",
|
||||||
|
showTotal: (total, range) => `${range[0]} to ${range[1]} of ${total}`,
|
||||||
|
onChange: (page, perPage) => {
|
||||||
|
this.fetchRecords({ page: page, per_page: perPage })
|
||||||
|
},
|
||||||
|
onShowSizeChange: (page, perPage) => {
|
||||||
|
this.fetchRecords({ page: page, per_page: perPage })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -295,8 +314,28 @@ class Lists extends React.PureComponent {
|
||||||
this.fetchRecords()
|
this.fetchRecords()
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchRecords = () => {
|
fetchRecords = params => {
|
||||||
this.props.modelRequest(cs.ModelLists, cs.Routes.GetLists, cs.MethodGet)
|
let qParams = {
|
||||||
|
page: this.state.queryParams.page,
|
||||||
|
per_page: this.state.queryParams.per_page
|
||||||
|
}
|
||||||
|
if (params) {
|
||||||
|
qParams = { ...qParams, ...params }
|
||||||
|
}
|
||||||
|
|
||||||
|
this.props
|
||||||
|
.modelRequest(cs.ModelLists, cs.Routes.GetLists, cs.MethodGet, qParams)
|
||||||
|
.then(() => {
|
||||||
|
this.setState({
|
||||||
|
queryParams: {
|
||||||
|
...this.state.queryParams,
|
||||||
|
total: this.props.data[cs.ModelLists].total,
|
||||||
|
perPage: this.props.data[cs.ModelLists].per_page,
|
||||||
|
page: this.props.data[cs.ModelLists].page,
|
||||||
|
query: this.props.data[cs.ModelLists].query
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteRecord = record => {
|
deleteRecord = record => {
|
||||||
|
@ -340,7 +379,7 @@ class Lists extends React.PureComponent {
|
||||||
<section className="content">
|
<section className="content">
|
||||||
<Row>
|
<Row>
|
||||||
<Col span={22}>
|
<Col span={22}>
|
||||||
<h1>Lists ({this.props.data[cs.ModelLists].length}) </h1>
|
<h1>Lists ({this.props.data[cs.ModelLists].total}) </h1>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={2}>
|
<Col span={2}>
|
||||||
<Button
|
<Button
|
||||||
|
@ -358,9 +397,17 @@ class Lists extends React.PureComponent {
|
||||||
className="lists"
|
className="lists"
|
||||||
columns={this.columns}
|
columns={this.columns}
|
||||||
rowKey={record => record.uuid}
|
rowKey={record => record.uuid}
|
||||||
dataSource={this.props.data[cs.ModelLists]}
|
dataSource={(() => {
|
||||||
|
if (
|
||||||
|
!this.props.data[cs.ModelLists] ||
|
||||||
|
!this.props.data[cs.ModelLists].hasOwnProperty("results")
|
||||||
|
) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return this.props.data[cs.ModelLists].results
|
||||||
|
})()}
|
||||||
loading={this.props.reqStates[cs.ModelLists] !== cs.StateDone}
|
loading={this.props.reqStates[cs.ModelLists] !== cs.StateDone}
|
||||||
pagination={false}
|
pagination={{ ...this.paginationOptions, ...this.state.queryParams }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<CreateForm
|
<CreateForm
|
||||||
|
|
28
lists.go
28
lists.go
|
@ -13,12 +13,21 @@ import (
|
||||||
"github.com/labstack/echo"
|
"github.com/labstack/echo"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type listsWrap struct {
|
||||||
|
Results []models.List `json:"results"`
|
||||||
|
|
||||||
|
Total int `json:"total"`
|
||||||
|
PerPage int `json:"per_page"`
|
||||||
|
Page int `json:"page"`
|
||||||
|
}
|
||||||
|
|
||||||
// handleGetLists handles retrieval of lists.
|
// handleGetLists handles retrieval of lists.
|
||||||
func handleGetLists(c echo.Context) error {
|
func handleGetLists(c echo.Context) error {
|
||||||
var (
|
var (
|
||||||
app = c.Get("app").(*App)
|
app = c.Get("app").(*App)
|
||||||
out []models.List
|
out listsWrap
|
||||||
|
|
||||||
|
pg = getPagination(c.QueryParams())
|
||||||
listID, _ = strconv.Atoi(c.Param("id"))
|
listID, _ = strconv.Atoi(c.Param("id"))
|
||||||
single = false
|
single = false
|
||||||
)
|
)
|
||||||
|
@ -28,27 +37,32 @@ func handleGetLists(c echo.Context) error {
|
||||||
single = true
|
single = true
|
||||||
}
|
}
|
||||||
|
|
||||||
err := app.Queries.GetLists.Select(&out, listID)
|
err := app.Queries.GetLists.Select(&out.Results, listID, pg.Offset, pg.Limit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError,
|
return echo.NewHTTPError(http.StatusInternalServerError,
|
||||||
fmt.Sprintf("Error fetching lists: %s", pqErrMsg(err)))
|
fmt.Sprintf("Error fetching lists: %s", pqErrMsg(err)))
|
||||||
} else if single && len(out) == 0 {
|
} else if single && len(out.Results) == 0 {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "List not found.")
|
return echo.NewHTTPError(http.StatusBadRequest, "List not found.")
|
||||||
} else if len(out) == 0 {
|
} else if len(out.Results) == 0 {
|
||||||
return c.JSON(http.StatusOK, okResp{[]struct{}{}})
|
return c.JSON(http.StatusOK, okResp{[]struct{}{}})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace null tags.
|
// Replace null tags.
|
||||||
for i, v := range out {
|
for i, v := range out.Results {
|
||||||
if v.Tags == nil {
|
if v.Tags == nil {
|
||||||
out[i].Tags = make(pq.StringArray, 0)
|
out.Results[i].Tags = make(pq.StringArray, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if single {
|
if single {
|
||||||
return c.JSON(http.StatusOK, okResp{out[0]})
|
return c.JSON(http.StatusOK, okResp{out.Results[0]})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Meta.
|
||||||
|
out.Total = out.Results[0].Total
|
||||||
|
out.Page = pg.Page
|
||||||
|
out.PerPage = pg.PerPage
|
||||||
|
|
||||||
return c.JSON(http.StatusOK, okResp{out})
|
return c.JSON(http.StatusOK, okResp{out})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -121,6 +121,10 @@ type List struct {
|
||||||
|
|
||||||
// This is only relevant when querying the lists of a subscriber.
|
// This is only relevant when querying the lists of a subscriber.
|
||||||
SubscriptionStatus string `db:"subscription_status" json:"subscription_status,omitempty"`
|
SubscriptionStatus string `db:"subscription_status" json:"subscription_status,omitempty"`
|
||||||
|
|
||||||
|
// Pseudofield for getting the total number of subscribers
|
||||||
|
// in searches and queries.
|
||||||
|
Total int `db:"total" json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Campaign represents an e-mail campaign.
|
// Campaign represents an e-mail campaign.
|
||||||
|
|
|
@ -226,11 +226,11 @@ UPDATE subscriber_lists SET status='unsubscribed', updated_at=NOW()
|
||||||
|
|
||||||
-- lists
|
-- lists
|
||||||
-- name: get-lists
|
-- name: get-lists
|
||||||
SELECT lists.*, COUNT(subscriber_lists.subscriber_id) AS subscriber_count
|
SELECT COUNT(*) OVER () AS total, lists.*, COUNT(subscriber_lists.subscriber_id) AS subscriber_count
|
||||||
FROM lists LEFT JOIN subscriber_lists
|
FROM lists LEFT JOIN subscriber_lists
|
||||||
ON (subscriber_lists.list_id = lists.id AND subscriber_lists.status != 'unsubscribed')
|
ON (subscriber_lists.list_id = lists.id AND subscriber_lists.status != 'unsubscribed')
|
||||||
WHERE ($1 = 0 OR id = $1)
|
WHERE ($1 = 0 OR id = $1)
|
||||||
GROUP BY lists.id ORDER BY lists.created_at;
|
GROUP BY lists.id ORDER BY lists.created_at OFFSET $2 LIMIT $3;
|
||||||
|
|
||||||
-- name: create-list
|
-- name: create-list
|
||||||
INSERT INTO lists (uuid, name, type, tags) VALUES($1, $2, $3, $4) RETURNING id;
|
INSERT INTO lists (uuid, name, type, tags) VALUES($1, $2, $3, $4) RETURNING id;
|
||||||
|
|
Loading…
Reference in New Issue