From 34fee3729cb4e5c62a94e5875436eabee7099777 Mon Sep 17 00:00:00 2001 From: angusmcleod Date: Wed, 14 Jul 2021 14:04:19 +0800 Subject: [PATCH] Add pagination to submissions --- .../admin-wizards-submissions-show.js.es6 | 28 ++++++++++++ .../discourse/models/custom-wizard.js.es6 | 44 ++++++++++++++++++- .../admin-wizards-submissions-show.js.es6 | 38 +++------------- .../admin-wizards-submissions-show.hbs | 44 +++++++++++-------- .../custom_wizard/admin/submissions.rb | 12 +++-- lib/custom_wizard/submission.rb | 30 +++++++++---- lib/custom_wizard/wizard.rb | 2 +- .../custom_wizard/submission_serializer.rb | 5 +-- .../custom_wizard/submission_spec.rb | 15 +++++-- 9 files changed, 146 insertions(+), 72 deletions(-) diff --git a/assets/javascripts/discourse/controllers/admin-wizards-submissions-show.js.es6 b/assets/javascripts/discourse/controllers/admin-wizards-submissions-show.js.es6 index f5f9926d..bc38648d 100644 --- a/assets/javascripts/discourse/controllers/admin-wizards-submissions-show.js.es6 +++ b/assets/javascripts/discourse/controllers/admin-wizards-submissions-show.js.es6 @@ -1,6 +1,34 @@ import Controller from "@ember/controller"; import { fmt } from "discourse/lib/computed"; +import { empty } from '@ember/object/computed'; +import CustomWizard from "../models/custom-wizard"; export default Controller.extend({ 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(); + } + } + } }); diff --git a/assets/javascripts/discourse/models/custom-wizard.js.es6 b/assets/javascripts/discourse/models/custom-wizard.js.es6 index e6a8408d..e4b0a530 100644 --- a/assets/javascripts/discourse/models/custom-wizard.js.es6 +++ b/assets/javascripts/discourse/models/custom-wizard.js.es6 @@ -211,9 +211,51 @@ CustomWizard.reopenClass({ .catch(popupAjaxError); }, - submissions(wizardId) { + submissions(wizardId, page = null) { + let data = {}; + + if (page) { + data.page = page; + } + return ajax(`/admin/wizards/submissions/${wizardId}`, { 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); }, diff --git a/assets/javascripts/discourse/routes/admin-wizards-submissions-show.js.es6 b/assets/javascripts/discourse/routes/admin-wizards-submissions-show.js.es6 index 73168ff3..509816da 100644 --- a/assets/javascripts/discourse/routes/admin-wizards-submissions-show.js.es6 +++ b/assets/javascripts/discourse/routes/admin-wizards-submissions-show.js.es6 @@ -1,7 +1,6 @@ import CustomWizard from "../models/custom-wizard"; import DiscourseRoute from "discourse/routes/discourse"; - -const excludedMetaFields = ["route_to", "redirect_on_complete", "redirect_to"]; +import { A } from "@ember/array"; export default DiscourseRoute.extend({ model(params) { @@ -9,34 +8,11 @@ export default DiscourseRoute.extend({ }, setupController(controller, model) { - if (model && model.submissions) { - let fields = ["username"]; - model.submissions.forEach((s) => { - Object.keys(s.fields).forEach((k) => { - if (!excludedMetaFields.includes(k) && fields.indexOf(k) < 0) { - 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, - }); - } + controller.setProperties({ + wizard: model.wizard, + fields: model.fields, + submissions: A(model.submissions), + total: model.total + }); }, }); diff --git a/assets/javascripts/discourse/templates/admin-wizards-submissions-show.hbs b/assets/javascripts/discourse/templates/admin-wizards-submissions-show.hbs index 6d1f255b..9e8e10c8 100644 --- a/assets/javascripts/discourse/templates/admin-wizards-submissions-show.hbs +++ b/assets/javascripts/discourse/templates/admin-wizards-submissions-show.hbs @@ -11,23 +11,31 @@
- - - - {{#each fields as |f|}} - - {{/each}} - - - - {{#each submissions as |s|}} - - {{#each-in s as |k v|}} - - {{/each-in}} - - {{/each}} - -
{{f}}
{{v}}
+ {{#load-more selector=".wizard-submissions tr" action=(action "loadMore")}} + {{#if noResults}} +

{{i18n "search.no_results"}}

+ {{else}} + + + + {{#each fields as |f|}} + + {{/each}} + + + + {{#each submissions as |s|}} + + {{#each-in s as |k v|}} + + {{/each-in}} + + {{/each}} + +
{{f}}
{{v}}
+ {{/if}} + + {{conditional-loading-spinner condition=loadingMore}} + {{/load-more}}
{{/if}} diff --git a/controllers/custom_wizard/admin/submissions.rb b/controllers/custom_wizard/admin/submissions.rb index 4cb2a0e4..c3bf809f 100644 --- a/controllers/custom_wizard/admin/submissions.rb +++ b/controllers/custom_wizard/admin/submissions.rb @@ -13,12 +13,16 @@ class CustomWizard::AdminSubmissionsController < CustomWizard::AdminController def show render_json_dump( 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 def download - send_data ordered_submissions.to_json, + send_data submission_list.submissions.to_json, filename: "#{Discourse.current_hostname}-wizard-submissions-#{@wizard.name}.json", content_type: "application/json", disposition: "attachment" @@ -26,7 +30,7 @@ class CustomWizard::AdminSubmissionsController < CustomWizard::AdminController protected - def ordered_submissions - CustomWizard::Submission.list(@wizard, order_by: 'id') + def submission_list + CustomWizard::Submission.list(@wizard, page: params[:page].to_i) end end diff --git a/lib/custom_wizard/submission.rb b/lib/custom_wizard/submission.rb index e50cb259..95b4f7fa 100644 --- a/lib/custom_wizard/submission.rb +++ b/lib/custom_wizard/submission.rb @@ -1,7 +1,8 @@ # frozen_string_literal: true class CustomWizard::Submission include ActiveModel::SerializerSupport - + + PAGE_LIMIT = 50 KEY ||= "submissions" META ||= %w(submitted_at route_to redirect_on_complete redirect_to) @@ -44,7 +45,7 @@ class CustomWizard::Submission validate 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) submission_data = submissions.map { |submission| data_to_save(submission) } @@ -92,27 +93,38 @@ class CustomWizard::Submission end 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) 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[:key] = user_id if user_id.present? query = PluginStoreRow.where(params) - query = query.order("#{order_by} DESC") if order_by.present? - - result = [] + result = OpenStruct.new(submissions: [], total: nil) 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| - result.push(new(wizard, data, record.key)) + result.submissions.push(new(wizard, data, record.key)) 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 end end diff --git a/lib/custom_wizard/wizard.rb b/lib/custom_wizard/wizard.rb index 8f5a897f..e8427334 100644 --- a/lib/custom_wizard/wizard.rb +++ b/lib/custom_wizard/wizard.rb @@ -272,7 +272,7 @@ class CustomWizard::Wizard def submissions 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 def current_submission diff --git a/serializers/custom_wizard/submission_serializer.rb b/serializers/custom_wizard/submission_serializer.rb index 52f0cb32..992deacb 100644 --- a/serializers/custom_wizard/submission_serializer.rb +++ b/serializers/custom_wizard/submission_serializer.rb @@ -3,10 +3,7 @@ class CustomWizard::SubmissionSerializer < ApplicationSerializer attributes :id, :username, :fields, - :submitted_at, - :route_to, - :redirect_on_complete, - :redirect_to + :submitted_at def username object.user.present? ? diff --git a/spec/components/custom_wizard/submission_spec.rb b/spec/components/custom_wizard/submission_spec.rb index a8c33861..ce9756d1 100644 --- a/spec/components/custom_wizard/submission_spec.rb +++ b/spec/components/custom_wizard/submission_spec.rb @@ -21,8 +21,11 @@ describe CustomWizard::Submission do @wizard = CustomWizard::Wizard.create(template_json["id"], user) @wizard2 = CustomWizard::Wizard.create(template_json["id"], user2) @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(@wizard3, step_1_field_1: "I am a user submission on another wizard").save end @@ -30,14 +33,18 @@ describe CustomWizard::Submission do it "saves a user's submission" do expect( 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 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 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