diff --git a/ui/core/app/components/error/message.hbs b/ui/core/app/components/error/message.hbs
new file mode 100644
index 000000000..90c471554
--- /dev/null
+++ b/ui/core/app/components/error/message.hbs
@@ -0,0 +1,6 @@
+
+ {{t (concat "errors." this.messageCode ".description")}}
+ {{#if this.helpRoute}}
+ {{t "actions.help"}}
+ {{/if}}
+
\ No newline at end of file
diff --git a/ui/core/app/components/error/message.js b/ui/core/app/components/error/message.js
new file mode 100644
index 000000000..21b362c5f
--- /dev/null
+++ b/ui/core/app/components/error/message.js
@@ -0,0 +1,61 @@
+import Message from 'rose/components/rose/message';
+import { computed } from '@ember/object';
+
+/*
+ * Helpful error booleans are attached based on the error status code:
+ *
+ * - 401 - `error.isUnauthenticated`: the session isn't authenticated
+ * - 403 - `error.isForbidden`: the session is authenticated but does not have
+ * permission to perform the requested action
+ * - 404 - `error.isNotFound`: the requested resource could not be found
+ * - 500 - `error.isServer`: an internal server error occurred
+ *
+ * For an unknown error state, i.e error state not matching to the above defined list:
+ * - unknown - `error.isUnknown`: an error occurred, but we don't know which or
+ * we don't distinguish it yet
+ */
+
+const statuses = ['401', '403', '404', '500'];
+
+export default class ErrorMessageComponent extends Message {
+ // =methods
+
+ /**
+ * Returns an icon for error status.
+ * @return {string}
+ */
+ @computed('status')
+ get icon() {
+ switch (this.status) {
+ case '401':
+ case '403':
+ return 'disabled';
+ case '404':
+ return 'help-circle-outline';
+ default:
+ return 'alert-circle-outline';
+ }
+ }
+
+ // TODO: Enable when help documentation can be linked in.
+ /**
+ * Returns an route string for help text in message.
+ * @return {string}
+ */
+ // get helpRoute() {
+ // return 'index'
+ // }
+
+ /**
+ * Returns 'unknown' status code when provided error status
+ * isn't part of predefined statuses.
+ * @return {string}
+ */
+ @computed('status')
+ get messageCode() {
+ let messageCode = this.status;
+ if(!statuses.includes(messageCode)) messageCode = 'unknown';
+ return messageCode;
+ }
+
+}
diff --git a/ui/core/app/templates/scopes/scope/error.hbs b/ui/core/app/templates/scopes/scope/error.hbs
new file mode 100644
index 000000000..8d56c81ce
--- /dev/null
+++ b/ui/core/app/templates/scopes/scope/error.hbs
@@ -0,0 +1,6 @@
+{{title (t "errors.titles.error") }}
+
+ {{#each @model.errors as |error|}}
+
+ {{/each}}
+
\ No newline at end of file
diff --git a/ui/core/mirage/config.js b/ui/core/mirage/config.js
index e7044298f..399d7f03e 100644
--- a/ui/core/mirage/config.js
+++ b/ui/core/mirage/config.js
@@ -1,6 +1,7 @@
import config from '../config/environment';
import { authHandler, deauthHandler } from './route-handlers/auth';
-//import { Response } from 'miragejs';
+// Uncomment to use in simulating error responses
+// import { Response } from 'miragejs';
export default function() {
@@ -292,4 +293,18 @@ export default function() {
}
return target.update(updatedAttrs);
});
+
+ /* Uncomment the following line and the Response import above
+ * Then change the response code to simulate error responses.
+ * this.get('/scopes', () => new Response(505));
+ *
+ * Update error payload to simulate specific error responses.
+ */
+ // this.get('/host-catalogs', () => new Response(404));
+ // this.get('/scopes/:id', () => new Response(505, {}, {
+ // errors: [{
+ // status: 505,
+ // message: 'HTTP version not supported.',
+ // }]
+ // }));
}
diff --git a/ui/core/tests/integration/components/error/message-test.js b/ui/core/tests/integration/components/error/message-test.js
new file mode 100644
index 000000000..2671c9b7e
--- /dev/null
+++ b/ui/core/tests/integration/components/error/message-test.js
@@ -0,0 +1,37 @@
+import { module, test } from 'qunit';
+import { setupRenderingTest } from 'ember-qunit';
+import { render, find } from '@ember/test-helpers';
+import { hbs } from 'ember-cli-htmlbars';
+
+module('Integration | Component | error/message', function (hooks) {
+ setupRenderingTest(hooks);
+
+ test('it renders predefined message for known error status', async function (assert) {
+ await render(hbs``);
+ assert.equal(
+ find('.rose-message-title').textContent.trim(),
+ 'You are not signed in'
+ );
+ assert.equal(
+ find('.rose-message-subtitle').textContent.trim(),
+ 'Error 401'
+ );
+ assert.equal(
+ find('.rose-message-description').textContent.trim(),
+ 'You are not authenticated. Please authenticate and try again later.'
+ );
+ });
+
+ test('it renders default error for unknown error status', async function (assert) {
+ await render(hbs``);
+ assert.equal(
+ find('.rose-message-title').textContent.trim(),
+ 'Something went wrong'
+ );
+ assert.equal(find('.rose-message-subtitle').textContent.trim(), 'Error 599');
+ assert.equal(
+ find('.rose-message-description').textContent.trim(),
+ 'Please contact your administrator or try again later.'
+ );
+ });
+});
diff --git a/ui/core/translations/en-us.yaml b/ui/core/translations/en-us.yaml
index e458c2b50..fdfb779f9 100644
--- a/ui/core/translations/en-us.yaml
+++ b/ui/core/translations/en-us.yaml
@@ -158,19 +158,24 @@ form:
current_password: Current Password
new_password: New Password
errors:
+ 401:
+ title: You are not signed in
+ description: You are not authenticated. Please authenticate and try again later.
+ 403:
+ title: You are not authorized
+ description: You must be granted permissions to view this data. Ask your administrator if you think you should have access.
+ 404:
+ title: Resource not found
+ description: We could not find the requested resource. You can ask your administrator or try again later.
+ 500:
+ title: Server error
+ description: We ran into a problem and could not continue. You can ask your administrator or try again later.
+ unknown:
+ title: Something went wrong
+ description: Please contact your administrator or try again later.
titles:
- unauthenticated-error: You are not signed in
- forbidden-error: You are not authorized
- notfound-error: Resource not found
- server-error: Server error
- unknown-error: Something went wrong
authentication-failed: Authentication Failed
- descriptions:
- unauthenticated-error: You are not authenticated. Please authenticate and try again later.
- forbidden-error: You must be granted permissions to view this data. Ask your administrator if you think you should have access.
- notfound-error: We could not find the requested resource. You can ask your administrator or try again later.
- server-error: We ran into a problem and could not continue. You can ask your administrator or try again later.
- unknown-error: Please contact your administrator or try again later.
+ error: Error
notify:
create-success: Created succesfully.
save-success: Saved succesfully.