diff --git a/app/controllers/discourse_subscriptions/admin/subscriptions_controller.rb b/app/controllers/discourse_subscriptions/admin/subscriptions_controller.rb index a3f7f7f..8498c37 100644 --- a/app/controllers/discourse_subscriptions/admin/subscriptions_controller.rb +++ b/app/controllers/discourse_subscriptions/admin/subscriptions_controller.rb @@ -7,14 +7,33 @@ module DiscourseSubscriptions include DiscourseSubscriptions::Group before_action :set_api_key + PAGE_LIMIT = 10 + def index begin subscription_ids = Subscription.all.pluck(:external_id) - subscriptions = [] + subscriptions = { + has_more: false, + data: [], + length: 0, + last_record: params[:last_record] + } if subscription_ids.present? && is_stripe_configured? - subscriptions = ::Stripe::Subscription.list(expand: ['data.plan.product']) - subscriptions = subscriptions.select { |sub| subscription_ids.include?(sub[:id]) } + while subscriptions[:length] < PAGE_LIMIT + current_set = get_subscriptions(subscriptions[:last_record]) + + until valid_subscriptions = find_valid_subscriptions(current_set[:data], subscription_ids) do + current_set = get_subscriptions(current_set[:data].last) + break if current_set[:has_more] == false + end + + subscriptions[:data] = subscriptions[:data].concat(valid_subscriptions.to_a) + subscriptions[:last_record] = current_set[:data].last[:id] if current_set[:data].present? + subscriptions[:length] = subscriptions[:data].length + subscriptions[:has_more] = current_set[:has_more] + break if subscriptions[:has_more] == false + end elsif !is_stripe_configured? subscriptions = nil end @@ -54,6 +73,15 @@ module DiscourseSubscriptions private + def get_subscriptions(start) + ::Stripe::Subscription.list(expand: ['data.plan.product'], limit: PAGE_LIMIT, starting_after: start) + end + + def find_valid_subscriptions(data, ids) + valid = data.select { |sub| ids.include?(sub[:id]) } + valid.empty? ? nil : valid + end + # this will only refund the most recent subscription payment def refund_subscription(subscription_id) subscription = ::Stripe::Subscription.retrieve(subscription_id) diff --git a/assets/javascripts/discourse/controllers/admin-plugins-discourse-subscriptions-subscriptions.js.es6 b/assets/javascripts/discourse/controllers/admin-plugins-discourse-subscriptions-subscriptions.js.es6 index f4b51f9..541ef9f 100644 --- a/assets/javascripts/discourse/controllers/admin-plugins-discourse-subscriptions-subscriptions.js.es6 +++ b/assets/javascripts/discourse/controllers/admin-plugins-discourse-subscriptions-subscriptions.js.es6 @@ -1,12 +1,30 @@ +import AdminSubscription from "discourse/plugins/discourse-subscriptions/discourse/models/admin-subscription"; import Controller from "@ember/controller"; import showModal from "discourse/lib/show-modal"; export default Controller.extend({ + loading: false, + actions: { showCancelModal(subscription) { showModal("admin-cancel-subscription", { model: subscription, }); }, + + loadMore() { + if (!this.loading && this.model.has_more) { + this.set("loading", true); + + return AdminSubscription.loadMore(this.model.last_record).then( + (result) => { + const updated = this.model.data.concat(result.data); + this.set("model", result); + this.set("model.data", updated); + this.set("loading", false); + } + ); + } + }, }, }); diff --git a/assets/javascripts/discourse/models/admin-subscription.js.es6 b/assets/javascripts/discourse/models/admin-subscription.js.es6 index 0641244..b20625e 100644 --- a/assets/javascripts/discourse/models/admin-subscription.js.es6 +++ b/assets/javascripts/discourse/models/admin-subscription.js.es6 @@ -38,9 +38,20 @@ AdminSubscription.reopenClass({ if (result === null) { return { unconfigured: true }; } - return result.map((subscription) => + result.data = result.data.map((subscription) => AdminSubscription.create(subscription) ); + return result; + }); + }, + loadMore(lastRecord) { + return ajax(`/s/admin/subscriptions?last_record=${lastRecord}`, { + method: "get", + }).then((result) => { + result.data = result.data.map((subscription) => + AdminSubscription.create(subscription) + ); + return result; }); }, }); diff --git a/assets/javascripts/discourse/templates/admin/plugins-discourse-subscriptions-subscriptions.hbs b/assets/javascripts/discourse/templates/admin/plugins-discourse-subscriptions-subscriptions.hbs index fcf5877..151a9c2 100644 --- a/assets/javascripts/discourse/templates/admin/plugins-discourse-subscriptions-subscriptions.hbs +++ b/assets/javascripts/discourse/templates/admin/plugins-discourse-subscriptions-subscriptions.hbs @@ -2,42 +2,45 @@

{{i18n 'discourse_subscriptions.admin.unconfigured'}}

