Add pagination to submissions
Dieser Commit ist enthalten in:
Ursprung
7375c63403
Commit
34fee3729c
9 geänderte Dateien mit 146 neuen und 72 gelöschten Zeilen
|
@ -1,6 +1,34 @@
|
||||||
import Controller from "@ember/controller";
|
import Controller from "@ember/controller";
|
||||||
import { fmt } from "discourse/lib/computed";
|
import { fmt } from "discourse/lib/computed";
|
||||||
|
import { empty } from '@ember/object/computed';
|
||||||
|
import CustomWizard from "../models/custom-wizard";
|
||||||
|
|
||||||
export default Controller.extend({
|
export default Controller.extend({
|
||||||
downloadUrl: fmt("wizard.id", "/admin/wizards/submissions/%@/download"),
|
downloadUrl: fmt("wizard.id", "/admin/wizards/submissions/%@/download"),
|
||||||
|
noResults: empty('submissions'),
|
||||||
|
page: 0,
|
||||||
|
total: 0,
|
||||||
|
|
||||||
|
loadMoreSubmissions() {
|
||||||
|
const page = this.get('page');
|
||||||
|
const wizardId = this.get('wizard.id');
|
||||||
|
|
||||||
|
this.set('loadingMore', true);
|
||||||
|
CustomWizard.submissions(wizardId, page).then(result => {
|
||||||
|
if (result.submissions) {
|
||||||
|
this.get('submissions').pushObjects(result.submissions);
|
||||||
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
this.set('loadingMore', false);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
loadMore() {
|
||||||
|
if (!this.loadingMore && (this.submissions.length < this.total)) {
|
||||||
|
this.set('page', this.get('page') + 1);
|
||||||
|
this.loadMoreSubmissions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -211,9 +211,51 @@ CustomWizard.reopenClass({
|
||||||
.catch(popupAjaxError);
|
.catch(popupAjaxError);
|
||||||
},
|
},
|
||||||
|
|
||||||
submissions(wizardId) {
|
submissions(wizardId, page = null) {
|
||||||
|
let data = {};
|
||||||
|
|
||||||
|
if (page) {
|
||||||
|
data.page = page;
|
||||||
|
}
|
||||||
|
|
||||||
return ajax(`/admin/wizards/submissions/${wizardId}`, {
|
return ajax(`/admin/wizards/submissions/${wizardId}`, {
|
||||||
type: "GET",
|
type: "GET",
|
||||||
|
data
|
||||||
|
}).then(result => {
|
||||||
|
if (result.wizard) {
|
||||||
|
let fields = ["username"];
|
||||||
|
let submissions = [];
|
||||||
|
let wizard = result.wizard;
|
||||||
|
let total = result.total;
|
||||||
|
|
||||||
|
result.submissions.forEach((s) => {
|
||||||
|
let submission = {
|
||||||
|
username: s.username,
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.keys(s.fields).forEach((f) => {
|
||||||
|
if (fields.indexOf(f) < 0) {
|
||||||
|
fields.push(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fields.includes(f)) {
|
||||||
|
submission[f] = s.fields[f];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
submission['submitted_at'] = s.submitted_at;
|
||||||
|
submissions.push(submission);
|
||||||
|
});
|
||||||
|
|
||||||
|
fields.push("submitted_at");
|
||||||
|
|
||||||
|
return {
|
||||||
|
wizard,
|
||||||
|
fields,
|
||||||
|
submissions,
|
||||||
|
total
|
||||||
|
};
|
||||||
|
}
|
||||||
}).catch(popupAjaxError);
|
}).catch(popupAjaxError);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import CustomWizard from "../models/custom-wizard";
|
import CustomWizard from "../models/custom-wizard";
|
||||||
import DiscourseRoute from "discourse/routes/discourse";
|
import DiscourseRoute from "discourse/routes/discourse";
|
||||||
|
import { A } from "@ember/array";
|
||||||
const excludedMetaFields = ["route_to", "redirect_on_complete", "redirect_to"];
|
|
||||||
|
|
||||||
export default DiscourseRoute.extend({
|
export default DiscourseRoute.extend({
|
||||||
model(params) {
|
model(params) {
|
||||||
|
@ -9,34 +8,11 @@ export default DiscourseRoute.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
setupController(controller, model) {
|
setupController(controller, model) {
|
||||||
if (model && model.submissions) {
|
controller.setProperties({
|
||||||
let fields = ["username"];
|
wizard: model.wizard,
|
||||||
model.submissions.forEach((s) => {
|
fields: model.fields,
|
||||||
Object.keys(s.fields).forEach((k) => {
|
submissions: A(model.submissions),
|
||||||
if (!excludedMetaFields.includes(k) && fields.indexOf(k) < 0) {
|
total: model.total
|
||||||
fields.push(k);
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
let submissions = [];
|
|
||||||
model.submissions.forEach((s) => {
|
|
||||||
let submission = {
|
|
||||||
username: s.username,
|
|
||||||
};
|
|
||||||
Object.keys(s.fields).forEach((f) => {
|
|
||||||
if (fields.includes(f)) {
|
|
||||||
submission[f] = s.fields[f];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
submissions.push(submission);
|
|
||||||
});
|
|
||||||
|
|
||||||
controller.setProperties({
|
|
||||||
wizard: model.wizard,
|
|
||||||
submissions,
|
|
||||||
fields,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,23 +11,31 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="wizard-submissions">
|
<div class="wizard-submissions">
|
||||||
<table>
|
{{#load-more selector=".wizard-submissions tr" action=(action "loadMore")}}
|
||||||
<thead>
|
{{#if noResults}}
|
||||||
<tr>
|
<p>{{i18n "search.no_results"}}</p>
|
||||||
{{#each fields as |f|}}
|
{{else}}
|
||||||
<th>{{f}}</th>
|
<table>
|
||||||
{{/each}}
|
<thead>
|
||||||
</tr>
|
<tr>
|
||||||
</thead>
|
{{#each fields as |f|}}
|
||||||
<tbody>
|
<th>{{f}}</th>
|
||||||
{{#each submissions as |s|}}
|
{{/each}}
|
||||||
<tr>
|
</tr>
|
||||||
{{#each-in s as |k v|}}
|
</thead>
|
||||||
<td>{{v}}</td>
|
<tbody>
|
||||||
{{/each-in}}
|
{{#each submissions as |s|}}
|
||||||
</tr>
|
<tr>
|
||||||
{{/each}}
|
{{#each-in s as |k v|}}
|
||||||
</tbody>
|
<td>{{v}}</td>
|
||||||
</table>
|
{{/each-in}}
|
||||||
|
</tr>
|
||||||
|
{{/each}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{conditional-loading-spinner condition=loadingMore}}
|
||||||
|
{{/load-more}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
@ -13,12 +13,16 @@ class CustomWizard::AdminSubmissionsController < CustomWizard::AdminController
|
||||||
def show
|
def show
|
||||||
render_json_dump(
|
render_json_dump(
|
||||||
wizard: CustomWizard::BasicWizardSerializer.new(@wizard, root: false),
|
wizard: CustomWizard::BasicWizardSerializer.new(@wizard, root: false),
|
||||||
submissions: ActiveModel::ArraySerializer.new(ordered_submissions, each_serializer: CustomWizard::SubmissionSerializer)
|
submissions: ActiveModel::ArraySerializer.new(
|
||||||
|
submission_list.submissions,
|
||||||
|
each_serializer: CustomWizard::SubmissionSerializer
|
||||||
|
),
|
||||||
|
total: submission_list.total
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def download
|
def download
|
||||||
send_data ordered_submissions.to_json,
|
send_data submission_list.submissions.to_json,
|
||||||
filename: "#{Discourse.current_hostname}-wizard-submissions-#{@wizard.name}.json",
|
filename: "#{Discourse.current_hostname}-wizard-submissions-#{@wizard.name}.json",
|
||||||
content_type: "application/json",
|
content_type: "application/json",
|
||||||
disposition: "attachment"
|
disposition: "attachment"
|
||||||
|
@ -26,7 +30,7 @@ class CustomWizard::AdminSubmissionsController < CustomWizard::AdminController
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def ordered_submissions
|
def submission_list
|
||||||
CustomWizard::Submission.list(@wizard, order_by: 'id')
|
CustomWizard::Submission.list(@wizard, page: params[:page].to_i)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
class CustomWizard::Submission
|
class CustomWizard::Submission
|
||||||
include ActiveModel::SerializerSupport
|
include ActiveModel::SerializerSupport
|
||||||
|
|
||||||
|
PAGE_LIMIT = 50
|
||||||
KEY ||= "submissions"
|
KEY ||= "submissions"
|
||||||
META ||= %w(submitted_at route_to redirect_on_complete redirect_to)
|
META ||= %w(submitted_at route_to redirect_on_complete redirect_to)
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ class CustomWizard::Submission
|
||||||
validate
|
validate
|
||||||
|
|
||||||
submission_list = self.class.list(wizard, user_id: user.id)
|
submission_list = self.class.list(wizard, user_id: user.id)
|
||||||
submissions = submission_list.select { |submission| submission.id != self.id }
|
submissions = submission_list.submissions.select { |submission| submission.id != self.id }
|
||||||
submissions.push(self)
|
submissions.push(self)
|
||||||
|
|
||||||
submission_data = submissions.map { |submission| data_to_save(submission) }
|
submission_data = submissions.map { |submission| data_to_save(submission) }
|
||||||
|
@ -92,27 +93,38 @@ class CustomWizard::Submission
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.get(wizard, user_id)
|
def self.get(wizard, user_id)
|
||||||
data = PluginStore.get("#{wizard.id}_#{KEY}", user_id).first
|
data = PluginStore.get("#{wizard.id}_#{KEY}", user_id).last
|
||||||
new(wizard, data, user_id)
|
new(wizard, data, user_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.list(wizard, user_id: nil, order_by: nil)
|
def self.list(wizard, user_id: nil, page: nil)
|
||||||
params = { plugin_name: "#{wizard.id}_#{KEY}" }
|
params = { plugin_name: "#{wizard.id}_#{KEY}" }
|
||||||
params[:key] = user_id if user_id.present?
|
params[:key] = user_id if user_id.present?
|
||||||
|
|
||||||
query = PluginStoreRow.where(params)
|
query = PluginStoreRow.where(params)
|
||||||
query = query.order("#{order_by} DESC") if order_by.present?
|
result = OpenStruct.new(submissions: [], total: nil)
|
||||||
|
|
||||||
result = []
|
|
||||||
|
|
||||||
query.each do |record|
|
query.each do |record|
|
||||||
if (submission_data = ::JSON.parse(record.value)).any?
|
if (submission_data = ::JSON.parse(record.value)).any?
|
||||||
submission_data.each do |data|
|
submission_data.each do |data|
|
||||||
result.push(new(wizard, data, record.key))
|
result.submissions.push(new(wizard, data, record.key))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
result.total = result.submissions.size
|
||||||
|
|
||||||
|
if !page.nil?
|
||||||
|
start = page * PAGE_LIMIT
|
||||||
|
length = PAGE_LIMIT
|
||||||
|
|
||||||
|
if result.submissions.length > start
|
||||||
|
result.submissions = result.submissions[start, length]
|
||||||
|
else
|
||||||
|
result.submissions = []
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -272,7 +272,7 @@ class CustomWizard::Wizard
|
||||||
|
|
||||||
def submissions
|
def submissions
|
||||||
return nil unless user.present?
|
return nil unless user.present?
|
||||||
@submissions ||= CustomWizard::Submission.list(self, user_id: user.id)
|
@submissions ||= CustomWizard::Submission.list(self, user_id: user.id).submissions
|
||||||
end
|
end
|
||||||
|
|
||||||
def current_submission
|
def current_submission
|
||||||
|
|
|
@ -3,10 +3,7 @@ class CustomWizard::SubmissionSerializer < ApplicationSerializer
|
||||||
attributes :id,
|
attributes :id,
|
||||||
:username,
|
:username,
|
||||||
:fields,
|
:fields,
|
||||||
:submitted_at,
|
:submitted_at
|
||||||
:route_to,
|
|
||||||
:redirect_on_complete,
|
|
||||||
:redirect_to
|
|
||||||
|
|
||||||
def username
|
def username
|
||||||
object.user.present? ?
|
object.user.present? ?
|
||||||
|
|
|
@ -21,8 +21,11 @@ describe CustomWizard::Submission do
|
||||||
@wizard = CustomWizard::Wizard.create(template_json["id"], user)
|
@wizard = CustomWizard::Wizard.create(template_json["id"], user)
|
||||||
@wizard2 = CustomWizard::Wizard.create(template_json["id"], user2)
|
@wizard2 = CustomWizard::Wizard.create(template_json["id"], user2)
|
||||||
@wizard3 = CustomWizard::Wizard.create(template_json_2["id"], user)
|
@wizard3 = CustomWizard::Wizard.create(template_json_2["id"], user)
|
||||||
|
@count = CustomWizard::Submission::PAGE_LIMIT + 20
|
||||||
|
|
||||||
described_class.new(@wizard, step_1_field_1: "I am a user submission").save
|
@count.times do |index|
|
||||||
|
described_class.new(@wizard, step_1_field_1: "I am user submission #{index+1}").save
|
||||||
|
end
|
||||||
described_class.new(@wizard2, step_1_field_1: "I am another user's submission").save
|
described_class.new(@wizard2, step_1_field_1: "I am another user's submission").save
|
||||||
described_class.new(@wizard3, step_1_field_1: "I am a user submission on another wizard").save
|
described_class.new(@wizard3, step_1_field_1: "I am a user submission on another wizard").save
|
||||||
end
|
end
|
||||||
|
@ -30,14 +33,18 @@ describe CustomWizard::Submission do
|
||||||
it "saves a user's submission" do
|
it "saves a user's submission" do
|
||||||
expect(
|
expect(
|
||||||
described_class.get(@wizard, user.id).fields["step_1_field_1"]
|
described_class.get(@wizard, user.id).fields["step_1_field_1"]
|
||||||
).to eq("I am a user submission")
|
).to eq("I am user submission #{@count}")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "list submissions by wizard" do
|
it "list submissions by wizard" do
|
||||||
expect(described_class.list(@wizard).size).to eq(2)
|
expect(described_class.list(@wizard).total).to eq(@count + 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "list submissions by wizard and user" do
|
it "list submissions by wizard and user" do
|
||||||
expect(described_class.list(@wizard, user_id: user.id).size).to eq(1)
|
expect(described_class.list(@wizard, user_id: user.id).total).to eq(@count)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "paginates submission lists" do
|
||||||
|
expect(described_class.list(@wizard, page: 1).submissions.size).to eq((@count + 1) - CustomWizard::Submission::PAGE_LIMIT)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Laden …
In neuem Issue referenzieren