Fix import and campaign page and integrate new paginated lists API
This commit is contained in:
parent
3cf075e3a9
commit
8701cb445a
|
@ -79,7 +79,9 @@ class App extends React.PureComponent {
|
||||||
|
|
||||||
// If it's a GET call, set the response as the data state.
|
// If it's a GET call, set the response as the data state.
|
||||||
if (method === cs.MethodGet) {
|
if (method === cs.MethodGet) {
|
||||||
this.setState({ data: { ...this.state.data, [model]: res.data.data } })
|
this.setState({
|
||||||
|
data: { ...this.state.data, [model]: res.data.data }
|
||||||
|
})
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
@ -440,17 +440,20 @@ class TheFormDef extends React.PureComponent {
|
||||||
initialValue:
|
initialValue:
|
||||||
subLists.length > 0
|
subLists.length > 0
|
||||||
? subLists
|
? subLists
|
||||||
: this.props.data[cs.ModelLists].length === 1
|
: this.props.data[cs.ModelLists].hasOwnProperty(
|
||||||
? [this.props.data[cs.ModelLists][0].id]
|
"results"
|
||||||
|
) && this.props.data[cs.ModelLists].results.length === 1
|
||||||
|
? [this.props.data[cs.ModelLists].results[0].id]
|
||||||
: undefined,
|
: undefined,
|
||||||
rules: [{ required: true }]
|
rules: [{ required: true }]
|
||||||
})(
|
})(
|
||||||
<Select disabled={this.props.formDisabled} mode="multiple">
|
<Select disabled={this.props.formDisabled} mode="multiple">
|
||||||
{[...this.props.data[cs.ModelLists]].map((v, i) => (
|
{this.props.data[cs.ModelLists].hasOwnProperty("results") &&
|
||||||
<Select.Option value={v["id"]} key={v["id"]}>
|
[...this.props.data[cs.ModelLists].results].map((v, i) => (
|
||||||
{v["name"]}
|
<Select.Option value={v["id"]} key={v["id"]}>
|
||||||
</Select.Option>
|
{v["name"]}
|
||||||
))}
|
</Select.Option>
|
||||||
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
)}
|
)}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
@ -585,7 +588,9 @@ class Campaign extends React.PureComponent {
|
||||||
|
|
||||||
componentDidMount = () => {
|
componentDidMount = () => {
|
||||||
// Fetch lists.
|
// Fetch lists.
|
||||||
this.props.modelRequest(cs.ModelLists, cs.Routes.GetLists, cs.MethodGet)
|
this.props.modelRequest(cs.ModelLists, cs.Routes.GetLists, cs.MethodGet, {
|
||||||
|
per_page: "all"
|
||||||
|
})
|
||||||
|
|
||||||
// Fetch templates.
|
// Fetch templates.
|
||||||
this.props.modelRequest(
|
this.props.modelRequest(
|
||||||
|
|
|
@ -33,7 +33,9 @@ class TheFormDef extends React.PureComponent {
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
// Fetch lists.
|
// Fetch lists.
|
||||||
this.props.modelRequest(cs.ModelLists, cs.Routes.GetLists, cs.MethodGet)
|
this.props.modelRequest(cs.ModelLists, cs.Routes.GetLists, cs.MethodGet, {
|
||||||
|
per_page: "all"
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle create / edit form submission.
|
// Handle create / edit form submission.
|
||||||
|
@ -413,7 +415,11 @@ class Import extends React.PureComponent {
|
||||||
<TheForm
|
<TheForm
|
||||||
{...this.props}
|
{...this.props}
|
||||||
fetchimportState={this.fetchimportState}
|
fetchimportState={this.fetchimportState}
|
||||||
lists={this.props.data[cs.ModelLists]}
|
lists={
|
||||||
|
this.props.data[cs.ModelLists].hasOwnProperty("results")
|
||||||
|
? this.props.data[cs.ModelLists].results
|
||||||
|
: []
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
|
15
handlers.go
15
handlers.go
|
@ -171,12 +171,19 @@ func makeAttribsBlob(keys []string, vals []string) ([]byte, bool) {
|
||||||
// getPagination takes form values and extracts pagination values from it.
|
// getPagination takes form values and extracts pagination values from it.
|
||||||
func getPagination(q url.Values) pagination {
|
func getPagination(q url.Values) pagination {
|
||||||
var (
|
var (
|
||||||
perPage, _ = strconv.Atoi(q.Get("per_page"))
|
page, _ = strconv.Atoi(q.Get("page"))
|
||||||
page, _ = strconv.Atoi(q.Get("page"))
|
perPage = defaultPerPage
|
||||||
)
|
)
|
||||||
|
|
||||||
if perPage < 1 || perPage > maxPerPage {
|
pp := q.Get("per_page")
|
||||||
perPage = defaultPerPage
|
if pp == "all" {
|
||||||
|
// No limit.
|
||||||
|
perPage = 0
|
||||||
|
} else {
|
||||||
|
ppi, _ := strconv.Atoi(pp)
|
||||||
|
if ppi < 1 || ppi > maxPerPage {
|
||||||
|
perPage = defaultPerPage
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if page < 1 {
|
if page < 1 {
|
||||||
|
|
1
main.go
1
main.go
|
@ -204,6 +204,7 @@ func main() {
|
||||||
}
|
}
|
||||||
app.Importer = subimporter.New(q.UpsertSubscriber.Stmt,
|
app.Importer = subimporter.New(q.UpsertSubscriber.Stmt,
|
||||||
q.UpsertBlacklistSubscriber.Stmt,
|
q.UpsertBlacklistSubscriber.Stmt,
|
||||||
|
q.UpdateListsDate.Stmt,
|
||||||
db.DB,
|
db.DB,
|
||||||
importNotifCB)
|
importNotifCB)
|
||||||
|
|
||||||
|
|
|
@ -36,10 +36,11 @@ type Queries struct {
|
||||||
DeleteSubscriptionsByQuery string `query:"delete-subscriptions-by-query"`
|
DeleteSubscriptionsByQuery string `query:"delete-subscriptions-by-query"`
|
||||||
UnsubscribeSubscribersFromListsByQuery string `query:"unsubscribe-subscribers-from-lists-by-query"`
|
UnsubscribeSubscribersFromListsByQuery string `query:"unsubscribe-subscribers-from-lists-by-query"`
|
||||||
|
|
||||||
CreateList *sqlx.Stmt `query:"create-list"`
|
CreateList *sqlx.Stmt `query:"create-list"`
|
||||||
GetLists *sqlx.Stmt `query:"get-lists"`
|
GetLists *sqlx.Stmt `query:"get-lists"`
|
||||||
UpdateList *sqlx.Stmt `query:"update-list"`
|
UpdateList *sqlx.Stmt `query:"update-list"`
|
||||||
DeleteLists *sqlx.Stmt `query:"delete-lists"`
|
UpdateListsDate *sqlx.Stmt `query:"update-lists-date"`
|
||||||
|
DeleteLists *sqlx.Stmt `query:"delete-lists"`
|
||||||
|
|
||||||
CreateCampaign *sqlx.Stmt `query:"create-campaign"`
|
CreateCampaign *sqlx.Stmt `query:"create-campaign"`
|
||||||
QueryCampaigns *sqlx.Stmt `query:"query-campaigns"`
|
QueryCampaigns *sqlx.Stmt `query:"query-campaigns"`
|
||||||
|
|
|
@ -230,7 +230,7 @@ SELECT COUNT(*) OVER () AS total, lists.*, COUNT(subscriber_lists.subscriber_id)
|
||||||
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 OFFSET $2 LIMIT $3;
|
GROUP BY lists.id ORDER BY lists.created_at OFFSET $2 LIMIT (CASE WHEN $3 = 0 THEN NULL ELSE $3 END);
|
||||||
|
|
||||||
-- 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;
|
||||||
|
@ -243,6 +243,9 @@ UPDATE lists SET
|
||||||
updated_at=NOW()
|
updated_at=NOW()
|
||||||
WHERE id = $1;
|
WHERE id = $1;
|
||||||
|
|
||||||
|
-- name: update-lists-date
|
||||||
|
UPDATE lists SET updated_at=NOW() WHERE id = ANY($1);
|
||||||
|
|
||||||
-- name: delete-lists
|
-- name: delete-lists
|
||||||
DELETE FROM lists WHERE id = ALL($1);
|
DELETE FROM lists WHERE id = ALL($1);
|
||||||
|
|
||||||
|
|
|
@ -47,10 +47,11 @@ const (
|
||||||
|
|
||||||
// Importer represents the bulk CSV subscriber import system.
|
// Importer represents the bulk CSV subscriber import system.
|
||||||
type Importer struct {
|
type Importer struct {
|
||||||
upsert *sql.Stmt
|
upsert *sql.Stmt
|
||||||
blacklist *sql.Stmt
|
blacklist *sql.Stmt
|
||||||
db *sql.DB
|
updateListDate *sql.Stmt
|
||||||
notifCB models.AdminNotifCallback
|
db *sql.DB
|
||||||
|
notifCB models.AdminNotifCallback
|
||||||
|
|
||||||
stop chan bool
|
stop chan bool
|
||||||
status Status
|
status Status
|
||||||
|
@ -93,14 +94,16 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
// New returns a new instance of Importer.
|
// New returns a new instance of Importer.
|
||||||
func New(upsert *sql.Stmt, blacklist *sql.Stmt, db *sql.DB, notifCB models.AdminNotifCallback) *Importer {
|
func New(upsert *sql.Stmt, blacklist *sql.Stmt, updateListDate *sql.Stmt,
|
||||||
|
db *sql.DB, notifCB models.AdminNotifCallback) *Importer {
|
||||||
im := Importer{
|
im := Importer{
|
||||||
upsert: upsert,
|
upsert: upsert,
|
||||||
blacklist: blacklist,
|
blacklist: blacklist,
|
||||||
stop: make(chan bool, 1),
|
updateListDate: updateListDate,
|
||||||
db: db,
|
stop: make(chan bool, 1),
|
||||||
notifCB: notifCB,
|
db: db,
|
||||||
status: Status{Status: StatusNone, logBuf: bytes.NewBuffer(nil)},
|
notifCB: notifCB,
|
||||||
|
status: Status{Status: StatusNone, logBuf: bytes.NewBuffer(nil)},
|
||||||
}
|
}
|
||||||
|
|
||||||
return &im
|
return &im
|
||||||
|
@ -276,6 +279,10 @@ func (s *Session) Start() {
|
||||||
s.log.Printf("imported finished")
|
s.log.Printf("imported finished")
|
||||||
s.im.sendNotif(StatusFinished)
|
s.im.sendNotif(StatusFinished)
|
||||||
|
|
||||||
|
if _, err := s.im.updateListDate.Exec(listIDs); err != nil {
|
||||||
|
s.log.Printf("error updating lists date: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,6 +299,10 @@ func (s *Session) Start() {
|
||||||
s.im.setStatus(StatusFinished)
|
s.im.setStatus(StatusFinished)
|
||||||
s.log.Printf("imported finished")
|
s.log.Printf("imported finished")
|
||||||
s.im.sendNotif(StatusFinished)
|
s.im.sendNotif(StatusFinished)
|
||||||
|
|
||||||
|
if _, err := s.im.updateListDate.Exec(listIDs); err != nil {
|
||||||
|
s.log.Printf("error updating lists date: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop stops an active import session.
|
// Stop stops an active import session.
|
||||||
|
|
Loading…
Reference in New Issue