Discourse Subscriptions on Meta

{{else}} - - - - - - - - - - - - - - {{#each model as |subscription|}} - - - - - - - - - - - {{/each}} -
{{i18n 'discourse_subscriptions.admin.subscriptions.subscription.user'}}{{i18n 'discourse_subscriptions.admin.subscriptions.subscription.subscription_id'}}{{i18n 'discourse_subscriptions.admin.subscriptions.subscription.customer'}}{{i18n 'discourse_subscriptions.admin.subscriptions.subscription.product'}}{{i18n 'discourse_subscriptions.admin.subscriptions.subscription.plan'}}{{i18n 'discourse_subscriptions.admin.subscriptions.subscription.status'}}{{i18n 'discourse_subscriptions.admin.subscriptions.subscription.created_at'}}
- {{#if subscription.metadataUserExists}} - - {{subscription.metadata.username}} - - {{/if}} - {{subscription.id}}{{subscription.customer}}{{subscription.plan.product.name}}{{subscription.plan.nickname}}{{subscription.status}}{{format-unix-date subscription.created}} - {{#if subscription.loading}} - {{loading-spinner size="small"}} - {{else}} - {{d-button disabled=subscription.canceled label="cancel" action=(action "showCancelModal" subscription) icon="times"}} - {{/if}} -
+ {{#load-more selector=".discourse-patrons-table tr" action=(action "loadMore")}} + + + + + + + + + + + + + + {{#each model.data as |subscription|}} + + + + + + + + + + + {{/each}} +
{{i18n 'discourse_subscriptions.admin.subscriptions.subscription.user'}}{{i18n 'discourse_subscriptions.admin.subscriptions.subscription.subscription_id'}}{{i18n 'discourse_subscriptions.admin.subscriptions.subscription.customer'}}{{i18n 'discourse_subscriptions.admin.subscriptions.subscription.product'}}{{i18n 'discourse_subscriptions.admin.subscriptions.subscription.plan'}}{{i18n 'discourse_subscriptions.admin.subscriptions.subscription.status'}}{{i18n 'discourse_subscriptions.admin.subscriptions.subscription.created_at'}}
+ {{#if subscription.metadataUserExists}} + + {{subscription.metadata.username}} + + {{/if}} + {{subscription.id}}{{subscription.customer}}{{subscription.plan.product.name}}{{subscription.plan.nickname}}{{subscription.status}}{{format-unix-date subscription.created}} + {{#if subscription.loading}} + {{loading-spinner size="small"}} + {{else}} + {{d-button disabled=subscription.canceled label="cancel" action=(action "showCancelModal" subscription) icon="times"}} + {{/if}} +
+ {{/load-more}} + {{conditional-loading-spinner condition=loading}} {{/if}} diff --git a/spec/requests/admin/subscriptions_controller_spec.rb b/spec/requests/admin/subscriptions_controller_spec.rb index cb5b693..e27ee16 100644 --- a/spec/requests/admin/subscriptions_controller_spec.rb +++ b/spec/requests/admin/subscriptions_controller_spec.rb @@ -13,6 +13,7 @@ module DiscourseSubscriptions before do Fabricate(:subscription, external_id: "sub_12345", customer_id: customer.id) + Fabricate(:subscription, external_id: "sub_77777", customer_id: customer.id) end context 'unauthenticated' do @@ -34,21 +35,44 @@ module DiscourseSubscriptions before { sign_in(admin) } describe "index" do - it "gets the subscriptions and products" do + before do SiteSetting.discourse_subscriptions_public_key = "public-key" SiteSetting.discourse_subscriptions_secret_key = "secret-key" - ::Stripe::Subscription.expects(:list).with(expand: ['data.plan.product']).returns( - [ - { id: "sub_12345" }, - { id: "sub_nope" } - ] - ) + end + + it "gets the subscriptions and products" do + ::Stripe::Subscription.expects(:list) + .with(expand: ['data.plan.product'], limit: 10, starting_after: nil) + .returns( + has_more: false, + data: [ + { id: "sub_12345" }, + { id: "sub_nope" } + ] + ) get "/s/admin/subscriptions.json" - subscriptions = response.parsed_body[0]["id"] + subscriptions = response.parsed_body["data"][0]["id"] expect(response.status).to eq(200) expect(subscriptions).to eq("sub_12345") end + + it "handles starting at a different point in the set" do + ::Stripe::Subscription.expects(:list) + .with(expand: ['data.plan.product'], limit: 10, starting_after: 'sub_nope') + .returns( + has_more: false, + data: [ + { id: "sub_77777" }, + { id: "sub_yepnoep" } + ] + ) + get "/s/admin/subscriptions.json", params: { last_record: 'sub_nope' } + subscriptions = response.parsed_body["data"][0]["id"] + + expect(response.status).to eq(200) + expect(subscriptions).to eq("sub_77777") + end end describe "destroy" do