diff --git a/app/assets/javascripts/admin/components/admin-report.js.es6 b/app/assets/javascripts/admin/components/admin-report.js.es6
index c126d90ee60..f4ed1372eaf 100644
--- a/app/assets/javascripts/admin/components/admin-report.js.es6
+++ b/app/assets/javascripts/admin/components/admin-report.js.es6
@@ -43,6 +43,7 @@ export default Ember.Component.extend({
isEnabled: true,
disabledLabel: "admin.dashboard.disabled",
isLoading: false,
+ rateLimitationString: null,
dataSourceName: null,
report: null,
model: null,
@@ -303,7 +304,7 @@ export default Ember.Component.extend({
_fetchReport() {
this._super();
- this.set("isLoading", true);
+ this.setProperties({ isLoading: true, rateLimitationString: null });
let payload = this._buildPayload(["prev_period"]);
@@ -315,6 +316,12 @@ export default Ember.Component.extend({
console.log("failed loading", this.get("dataSource"));
}
})
+ .catch(data => {
+ if (data.jqXHR && data.jqXHR.status === 429) {
+ const error = data.jqXHR.responseJSON.errors[0];
+ this.set("rateLimitationString", error);
+ }
+ })
.finally(() => {
if (this.element && !this.isDestroying && !this.isDestroyed) {
this.set("isLoading", false);
diff --git a/app/assets/javascripts/admin/templates/components/admin-report.hbs b/app/assets/javascripts/admin/templates/components/admin-report.hbs
index 37335e56368..9024f099f06 100644
--- a/app/assets/javascripts/admin/templates/components/admin-report.hbs
+++ b/app/assets/javascripts/admin/templates/components/admin-report.hbs
@@ -57,21 +57,28 @@
{{/if}}
{{/if}}
{{else}}
-
+ {{#if rateLimitationString}}
+
+ {{d-icon "thermometer-three-quarters"}}
+ {{rateLimitationString}}
+
+ {{else}}
+
+ {{/if}}
{{/if}}
{{else}}
{{#if showTimeoutError}}
diff --git a/app/assets/stylesheets/common/admin/admin_report.scss b/app/assets/stylesheets/common/admin/admin_report.scss
index de14fe43881..9bed7a769d5 100644
--- a/app/assets/stylesheets/common/admin/admin_report.scss
+++ b/app/assets/stylesheets/common/admin/admin_report.scss
@@ -96,12 +96,17 @@
display: block;
}
- &.no-data {
+ &.no-data,
+ &.rate-limited {
background: $secondary;
border-color: $primary-low;
color: $primary-low-mid;
}
+ &.rate-limited .d-icon {
+ color: $danger;
+ }
+
&.timeout,
&.exception {
border-color: $danger-low;
diff --git a/app/assets/stylesheets/common/admin/dashboard_next.scss b/app/assets/stylesheets/common/admin/dashboard_next.scss
index 42d6bcd1443..ce1ac7deb2e 100644
--- a/app/assets/stylesheets/common/admin/dashboard_next.scss
+++ b/app/assets/stylesheets/common/admin/dashboard_next.scss
@@ -309,6 +309,7 @@
flex-direction: row;
padding: 0.5em 0.25em;
align-items: center;
+ text-align: left;
border: 0;
&:hover {
diff --git a/test/javascripts/components/admin-report-test.js.es6 b/test/javascripts/components/admin-report-test.js.es6
index d7a94d1068a..d92ef4051fb 100644
--- a/test/javascripts/components/admin-report-test.js.es6
+++ b/test/javascripts/components/admin-report-test.js.es6
@@ -130,3 +130,25 @@ componentTest("exception", {
assert.ok(exists(".alert-error.exception"), "it displays an error");
}
});
+
+componentTest("rate limited", {
+ beforeEach() {
+ const response = object => {
+ return [429, { "Content-Type": "application/json" }, object];
+ };
+
+ // prettier-ignore
+ server.get("/admin/reports/signups_rate_limited", () => { //eslint-disable-line
+ return response({"errors":["You’ve performed this action too many times. Please wait 10 seconds before trying again."],"error_type":"rate_limit","extras":{"wait_seconds":10}});
+ });
+ },
+
+ template: "{{admin-report dataSourceName='signups_rate_limited'}}",
+
+ test(assert) {
+ assert.ok(
+ exists(".alert-error.rate-limited"),
+ "it displays a rate limited error"
+ );
+ }
+});