From 3bb71d04f7cd8bc4c6b716ef707c2c8d04cf3ee7 Mon Sep 17 00:00:00 2001 From: Phil Renaud Date: Fri, 17 Jun 2022 14:05:30 -0400 Subject: [PATCH] Toast-style global notification state (#13341) * toast style notification init * Notificatino styles and messaging for variable save * pre-PR cleanup * Typo fix and 5sec timeout * Prevent text from overlapping the close button --- ui/app/components/secure-variable-form.js | 25 ++++++++-- ui/app/controllers/application.js | 1 + ui/app/router.js | 2 +- ui/app/styles/core.scss | 1 + ui/app/styles/core/notifications.scss | 58 +++++++++++++++++++++++ ui/app/templates/application.hbs | 20 ++++++++ ui/package.json | 1 + ui/tests/helpers/flash-message.js | 3 ++ ui/yarn.lock | 14 +++++- 9 files changed, 119 insertions(+), 6 deletions(-) create mode 100644 ui/app/styles/core/notifications.scss create mode 100644 ui/tests/helpers/flash-message.js diff --git a/ui/app/components/secure-variable-form.js b/ui/app/components/secure-variable-form.js index 195235af1..1b119d855 100644 --- a/ui/app/components/secure-variable-form.js +++ b/ui/app/components/secure-variable-form.js @@ -10,6 +10,7 @@ import EmberObject from '@ember/object'; export default class SecureVariableFormComponent extends Component { @service router; + @service flashMessages; @tracked shouldHideValues = true; @@ -87,9 +88,27 @@ export default class SecureVariableFormComponent extends Component { @action async save(e) { e.preventDefault(); - this.args.model.set('keyValues', this.keyValues); - this.args.model.setAndTrimPath(); - await this.args.model.save(); + try { + this.args.model.set('keyValues', this.keyValues); + this.args.model.setAndTrimPath(); + await this.args.model.save(); + this.flashMessages.add({ + title: 'Secure Variable saved', + message: `${this.args.model.path} successfully saved`, + type: 'success', + destroyOnClick: false, + timeout: 5000, + showProgress: true, + }); + } catch (error) { + this.flashMessages.add({ + title: `Error saving ${this.args.model.path}`, + message: error, + type: 'error', + destroyOnClick: false, + sticky: true, + }); + } this.router.transitionTo('variables.variable', this.args.model.path); } } diff --git a/ui/app/controllers/application.js b/ui/app/controllers/application.js index 8e862ead6..e4ac82c7c 100644 --- a/ui/app/controllers/application.js +++ b/ui/app/controllers/application.js @@ -15,6 +15,7 @@ export default class ApplicationController extends Controller { @service config; @service system; @service token; + @service flashMessages; queryParams = [ { diff --git a/ui/app/router.js b/ui/app/router.js index 01ee4136d..ba7cfc5d5 100644 --- a/ui/app/router.js +++ b/ui/app/router.js @@ -84,7 +84,7 @@ Router.map(function () { this.route( 'variable', { - path: '/*path', + path: '/var/*path', }, function () { this.route('edit'); diff --git a/ui/app/styles/core.scss b/ui/app/styles/core.scss index 786e83e1c..b622d79aa 100644 --- a/ui/app/styles/core.scss +++ b/ui/app/styles/core.scss @@ -35,3 +35,4 @@ @import './core/tag'; @import './core/title'; @import './core/typography'; +@import './core/notifications'; diff --git a/ui/app/styles/core/notifications.scss b/ui/app/styles/core/notifications.scss new file mode 100644 index 000000000..90ff30662 --- /dev/null +++ b/ui/app/styles/core/notifications.scss @@ -0,0 +1,58 @@ +section.notifications { + position: fixed; + bottom: 10px; + right: 10px; + + .flash-message { + width: 300px; + transition: all 700ms cubic-bezier(0.68, -0.55, 0.265, 1.55); + padding: 1rem; + margin-bottom: 1rem; + box-shadow: 1px 1px 4px 0px rgb(0, 0, 0, 0.1); + position: relative; + overflow: hidden; + padding-right: 20px; + + &.alert-success { + background-color: lighten($nomad-green, 50%); + } + &.alert-error { + background-color: lighten($danger, 45%); + } + + h3 { + font-weight: bold; + } + + span.close-button { + position: absolute; + top: 0; + right: 0; + padding: 10px; + line-height: 100%; + font-size: 1.5rem; + cursor: pointer; + } + + .alert-progress { + width: 100%; + border-radius: 3px; + position: absolute; + bottom: 0; + left: 0; + .alert-progressBar { + background-color: $nomad-green; + height: 2px; + width: 0%; + } + } + + &.active { + .alert-progress { + .alert-progressBar { + width: 100%; + } + } + } + } +} diff --git a/ui/app/templates/application.hbs b/ui/app/templates/application.hbs index a51eea0a2..755848011 100644 --- a/ui/app/templates/application.hbs +++ b/ui/app/templates/application.hbs @@ -4,6 +4,26 @@ separator=" - " }} + +
+ {{#each this.flashMessages.queue as |flash|}} + + × + {{#if flash.title}} +

{{flash.title}}

+ {{/if}} + {{#if flash.message}} +

{{flash.message}}

+ {{/if}} + {{#if component.showProgressBar}} +
+
+
+ {{/if}} +
+ {{/each}} +
+ {{#if this.error}}
diff --git a/ui/package.json b/ui/package.json index 955ef5cc2..7f76f4ccc 100644 --- a/ui/package.json +++ b/ui/package.json @@ -71,6 +71,7 @@ "ember-cli-clipboard": "^0.13.0", "ember-cli-dependency-checker": "^3.2.0", "ember-cli-deprecation-workflow": "^2.1.0", + "ember-cli-flash": "^3.0.0", "ember-cli-funnel": "^0.6.1", "ember-cli-htmlbars": "^5.7.2", "ember-cli-inject-live-reload": "^2.1.0", diff --git a/ui/tests/helpers/flash-message.js b/ui/tests/helpers/flash-message.js new file mode 100644 index 000000000..56646e876 --- /dev/null +++ b/ui/tests/helpers/flash-message.js @@ -0,0 +1,3 @@ +import FlashObject from 'ember-cli-flash/flash/object'; + +FlashObject.reopen({ init() {} }); diff --git a/ui/yarn.lock b/ui/yarn.lock index 900478fae..cd77a12e7 100644 --- a/ui/yarn.lock +++ b/ui/yarn.lock @@ -2500,7 +2500,7 @@ ember-cli-babel "^7.22.1" ember-compatibility-helpers "^1.1.1" -"@ember/render-modifiers@^2.0.0", "@ember/render-modifiers@^2.0.4": +"@ember/render-modifiers@^2.0.0", "@ember/render-modifiers@^2.0.2", "@ember/render-modifiers@^2.0.4": version "2.0.4" resolved "https://registry.yarnpkg.com/@ember/render-modifiers/-/render-modifiers-2.0.4.tgz#0ac7af647cb736076dbfcd54ca71e090cd329d71" integrity sha512-Zh/fo5VUmVzYHkHVvzWVjJ1RjFUxA2jH0zCp2+DQa80Bf3DUXauiEByxU22UkN4LFT55DBFttC0xCQSJG3WTsg== @@ -9235,7 +9235,7 @@ ember-assign-helper@^0.3.0: ember-cli-babel "^7.19.0" ember-cli-htmlbars "^4.3.1" -ember-auto-import@^1.10.1, ember-auto-import@^1.11.3, ember-auto-import@^1.2.19, ember-auto-import@^1.6.0, ember-auto-import@^2.4.0: +ember-auto-import@^1.10.1, ember-auto-import@^1.11.3, ember-auto-import@^1.2.19, ember-auto-import@^1.6.0, ember-auto-import@^2.2.4, ember-auto-import@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/ember-auto-import/-/ember-auto-import-2.4.0.tgz#91c4797f08315728086e35af954cb60bd23c14bc" integrity sha512-BwF6iTaoSmT2vJ9NEHEGRBCh2+qp+Nlaz/Q7roqNSxl5oL5iMRwenPnHhOoBPTYZvPhcV/KgXR5e+pBQ107plQ== @@ -9413,6 +9413,16 @@ ember-cli-deprecation-workflow@^2.1.0: broccoli-plugin "^4.0.5" ember-cli-htmlbars "^5.3.2" +ember-cli-flash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ember-cli-flash/-/ember-cli-flash-3.0.0.tgz#ca914b18427472608805a82e6737fa45f5945a9f" + integrity sha512-AIJJm+Kg7qFkQLnNxNkiIypi7m8MK8Ix4ZA1DCPyuZbjI8JBc3Q0rqQcCd0AflxH2/X5bhYG+ej0885XtH1svQ== + dependencies: + "@ember/render-modifiers" "^2.0.2" + ember-auto-import "^2.2.4" + ember-cli-babel "^7.26.10" + ember-cli-htmlbars "^6.0.1" + ember-cli-funnel@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/ember-cli-funnel/-/ember-cli-funnel-0.6.1.tgz#f8b248a35fb88bc3aea2ac6e2a74e3e6083b4283"