diff --git a/ui/app/mixins/with-watchers.js b/ui/app/mixins/with-watchers.js
index c9690dbdf02..ef3337866ec 100644
--- a/ui/app/mixins/with-watchers.js
+++ b/ui/app/mixins/with-watchers.js
@@ -33,6 +33,9 @@ export default Mixin.create(WithVisibilityDetection, {
actions: {
willTransition() {
this.cancelAllWatchers();
+
+ // Bubble the action up to the application route
+ return true;
},
},
});
diff --git a/ui/app/styles/components/error-container.scss b/ui/app/styles/components/error-container.scss
index 298d7fe52fb..82e5cf10914 100644
--- a/ui/app/styles/components/error-container.scss
+++ b/ui/app/styles/components/error-container.scss
@@ -3,20 +3,32 @@
height: 100%;
padding-top: 25vh;
display: flex;
- justify-content: center;
- background: $grey-lighter;
+ flex-direction: column;
+ justify-content: start;
+ align-items: center;
+ background: $white-ter;
.error-message {
+ width: 95vw;
max-width: 600px;
- .title,
- .subtitle {
+ .title {
text-align: center;
}
}
.error-stack-trace {
- border: 1px solid $grey-light;
+ border: 1px solid $grey-lighter;
border-radius: $radius;
+ background: $white;
+ }
+
+ .error-links {
+ padding-top: 15px;
+ margin-top: 15px;
+ border-top: 1px solid $grey-lighter;
+ width: 95vw;
+ max-width: 600px;
+ text-align: center;
}
}
diff --git a/ui/app/templates/application.hbs b/ui/app/templates/application.hbs
index a12a00c5f5d..cfa4247bff4 100644
--- a/ui/app/templates/application.hbs
+++ b/ui/app/templates/application.hbs
@@ -30,5 +30,9 @@
{{errorStr}}
{{/if}}
+
+ {{#link-to "jobs" data-test-error-jobs-link class="button is-white"}}Go to Jobs{{/link-to}}
+ {{#link-to "clients" data-test-error-clients-link class="button is-white"}}Go to Clients{{/link-to}}
+
{{/unless}}
diff --git a/ui/tests/acceptance/application-errors-test.js b/ui/tests/acceptance/application-errors-test.js
index b07dbdd63ca..266375c522b 100644
--- a/ui/tests/acceptance/application-errors-test.js
+++ b/ui/tests/acceptance/application-errors-test.js
@@ -67,3 +67,28 @@ test('the no leader error state gets its own error message', function(assert) {
);
});
});
+
+test('error pages include links to the jobs and clients pages', function(assert) {
+ visit('/a/non-existent/page');
+
+ andThen(() => {
+ assert.ok(JobsList.error.isPresent, 'An error is shown');
+ JobsList.error.gotoJobs();
+ });
+
+ andThen(() => {
+ assert.equal(currentURL(), '/jobs', 'Now on the jobs page');
+ assert.notOk(JobsList.error.isPresent, 'The error is gone now');
+ visit('/a/non-existent/page');
+ });
+
+ andThen(() => {
+ assert.ok(JobsList.error.isPresent, 'An error is shown');
+ JobsList.error.gotoClients();
+ });
+
+ andThen(() => {
+ assert.equal(currentURL(), '/clients', 'Now on the clients page');
+ assert.notOk(JobsList.error.isPresent, 'The error is gone now');
+ });
+});
diff --git a/ui/tests/pages/jobs/list.js b/ui/tests/pages/jobs/list.js
index 37ebd67468a..24aff62f287 100644
--- a/ui/tests/pages/jobs/list.js
+++ b/ui/tests/pages/jobs/list.js
@@ -44,6 +44,8 @@ export default create({
title: text('[data-test-error-title]'),
message: text('[data-test-error-message]'),
seekHelp: clickable('[data-test-error-message] a'),
+ gotoJobs: clickable('[data-test-error-jobs-link]'),
+ gotoClients: clickable('[data-test-error-clients-link]'),
},
namespaceSwitcher: {